Доступ к HKCU от поставщика услуг TAPI
Я пишу адаптер TSP для телефонной системы. Эта система имеет TAPI API, но она несовместима с приложением, которое я пытаюсь включить TAPI. Чтобы позвонить с правильной линии, мне нужно знать некоторую информацию (из HKCU) о том, кто делает запрос. Поскольку TSP работает в контексте службы телефонии, я не могу получить доступ напрямую. Я планировал использовать функциональность LINE_CREATEDIALOGINSTANCE, чтобы прочитать эту информацию.
Проблема, с которой я столкнулся, заключается в том, что служба телефонии дает сбой сразу после возврата из TUISPI_providerGenericDialog со следующей трассировкой стека:
72004400()
tapisrv.dll!_FreeDialogInstance@20() + 0xa93 bytes
tapisrv.dll!_ClientRequest@16() + 0x8f bytes
rpcrt4.dll!_Invoke@12() + 0x30 bytes
rpcrt4.dll!_NdrStubCall2@16() + 0x217 bytes
rpcrt4.dll!_NdrServerCall2@4() + 0x19 bytes
rpcrt4.dll!_DispatchToStubInCNoAvrf@12() + 0x17 bytes
rpcrt4.dll!RPC_INTERFACE::DispatchToStubWorker() + 0xae bytes
rpcrt4.dll!RPC_INTERFACE::DispatchToStub() + 0x4b bytes
rpcrt4.dll!LRPC_SCALL::DealWithRequestMessage() + 0x1d5 bytes
rpcrt4.dll!LRPC_ADDRESS::DealWithLRPCRequest() + 0x90 bytes
rpcrt4.dll!LRPC_ADDRESS::ReceiveLotsaCalls() + 0x20c bytes
rpcrt4.dll!RecvLotsaCallsWrapper() + 0xd bytes
rpcrt4.dll!BaseCachedThreadRoutine() + 0x92 bytes
rpcrt4.dll!ThreadStartRoutine() + 0x1b bytes
kernel32.dll!_BaseThreadStart@8() + 0x34 bytes
Согласно этой книге, служба телефонии будет аварийно завершать работу, если TSPI_providerFreeDialogInstance не реализован. Я реализовал эту функцию, и DepWalker показывает, что она правильно экспортируется. ApiSpy32 показывает, что его адрес корректно возвращается через GetProcAddress при загрузке моего TSP. Почему это все еще терпит крах?
Соответствующий код:
LONG TSPIAPI TSPI_lineMakeCall(DRV_REQUESTID dwRequestID, HDRVLINE hdLine, HTAPICALL htCall,
LPHDRVCALL lphdCall, LPCWSTR lpszDestAddress, DWORD dwCountryCode, LPLINECALLPARAMS const lpCallParams)
{
OutputDebugString("TSPI_lineMakeCall\n");
PDRVLINE pLine = (PDRVLINE) hdLine;
*lphdCall = (HDRVCALL)hdLine;
typedef TUISPICREATEDIALOGINSTANCEPARAMS PARAMS;
pLine->htCall = htCall;
DWORD lLength = (lstrlenW(lpszDestAddress) + 1) * sizeof(WCHAR);
PARAMS* lParams = (PARAMS*)DrvAlloc(sizeof(PARAMS) + lLength);
RtlZeroMemory(lParams, sizeof(PARAMS) + lLength);
lParams->dwRequestID = dwRequestID;
lParams->hdDlgInst = (HDRVDIALOGINSTANCE)1000;
lParams->lpszUIDLLName = L"TapiAdapter.tsp";
lParams->lpParams = lParams + 1;
lParams->dwSize = lLength;
lstrcpyW((LPWSTR)(lParams + 1), lpszDestAddress);
(*pLine->pfnEventProc)(pLine->htLine, 0, LINE_CREATEDIALOGINSTANCE, (DWORD)lParams, 0, 0);
return dwRequestID;
}
LONG TSPIAPI TSPI_providerGenericDialogData(DWORD_PTR dwObjectID, DWORD dwObjectType, LPVOID lpParams, DWORD dwSize)
{
OutputDebugString("TSPI_providerGenericDialogData\n");
return 0;
}
LONG TSPIAPI TSPI_providerFreeDialogInstance(HDRVDIALOGINSTANCE hdDlgInst)
{
OutputDebugString("TSPI_providerFreeDialogInstance\n");
return 0;
}
LONG TSPIAPI TUISPI_providerGenericDialog(TUISPIDLLCALLBACK lpfnUIDLLCallback, HTAPIDIALOGINSTANCE htDlgInst, LPVOID lpParams, DWORD dwSize, HANDLE hEvent)
{
SetEvent(hEvent);
LPCWSTR lNumber = (LPCWSTR)lpParams;
MessageBoxW(0, lNumber, L"Dial Number", MB_OK);
return 0;
}
2 ответа
Я нашел решение: согласно MSDN, первым параметром вызова LINEEVENT для этого события должен быть только HPROVIDER, а не HTAPILINE. Поскольку первый параметр LINEEVENT имеет тип HTAPILINE, HPROVIDER необходимо будет привести.
Я не знаю, но помощь для структуры TUISPICREATEDIALOGINSTANCEPARAMS говорит, что lpszUIDLLName
должен быть...
указатель на строку с нулевым символом в конце, указывающую полное имя DLL пользовательского интерфейса для загрузки в контексте приложения
... тем не мение L"TapiAdapter.tsp"
не похоже на полное имя библиотеки UI DLL ("полностью определенное" означает, что оно включает имя пути). У вас есть UI DLL для загрузки? Это загружено? Отображает ли это диалог? Это выгружено? Есть ли TUISPI_providerGenericDialog
существует в вашем TSP, или он существует в вашей UI DLL (они должны быть двумя разными DLL)?