Skip to content

Commit a745c98

Browse files
jenataliXinfengZhang
authored andcommitted
win32: Rewrite driver registry query and fix some bugs/leaks/inefficiencies
Signed-off-by: Jesse Natalie <jenatali@microsoft.com>
1 parent 74f4252 commit a745c98

2 files changed

Lines changed: 71 additions & 151 deletions

File tree

va/compat_win32.h

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,14 @@ inline int gettimeofday(struct timeval *tv, struct timezone* tz)
128128
//
129129
typedef UINT D3DKMT_HANDLE;
130130

131-
typedef struct _D3DKMT_ADAPTERINFO {
132-
D3DKMT_HANDLE hAdapter;
133-
LUID AdapterLuid;
134-
ULONG NumOfSources;
135-
BOOL bPrecisePresentRegionsPreferred;
136-
} D3DKMT_ADAPTERINFO;
137-
138-
typedef struct _D3DKMT_ENUMADAPTERS2 {
139-
ULONG NumAdapters; // in/out: On input, the count of the pAdapters array buffer. On output, the number of adapters enumerated.
140-
D3DKMT_ADAPTERINFO* pAdapters; // out: Array of enumerated adapters containing NumAdapters elements
141-
} D3DKMT_ENUMADAPTERS2;
131+
typedef struct _D3DKMT_CLOSEADAPTER {
132+
D3DKMT_HANDLE hAdapter; // in: adapter handle
133+
} D3DKMT_CLOSEADAPTER;
142134

135+
typedef struct _D3DKMT_OPENADAPTERFROMLUID {
136+
LUID AdapterLuid;
137+
D3DKMT_HANDLE hAdapter;
138+
} D3DKMT_OPENADAPTERFROMLUID;
143139

144140
typedef enum _KMTQUERYADAPTERINFOTYPE {
145141
KMTQAITYPE_QUERYREGISTRY = 48,
@@ -188,7 +184,8 @@ typedef struct _D3DDDI_QUERYREGISTRY_INFO {
188184
};
189185
} D3DDDI_QUERYREGISTRY_INFO;
190186

191-
typedef _Check_return_ NTSTATUS(APIENTRY *PFND3DKMT_ENUMADAPTERS2)(_Inout_ CONST D3DKMT_ENUMADAPTERS2*);
187+
typedef _Check_return_ NTSTATUS(APIENTRY *PFND3DKMT_CLOSEADAPTER)(_In_ CONST D3DKMT_CLOSEADAPTER*);
188+
typedef _Check_return_ NTSTATUS(APIENTRY *PFND3DKMT_OPENADAPTERFROMLUID)(_Inout_ D3DKMT_OPENADAPTERFROMLUID*);
192189
typedef _Check_return_ NTSTATUS(APIENTRY *PFND3DKMT_QUERYADAPTERINFO)(_Inout_ CONST D3DKMT_QUERYADAPTERINFO*);
193190

194191
#endif

va/win32/va_win32.c

Lines changed: 62 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,6 @@
3535
* does not have a registered VA driver
3636
*/
3737
const char VAAPI_DEFAULT_DRIVER_NAME[] = "vaon12";
38-
const char VAAPI_REG_SUB_KEY[] = "VAAPIDriverName";
39-
const char VAAPI_REG_SUB_KEY_WOW[] = "VAAPIDriverNameWow";
40-
41-
inline const char* GetVAAPIRegKeyName()
42-
{
43-
#ifdef _WIN64
44-
return VAAPI_REG_SUB_KEY;
45-
#else
46-
BOOL is_wow64 = FALSE;
47-
if (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)
48-
return VAAPI_REG_SUB_KEY_WOW;
49-
return VAAPI_REG_SUB_KEY;
50-
#endif
51-
}
5238

5339
typedef struct _VADisplayContextWin32 {
5440
LUID adapter_luid;
@@ -58,136 +44,73 @@ typedef struct _VADisplayContextWin32 {
5844

5945
static bool TryLoadDriverNameFromRegistry(const LUID* adapter_luid, VADisplayContextWin32* pWin32Ctx)
6046
{
61-
if (!adapter_luid)
62-
return false;
63-
64-
/* Get handle to GDI Runtime */
65-
HMODULE h = LoadLibrary("gdi32.dll");
66-
if (h == NULL)
47+
HMODULE hGdi32 = LoadLibraryA("gdi32.dll");
48+
if (!hGdi32)
6749
return false;
6850

51+
D3DKMT_OPENADAPTERFROMLUID OpenArgs = { .AdapterLuid = *adapter_luid };
52+
D3DDDI_QUERYREGISTRY_INFO RegistryInfo = {
53+
.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY,
54+
.QueryFlags.TranslatePath = true,
55+
.ValueName = L"VAAPIDriverName",
56+
.ValueType = REG_SZ,
57+
};
58+
D3DDDI_QUERYREGISTRY_INFO *pRegistryInfo = &RegistryInfo;
59+
#ifndef _WIN64
60+
BOOL isWowProcess = false;
61+
if (IsWow64Process(GetCurrentProcess(), &isWowProcess) && isWowProcess)
62+
wcscpy(RegistryInfo.ValueName, "VAAPIDriverNameWow");
63+
#endif
64+
D3DKMT_QUERYADAPTERINFO QAI = {
65+
.Type = KMTQAITYPE_QUERYREGISTRY,
66+
.pPrivateDriverData = &RegistryInfo,
67+
.PrivateDriverDataSize = sizeof(RegistryInfo),
68+
};
6969
bool ret = false;
70-
int result = 0;
71-
/* Check the OS version */
72-
if (GetProcAddress(h, "D3DKMTSubmitPresentBltToHwQueue")) {
73-
D3DKMT_ENUMADAPTERS2 EnumAdapters;
74-
NTSTATUS status = STATUS_SUCCESS;
7570

76-
EnumAdapters.NumAdapters = 0;
77-
EnumAdapters.pAdapters = NULL;
78-
PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress(h, "D3DKMTEnumAdapters2");
79-
if (!pEnumAdapters2) {
80-
fprintf(stderr, "VA_Win32: GetProcAddress failed for D3DKMTEnumAdapters2\n");
81-
goto out;
82-
}
83-
PFND3DKMT_QUERYADAPTERINFO pQueryAdapterInfo = (PFND3DKMT_QUERYADAPTERINFO)GetProcAddress(h, "D3DKMTQueryAdapterInfo");
84-
if (!pQueryAdapterInfo) {
85-
fprintf(stderr, "VA_Win32: GetProcAddress failed for D3DKMTQueryAdapterInfo\n");
86-
goto out;
87-
}
88-
while (1) {
89-
EnumAdapters.NumAdapters = 0;
90-
EnumAdapters.pAdapters = NULL;
91-
status = pEnumAdapters2(&EnumAdapters);
92-
if (status == STATUS_BUFFER_TOO_SMALL) {
93-
/* Number of Adapters increased between calls, retry; */
94-
continue;
95-
} else if (!NT_SUCCESS(status)) {
96-
fprintf(stderr, "VA_Win32: D3DKMTEnumAdapters2 status != SUCCESS\n");
97-
goto out;
98-
}
99-
break;
100-
}
101-
EnumAdapters.pAdapters = malloc(sizeof(*EnumAdapters.pAdapters) * (EnumAdapters.NumAdapters));
102-
if (EnumAdapters.pAdapters == NULL) {
103-
fprintf(stderr, "VA_Win32: Allocation failure for adapters buffer\n");
104-
goto out;
105-
}
106-
status = pEnumAdapters2(&EnumAdapters);
107-
if (!NT_SUCCESS(status)) {
108-
fprintf(stderr, "VA_Win32: D3DKMTEnumAdapters2 status != SUCCESS\n");
109-
goto out;
110-
}
111-
const char* cszVAAPIRegKeyName = GetVAAPIRegKeyName();
112-
const int szVAAPIRegKeyName = (int)(strlen(cszVAAPIRegKeyName) + 1) * sizeof(cszVAAPIRegKeyName[0]);
113-
for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.NumAdapters; AdapterIndex++) {
114-
D3DDDI_QUERYREGISTRY_INFO queryArgs = {0};
115-
D3DDDI_QUERYREGISTRY_INFO* pQueryArgs = &queryArgs;
116-
D3DDDI_QUERYREGISTRY_INFO* pQueryBuffer = NULL;
117-
queryArgs.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY;
118-
queryArgs.QueryFlags.TranslatePath = TRUE;
119-
queryArgs.ValueType = REG_SZ;
120-
result = MultiByteToWideChar(
121-
CP_ACP,
122-
0,
123-
cszVAAPIRegKeyName,
124-
szVAAPIRegKeyName,
125-
queryArgs.ValueName,
126-
ARRAYSIZE(queryArgs.ValueName));
127-
if (!result) {
128-
fprintf(stderr, "VA_Win32: MultiByteToWideChar status != SUCCESS\n");
129-
continue;
130-
}
131-
D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {0};
132-
queryAdapterInfo.hAdapter = EnumAdapters.pAdapters[AdapterIndex].hAdapter;
133-
queryAdapterInfo.Type = KMTQAITYPE_QUERYREGISTRY;
134-
queryAdapterInfo.pPrivateDriverData = &queryArgs;
135-
queryAdapterInfo.PrivateDriverDataSize = sizeof(queryArgs);
136-
status = pQueryAdapterInfo(&queryAdapterInfo);
137-
if (!NT_SUCCESS(status)) {
138-
/* Try a different value type. Some vendors write the key as a multi-string type. */
139-
queryArgs.ValueType = REG_MULTI_SZ;
140-
status = pQueryAdapterInfo(&queryAdapterInfo);
141-
if (NT_SUCCESS(status)) {
142-
fprintf(stderr, "VA_Win32: Accepting multi-string registry key type\n");
143-
} else {
144-
/* Continue trying to get as much info on each adapter as possible. */
145-
/* It's too late to return FALSE and claim WDDM2_4 enumeration is not available here. */
146-
continue;
147-
}
148-
}
149-
if (NT_SUCCESS(status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW) {
150-
ULONG queryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + queryArgs.OutputValueSize;
151-
pQueryBuffer = malloc(queryBufferSize);
152-
if (pQueryBuffer == NULL)
153-
continue;
154-
memcpy(pQueryBuffer, &queryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
155-
queryAdapterInfo.pPrivateDriverData = pQueryBuffer;
156-
queryAdapterInfo.PrivateDriverDataSize = queryBufferSize;
157-
status = pQueryAdapterInfo(&queryAdapterInfo);
158-
pQueryArgs = pQueryBuffer;
159-
}
160-
if (NT_SUCCESS(status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS) {
161-
wchar_t* pWchar = pQueryArgs->OutputString;
162-
memset(pWin32Ctx->registry_driver_name, 0, sizeof(pWin32Ctx->registry_driver_name));
163-
size_t len;
164-
wcstombs_s(&len, pWin32Ctx->registry_driver_name, sizeof(pWin32Ctx->registry_driver_name), pWchar, sizeof(pWin32Ctx->registry_driver_name));
165-
assert(len <= (sizeof(pWin32Ctx->registry_driver_name) - 1));
166-
if (0 == memcmp(adapter_luid, &EnumAdapters.pAdapters[AdapterIndex].AdapterLuid, sizeof(EnumAdapters.pAdapters[AdapterIndex].AdapterLuid))) {
167-
ret = true;
168-
/* Found the adapter we wanted, finish iteration. Associated driver string is loaded in pWin32Ctx->registry_driver_name */
169-
/* VAAPI needs the stripped driver filename, without the absolute path or the extension. */
170-
171-
/* Zero-out the extension section with null terminators if present */
172-
char* pExtPosition = strstr(pWin32Ctx->registry_driver_name, ".dll");
173-
if (pExtPosition)
174-
memset(pExtPosition, '\0', 4 /*size of the 4 chars of .dll*/);
175-
176-
free(pQueryBuffer);
177-
goto out;
178-
}
179-
} else if (status == (NTSTATUS)STATUS_INVALID_PARAMETER) {
180-
free(pQueryBuffer);
181-
goto out;
182-
}
183-
free(pQueryBuffer);
184-
}
185-
out:
186-
free(EnumAdapters.pAdapters);
71+
PFND3DKMT_OPENADAPTERFROMLUID pfnOpenAdapterFromLuid = (PFND3DKMT_OPENADAPTERFROMLUID)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromLuid");
72+
PFND3DKMT_CLOSEADAPTER pfnCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(hGdi32, "D3DKMTCloseAdapter");
73+
PFND3DKMT_QUERYADAPTERINFO pfnQueryAdapterInfo = (PFND3DKMT_QUERYADAPTERINFO)GetProcAddress(hGdi32, "D3DKMTQueryAdapterInfo");
74+
if (!pfnOpenAdapterFromLuid || !pfnCloseAdapter || !pfnQueryAdapterInfo)
75+
goto cleanup;
76+
77+
if (!NT_SUCCESS(pfnOpenAdapterFromLuid(&OpenArgs)))
78+
goto cleanup;
79+
80+
QAI.hAdapter = OpenArgs.hAdapter;
81+
if (!NT_SUCCESS(pfnQueryAdapterInfo(&QAI)) ||
82+
pRegistryInfo->Status != D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
83+
goto cleanup;
84+
85+
size_t RegistryInfoSize = sizeof(RegistryInfo) + RegistryInfo.OutputValueSize;
86+
pRegistryInfo = malloc(RegistryInfoSize);
87+
if (!pRegistryInfo)
88+
goto cleanup;
89+
90+
memcpy(pRegistryInfo, &RegistryInfo, sizeof(RegistryInfo));
91+
QAI.pPrivateDriverData = pRegistryInfo;
92+
QAI.PrivateDriverDataSize = RegistryInfoSize;
93+
if (!NT_SUCCESS(pfnQueryAdapterInfo(&QAI)) ||
94+
pRegistryInfo->Status != D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
95+
goto cleanup;
96+
97+
if (!WideCharToMultiByte(CP_ACP, 0, pRegistryInfo->OutputString,
98+
RegistryInfo.OutputValueSize / sizeof(wchar_t),
99+
pWin32Ctx->registry_driver_name,
100+
sizeof(pWin32Ctx->registry_driver_name),
101+
NULL, NULL))
102+
goto cleanup;
103+
104+
ret = true;
105+
106+
cleanup:
107+
if (pRegistryInfo && pRegistryInfo != &RegistryInfo)
108+
free(pRegistryInfo);
109+
if (pfnCloseAdapter && OpenArgs.hAdapter) {
110+
D3DKMT_CLOSEADAPTER Close = { OpenArgs.hAdapter };
111+
pfnCloseAdapter(&Close);
187112
}
188-
189-
FreeLibrary(h);
190-
113+
FreeLibrary(hGdi32);
191114
return ret;
192115
}
193116

0 commit comments

Comments
 (0)