How to call EnumAdapters from IDXGFactory in c? - c

How to call the EnumAdapters function in c from IDXGFactory
UINT i = 0;
IDXGIFactory* pFactory = NULL;
IDXGIAdapter * pAdapter;
HRESULT hr = CreateDXGIFactory(&IID_IDXGIFactory, (void**)(&pFactory) );
if (hr != S_OK)
{
printf("Failed to create DXIFactory object\n");
}
using pFactory->EnumAdapters(i, pAdapter) does not work and causes this error
struct "IDXGIFactory" has no field "EnumAdapters"

You are interested in reading up on topic "using COM in plain C", where you can find relevant detailed explanations.
For you very specific question the code might look like:
#include <dxgi.h>
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "dxguid.lib")
int main()
{
IDXGIFactory* pFactory = NULL;
UINT i = 0;
IDXGIAdapter* pAdapter;
HRESULT hr;
hr = CreateDXGIFactory(&IID_IDXGIFactory, (void**)(&pFactory));
hr = pFactory->lpVtbl->EnumAdapters(pFactory, i, &pAdapter);
return 0;
}
Or, another way is to take advantage of COBJMACROS in which case you have IDXGIFactory_EnumAdapters available to you.
#define COBJMACROS
#include <dxgi.h>
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "dxguid.lib")
int main()
{
IDXGIFactory* pFactory = NULL;
UINT i = 0;
IDXGIAdapter* pAdapter;
HRESULT hr;
hr = CreateDXGIFactory(&IID_IDXGIFactory, (void**)(&pFactory));
hr = IDXGIFactory_EnumAdapters(pFactory, i, &pAdapter);
return 0;
}

Related

Access violation reading location in C Direct Show

I keep getting an access violation reading location error in Visual Studio when I execute the code. I also am unable to print the address for troubleshooting. I have no idea what is going on and according to a friend, my code is flawless and that it is a hardware issue. The file seems to be alright so idk if my friend is trolling me or not. My code is here:
#include <dshow.h>
#include <stdio.h>
#include <Windows.h>
void main(void)
{
while (TRUE)
{
char SongName[10];
printf("Song name:\n");
scanf_s("%s", &SongName,10);
HRESULT hr = CoInitialize(NULL);
IGraphBuilder* pGraph = NULL;
hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (void**)&pGraph);
IMediaControl* pControl = NULL;
IMediaEvent* pEvent = NULL;
hr = pGraph->lpVtbl->QueryInterface(pGraph, &IID_IMediaControl, (void**)&pControl);
hr = pGraph->lpVtbl->QueryInterface(pGraph, &IID_IMediaEvent, (void**)&pEvent);
char SongAddress = (L"C:/Users/Desktop/AudioPlayer/%s",SongName);
wprintf("%s", SongAddress);
hr = pGraph->lpVtbl->RenderFile(pGraph,SongAddress, NULL);
hr = pControl->lpVtbl->Run(pControl);
FILTER_STATE fs;
hr = pControl->lpVtbl->GetState(pControl,10000, (OAFilterState*)&fs);
if (fs != NULL) {
printf("%d", fs);
}
long evCode = 0;
pEvent->lpVtbl->WaitForCompletion(pEvent, INFINITE, &evCode);
pControl->lpVtbl->Release(pControl);
pEvent->lpVtbl->Release(pEvent);
pGraph->lpVtbl->Release(pGraph);
CoUninitialize();
}
}
Error shows in this line:
hr = pGraph->lpVtbl->RenderFile(pGraph,SongAddress, NULL);

vkCreateInsatance segmentation fault

I followed by vulkan tutorial, and i get segfault on vkCreateInstance.
I use arch (btw), and i install vulkan by paru -S vulkan-devel (also linux-firmware and mesa are installed). My CPU is AMD Ryzen 7 2700, and GPU is Radeon RX 580 4GB.
I saw a similar question, but the answer did not solve my problem (and besides, they use C++, not C)
#include <stdio.h>
#include <stdlib.h>
#include <vulkan/vulkan.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
const char* APPLICATION_NAME = "Vulkan Teach";
const uint16_t WIDTH = 800;
const uint16_t HEIGHT = 600;
static GLFWwindow* window;
static VkInstance instance;
void error(char* message, int code) {
fprintf(stderr, "%s (status code: %d)\n", message, code);
exit(code);
}
void initWindow() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, APPLICATION_NAME, NULL, NULL);
}
void mainLoop() {
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
}
void createInsance() {
VkApplicationInfo appInfo;
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = APPLICATION_NAME;
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
uint32_t glfwExtensionsCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionsCount);
createInfo.enabledExtensionCount = glfwExtensionsCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
createInfo.enabledLayerCount = 0;
VkResult result = vkCreateInstance(&createInfo, NULL, &instance);
if(result != VK_SUCCESS) {
error("Failed to create vulkan instance.", result);
}
}
void initVulkan() {
createInsance();
}
void cleanup() {
vkDestroyInstance(instance, NULL);
glfwDestroyWindow(window);
glfwTerminate();
}
int main() {
initWindow();
initVulkan();
mainLoop();
cleanup();
return 0;
}
You are most probably passing uninitialized values to your instance creation. This part of the code:
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
Only initializes the sType and pApplicationInfo members of the create info, while other important members such as pNext are uninitialized and as such may contain values that the driver doesn't know how to handle, resulting in the segfault.
So as a general rule for all (Vulkan) structs: Zero initialize like this:
VkInstanceCreateInfo createInfo = {0};

C library works by itself in executable form, but when used as Rust library using CC, it no longer works

I am trying to inject a dll into a specific application in rust. I gave up trying to do so in pure rust, as it was not working no matter what. So, I used a C injector and compiled it and it worked perfectly. However, when I use the CC crate to compile it and use the function, it no longer works at all. In this case, I was simply trying to inject a dll I made.
The code for the C is:
// test.c
#include <windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#pragma comment(lib, "ntdll.lib")
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtCreateThreadEx(PHANDLE,
ACCESS_MASK, LPVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID,
BOOL, SIZE_T, SIZE_T, SIZE_T, LPVOID);
struct NtCreateThreadExBuffer
{
SIZE_T Size;
SIZE_T Unknown1;
SIZE_T Unknown2;
PULONG Unknown3;
SIZE_T Unknown4;
SIZE_T Unknown5;
SIZE_T Unknown6;
PULONG Unknown7;
SIZE_T Unknown8;
};
DWORD GetPid(const wchar_t *targetProcess)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if (snap && snap != INVALID_HANDLE_VALUE && Process32First(snap, &procEntry))
{
do
{
if (!wcscmp(procEntry.szExeFile, targetProcess))
{
break;
}
} while (Process32Next(snap, &procEntry));
}
CloseHandle(snap);
return procEntry.th32ProcessID;
}
void injectAmongUs()
{
DWORD dwPid = GetPid(L"Among Us.exe");
struct NtCreateThreadExBuffer ntbuffer;
memset(&ntbuffer, 0, sizeof(struct NtCreateThreadExBuffer));
DWORD temp1 = 0;
DWORD temp2 = 0;
ntbuffer.Size = sizeof(struct NtCreateThreadExBuffer);
ntbuffer.Unknown1 = 0x10003;
ntbuffer.Unknown2 = 0x8;
ntbuffer.Unknown3 = (DWORD *)&temp2;
ntbuffer.Unknown4 = 0;
ntbuffer.Unknown5 = 0x10004;
ntbuffer.Unknown6 = 4;
ntbuffer.Unknown7 = &temp1;
ntbuffer.Unknown8 = 0;
HANDLE proc = OpenProcess(GENERIC_ALL, 0, dwPid);
HANDLE hThread;
wchar_t path[] = L"path/to/dll";
LPVOID allocAddr = VirtualAllocEx(proc, 0, sizeof(path), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(proc, allocAddr, path, sizeof(path), NULL);
NTSTATUS status = NtCreateThreadEx(&hThread, GENERIC_ALL, NULL, proc,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"), allocAddr,
FALSE, NULL, NULL, NULL, &ntbuffer);
}
If I compile this file exactly the way it is but add a main method:
int main()
{
injectAmongUs();
return 1;
}
It works perfectly as intended. However, if I remove the main method and use CC with this build script:
// build.rs
fn main() {
cc::Build::new()
.file("test.c")
.compile("injector.dll");
}
and then call it in main with
//main.rs
extern "C" {
fn injectAmongUs();
}
fn main() {
unsafe {
injectAmongUs();;
}
}
which results in (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION).
How can I get it to successfully inject as if I just ran the .exe normally? Currently I just put the .exe with it, but that is not desirable and would rather it be built and used as a library. Note, I am trying to inject Among Us, and so I am running this as 32 bit with cargo run --target i686-pc-windows-msvc.

Why OLE DB IRowset.GetNextRows access violation

I'm using OLE DB to retrieve some data from a SQL server, the outline of the code is
m_spCmd->SetCommandText(DBGUID_DEFAULT,L"SELECT * FROM sys.DM_OS_PERFORMANCE_COUNTERS"); // S_OK
CComPtr<IRowset> result;
m_spCmd->Execute(nullptr,__uuidof(IRowset),nullptr,nullptr,(IUnknown**)&result); // S_OK
DBCOUNTITEM fetched;
HROW *hrow;
result->GetNextRows(DB_NULL_HCHAPTER,0,1,&fetched,&hrow); // A
at A , I got an access violation exception (which means something is null, the result itself is not null). I think I have missed some step(s) in the code, what's that? Many thanks!!!
Update
sqlcmd.h
#pragma once
#include <windows.h>
#include <msdaguid.h>
#include <msdasql.h>
#include <oledb.h>
#include <oledberr.h>
#include <iostream>
#include <atlbase.h>
#include <atldbcli.h>
using namespace std;
struct SQLCmd
{
SQLCmd();
~SQLCmd();
private:
template<typename T> void print(T);
private:
CComPtr<IDBInitialize> m_spDb;
CComPtr<IDBProperties> m_spDbProperty;
CComPtr<ISessionProperties> m_spSsProperty;
CComPtr<ICommandText> m_spCmd;
CComPtr<ISQLErrorInfo> m_spErr;
CComPtr<IAccessor> m_spAccessor;
CComPtr<IDBCreateSession> m_spCrsession;
HRESULT hr;
};
sqlcmd.cpp
#include "sqlcmd.h"
template<>
void SQLCmd::print(CComPtr<IRowset> ptr)
{
DBORDINAL count;
DBCOLUMNINFO *info;
OLECHAR *buf;
auto accessor = CComQIPtr<IAccessor>(ptr);
auto colinfo = CComQIPtr<IColumnsInfo>(ptr);
colinfo->GetColumnInfo(&count,&info,&buf);
/*
DBBINDING *bindings = new DBBINDING[count];
memset(bindings,0,sizeof(DBBINDING)*count);
DBBINDSTATUS *bindingstatus = new DBBINDSTATUS[count];
memset(bindingstatus,0,sizeof(DBBINDSTATUS)*count);
DBBYTEOFFSET offset = 0;
int rowsize = 0;
for(int i = 0 ; i < count ; i++)
{
auto &[pwszName,pTypeInfo,iOrdinal,dwFlags,ulColumnSize,wType,bPrecision,bScale,columnid] = info[i];
bindings[i].iOrdinal = iOrdinal;
bindings[i].obValue = offset;
bindings[i].wType = wType;
bindings[i].dwPart = DBPART_VALUE;
bindings[i].bPrecision = bPrecision;
bindings[i].bScale = bScale;
offset += ulColumnSize;
rowsize += ulColumnSize;
printf("%ws %lld %d\n",pwszName,ulColumnSize,wType);
}
HACCESSOR haccessor;
hr = accessor->CreateAccessor(DBACCESSOR_ROWDATA,count,bindings,rowsize,&haccessor,bindingstatus);
printf("CreateAccessor %x %llx\n",hr,haccessor);
for(int i = 0 ; i < count ; i++)
if(DBBINDSTATUS_OK != bindingstatus[i])
printf("%d - %d\n",i,bindingstatus[i]);*/
DBCOUNTITEM fetched;
HROW *hrow;
printf("before GetNextRows\n");
hr = ptr->GetNextRows(DB_NULL_HCHAPTER,0,1,&fetched,&hrow);
printf("GetNextRows %x %lld\n",hr,fetched);
}
SQLCmd::SQLCmd()
{
GUID msoledbsql;
CLSIDFromString(L"{5A23DE84-1D7B-4A16-8DED-B29C09CB648D}",&msoledbsql);
m_spDb.CoCreateInstance(msoledbsql);
m_spDbProperty = CComQIPtr<IDBProperties>(m_spDb);
CDBPropSet set(DBPROPSET_DBINIT);
set.AddProperty(DBPROP_AUTH_INTEGRATED,L"SSPI");
set.AddProperty(DBPROP_INIT_CATALOG,L"master");
set.AddProperty(DBPROP_INIT_DATASOURCE,L"localhost");
m_spDbProperty->SetProperties(1,&set);
m_spDb->Initialize();
auto m_spCrsession = CComQIPtr<IDBCreateSession>(m_spDb);
if (!!m_spCrsession)
{
hr = m_spCrsession->CreateSession(nullptr,__uuidof(ISessionProperties),(IUnknown**)&m_spSsProperty);
auto _ = CComQIPtr<IDBCreateCommand>(m_spSsProperty);
if (!!_)
hr = _->CreateCommand(nullptr,__uuidof(ICommandText),(IUnknown**)&m_spCmd);
}
CComPtr<IRowset> result;
hr = m_spCmd->SetCommandText(DBGUID_DEFAULT,L"SELECT * FROM sys.DM_OS_PERFORMANCE_COUNTERS");
printf("SetCommandText 0x%x\n",hr);
DBROWCOUNT rowcount;
hr = m_spCmd->Execute(nullptr,__uuidof(IRowset),nullptr,&rowcount,(IUnknown**)&result);
printf("Execute 0x%x %lld\n",hr,rowcount);
if (!!result)
{
print(result);
}
}
SQLCmd::~SQLCmd()
{
if (!!m_spDb) m_spDb->Uninitialize();
}
test.cpp
#include "sqlcmd.h"
int main()
{
CoInitialize(nullptr);
SQLCmd cmd;
}
compile
cl /nologo /EHsc /std:c++latest test.cpp sqlcmd.cpp /link /debug
run
>test
SetCommandText 0x0
Execute 0x0 -1
before GetNextRows
IRowset::GetNextRows documentation: says this
If *prghRows is not a null pointer on input, it must be a pointer to
consumer-allocated memory large enough to return the handles of the
requested number of rows. If the consumer-allocated memory is larger
than needed, the provider fills in as many row handles as specified by
pcRowsObtained; the contents of the remaining memory are undefined.
So you can't pass a random pointer on input. You must set it to something valid or NULL:
HROW* hrow = NULL;

kprobe, function scheduling - processor lockup - Linux kernel

I've a function I wrote in order to run a given function on all processors. It works perfectly well in all cases except the following case:
When I try to use it within a kprobe that I registered.
Here's some code:
static DEFINE_MUTEX(entryMutex);
static struct kretprobe my_kprobe = {
.entry_handler = (kprobe_opcode_t *) NULL,
.handler = (kprobe_opcode_t *) process_entry_callback,
.maxactive = 1000,
.data_size = 0
};
static int driver_init(void)
{
my_kprobe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("sys_execve");
if ((ret = register_kretprobe(&my_kprobe)) < 0)
return -1;
return 0;
}
void foo(void* nothing)
{
printk("In foo\n");
}
static int process_entry_callback(struct kretprobe_instance* instance, struct pt_regs* regs)
{
mutex_lock(&entryMutex);
for(int i = 0; i < 4; ++i) // assumes there are 4 processors
run_func(foo, NULL, i);
mutex_unlock(&entryMutex);
return 0;
}
void run_func_wrap(struct function_data* data)
{
data->func(data->context);
wake_up_process(data->waiting_task);
*(data->condition) = TRUE;
}
void run_func(SCHEDULED_FUNC func, void *context, int processor)
{
struct function_data data;
struct task_struct* th;
BOOLEAN condition = FALSE;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
data.func = func;
data.waiting_task = current;
data.context = context;
data.condition = &condition;
th = kthread_create(sched_func_wrap, &data, "th");
kthread_bind(th, processor);
wake_up_process(th);
wait_event(queue, condition);
}
F
After the call to 'run_func' in process_entry_callback I can no longer run any programs. Every time I start a new program it just stuck. After a while I get 'processor lockup' warning in the system log.
I suspect that it has something to do with the IRQ levels.
Any suggestions ?
EDIT:
It also happens when using the following function:
smp_call_function_single
which can be found in smp.c # the Linux kernel source code.
instead of my function:
run_func

Resources