1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2025-02-17 11:18:31 +01:00

camhook: split cam-detect code to different file

This commit is contained in:
Will Xyen 2024-05-11 19:42:59 -07:00 committed by Will
parent a03c4e0d93
commit 8307837995
5 changed files with 418 additions and 372 deletions

View File

@ -8,4 +8,5 @@ libs_camhook := \
src_camhook := \
cam.c \
cam-detect.c \
config-cam.c \

View File

@ -0,0 +1,375 @@
#define LOG_MODULE "cam-hook"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <initguid.h>
// clang-format on
#include <mfapi.h>
#include <mfidl.h>
#include <mfobjects.h>
#include <cfgmgr32.h>
#include <setupapi.h>
#include <stdio.h>
#include "camhook/cam-detect.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
EXTERN_GUID(
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
0xc60ac5fe,
0x252a,
0x478f,
0xa0,
0xef,
0xbc,
0x8f,
0xa5,
0xf7,
0xca,
0xd3);
EXTERN_GUID(
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID,
0x8ac3587a,
0x4ae7,
0x42d8,
0x99,
0xe0,
0x0a,
0x60,
0x13,
0xee,
0xf9,
0x0f);
EXTERN_GUID(
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
0x58f0aad8,
0x22bf,
0x4f8a,
0xbb,
0x3d,
0xd2,
0xc4,
0x97,
0x8c,
0x6e,
0x2f);
// define ourselves cause mingw has these wrong
bool check_four(const char inA[4], const char inB[4])
{
return (*(uint32_t *) inA == *(uint32_t *) inB);
}
char *grab_next_camera_id(char *buffer, size_t bsz)
{
static size_t gotten = 0;
IMFAttributes *pAttributes = NULL;
IMFActivate **ppDevices = NULL;
buffer[0] = '\0';
HRESULT hr = MFCreateAttributes(&pAttributes, 1);
if (FAILED(hr)) {
log_info("MFCreateAttributes failed: %ld", hr);
goto done;
}
hr = pAttributes->lpVtbl->SetGUID(
pAttributes,
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if (FAILED(hr)) {
log_info("SetGUID failed: %ld", hr);
goto done;
}
UINT32 count;
hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
if (FAILED(hr)) {
log_info("MFEnumDeviceSources failed: %ld", hr);
goto done;
}
if (count <= gotten) {
log_info("gotten failed: %d < %d", count, (int) gotten);
// not enough remaining
goto done;
}
wchar_t wSymLink[CAMERA_DATA_STRING_SIZE];
UINT32 sz;
hr = ppDevices[gotten]->lpVtbl->GetString(
ppDevices[gotten],
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
wSymLink,
CAMERA_DATA_STRING_SIZE,
&sz);
if (FAILED(hr)) {
log_info("GetString failed: %ld", hr);
goto done;
}
wcstombs(buffer, wSymLink, bsz);
log_info("Detected webcam: %s\n", buffer);
++gotten;
done:
if (pAttributes) {
pAttributes->lpVtbl->Release(pAttributes);
}
for (DWORD i = 0; i < count; i++) {
if (ppDevices != NULL && ppDevices[i]) {
ppDevices[i]->lpVtbl->Release(ppDevices[i]);
}
}
CoTaskMemFree(ppDevices);
return buffer;
}
bool convert_sym_to_path(const char *sym, char *path)
{
HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
log_info("Could not open SetupDiCreateDeviceInfoList\n");
return 0;
}
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = {0};
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if (!SetupDiOpenDeviceInterfaceA(
DeviceInfoSet, sym, 0, &DeviceInterfaceData)) {
log_info("Could not SetupDiOpenDeviceInterfaceA\n");
return 0;
}
SP_DEVINFO_DATA DeviceInfoData = {0};
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiGetDeviceInterfaceDetailA(
DeviceInfoSet,
&DeviceInterfaceData,
NULL,
0,
NULL,
&DeviceInfoData)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
log_info("Could not SetupDiGetDeviceInterfaceDetailA\n");
return 0;
}
}
DWORD sz;
if (!SetupDiGetDeviceInstanceIdA(
DeviceInfoSet,
&DeviceInfoData,
path,
CAMERA_DATA_STRING_SIZE,
&sz)) {
log_info("Could not SetupDiGetDeviceInstanceIdA\n");
return 0;
}
if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
if (!SetupDiDeleteDeviceInterfaceData(
DeviceInfoSet, &DeviceInterfaceData)) {
log_info("Could not SetupDiDeleteDeviceInterfaceData\n");
return 0;
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return 1;
}
void strtolower(char *str)
{
for (size_t i = 0; str[i]; i++) {
str[i] = tolower(str[i]);
}
}
bool convert_path_to_fakesym(const char *path, wchar_t *sym, char *extra_o)
{
char root[16] = {0};
char vidstr[16] = {0};
char pidstr[16] = {0};
char mistr[16] = {0};
char extra[64] = {0};
sscanf(
path,
"%[^\\]\\%[^&]&%[^&]&%[^\\]\\%s",
root,
vidstr,
pidstr,
mistr,
extra);
strcpy(extra_o, extra);
strtolower(root);
strtolower(vidstr);
strtolower(pidstr);
strtolower(mistr);
strtolower(extra);
char buffer[CAMERA_DATA_STRING_SIZE];
snprintf(
buffer,
CAMERA_DATA_STRING_SIZE,
"\\\\?\\%s#%s&%s&%s#%s",
root,
vidstr,
pidstr,
mistr,
extra);
mbstowcs(sym, buffer, CAMERA_DATA_STRING_SIZE);
return true;
}
void fill_cam_struct(struct CameraData *data, const char *devid)
{
char buffer[CAMERA_DATA_STRING_SIZE];
data->setup = false;
if (!devid || strlen(devid) == 0) {
devid = grab_next_camera_id(buffer, CAMERA_DATA_STRING_SIZE);
}
if (!devid || strlen(devid) == 0) {
// no more cameras remain?
return;
}
if (strlen(devid) >= CAMERA_DATA_STRING_SIZE) {
// error probably log something?
return;
}
// detect input type
if (check_four(devid, "\\\\?\\")) {
// SYMBOLIC_LINK
if (!convert_sym_to_path(devid, data->deviceInstancePath)) {
log_info("Could not convert %s to path", devid);
return;
}
} else if (check_four(devid, "USB\\")) {
// Device instance path
strcpy(data->deviceInstancePath, devid);
// continue
} else {
// UNKNOWN ENTRY
log_info("UNK: %s", devid);
log_info("Please enter the device instance path");
return;
}
if (!convert_path_to_fakesym(
data->deviceInstancePath,
data->deviceSymbolicLink,
data->extra_upper)) {
log_info("Could not convert %s to sym", data->deviceInstancePath);
return;
}
log_info("dev path: %s", data->deviceInstancePath);
// locate device nodes
DEVINST dnDevInst;
DEVINST parentDev;
CONFIGRET cmret;
cmret = CM_Locate_DevNodeA(
&dnDevInst, data->deviceInstancePath, CM_LOCATE_DEVNODE_NORMAL);
if (cmret != CR_SUCCESS) {
log_info("CM_Locate_DevNodeA fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_Parent(&parentDev, dnDevInst, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_Parent fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_Device_IDA(
parentDev, data->parent_deviceInstancePath, CAMERA_DATA_STRING_SIZE, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_Device_IDA parent fail: %s", data->deviceInstancePath);
return;
}
ULONG szAddr;
ULONG szDesc;
szAddr = 4;
szDesc = CAMERA_DATA_STRING_SIZE;
cmret = CM_Get_DevNode_Registry_PropertyA(
dnDevInst, CM_DRP_ADDRESS, NULL, &data->address, &szAddr, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA fail: %s",
data->deviceInstancePath);
return;
}
cmret = CM_Get_DevNode_Registry_PropertyA(
dnDevInst, CM_DRP_DEVICEDESC, NULL, &data->name, &szDesc, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA fail: %s",
data->deviceInstancePath);
return;
}
szAddr = 4;
szDesc = CAMERA_DATA_STRING_SIZE;
cmret = CM_Get_DevNode_Registry_PropertyA(
parentDev, CM_DRP_ADDRESS, NULL, &data->parent_address, &szAddr, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA parent fail: %s",
data->deviceInstancePath);
return;
}
cmret = CM_Get_DevNode_Registry_PropertyA(
parentDev, CM_DRP_DEVICEDESC, NULL, &data->parent_name, &szDesc, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA parent fail: %s",
data->deviceInstancePath);
return;
}
log_info("Found %s @ %d", data->name, data->address);
log_info("Parent %s @ %d", data->parent_name, data->parent_address);
data->setup = true;
}

View File

@ -0,0 +1,29 @@
#ifndef CAMHOOK_CAM_DETECT_H
#define CAMHOOK_CAM_DETECT_H
#include <stdbool.h>
#include <wchar.h>
#define CAMERA_DATA_STRING_SIZE 0x100
struct CameraData {
bool setup;
char name[CAMERA_DATA_STRING_SIZE];
char deviceInstancePath[CAMERA_DATA_STRING_SIZE];
wchar_t deviceSymbolicLink[CAMERA_DATA_STRING_SIZE];
char extra_upper[CAMERA_DATA_STRING_SIZE];
int address;
char parent_name[CAMERA_DATA_STRING_SIZE];
char parent_deviceInstancePath[CAMERA_DATA_STRING_SIZE];
int parent_address;
bool fake_addressed;
int fake_address;
bool fake_located;
size_t fake_located_node;
};
void fill_cam_struct(struct CameraData *data, const char *devid);
#endif

View File

@ -19,72 +19,11 @@
#include "hook/table.h"
#include "camhook/cam.h"
#include "camhook/cam-detect.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
#define CAMERA_DATA_STRING_SIZE 0x100
EXTERN_GUID(
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
0xc60ac5fe,
0x252a,
0x478f,
0xa0,
0xef,
0xbc,
0x8f,
0xa5,
0xf7,
0xca,
0xd3);
EXTERN_GUID(
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID,
0x8ac3587a,
0x4ae7,
0x42d8,
0x99,
0xe0,
0x0a,
0x60,
0x13,
0xee,
0xf9,
0x0f);
EXTERN_GUID(
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
0x58f0aad8,
0x22bf,
0x4f8a,
0xbb,
0x3d,
0xd2,
0xc4,
0x97,
0x8c,
0x6e,
0x2f);
// define ourselves cause mingw has these wrong
struct CameraData {
bool setup;
char name[CAMERA_DATA_STRING_SIZE];
char deviceInstancePath[CAMERA_DATA_STRING_SIZE];
wchar_t deviceSymbolicLink[CAMERA_DATA_STRING_SIZE];
char extra_upper[CAMERA_DATA_STRING_SIZE];
int address;
char parent_name[CAMERA_DATA_STRING_SIZE];
char parent_deviceInstancePath[CAMERA_DATA_STRING_SIZE];
int parent_address;
bool fake_addressed;
int fake_address;
bool fake_located;
size_t fake_located_node;
};
static struct CameraData camData[CAMHOOK_CONFIG_CAM_MAX];
int camAddresses[CAMHOOK_CONFIG_CAM_MAX] = {
@ -94,6 +33,8 @@ int camAddresses[CAMHOOK_CONFIG_CAM_MAX] = {
static size_t num_addressed_cams = 0;
static size_t num_located_cams = 0;
static enum camhook_version camhook_version = CAMHOOK_OLD;
static CONFIGRET my_CM_Locate_DevNodeA(
PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags);
@ -280,7 +221,7 @@ HRESULT my_GetAllocatedString(
HRESULT ret;
log_info("Inside: %s", __FUNCTION__);
// should probably check GUID, oh well
// should probably check GUID == MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, oh well
ret = real_GetAllocatedString(self, guidKey, ppwszValue, pcchLength);
char *pMBBuffer = (char *) malloc(0x100);
wcstombs(pMBBuffer, *ppwszValue, 0x100);
@ -491,315 +432,8 @@ static HDEVINFO my_SetupDiGetClassDevsA(
return real_SetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
}
bool check_four(const char inA[4], const char inB[4])
{
return (*(uint32_t *) inA == *(uint32_t *) inB);
}
char *grab_next_camera_id(char *buffer, size_t bsz)
{
static size_t gotten = 0;
IMFAttributes *pAttributes = NULL;
IMFActivate **ppDevices = NULL;
buffer[0] = '\0';
HRESULT hr = MFCreateAttributes(&pAttributes, 1);
if (FAILED(hr)) {
log_info("MFCreateAttributes failed: %ld", hr);
goto done;
}
hr = pAttributes->lpVtbl->SetGUID(
pAttributes,
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if (FAILED(hr)) {
log_info("SetGUID failed: %ld", hr);
goto done;
}
UINT32 count;
hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
if (FAILED(hr)) {
log_info("MFEnumDeviceSources failed: %ld", hr);
goto done;
}
if (count <= gotten) {
log_info("gotten failed: %d < %d", count, (int) gotten);
// not enough remaining
goto done;
}
wchar_t wSymLink[CAMERA_DATA_STRING_SIZE];
UINT32 sz;
hr = ppDevices[gotten]->lpVtbl->GetString(
ppDevices[gotten],
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
wSymLink,
CAMERA_DATA_STRING_SIZE,
&sz);
if (FAILED(hr)) {
log_info("GetString failed: %ld", hr);
goto done;
}
wcstombs(buffer, wSymLink, bsz);
log_info("Detected webcam: %s\n", buffer);
++gotten;
done:
if (pAttributes) {
pAttributes->lpVtbl->Release(pAttributes);
}
for (DWORD i = 0; i < count; i++) {
if (ppDevices != NULL && ppDevices[i]) {
ppDevices[i]->lpVtbl->Release(ppDevices[i]);
}
}
CoTaskMemFree(ppDevices);
return buffer;
}
bool convert_sym_to_path(const char *sym, char *path)
{
HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
log_info("Could not open SetupDiCreateDeviceInfoList\n");
return 0;
}
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = {0};
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if (!SetupDiOpenDeviceInterfaceA(
DeviceInfoSet, sym, 0, &DeviceInterfaceData)) {
log_info("Could not SetupDiOpenDeviceInterfaceA\n");
return 0;
}
SP_DEVINFO_DATA DeviceInfoData = {0};
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiGetDeviceInterfaceDetailA(
DeviceInfoSet,
&DeviceInterfaceData,
NULL,
0,
NULL,
&DeviceInfoData)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
log_info("Could not SetupDiGetDeviceInterfaceDetailA\n");
return 0;
}
}
DWORD sz;
if (!SetupDiGetDeviceInstanceIdA(
DeviceInfoSet,
&DeviceInfoData,
path,
CAMERA_DATA_STRING_SIZE,
&sz)) {
log_info("Could not SetupDiGetDeviceInstanceIdA\n");
return 0;
}
if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
if (!SetupDiDeleteDeviceInterfaceData(
DeviceInfoSet, &DeviceInterfaceData)) {
log_info("Could not SetupDiDeleteDeviceInterfaceData\n");
return 0;
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return 1;
}
void strtolower(char *str)
{
for (size_t i = 0; str[i]; i++) {
str[i] = tolower(str[i]);
}
}
bool convert_path_to_fakesym(const char *path, wchar_t *sym, char *extra_o)
{
char root[16] = {0};
char vidstr[16] = {0};
char pidstr[16] = {0};
char mistr[16] = {0};
char extra[64] = {0};
sscanf(
path,
"%[^\\]\\%[^&]&%[^&]&%[^\\]\\%s",
root,
vidstr,
pidstr,
mistr,
extra);
strcpy(extra_o, extra);
strtolower(root);
strtolower(vidstr);
strtolower(pidstr);
strtolower(mistr);
strtolower(extra);
char buffer[CAMERA_DATA_STRING_SIZE];
snprintf(
buffer,
CAMERA_DATA_STRING_SIZE,
"\\\\?\\%s#%s&%s&%s#%s",
root,
vidstr,
pidstr,
mistr,
extra);
mbstowcs(sym, buffer, CAMERA_DATA_STRING_SIZE);
return true;
}
void fill_cam_struct(struct CameraData *data, const char *devid)
{
char buffer[CAMERA_DATA_STRING_SIZE];
data->setup = false;
if (!devid || strlen(devid) == 0) {
devid = grab_next_camera_id(buffer, CAMERA_DATA_STRING_SIZE);
}
if (!devid || strlen(devid) == 0) {
// no more cameras remain?
return;
}
if (strlen(devid) >= CAMERA_DATA_STRING_SIZE) {
// error probably log something?
return;
}
// detect input type
if (check_four(devid, "\\\\?\\")) {
// SYMBOLIC_LINK
if (!convert_sym_to_path(devid, data->deviceInstancePath)) {
log_info("Could not convert %s to path", devid);
return;
}
} else if (check_four(devid, "USB\\")) {
// Device instance path
strcpy(data->deviceInstancePath, devid);
// continue
} else {
// UNKNOWN ENTRY
log_info("UNK: %s", devid);
log_info("Please enter the device instance path");
return;
}
if (!convert_path_to_fakesym(
data->deviceInstancePath,
data->deviceSymbolicLink,
data->extra_upper)) {
log_info("Could not convert %s to sym", data->deviceInstancePath);
return;
}
log_info("dev path: %s", data->deviceInstancePath);
// locate device nodes
DEVINST dnDevInst;
DEVINST parentDev;
CONFIGRET cmret;
cmret = CM_Locate_DevNodeA(
&dnDevInst, data->deviceInstancePath, CM_LOCATE_DEVNODE_NORMAL);
if (cmret != CR_SUCCESS) {
log_info("CM_Locate_DevNodeA fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_Parent(&parentDev, dnDevInst, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_Parent fail: %s", data->deviceInstancePath);
return;
}
cmret = CM_Get_Device_IDA(
parentDev, data->parent_deviceInstancePath, CAMERA_DATA_STRING_SIZE, 0);
if (cmret != CR_SUCCESS) {
log_info("CM_Get_Device_IDA parent fail: %s", data->deviceInstancePath);
return;
}
ULONG szAddr;
ULONG szDesc;
szAddr = 4;
szDesc = CAMERA_DATA_STRING_SIZE;
cmret = CM_Get_DevNode_Registry_PropertyA(
dnDevInst, CM_DRP_ADDRESS, NULL, &data->address, &szAddr, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA fail: %s",
data->deviceInstancePath);
return;
}
cmret = CM_Get_DevNode_Registry_PropertyA(
dnDevInst, CM_DRP_DEVICEDESC, NULL, &data->name, &szDesc, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA fail: %s",
data->deviceInstancePath);
return;
}
szAddr = 4;
szDesc = CAMERA_DATA_STRING_SIZE;
cmret = CM_Get_DevNode_Registry_PropertyA(
parentDev, CM_DRP_ADDRESS, NULL, &data->parent_address, &szAddr, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA parent fail: %s",
data->deviceInstancePath);
return;
}
cmret = CM_Get_DevNode_Registry_PropertyA(
parentDev, CM_DRP_DEVICEDESC, NULL, &data->parent_name, &szDesc, 0);
if (cmret != CR_SUCCESS) {
log_info(
"CM_Get_DevNode_Registry_PropertyA parent fail: %s",
data->deviceInstancePath);
return;
}
log_info("Found %s @ %d", data->name, data->address);
log_info("Parent %s @ %d", data->parent_name, data->parent_address);
data->setup = true;
void camhook_set_version(enum camhook_version version) {
camhook_version = version;
}
void camhook_init(struct camhook_config_cam *config_cam)

View File

@ -3,6 +3,13 @@
#include "camhook/config-cam.h"
enum camhook_version {
CAMHOOK_OLD,
CAMHOOK_NEW,
};
void camhook_set_version(enum camhook_version version);
void camhook_init(struct camhook_config_cam *config_cam);
void camhook_fini(void);