Commit 86690168 authored by Michael Müller's avatar Michael Müller Committed by Vitaly Lipatov

nvapi: First implementation.

parent 3875a142
......@@ -1251,6 +1251,7 @@ enable_ntdll
enable_ntdsapi
enable_ntoskrnl_exe
enable_ntprint
enable_win32
enable_nvcuda
enable_objsel
enable_odbc32
......@@ -5565,6 +5566,12 @@ enable_win16=${enable_win16:-no}
enable_win64=${enable_win64:-no}
enable_wow64=${enable_wow64:-no}
enable_wow64win=${enable_wow64win:-no}
if test "x$enable_win64" != "xyes"
then
enable_win32="yes"
else
enable_win32="no"
fi
enable_wow64cpu=${enable_wow64cpu:-no}
enable_winetest=${enable_winetest:-$enable_tests}
......@@ -19509,6 +19516,9 @@ wine_fn_config_makefile dlls/ntoskrnl.exe enable_ntoskrnl_exe
wine_fn_config_makefile dlls/ntoskrnl.exe/tests enable_tests
wine_fn_config_makefile dlls/ntprint enable_ntprint
wine_fn_config_makefile dlls/ntprint/tests enable_tests
wine_fn_config_makefile dlls/nvapi enable_win32
wine_fn_config_makefile dlls/nvapi/tests enable_tests
wine_fn_config_makefile dlls/nvapi64 enable_win64
wine_fn_config_makefile dlls/nvcuda enable_nvcuda
wine_fn_config_makefile dlls/nvcuda/tests enable_tests
wine_fn_config_makefile dlls/objsel enable_objsel
......
......@@ -207,6 +207,12 @@ enable_win16=${enable_win16:-no}
enable_win64=${enable_win64:-no}
enable_wow64=${enable_wow64:-no}
enable_wow64win=${enable_wow64win:-no}
if test "x$enable_win64" != "xyes"
then
enable_win32="yes"
else
enable_win32="no"
fi
enable_wow64cpu=${enable_wow64cpu:-no}
dnl Disable winetest too if tests are disabled
......@@ -2928,6 +2934,9 @@ WINE_CONFIG_MAKEFILE(dlls/ntoskrnl.exe)
WINE_CONFIG_MAKEFILE(dlls/ntoskrnl.exe/tests)
WINE_CONFIG_MAKEFILE(dlls/ntprint)
WINE_CONFIG_MAKEFILE(dlls/ntprint/tests)
WINE_CONFIG_MAKEFILE(dlls/nvapi,enable_win32)
WINE_CONFIG_MAKEFILE(dlls/nvapi/tests)
WINE_CONFIG_MAKEFILE(dlls/nvapi64,enable_win64)
WINE_CONFIG_MAKEFILE(dlls/nvcuda)
WINE_CONFIG_MAKEFILE(dlls/nvcuda/tests)
WINE_CONFIG_MAKEFILE(dlls/objsel)
......
MODULE = nvapi.dll
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
nvapi.c
/*
* Copyright (C) 2015 Michael Müller
* Copyright (C) 2015 Sebastian Lackner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "nvapi.h"
#include "d3d9.h"
WINE_DEFAULT_DEBUG_CHANNEL(nvapi);
#define FAKE_PHYSICAL_GPU ((NvPhysicalGpuHandle)0xdead0001)
#define FAKE_DISPLAY ((NvDisplayHandle)0xdead0002)
#if defined(__i386__) || defined(__x86_64__)
static NvAPI_Status CDECL unimplemented_stub(unsigned int offset)
{
FIXME("function 0x%x is unimplemented!\n", offset);
return NVAPI_ERROR;
}
#ifdef __i386__
#include "pshpack1.h"
struct thunk
{
unsigned char push_ebp;
unsigned short mov_esp_ebp;
unsigned char sub_0x08_esp[3];
unsigned char mov_dword_esp[3];
unsigned int offset;
unsigned char mov_eax;
void *stub;
unsigned short call_eax;
unsigned char leave;
unsigned char ret;
};
#include "poppack.h"
static void* prepare_thunk(struct thunk *thunk, unsigned int offset)
{
thunk->push_ebp = 0x55;
thunk->mov_esp_ebp = 0xE589;
thunk->sub_0x08_esp[0] = 0x83;
thunk->sub_0x08_esp[1] = 0xEC;
thunk->sub_0x08_esp[2] = 0x08;
thunk->mov_dword_esp[0] = 0xC7;
thunk->mov_dword_esp[1] = 0x04;
thunk->mov_dword_esp[2] = 0x24;
thunk->offset = offset;
thunk->mov_eax = 0xB8;
thunk->stub = &unimplemented_stub;
thunk->call_eax = 0xD0FF;
thunk->leave = 0xC9;
thunk->ret = 0xC3;
return thunk;
}
#else
#include "pshpack1.h"
struct thunk
{
unsigned short mov_rcx;
unsigned int offset;
unsigned int zero;
unsigned short mov_rax;
void *stub;
unsigned short jmp_rax;
};
#include "poppack.h"
static void* prepare_thunk(struct thunk *thunk, unsigned int offset)
{
thunk->mov_rcx = 0xB948;
thunk->offset = offset;
thunk->zero = 0;
thunk->mov_rax = 0xB848;
thunk->stub = &unimplemented_stub;
thunk->jmp_rax = 0xE0FF;
return thunk;
}
#endif
struct thunk_entry
{
struct list entry;
int num_thunks;
struct thunk thunks[0];
};
static struct list unimplemented_thunks = LIST_INIT( unimplemented_thunks );
static SYSTEM_BASIC_INFORMATION system_info;
static RTL_CRITICAL_SECTION unimplemented_thunk_section;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &unimplemented_thunk_section,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": unimplemented_thunk_section") }
};
static RTL_CRITICAL_SECTION unimplemented_thunk_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static void* lookup_thunk_function(unsigned int offset)
{
struct list *ptr;
unsigned int i;
/* check for existing thunk */
LIST_FOR_EACH( ptr, &unimplemented_thunks )
{
struct thunk_entry *entry = LIST_ENTRY( ptr, struct thunk_entry, entry );
for (i = 0; i < entry->num_thunks; i++)
if (entry->thunks[i].offset == offset)
return &entry->thunks[i];
}
return NULL;
}
static void* allocate_thunk_function(unsigned int offset)
{
struct thunk_entry *entry;
struct list *ptr;
/* append after last existing thunk if possible */
if ((ptr = list_tail( &unimplemented_thunks )))
{
entry = LIST_ENTRY( ptr, struct thunk_entry, entry );
if (FIELD_OFFSET( struct thunk_entry, thunks[entry->num_thunks + 1] ) <= system_info.PageSize)
return prepare_thunk( &entry->thunks[entry->num_thunks++], offset );
}
/* allocate a new block */
entry = VirtualAlloc( NULL, system_info.PageSize, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE );
if (entry)
{
list_add_tail( &unimplemented_thunks, &entry->entry );
entry->num_thunks = 1;
return prepare_thunk( &entry->thunks[0], offset );
}
return NULL;
}
static void* get_thunk_function(unsigned int offset)
{
void *ret;
TRACE("(%x)\n", offset);
EnterCriticalSection( &unimplemented_thunk_section );
ret = lookup_thunk_function( offset );
if (!ret) ret = allocate_thunk_function( offset );
LeaveCriticalSection( &unimplemented_thunk_section );
return ret;
}
static void init_thunks(void)
{
NtQuerySystemInformation( SystemBasicInformation, &system_info, sizeof(system_info), NULL );
/* we assume here that system_info.PageSize will always be great enough to hold at least one thunk */
}
static void free_thunks(void)
{
struct list *ptr, *ptr2;
EnterCriticalSection( &unimplemented_thunk_section );
LIST_FOR_EACH_SAFE( ptr, ptr2, &unimplemented_thunks )
{
struct thunk_entry *entry = LIST_ENTRY( ptr, struct thunk_entry, entry );
list_remove( ptr );
VirtualFree( entry, 0, MEM_RELEASE );
}
LeaveCriticalSection( &unimplemented_thunk_section );
}
#else
static NvAPI_Status CDECL unimplemented_stub()
{
FIXME("function is unimplemented!\n");
return NVAPI_ERROR;
}
static void* get_thunk_function(unsigned int offset)
{
TRACE("(%x)\n", offset);
return &unimplemented_stub;
}
static void init_thunks(void)
{
/* unimplemented */
}
static void free_thunks(void)
{
/* unimplemented */
}
#endif
static NvAPI_Status CDECL NvAPI_Initialize(void)
{
TRACE("()\n");
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Unknown1(NV_UNKNOWN_1 *param)
{
TRACE("(%p)\n", param);
if (!param)
return NVAPI_INVALID_ARGUMENT;
if (param->version != NV_UNKNOWN_1_VER)
return NVAPI_INCOMPATIBLE_STRUCT_VERSION;
param->gpu_count = 1;
param->gpus[0].gpuHandle = FAKE_PHYSICAL_GPU;
param->gpus[0].unknown2 = 11;
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Unknown2(NvPhysicalGpuHandle gpuHandle, NvPhysicalGpuHandle *retHandle)
{
TRACE("(%p, %p)\n", gpuHandle, retHandle);
if (!gpuHandle)
return NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE;
if (!retHandle)
return NVAPI_INVALID_ARGUMENT;
if (gpuHandle == FAKE_PHYSICAL_GPU)
*retHandle = (void *)gpuHandle;
else
{
FIXME("invalid handle: %p\n", gpuHandle);
*retHandle = (void*)0xffffffff;
}
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Unknown3(NvPhysicalGpuHandle gpuHandle, NvPhysicalGpuHandle *retHandle)
{
TRACE("(%p, %p)\n", gpuHandle, retHandle);
if (!gpuHandle || !retHandle)
return NVAPI_INVALID_ARGUMENT;
if (gpuHandle == FAKE_PHYSICAL_GPU)
*retHandle = (void *)gpuHandle;
else
{
FIXME("invalid handle: %p\n", gpuHandle);
*retHandle = (void *)0xffffffff;
}
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_GetDisplayDriverVersion(NvDisplayHandle hNvDisplay, NV_DISPLAY_DRIVER_VERSION *pVersion)
{
NvAPI_ShortString build_str = {'r','3','3','7','_','0','0','-','1','8','9',0};
NvAPI_ShortString adapter = {'G','e','F','o','r','c','e',' ','9','9','9',' ','G','T','X', 0};
/* TODO: find a good way to get the graphic card name, EnumDisplayDevices is useless in Wine */
/* For now we return the non existing GeForce 999 GTX as graphic card name */
TRACE("(%p, %p)\n", hNvDisplay, pVersion);
if (hNvDisplay && hNvDisplay != FAKE_DISPLAY)
{
FIXME("invalid display handle: %p\n", hNvDisplay);
return NVAPI_INVALID_HANDLE;
}
if (!pVersion)
return NVAPI_INVALID_ARGUMENT;
pVersion->drvVersion = 33788;
pVersion->bldChangeListNum = 0;
memcpy(pVersion->szBuildBranchString, build_str, sizeof(build_str));
memcpy(pVersion->szAdapterString, adapter, sizeof(adapter));
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_GetAssociatedNvidiaDisplayHandle(const char *szDisplayName, NvDisplayHandle *pNvDispHandle)
{
TRACE("(%s, %p)\n", szDisplayName, pNvDispHandle);
*pNvDispHandle = FAKE_DISPLAY;
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_GetPhysicalGPUsFromDisplay(NvDisplayHandle hNvDisp, NvPhysicalGpuHandle nvGPUHandle[NVAPI_MAX_PHYSICAL_GPUS], NvU32 *pGpuCount)
{
TRACE("(%p, %p, %p)\n", hNvDisp, nvGPUHandle, pGpuCount);
nvGPUHandle[0] = FAKE_PHYSICAL_GPU;
*pGpuCount = 1;
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Stereo_Disable(void)
{
TRACE("()\n");
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Stereo_IsEnabled(NvU8 *pIsStereoEnabled)
{
TRACE("(%p)\n", pIsStereoEnabled);
*pIsStereoEnabled = 0;
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Stereo_CreateHandleFromIUnknown(void *pDevice, StereoHandle *pStereoHandle)
{
TRACE("(%p, %p)\n", pDevice, pStereoHandle);
return NVAPI_STEREO_NOT_INITIALIZED;
}
static NvAPI_Status CDECL NvAPI_Stereo_DestroyHandle(StereoHandle stereoHandle)
{
TRACE("(%p)\n", stereoHandle);
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Stereo_Activate(StereoHandle stereoHandle)
{
TRACE("(%p)\n", stereoHandle);
return NVAPI_STEREO_NOT_INITIALIZED;
}
static NvAPI_Status CDECL NvAPI_Stereo_Deactivate(StereoHandle stereoHandle)
{
TRACE("(%p)\n", stereoHandle);
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Stereo_IsActivated(StereoHandle stereoHandle, NvU8 *pIsStereoOn)
{
TRACE("(%p, %p)\n", stereoHandle, pIsStereoOn);
*pIsStereoOn = 0;
return NVAPI_OK;
}
static NvAPI_Status CDECL NvAPI_Stereo_GetSeparation(StereoHandle stereoHandle, float *pSeparationPercentage)
{
TRACE("(%p, %p)\n", stereoHandle, pSeparationPercentage);
return NVAPI_STEREO_NOT_INITIALIZED;
}
static NvAPI_Status CDECL NvAPI_Stereo_SetSeparation(StereoHandle stereoHandle, float newSeparationPercentage)
{
TRACE("(%p, %f)\n", stereoHandle, newSeparationPercentage);
return NVAPI_STEREO_NOT_INITIALIZED;
}
static NvAPI_Status CDECL NvAPI_Stereo_Enable(void)
{
TRACE("()\n");
return NVAPI_STEREO_NOT_INITIALIZED;
}
static NvAPI_Status CDECL NvAPI_D3D9_StretchRectEx(IDirect3DDevice9 *pDevice, IDirect3DResource9 *pSourceResource,
const RECT *pSourceRect, IDirect3DResource9 *pDestResource,
const RECT *pDestRect, D3DTEXTUREFILTERTYPE Filter)
{
FIXME("(%p, %p, %p, %p, %p, %d): stub\n", pDevice, pSourceResource, pSourceRect, pDestResource, pDestRect, Filter);
return NVAPI_UNREGISTERED_RESOURCE;
}
void* CDECL nvapi_QueryInterface(unsigned int offset)
{
static const struct
{
unsigned int offset;
void *function;
}
function_list[] =
{
{0x0150E828, NvAPI_Initialize},
{0xF951A4D1, NvAPI_GetDisplayDriverVersion},
{0x5786cc6e, NvAPI_Unknown1},
{0x6533ea3e, NvAPI_Unknown2},
{0x5380ad1a, NvAPI_Unknown3},
{0x35c29134, NvAPI_GetAssociatedNvidiaDisplayHandle},
{0x34ef9506, NvAPI_GetPhysicalGPUsFromDisplay},
{0x2ec50c2b, NvAPI_Stereo_Disable},
{0x348ff8e1, NvAPI_Stereo_IsEnabled},
{0xac7e37f4, NvAPI_Stereo_CreateHandleFromIUnknown},
{0x3a153134, NvAPI_Stereo_DestroyHandle},
{0xf6a1ad68, NvAPI_Stereo_Activate},
{0x2d68de96, NvAPI_Stereo_Deactivate},
{0x1fb0bc30, NvAPI_Stereo_IsActivated},
{0x451f2134, NvAPI_Stereo_GetSeparation},
{0x5c069fa3, NvAPI_Stereo_SetSeparation},
{0x239c4545, NvAPI_Stereo_Enable},
{0xaeaecd41, NvAPI_D3D9_StretchRectEx},
};
unsigned int i;
TRACE("(%x)\n", offset);
for (i = 0; i < sizeof(function_list) / sizeof(function_list[0]); i++)
{
if (function_list[i].offset == offset)
return function_list[i].function;
}
return get_thunk_function(offset);
}
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
TRACE("(%p, %u, %p)\n", instance, reason, reserved);
switch (reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(instance);
init_thunks();
break;
case DLL_PROCESS_DETACH:
free_thunks();
break;
}
return TRUE;
}
@ cdecl nvapi_QueryInterface(long)
@ stub DllCanUnloadNow
@ stub DllGetClassObject
@ stub DllRegisterServer
@ stub DllUnregisterServer
TESTDLL = nvapi.dll
IMPORTS = user32 shlwapi
C_SRCS = \
nvapi.c
/*
* Copyright (C) 2015 Michael Müller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "shlwapi.h"
#include "winerror.h"
#include "nvapi.h"
#include "wine/test.h"
#define NvAPI_Initialize_Offset 0x0150E828
#define NvAPI_GetDisplayDriverVersion_Offset 0xF951A4D1
#define NvAPI_unknown1_Offset 0x5786cc6e
#define NvAPI_unknown2_Offset 0x6533ea3e
#define NvAPI_unknown3_Offset 0x5380ad1a
static void* (CDECL *pnvapi_QueryInterface)(unsigned int offset);
static NvAPI_Status (CDECL *pNvAPI_Initialize)(void);
static NvAPI_Status (CDECL *pNvAPI_GetDisplayDriverVersion)(NvDisplayHandle hNvDisplay, NV_DISPLAY_DRIVER_VERSION *pVersion);
static NvAPI_Status (CDECL *pNvAPI_unknown1)(void* param0);
static NvAPI_Status (CDECL *pNvAPI_unknown2)(NvPhysicalGpuHandle gpuHandle, void *param1);
static NvAPI_Status (CDECL *pNvAPI_unknown3)(void *param0, void *param1);
static BOOL init(void)
{
#ifdef __x86_64__
HMODULE nvapi = LoadLibraryA("nvapi64.dll");
#else
HMODULE nvapi = LoadLibraryA("nvapi.dll");
#endif
if (!nvapi)
{
skip("Could not load nvapi.dll\n");
return FALSE;
}
pnvapi_QueryInterface = (void *)GetProcAddress(nvapi, "nvapi_QueryInterface");
if (!pnvapi_QueryInterface)
{
win_skip("Failed to get entry point for nvapi_QueryInterface.\n");
return FALSE;
}
pNvAPI_Initialize = pnvapi_QueryInterface(NvAPI_Initialize_Offset);
pNvAPI_GetDisplayDriverVersion = pnvapi_QueryInterface(NvAPI_GetDisplayDriverVersion_Offset);
pNvAPI_unknown1 = pnvapi_QueryInterface(NvAPI_unknown1_Offset);
pNvAPI_unknown2 = pnvapi_QueryInterface(NvAPI_unknown2_Offset);
pNvAPI_unknown3 = pnvapi_QueryInterface(NvAPI_unknown3_Offset);
if (!pNvAPI_Initialize)
{
win_skip("Failed to get entry point for NvAPI_Initialize.\n");
return FALSE;
}
if (pNvAPI_Initialize())
{
skip("Failed to initialize nvapi.\n");
return FALSE;
}
return TRUE;
}
static void test_GetDisplayDriverVersion(void)
{
NV_DISPLAY_DRIVER_VERSION version;
NvAPI_Status status;
DISPLAY_DEVICEA dinfo;
char *gpuName;
if (!pNvAPI_GetDisplayDriverVersion)
{
win_skip("NvAPI_GetDisplayDriverVersion export not found.\n");
return;
}
status = pNvAPI_GetDisplayDriverVersion(0, NULL);
ok(status == NVAPI_INVALID_ARGUMENT, "Expected status NVAPI_INVALID_ARGUMENT, got %d\n", status);
memset(&version, 0, sizeof(version));
version.version = NV_DISPLAY_DRIVER_VERSION_VER;
status = pNvAPI_GetDisplayDriverVersion((void *)0xdeadbeef, &version);
ok(status == NVAPI_INVALID_HANDLE, "Expected status NVAPI_INVALID_HANDLE, got %d\n", status);
memset(&dinfo, 0, sizeof(dinfo));
dinfo.cb = sizeof(dinfo);
ok(EnumDisplayDevicesA(NULL, 0, &dinfo, 0), "Failed to get monitor info\n");
trace("Device name: %s\n", (char*)&dinfo.DeviceName);
trace("Device string: %s\n", (char*)&dinfo.DeviceString);
gpuName = (char*)&dinfo.DeviceString;
StrTrimA(gpuName, " \t\r\n");
if (!strncmp(gpuName, "NVIDIA ", 7))
gpuName += 7;
memset(&version, 0, sizeof(version));
version.version = NV_DISPLAY_DRIVER_VERSION_VER;
status = pNvAPI_GetDisplayDriverVersion(0, &version);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
trace("Driver version: %u\n", (unsigned int)version.drvVersion);
trace("Change list num: %u\n", (unsigned int)version.bldChangeListNum);
trace("Build string: %s\n", version.szBuildBranchString);
trace("Adapter string: %s\n", version.szAdapterString);
todo_wine ok(!strcmp(version.szAdapterString, gpuName), "Expected device name %s, got %s\n",
gpuName, version.szAdapterString);
}
static void test_unknown1(void)
{
NV_UNKNOWN_1 test;
NvAPI_Status status;
int i;
if (!pNvAPI_unknown1)
{
win_skip("pNvAPI_unknown1 export not found.\n");
return;
}
status = pNvAPI_unknown1(NULL);
ok(status == NVAPI_INVALID_ARGUMENT, "Expected status NVAPI_INVALID_ARGUMENT, got %d\n", status);
memset(&test, 0, sizeof(test));
test.version = NV_UNKNOWN_1_VER;
status = pNvAPI_unknown1(&test);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
ok(test.gpu_count > 0, "Expected gpu_count > 0, got %d\n", test.gpu_count);
for (i = 0; i < test.gpu_count; i++)
{
ok(test.gpus[i].gpuHandle != NULL, "Expected gpus[%d].gpuHandle != 0, got %p\n", i, test.gpus[i].gpuHandle);
ok(test.gpus[i].unknown2 != 0, "Expected gpus[%d].unknown2 != 0, got %d\n", i, test.gpus[i].unknown2);
}
for (; i < sizeof(test.gpus) / sizeof(test.gpus[0]); i++)
{
ok(test.gpus[i].gpuHandle == NULL, "Expected gpus[%d].gpuHandle == NULL, got %p\n", i, test.gpus[i].gpuHandle);
ok(test.gpus[i].unknown2 == 0, "Expected gpus[%d].unknown2 == 0, got %d\n", i, test.gpus[i].unknown2);
}
}
static void test_unknown2(void)
{
NV_UNKNOWN_1 test;
NvAPI_Status status;
NvPhysicalGpuHandle test2 = NULL;
if (!pNvAPI_unknown1)
{
win_skip("pNvAPI_unknown1 export not found.\n");
return;
}
if (!pNvAPI_unknown2)
{
win_skip("pNvAPI_unknown1 export not found.\n");
return;
}
status = pNvAPI_unknown2(NULL, NULL);
ok(status == NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE, "Expected status NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE, got %d\n", status);
memset(&test, 0, sizeof(test));
test.version = NV_UNKNOWN_1_VER;
status = pNvAPI_unknown1(&test);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
status = pNvAPI_unknown2(test.gpus[0].gpuHandle, NULL);
ok(status == NVAPI_INVALID_ARGUMENT, "Expected status NVAPI_INVALID_ARGUMENT, got %d\n", status);
status = pNvAPI_unknown2(NULL, &test2);
ok(status == NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE, "Expected status NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE, got %d\n", status);
test2 = NULL;
status = pNvAPI_unknown2((void *)0xdeadbeef, &test2);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
ok(test2 == (void*)0xffffffff, "Expected handle 0xffffffff, got %p\n", test2);
test2 = NULL;
status = pNvAPI_unknown2(test.gpus[0].gpuHandle, &test2);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
ok(test2 == test.gpus[0].gpuHandle, "Expected handle %p, got %p\n", test.gpus[0].gpuHandle, test2);
}
static void test_unknown3(void)
{
NV_UNKNOWN_1 test;
NvAPI_Status status;
NvPhysicalGpuHandle test2 = NULL;
NvPhysicalGpuHandle test3 = NULL;
if (!pNvAPI_unknown1)
{
win_skip("pNvAPI_unknown1 export not found.\n");
return;
}
if (!pNvAPI_unknown2)
{
win_skip("pNvAPI_unknown1 export not found.\n");
return;
}
if (!pNvAPI_unknown3)
{
win_skip("pNvAPI_unknown1 export not found.\n");
return;
}
status = pNvAPI_unknown3(NULL, NULL);
ok(status == NVAPI_INVALID_ARGUMENT, "Expected status NVAPI_INVALID_ARGUMENT, got %d\n", status);
memset(&test, 0, sizeof(test));
test.version = NV_UNKNOWN_1_VER;
status = pNvAPI_unknown1(&test);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
status = pNvAPI_unknown2(test.gpus[0].gpuHandle, &test2);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
status = pNvAPI_unknown3(test2, NULL);
ok(status == NVAPI_INVALID_ARGUMENT, "Expected status NVAPI_INVALID_ARGUMENT, got %d\n", status);
status = pNvAPI_unknown3(NULL, &test3);
ok(status == NVAPI_INVALID_ARGUMENT, "Expected status NVAPI_INVALID_ARGUMENT, got %d\n", status);
test3 = NULL;
status = pNvAPI_unknown3((void *)0xdeadbeef, &test3);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
ok(test3 == (void*)0xffffffff, "Expected handle 0xffffffff, got %p\n", test3);
test3 = NULL;
status = pNvAPI_unknown3(test2, &test3);
ok(!status, "Expected status NVAPI_OK, got %d\n", status);
ok(test2 == test3, "Expected handle %p, got %p\n", test2, test3);
}
START_TEST( nvapi )
{
if (!init())
return;
test_GetDisplayDriverVersion();
test_unknown1();
test_unknown2();
test_unknown3();
}
MODULE = nvapi64.dll
PARENTSRC = ../nvapi
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
nvapi.c
@ cdecl nvapi_QueryInterface(long)
@ stub DllCanUnloadNow
@ stub DllGetClassObject
@ stub DllRegisterServer
@ stub DllUnregisterServer
......@@ -571,6 +571,7 @@ SOURCES = \
ntsecpkg.h \
ntstatus.h \
ntuser.h \
nvapi.h \
oaidl.idl \
objbase.h \
objectarray.idl \
......
/*
* Copyright (C) 2015 Michael Müller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_NVAPI_H
#define __WINE_NVAPI_H
#include "pshpack8.h"
typedef unsigned char NvU8;
typedef unsigned int NvU32;
#define NvAPI_Status int
#define NVAPI_OK 0
#define NVAPI_ERROR -1
#define NVAPI_INVALID_ARGUMENT -5
#define NVAPI_INVALID_HANDLE -8
#define NVAPI_INCOMPATIBLE_STRUCT_VERSION -9
#define NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE -101
#define NVAPI_STEREO_NOT_INITIALIZED -140
#define NVAPI_UNREGISTERED_RESOURCE -170
#define NVAPI_SHORT_STRING_MAX 64
#define NVAPI_MAX_PHYSICAL_GPUS 64
typedef char NvAPI_ShortString[NVAPI_SHORT_STRING_MAX];
#define MAKE_NVAPI_VERSION(type,version) (NvU32)(sizeof(type) | ((version)<<16))
typedef void *NvPhysicalGpuHandle;
typedef void *NvDisplayHandle;
typedef void *StereoHandle;
typedef struct
{
NvU32 version;
NvU32 drvVersion;
NvU32 bldChangeListNum;
NvAPI_ShortString szBuildBranchString;
NvAPI_ShortString szAdapterString;
} NV_DISPLAY_DRIVER_VERSION;
#define NV_DISPLAY_DRIVER_VERSION_VER MAKE_NVAPI_VERSION(NV_DISPLAY_DRIVER_VERSION, 1)
/* undocumented stuff */
typedef struct
{
NvU32 version;
NvU32 gpu_count;
struct
{
NvPhysicalGpuHandle gpuHandle;
NvU32 unknown2;
} gpus[8];
}NV_UNKNOWN_1;
#define NV_UNKNOWN_1_VER MAKE_NVAPI_VERSION(NV_UNKNOWN_1, 1)
#include "poppack.h"
#endif /* __WINE_NVAPI_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment