|
#include <stdio.h> |
|
#include <windows.h> |
|
#include <D3dkmthk.h> |
|
#include <d3d11.h> |
|
#include <d3d11_1.h> |
|
#pragma comment(lib, "d3d11") |
|
|
|
extern "C" |
|
{ |
|
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; |
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; |
|
} |
|
|
|
/* |
|
* Simple hexdump |
|
* https://gist.github.com/ccbrown/9722406 |
|
*/ |
|
void DumpHex(const void* data, size_t size) { |
|
char ascii[17]; |
|
size_t i, j; |
|
ascii[16] = '\0'; |
|
for (i = 0; i < size; ++i) { |
|
printf(" %02X", ((unsigned char*)data)[i]); |
|
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { |
|
ascii[i % 16] = ((unsigned char*)data)[i]; |
|
} |
|
else { |
|
ascii[i % 16] = '.'; |
|
} |
|
if ((i + 1) % 8 == 0 || i + 1 == size) { |
|
printf(" "); |
|
if ((i + 1) % 16 == 0) { |
|
printf("| %s \n", ascii); |
|
//printf("\n"); |
|
} |
|
else if (i + 1 == size) { |
|
ascii[(i + 1) % 16] = '\0'; |
|
if ((i + 1) % 16 <= 8) { |
|
printf(" "); |
|
} |
|
for (j = (i + 1) % 16; j < 16; ++j) { |
|
printf(" "); |
|
} |
|
printf("| %s \n", ascii); |
|
//printf("\n"); |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
|
* Seems to be DXGI part of the data, representing a texture desc |
|
*/ |
|
typedef struct DXGI_PRIVATEDATA { |
|
UINT Size; |
|
INT Id; |
|
UINT Width; |
|
UINT Height; |
|
DXGI_FORMAT Format; |
|
UINT ArraySize; |
|
INT ReadOnly; |
|
INT Sync; |
|
INT KeyedMutex; |
|
INT unk0; |
|
INT NTHandle; |
|
INT uin1; |
|
INT unk2; |
|
INT unk3; |
|
D3D11_RESOURCE_DIMENSION Dimension; |
|
D3D11_TEXTURE2D_DESC Desc; |
|
} DXGI_PRIVATEDATA; |
|
|
|
/* |
|
* Seems to be the ICD implementation part of the data (vendor specific) |
|
*/ |
|
#pragma pack(1) |
|
typedef struct UNK_TOTALDRIVERPRIVATEDATA { |
|
const char unk_pad0[0x13E]; |
|
UINT pMagicValue; |
|
}; |
|
|
|
/* |
|
* Helper to debug D3DKMT returns |
|
*/ |
|
BOOL CHECK_NT(NTSTATUS status, const char* error) |
|
{ |
|
if (FAILED(status)) |
|
{ |
|
printf("Failed (%08X) %s\n", status, error); |
|
return true; |
|
} |
|
printf("Success: %s\n", error); |
|
return false; |
|
} |
|
#define CHECK_NTSTATUS(X) if(CHECK_NT(NT_RETURN, X)) return 0; |
|
|
|
|
|
int main() |
|
{ |
|
UINT WIDTH = 1000; |
|
UINT HEIGHT = 500; |
|
|
|
// Create a D3D11 device |
|
ID3D11Device* device = NULL; |
|
ID3D11DeviceContext* context = NULL; |
|
UINT creation_flags = (D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_BGRA_SUPPORT); |
|
static const D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; |
|
D3D_FEATURE_LEVEL* ftret = NULL; |
|
if (FAILED(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, creation_flags, feature_levels, 7, D3D11_SDK_VERSION, &device, ftret, &context))) return NULL; |
|
printf("Success: D3D11CreateDevice\n"); |
|
|
|
// Create a texture |
|
ID3D11Texture2D* texture = NULL; |
|
D3D11_TEXTURE2D_DESC texDesc{ 0 }; |
|
texDesc.Width = WIDTH; |
|
texDesc.Height = HEIGHT; |
|
texDesc.MipLevels = 1; |
|
texDesc.ArraySize = 1; |
|
texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
|
texDesc.SampleDesc.Count = 1; |
|
texDesc.SampleDesc.Quality = 0; |
|
texDesc.Usage = D3D11_USAGE_DEFAULT; |
|
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; |
|
texDesc.CPUAccessFlags = 0; |
|
texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED; |
|
if (FAILED(device->CreateTexture2D(&texDesc, NULL, &texture))) return NULL; |
|
printf("Success: ID3D11Device::CreateTexture2D (%dx%d)\n", texDesc.Width, texDesc.Height); |
|
|
|
// Share the texture to a NT HANDLE |
|
HANDLE ntHandle = 0; |
|
IDXGIResource* dxgiRsrc = 0; |
|
if (SUCCEEDED(texture->QueryInterface(&dxgiRsrc))) |
|
{ |
|
IDXGIResource1* dxgiResource = 0; |
|
if (SUCCEEDED(dxgiRsrc->QueryInterface(&dxgiResource))) |
|
{ |
|
if (SUCCEEDED(dxgiResource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, NULL, &ntHandle))) |
|
{ |
|
printf("Success: IDXGIResource::CreateSharedHandle (NTHANDLE: %08X)\n", ntHandle); |
|
} |
|
dxgiResource->Release(); |
|
} |
|
dxgiRsrc->Release(); |
|
} |
|
NTSTATUS NT_RETURN = 0; |
|
|
|
/* |
|
D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME OPENADAPTERFROMGDIDISPLAYNAME{ 0 }; |
|
wsprintf(OPENADAPTERFROMGDIDISPLAYNAME.DeviceName, L"\\\\.\\DISPLAY1"); |
|
NT_RETURN = D3DKMTOpenAdapterFromGdiDisplayName(&OPENADAPTERFROMGDIDISPLAYNAME); |
|
CHECK_NTSTATUS("D3DKMTOpenAdapterFromGdiDisplayName"); |
|
D3DKMT_HANDLE hAdapter = OPENADAPTERFROMGDIDISPLAYNAME.hAdapter; |
|
*/ |
|
|
|
D3DKMT_ENUMADAPTERS ENUMADAPTERS{ 0 }; |
|
NT_RETURN = D3DKMTEnumAdapters(&ENUMADAPTERS); |
|
CHECK_NTSTATUS("D3DKMTEnumAdapters"); |
|
|
|
D3DKMT_HANDLE hAdapter = ENUMADAPTERS.Adapters[0].hAdapter; |
|
|
|
// Create a kmt device, what is this device? i dont know, but we close it later |
|
D3DKMT_CREATEDEVICE CREATEDEVICE{ 0 }; |
|
CREATEDEVICE.hAdapter = hAdapter; |
|
NT_RETURN = D3DKMTCreateDevice(&CREATEDEVICE); |
|
CHECK_NTSTATUS("D3DKMTCreateDevice"); |
|
|
|
// Some debug info about the gl icd and device |
|
D3DKMT_QUERYADAPTERINFO QUERYADAPTERINFO{ 0 }; |
|
QUERYADAPTERINFO.hAdapter = hAdapter; |
|
QUERYADAPTERINFO.Type = KMTQAITYPE_ADAPTERREGISTRYINFO; |
|
D3DKMT_ADAPTERREGISTRYINFO ADAPTERREGISTRYINFO{ 0 }; |
|
QUERYADAPTERINFO.PrivateDriverDataSize = sizeof(D3DKMT_ADAPTERREGISTRYINFO); |
|
QUERYADAPTERINFO.pPrivateDriverData = &ADAPTERREGISTRYINFO; |
|
NT_RETURN = D3DKMTQueryAdapterInfo(&QUERYADAPTERINFO); |
|
CHECK_NTSTATUS("D3DKMTQueryAdapterInfo"); |
|
wprintf(L" Adapter: %s\n BIOS: %s\n DAC: %s\n CHIP: %s\n", ADAPTERREGISTRYINFO.AdapterString, ADAPTERREGISTRYINFO.BiosString, ADAPTERREGISTRYINFO.DacType, ADAPTERREGISTRYINFO.ChipType); |
|
|
|
D3DKMT_OPENGLINFO OPENGLINFO{ 0 }; |
|
QUERYADAPTERINFO.Type = KMTQAITYPE_UMOPENGLINFO; |
|
QUERYADAPTERINFO.PrivateDriverDataSize = sizeof(D3DKMT_OPENGLINFO); |
|
QUERYADAPTERINFO.pPrivateDriverData = &OPENGLINFO; |
|
NT_RETURN = D3DKMTQueryAdapterInfo(&QUERYADAPTERINFO); |
|
CHECK_NTSTATUS("D3DKMTQueryAdapterInfo"); |
|
wprintf(L" OpenGL ICD: %s\n Version: %d\n Flags: %d\n", OPENGLINFO.UmdOpenGlIcdFileName, OPENGLINFO.Version, OPENGLINFO.Flags); |
|
|
|
// Obtain the sizes of the private data structures |
|
D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE QUERYRESOURCEINFOFROMNTHANDLE{ 0 }; |
|
QUERYRESOURCEINFOFROMNTHANDLE.hDevice = CREATEDEVICE.hDevice; |
|
QUERYRESOURCEINFOFROMNTHANDLE.hNtHandle = ntHandle; |
|
NT_RETURN = D3DKMTQueryResourceInfoFromNtHandle(&QUERYRESOURCEINFOFROMNTHANDLE); |
|
CHECK_NTSTATUS("D3DKMTQueryResourceInfoFromNtHandle"); |
|
wprintf(L" PrivateRuntimeDataSize: %d\n TotalPrivateDriverDataSize: %d\n", QUERYRESOURCEINFOFROMNTHANDLE.PrivateRuntimeDataSize, QUERYRESOURCEINFOFROMNTHANDLE.TotalPrivateDriverDataSize); |
|
|
|
/* non nt handles? (KMT) |
|
D3DKMT_QUERYRESOURCEINFO QUERYRESOURCEINFO{ 0 }; |
|
ntret = D3DKMTQueryResourceInfo(&QUERYRESOURCEINFO); |
|
*/ |
|
|
|
// read the private data structures |
|
D3DKMT_OPENRESOURCEFROMNTHANDLE OPENRESOURCEFROMNTHANDLE{ 0 }; |
|
OPENRESOURCEFROMNTHANDLE.hDevice = CREATEDEVICE.hDevice; |
|
OPENRESOURCEFROMNTHANDLE.hNtHandle = ntHandle; |
|
OPENRESOURCEFROMNTHANDLE.NumAllocations = QUERYRESOURCEINFOFROMNTHANDLE.NumAllocations; |
|
D3DDDI_OPENALLOCATIONINFO2* OPENALLOCATIONINFO2 = (D3DDDI_OPENALLOCATIONINFO2*)calloc(sizeof(D3DDDI_OPENALLOCATIONINFO2), QUERYRESOURCEINFOFROMNTHANDLE.NumAllocations); |
|
OPENRESOURCEFROMNTHANDLE.pOpenAllocationInfo2 = OPENALLOCATIONINFO2; |
|
OPENRESOURCEFROMNTHANDLE.KeyedMutexPrivateRuntimeDataSize = 0; |
|
OPENRESOURCEFROMNTHANDLE.PrivateRuntimeDataSize = QUERYRESOURCEINFOFROMNTHANDLE.PrivateRuntimeDataSize; |
|
void* pPrivateRuntimeData = (void*)calloc(1, QUERYRESOURCEINFOFROMNTHANDLE.PrivateRuntimeDataSize); |
|
OPENRESOURCEFROMNTHANDLE.pPrivateRuntimeData = pPrivateRuntimeData; |
|
OPENRESOURCEFROMNTHANDLE.ResourcePrivateDriverDataSize = QUERYRESOURCEINFOFROMNTHANDLE.ResourcePrivateDriverDataSize; |
|
void* pResourcePrivateDriverData = (void*)calloc(1, QUERYRESOURCEINFOFROMNTHANDLE.ResourcePrivateDriverDataSize); |
|
OPENRESOURCEFROMNTHANDLE.pResourcePrivateDriverData = pResourcePrivateDriverData; |
|
OPENRESOURCEFROMNTHANDLE.TotalPrivateDriverDataBufferSize = QUERYRESOURCEINFOFROMNTHANDLE.TotalPrivateDriverDataSize; |
|
void* pTotalPrivateDriverDataBuffer = (void*)calloc(1, QUERYRESOURCEINFOFROMNTHANDLE.TotalPrivateDriverDataSize); |
|
OPENRESOURCEFROMNTHANDLE.pTotalPrivateDriverDataBuffer = pTotalPrivateDriverDataBuffer; |
|
NT_RETURN = D3DKMTOpenResourceFromNtHandle(&OPENRESOURCEFROMNTHANDLE); |
|
CHECK_NTSTATUS("D3DKMTOpenResourceFromNtHandle"); |
|
|
|
// hex dump the structures |
|
printf("PrivateRuntimeData:\n"); |
|
DumpHex(OPENRESOURCEFROMNTHANDLE.pPrivateRuntimeData, OPENRESOURCEFROMNTHANDLE.PrivateRuntimeDataSize); |
|
printf("TotalPrivateDriverData:\n"); |
|
DumpHex(OPENRESOURCEFROMNTHANDLE.pTotalPrivateDriverDataBuffer, OPENRESOURCEFROMNTHANDLE.TotalPrivateDriverDataBufferSize); |
|
|
|
// check sizes can be holded in our struct, seems to be constant, PrivateRuntimeDataSize: 104 and TotalPrivateDriverDataSize: 594 (at least on nvidia ICD) |
|
if (sizeof(UNK_TOTALDRIVERPRIVATEDATA) > QUERYRESOURCEINFOFROMNTHANDLE.TotalPrivateDriverDataSize) return 0; |
|
if (sizeof(DXGI_PRIVATEDATA) > QUERYRESOURCEINFOFROMNTHANDLE.PrivateRuntimeDataSize) return 0; |
|
|
|
// cast buffers to readable structures |
|
DXGI_PRIVATEDATA* dv = (DXGI_PRIVATEDATA*)OPENRESOURCEFROMNTHANDLE.pPrivateRuntimeData; |
|
UNK_TOTALDRIVERPRIVATEDATA* pv = (UNK_TOTALDRIVERPRIVATEDATA*)OPENRESOURCEFROMNTHANDLE.pTotalPrivateDriverDataBuffer; |
|
|
|
// debug |
|
printf(" Texture size: %dx%d\n", dv->Width, dv->Height); |
|
printf(" Texture format: %d MiscFlags: %d\n", dv->Format, dv->Desc.MiscFlags); |
|
printf("\n Texture size: %d Bytes\n\n", pv->pMagicValue); |
|
|
|
// the handle has been opened and an allocation is made, somehow this seems to close it |
|
D3DKMT_DESTROYALLOCATION DESTROYALLOCATION{ 0 }; |
|
DESTROYALLOCATION.hDevice = CREATEDEVICE.hDevice; |
|
DESTROYALLOCATION.hResource = OPENRESOURCEFROMNTHANDLE.hResource; |
|
NT_RETURN = D3DKMTDestroyAllocation(&DESTROYALLOCATION); |
|
CHECK_NTSTATUS("D3DKMTDestroyAllocation"); |
|
|
|
// not sure if i need to do this, i guess its ok¿? |
|
CloseHandle(ntHandle); |
|
|
|
// close the staging device |
|
D3DKMT_DESTROYDEVICE DESTROYDEVICE{ 0 }; |
|
DESTROYDEVICE.hDevice = CREATEDEVICE.hDevice; |
|
NT_RETURN = D3DKMTDestroyDevice(&DESTROYDEVICE); |
|
CHECK_NTSTATUS("D3DKMTDestroyDevice"); |
|
|
|
// free resources |
|
//ReleaseDC(0, OPENADAPTERFROMHDC.hDc); |
|
free(OPENALLOCATIONINFO2); |
|
free(pPrivateRuntimeData); |
|
free(pResourcePrivateDriverData); |
|
free(pTotalPrivateDriverDataBuffer); |
|
texture->Release(); |
|
context->Release(); |
|
device->Release(); |
|
|
|
getchar(); |
|
return 0; |
|
} |
|
|