Ошибка проверки времени выполнения WIA № 0 C++ (получение образа Windows)

я пытаюсь использовать WIA для отправки данных на камеру. Мне нужно разработать это на C++, поэтому я использовал официальный «учебник» на https://docs.microsoft.com/en-us/windows/win32/wia/-wia-wia-tutorial Я знаю другой проект, который работает с C#, и я хочу сделать то же самое на C++ (проект C# на: https://github.com/pixeltris/SonyAlphaUSB)

Когда я хочу использовать метод Escape https://docs.microsoft.com/en-us/windows/win32/api/wia_xp/nf-wia_xp-iwiaitemextras-escape я получаю

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.
This is usually a result of calling a function declared with one calling
convention with a function pointer declared with a different calling convention.

Ошибка, и я надеюсь, что вы можете помочь мне решить эту проблему. Мой код выглядит так:

 //initialize wia
HRESULT h = CoInitialize(NULL);
IWiaDevMgr* pWiaDevMgr = NULL;
//create wia device manager
HRESULT hr = CreateWiaDeviceManager(&pWiaDevMgr);
//show connected devices and get deviceId
BSTR bstrDeviceID = SysAllocString(L"");
HRESULT hr2 = EnumerateWiaDevices(pWiaDevMgr, &bstrDeviceID);
//create device with device id
IWiaItem* ppWiaDevice;
HRESULT hr3 = CreateWiaDevice(pWiaDevMgr, bstrDeviceID, &ppWiaDevice);

//case IWiaItem to IWiaItemExtras
IWiaItemExtras* ppWiaExtra = (IWiaItemExtras*)ppWiaDevice;

//try to send data
DWORD dwEscapeCode = 256;
BYTE* lpInData = new unsigned char[37]{ 0x01, 0x92, 0x00 , 0x00 , 0x00, 0x00, 0x00 , 0x00 , 0x00 , 0x01 ,
    0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
    0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 ,
    0x00 ,   0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x00 }; 
DWORD cbInDataSize = sizeof(lpInData);

BYTE* pOutData = new unsigned char[4]{ 0x00 , 0x00,0x00, 0x00};
DWORD dwOutDataSize = sizeof(pOutData);

DWORD pdwActualDataSize = NULL;

BSTR bstre = SysAllocString(L"");
//just to test if ppWiaExtra is working
HRESULT hr6 = ppWiaExtra->GetExtendedErrorInfo(&bstre); //works
//try to send data with Escape Method
//see https://docs.microsoft.com/en-us/windows/win32/api/wia_xp/nf-wia_xp-iwiaitemextras-escape
HRESULT hr5 = ppWiaExtra->Escape(dwEscapeCode, lpInData, cbInDataSize, pOutData, dwOutDataSize, &pdwActualDataSize); //Run-Time Check Failure #0

Методы, которые я использую, такие же, как в примере кода на https://github.com/microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/wia/wiassamp/wiassamp.cpp

Метод побега:

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Escape( 
        /* [in] */ DWORD dwEscapeCode,
        /* [size_is][in] */ __RPC__in_ecount_full(cbInDataSize) BYTE *lpInData,
        /* [in] */ DWORD cbInDataSize,
        /* [length_is][size_is][out] */ __RPC__out_ecount_part(dwOutDataSize, pdwActualDataSize ? *pdwActualDataSize : dwOutDataSize) BYTE *pOutData,
        /* [in] */ DWORD dwOutDataSize,
        /* [out] */ __RPC__out DWORD *pdwActualDataSize) = 0;

Итак, как я могу найти реальную проблему, почему отображается ошибка и как ее решить?

(Я использую WIA1, потому что WIA2 не находит устройство)

STDMETHODCALLTYPE 

определяется в winnt.h следующим образом:

#if defined(_WIN32) || defined(_MPPC_)

// Win32 doesn't support __export

#ifdef _68K_
#define STDMETHODCALLTYPE       __cdecl
#else
#define STDMETHODCALLTYPE       __stdcall
#endif
#define STDMETHODVCALLTYPE      __cdecl

#define STDAPICALLTYPE          __stdcall
#define STDAPIVCALLTYPE         __cdecl

#else

#define STDMETHODCALLTYPE       __export __stdcall
#define STDMETHODVCALLTYPE      __export __cdecl

#define STDAPICALLTYPE          __export __stdcall
#define STDAPIVCALLTYPE         __export __cdecl

#endif

ИЗМЕНИТЬ 1:

GetExtendedErrorInfo

теперь возвращает Not Implemented Error (но сейчас это не так важно для меня)

Большая проблема в том, что

ppWiaExtra->Escape

возвращает E_FAIL, и этот не указан, я думаю, что это снова какая-то проблема pointer или проблема с моим использованием sizeof


person kilian eller    schedule 27.02.2020    source источник
comment
Эта ошибка обычно возникает, если функция, которую вы вызываете, имеет соглашение о вызовах __stdcall, а ваш код использует соглашение __cdecl или наоборот. Где доказательства того, что функция, которую вы вызываете, может быть virtual?   -  person PaulMcKenzie    schedule 27.02.2020
comment
STDMETHODCALLTYPE определяется следующим образом (в winnt.h): '#ifdef 68K #define STDMETHODCALLTYPE __cdecl #else #define STDMETHODCALLTYPE __stdcall #endif #define STDMETHODVCALLTYPE __cdecl' и 'virtual' (весь код Escape Способ) я могу найти либо в wia_lh.h, либо в wia_xp.h (параметры точно такие же)   -  person kilian eller    schedule 27.02.2020


Ответы (1)


IWiaItemExtras* ppWiaExtra = (IWiaItemExtras*)ppWiaDevice;

Эта строка неверна; вы не можете просто указать указатели, чтобы получить разные COM-интерфейсы. Вот для чего нужен QueryInterface:

IWiaItemExtras* ppWiaExtra;
HRESULT result = ppWiaDevice->QueryInterface(IID_PPV_ARGS(&ppWiaExtra));
person smorgan    schedule 02.04.2020
comment
Спасибо, что исправил это - теперь я понимаю, что hr6 (GetExtendedErrorInfo) не реализован (не так важно для меня), но Escape возвращает E_FAIL - это неуказанная ошибка, возможно, какие-то проблемы с sizeof()? - person kilian eller; 03.04.2020
comment
Вы вообще не должны использовать sizeof. API запрашивает количество байтов в каждом аргументе (37 и 4 соответственно), а вместо этого вы передаете размер указателя в байтах. Я рекомендую потратить некоторое время на чтение примеров использования Win32 API в C++ в целом, чтобы узнать, как работают распространенные шаблоны. - person smorgan; 03.04.2020
comment
Ну, нет никакой полезной информации о WIA C++, которую я могу найти помимо информации на странице документов Microsoft. Это также не помогает при некоторых неизвестных сбоях — также довольно редко выполняются примеры, которые действительно работают и имеют открытый исходный код. - person kilian eller; 04.04.2020
comment
Я сказал, что использую Win32 API в C++ в целом; ни одна из проблем, с которыми вы сталкивались до сих пор, не была связана с WIA. И QueryInterface, и массив-как-указатель-плюс-длина — очень распространенные шаблоны в Win32. - person smorgan; 04.04.2020