How to compile and link a minimal .NET C++ program using mingw - c++

I'm trying to compile a minimal example of .NET C++ code (just calling CLRCreateInstance and starting a CLR runtime host). I'm not using Visual Studio, but mingw. I installed the Windows 10 SDK with .NET goodies, and I have the header and lib files correctly installed in Program Files. However, I cannot get g++ to link my program:
$ g++ -o clr.exe -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Include\um" -L"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Lib\um\x64" -lmscoree clr.cpp
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0x3d): undefined reference to `_GUID const& __mingw_uuidof<ICLRMetaHost>()'
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0x4f): undefined reference to `CLRCreateInstance'
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0x78): undefined reference to `_GUID const& __mingw_uuidof<ICLRRuntimeInfo>()'
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0xb3): undefined reference to `_GUID const& __mingw_uuidof<ICLRRuntimeHost>()'
collect2.exe: error: ld returned 1 exit status
the program is:
#include <iostream>
#include <Windows.h>
#include <metahost.h>
#include <mscoree.h>
#pragma comment(lib, "mscoree.lib")
int main()
{
HRESULT hr;
ICLRMetaHost *pMetaHost = NULL;
ICLRRuntimeInfo *pRuntimeInfo = NULL;
ICLRRuntimeHost *pClrRuntimeHost = NULL;
// build runtime
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
IID_PPV_ARGS(&pClrRuntimeHost));
// start runtime
hr = pClrRuntimeHost->Start();
hr = pClrRuntimeHost->Stop();
}

I finally made it work with the following two corrections:
I switched from vanilla MinGW to an msys2 packaged one. This solved the undefined reference to CLRCreateInstance, which I don't know why was failing with the vanilla MinGW. This basically consisted in downloading msys2 and running pacman -S mingw-w64-x86_64-gcc.
Thanks to this question I was able to solve the other three undefined references. I'm still not sure how all these COM things work, so unfortunately I'm not sure if this is the right way to solve the problem, or if I just introduced a fatal error but well... I went into mscoree.h and metahost.h in .NET SDK install dir, and looked for the things the linker was complaining about.
For example, in mscoree.h I found:
EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
so I went to my clr.cpp file and added:
__CRT_UUID_DECL(ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
which seems to work just fine. Did the same for the other two, and my code got into this, which compiled and run without errors:
#include <Windows.h>
#include <metahost.h>
#include <mscoree.h>
#include <cstdio>
__CRT_UUID_DECL(ICLRMetaHost, 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);
__CRT_UUID_DECL(ICLRRuntimeInfo, 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);
__CRT_UUID_DECL(ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
int main(int argc, char *argv[])
{
HRESULT hr;
ICLRMetaHost *pMetaHost = NULL;
ICLRRuntimeInfo *pRuntimeInfo = NULL;
ICLRRuntimeHost *pClrRuntimeHost = NULL;
// build runtime
if (CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)) != S_OK) {
printf("[x] Error: CLRCreateInstance(..)\n");
return 2;
}
if (pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)) != S_OK) {
printf("[x] Error: GetRuntime(..)\n");
return 2;
}
if (pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost)) != S_OK) {
printf("[x] Error: GetInterface(..)\n");
return 2;
}
// start runtime
if (pClrRuntimeHost->Start() != S_OK) {
printf("[x] Error: Start(..)\n");
return 2;
}
// start runtime
if (pClrRuntimeHost->Stop() != S_OK) {
printf("[x] Error: Stop(..)\n");
return 2;
}
printf("success!\n");
return 0;
}

Related

Why BCryptDeriveKeyPBKDF2 return STATUS_INVALID_PARAMETER?

#include <iostream>
#include<Windows.h>
#include<bcrypt.h>
#include <ntstatus.h>
#include<string>
#include<vector>
#pragma comment(lib, "bcrypt.lib")
void test_status(NTSTATUS return_val)
{
switch (return_val)
{
case(STATUS_SUCCESS):
{
std::cout << "STATUS_SUCCESS\n";
break;
}
case(STATUS_BUFFER_TOO_SMALL):
{
std::cout << "STATUS_BUFFER_TOO_SMALL\n";
break;
}
case(STATUS_INVALID_HANDLE):
{
std::cout << "STATUS_INVALID_HANDLE\n";
break;
}
case(STATUS_INVALID_PARAMETER):
{
std::cout << "STATUS_INVALID_PARAMETER\n";
break;
}
case(STATUS_NOT_SUPPORTED):
{
std::cout << "STATUS_NOT_SUPPORTED\n";
break;
}
};
}
int main()
{
BCRYPT_ALG_HANDLE phAlgorithm = nullptr;
BCRYPT_HASH_HANDLE phHash = nullptr;
LPCWSTR pszAlgId = TEXT("XTS-AES");
LPCWSTR pszImplementation = TEXT("Advanced Encryption Standard");
PUCHAR pbHashObject = nullptr;
std::vector<BYTE> pbSalt = { 0x77, 0x1f, 0x5b, 0x30, 0x2c, 0xf7, 0xc5, 0x31,
0xa9, 0x86, 0x46, 0x52, 0xe2, 0xff, 0x4a, 0x17,
0xab, 0xd0, 0x02, 0xdd, 0x4f, 0xb0, 0x2f, 0x71,
0x0f, 0xe5, 0xa8, 0x1a, 0xfe, 0xe7, 0x9c, 0x6b }; // 771f5b302cf7c531a9864652e2ff4a17abd002dd4fb02f710fe5a81afee79c6b
NTSTATUS status = BCryptOpenAlgorithmProvider(
&phAlgorithm,
BCRYPT_PBKDF2_ALGORITHM,
NULL,
NULL
);
test_status(status);
PUCHAR pbOutput = nullptr;
ULONG pcbResult = NULL;
status = BCryptGetProperty(
phAlgorithm,
BCRYPT_OBJECT_LENGTH,
pbOutput,
sizeof(DWORD),
&pcbResult,
NULL
);
test_status(status);
PUCHAR DerivedKey = nullptr;
DWORD cbDerivedKey = NULL;
std::string pbPassword = "MySecretPass";
std::string DerivedKeyString;
status = BCryptDeriveKeyPBKDF2(
phAlgorithm,
(BYTE*)pbPassword.data(),
pbPassword.length(),
(BYTE*)pbSalt.data(),
sizeof(BYTE),
10000,
(PUCHAR)DerivedKeyString.c_str(),
64,
0);
test_status(status);
status = BCryptCloseAlgorithmProvider(
phAlgorithm,
NULL
);
test_status(status);
}
This code should get the key from the password, but at this stage of generating this key, I get an error STATUS_INVALID_PARAMETER. Why is this happening and how to fix it
-I tried to change the encryption algorithm and pass the parameters in a different way, but all this did not lead to success or gave the error STATUS_INVALID_PARAMETER.
There are two errors:
Firstly, you are performing hash computation, the BCryptOpenAlgorithmProvider function must use flags and identifiers for the hash function's behavior.
In the function BCryptOpenAlgorithmProvider, replace BCRYPT_PBKDF2_ALGORITHM with BCRYPT_SHA256_ALGORITHM, use BCRYPT_ALG_HANDLE_HMAC_FLAG in the fourth dwFlags parameter.
The documentation for these two parameters is as follows:
https://learn.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-identifiers
https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmprovider
Secondly, do not use string type of the parameter pbDerivedKey, or it will crash the memory.
Replace std::string DerivedKeyString with BYTE DerivedKeyString[64].
In the function BCryptDeriveKeyPBKDF2, replace (PUCHAR)DerivedKeyString.c_str() with DerivedKeyString.

Some Service interface are not supported in the MFGetService helper function

I'm trying to get a pointer to the IDirect3DSurface9 and I use the the helper function MFGetService and I pass MR_BUFFER_SERVICE to the second parameter.While linking,I received a "unresolved external symbol _MR_BUFFER_SERVICE" error.
I looked up the definition of MR_BUFFER_SERVICE in evr.h and found a macro describing it:
DEFINE_GUID(MR_BUFFER_SERVICE,
0xa562248c,
0x9ac6,
0x4ffc,
0x9f, 0xba, 0x3a, 0xf8, 0xf8, 0xad, 0x1a, 0x4d
);
And then I decided to make this GUID on my own and passed to the MFGetService, but then I get the error code E_NOINTERFACE while debugging.
//Here are the GUID struct I made:
const GUID FAR MR_BUFFER_SERVICE = { 0xa562248c,0x9ac6,0x4ffc, {0x9f, 0xba, 0x3a, 0xf8, 0xf8, 0xad, 0x1a, 0x4d} };
//The main code of getting a pointer to IDirect3DSurface9:
IDirect3DSurface9 *d3dsurface9;
IMFMediaBuffer* pBuffer = NULL;
hr = MFCreateMemoryBuffer(1024 * 10, &pBuffer);
if (FAILED(hr))
{
MessageBox(NULL, L"fail in creating Media Buffer", NULL, NULL);
}
hr = MFGetService(pBuffer, MR_BUFFER_SERVICE,
IID_PPV_ARGS(&d3dsurface9));
if (FAILED(hr))
{
MessageBox(NULL, L"failed in getting IDirect3DSurface9", NULL, NULL);
}
Linker error is to be resolved by additionally linking strmiids.lib
#pragma comment(lib, "strmiids.lib")
MR_BUFFER_SERVICE is not available from generic system memory backed buffers you create by MFCreateMemoryBuffer. This service is only available from buffers which are wrapping respective D3D9 surface, esp. created with MFCreateDXSurfaceBuffer function.
The details are documented here: DirectX Surface Buffer.

Programmatically Check if Windows is Activated with C++

I am trying to write a C++ function that will tell the user if the windows OS they are currently using is activated of not.
I found a similar question Programmatically check if Windows 7 is activated , but this answer requires a UID argument. I DO NOT want the user to have to enter ANY arguments at all.
How do I programmatically Check if Windows is Activated with C++?
#define _WIN32_WINNT 0x600
#include <iostream>
#include <windows.h>
#include <slpublic.h>
/*'
From: C:/Windows/System32/SLMGR.vbs
' Copyright (c) Microsoft Corporation. All rights reserved.
'
' Windows Software Licensing Management Tool.
'
' Script Name: slmgr.vbs
'
' WMI class names
private const ServiceClass = "SoftwareLicensingService"
private const ProductClass = "SoftwareLicensingProduct"
private const TkaLicenseClass = "SoftwareLicensingTokenActivationLicense"
private const WindowsAppId = "55c92734-d682-4d71-983e-d6ec3f16059f"
*/
/** Use the WindowsAppId above to check if Windows OS itself is Genuine. **/
bool isGenuineWindows()
{
//WindowsAppId
unsigned char uuid_bytes[] = {0x35, 0x35, 0x63, 0x39, 0x32, 0x37, 0x33, 0x34, 0x2d, 0x64, 0x36,
0x38, 0x32, 0x2d, 0x34, 0x64, 0x37, 0x31, 0x2d, 0x39, 0x38, 0x33,
0x65, 0x2d, 0x64, 0x36, 0x65, 0x63, 0x33, 0x66, 0x31, 0x36, 0x30,
0x35, 0x39, 0x66};
GUID uuid;
SL_GENUINE_STATE state;
UuidFromStringA(uuid_bytes, &uuid);
SLIsGenuineLocal(&uuid, &state, nullptr);
return state == SL_GEN_STATE_IS_GENUINE;
}
int main()
{
std::cout<<isGenuineWindows();
return 0;
}
Link against: librpcrt4.a and libslwga.a
For some reason, the accepted answer failed on me. It's always returning false. I'll leave the code below for future purposes. It worked for me starting from Windows-Vista and, as of now Windows-10 version 20H2.
#define _WIN32_WINNT 0x600
#include <iostream>
#include <windows.h>
#include <slpublic.h>
#include <tchar.h>
#pragma comment(lib, "Slwga.lib")
#pragma comment(lib, "Rpcrt4.lib")
using std::cout;
using std::endl;
bool isGenuineWindows()
{
GUID uid;
RPC_WSTR rpc = (RPC_WSTR)_T("55c92734-d682-4d71-983e-d6ec3f16059f");
UuidFromString(rpc, &uid);
SL_GENUINE_STATE state;
SLIsGenuineLocal(&uid, &state, NULL);
return state == SL_GEN_STATE_IS_GENUINE;
}
int main()
{
if (isGenuineWindows()) {
cout << "Licensed" << endl;
}
else {
cout << "Unlicensed" << endl;
}
return 0;
}

How to control master mixer volume in windows 7 using mixer api?

In windows XP, it is quite easy to control master volume of a mixer device by setting volume of destination line using mixer api.It can be easily tested by sdk sample application provided by Microsoft.But in case of windows 7 whenever I open a mixer device in my application it shows it as new volume application and I am able to control only volume of my application.Not able to control complete sound of system.Can anyone suggest me how to control complete sound of speaker which will affect sound of all running application.
How can I change speakers volume using my application in windows 7 ?
I believe that the method you're looking for is SetMasterVolumeLevelScalar.
A short example in C (sorry for the lpVtbls):
BOOL AddMasterVolumeLevelScalar(float fMasterVolumeAdd)
{
IMMDeviceEnumerator *deviceEnumerator = NULL;
IMMDevice *defaultDevice = NULL;
IAudioEndpointVolume *endpointVolume = NULL;
HRESULT hr;
float fMasterVolume;
BOOL bSuccess = FALSE;
hr = CoCreateInstance(&XIID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &XIID_IMMDeviceEnumerator, (LPVOID *)&deviceEnumerator);
if(SUCCEEDED(hr))
{
hr = deviceEnumerator->lpVtbl->GetDefaultAudioEndpoint(deviceEnumerator, eRender, eConsole, &defaultDevice);
if(SUCCEEDED(hr))
{
hr = defaultDevice->lpVtbl->Activate(defaultDevice, &XIID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
if(SUCCEEDED(hr))
{
if(SUCCEEDED(endpointVolume->lpVtbl->GetMasterVolumeLevelScalar(endpointVolume, &fMasterVolume)))
{
fMasterVolume += fMasterVolumeAdd;
if(fMasterVolume < 0.0)
fMasterVolume = 0.0;
else if(fMasterVolume > 1.0)
fMasterVolume = 1.0;
if(SUCCEEDED(endpointVolume->lpVtbl->SetMasterVolumeLevelScalar(endpointVolume, fMasterVolume, NULL)))
bSuccess = TRUE;
}
endpointVolume->lpVtbl->Release(endpointVolume);
}
defaultDevice->lpVtbl->Release(defaultDevice);
}
deviceEnumerator->lpVtbl->Release(deviceEnumerator);
}
return bSuccess;
}
In case the GUIDs are not defined:
const static GUID XIID_IMMDeviceEnumerator = { 0xA95664D2, 0x9614, 0x4F35, { 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6 } };
const static GUID XIID_MMDeviceEnumerator = { 0xBCDE0395, 0xE52F, 0x467C, { 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E } };
const static GUID XIID_IAudioEndpointVolume = { 0x5CDF2C82, 0x841E, 0x4546, { 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A } };

Convert files of any types to a file with c strings

Please suggest a small command-line utility (for Windows) to convert files from particular directory to a valid c file. Maybe it can be done just with batch commands?
The resulting file should look like this:
static const unsigned char some_file[] = {
/* some_file.html */
0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65
}
static const unsigned char some_other_file[] = {
/* some_other_file.png*/
0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c
}
P.S. Please don't suggest Perl and Python ports. They are too heavy for this task.
P.P.S. May be someone knows more customizable utility than bin2h, but less heavy and complex than awt? Which can parse several files and put them into one C. Also specifing custom variable names (using some kind of an index file) whould be great. So it can be added to the build process.
Use xxd -i file.
I use the one included with Vim. For example:
C:\Documents and Settings\user> xxd -i error.log | head -n2
unsigned char error_log[] = {
0x0c, 0x0d, 0x0a, 0x3d, 0x3d, 0x32, 0x30, 0x30, 0x39, 0x2f, 0x35, 0x2f,
See also Is it possible to view a binary in ones and zeros?
Bin2h will do this.
Bin2h - Win32 binary to C header file
converter
A Win32 command-line utility for
converting a binary file into a C
header file, representing the contents
of that file as a block of data.
I don't believe the input file has to be a binary file.
If you want a utility that can be freely used (commercial or whatever) here's a GPL bin2c by Adrian Prantl:
/*
* bin2c: A Program to convert binary data into C source code
* Copyright 2004 by Adrian Prantl <adrian#f4z.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <stdio.h>
#include <stdlib.h>
char* self = 0;
void usage() {
printf("Usage:\n%s input.bin output.h name\n\n", self);
}
void bail_out(const char* s1, const char* s2) {
fprintf(stderr, "%s: FATAL ERROR:\n%s%s\n", self, s1, s2);
exit(1);
}
int main(int argc, char** argv) {
FILE *fi, *fo;
int c, i;
self = argv[0];
if (argc != 4) {
usage();
return 0;
}
if ((fi = fopen(argv[1], "rb")) == 0)
bail_out("Cannot open input file ", argv[1]);
if ((fo = fopen(argv[2], "w")) == 0)
bail_out("Cannot open output file ", argv[2]);
if ((c = fgetc(fi)) != EOF) {
fprintf(fo, "#ifndef %s_H\n", argv[3]);
fprintf(fo, "#define %s_H\n\n", argv[3]);
fprintf(fo, "const unsigned char %s[] = {\n", argv[3]);
fprintf(fo, c < 16 ? " 0x%02x" : " 0x%02x", (unsigned char) c);
}
i = 1;
while ((c = fgetc(fi)) != EOF) {
if (i < 12)
fprintf(fo, c < 16 ? ", 0x%02x" : ", 0x%02x", (unsigned char) c);
else {
fprintf(fo, c < 16 ? ",\n 0x%02x" : ",\n 0x%02x", (unsigned char) c);
i = 0;
}
i++;
}
fprintf(fo, "\n};\n\n");
fprintf(fo, "#endif\n");
printf("converted %s\n", argv[1]);
return 0;
}
It's a single 70 line or so C file - nothing to it to compile and run.
SRecord can do that, and more. Though it is hardly difficult to write your own in C.