Access user info at HKCU from TAPI Service Provider (TSP)

382 views Asked by At

I was trying to build a tsp. Now the problem is, I need to get some information (from HKCU where the user config is located ) about who is making the request.

Since the TSP runs in the context of the Telephony service, I cannot access is directly. My plan was to use the functionality of LINE_CREATEDIALOGINSTANCE to read this information exactly like the one described here and here.

The problem is again similar tho unrelated, the Telephony service + dialer is crashing with the following stack trace.

(1e4.e10): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
TSP_ATSPMod!TSPI_lineMakeCall+0x367:
000007fe`f25a53e7 48894828        **mov     qword ptr [rax+28h],rcx** ds:00000000`0000002d=????????????????
0:015> kP
Child-SP          RetAddr           Call Site
00000000`01dbebe0 000007fe`f49c65ca TSP_ATSPMod!TSPI_lineMakeCall(
            unsigned long dwRequestID = 0x103aa, 
            **struct HDRVLINE__ * hdLine = 0x00000000`00000005**, 
            struct HTAPICALL__ * htCall = 0x00000000`00010399, 
            struct HDRVCALL__ ** lphdCall = 0x00000000`00e85ee8, 
            wchar_t * lpszDestAddress = 0x00000000`00e85c80 "T444", 
            unsigned long dwCountryCode = 0, 
            struct linecallparams_tag * lpCallParams = 0x00000000`00e85df0)+0x367 [c:\freedomvoice_tsp\tsp_atspmod\tsp_atspmod.cpp @ 1714]
00000000`01dbec70 000007fe`f49db14c tapisrv+0x165ca
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\RPCRT4.dll - 
00000000`01dbed50 000007fe`fdd523d5 tapisrv!ServiceMain+0x4bb4
00000000`01dbed90 000007fe`fddfb68e RPCRT4!RpcBindingSetAuthInfoW+0xe5
00000000`01dbedf0 000007fe`fdd3ac40 RPCRT4!Ndr64AsyncServerCallAll+0x120e
00000000`01dbf3b0 000007fe`fdd450f4 RPCRT4!NdrServerCallAll+0x40
00000000`01dbf400 000007fe`fdd44f56 RPCRT4!NdrServerCall2+0x1d84
00000000`01dbf430 000007fe`fdd45679 RPCRT4!NdrServerCall2+0x1be6
00000000`01dbf550 000007fe`fdd4532d RPCRT4!NdrServerCall2+0x2309
00000000`01dbf630 000007fe`fdd62e7f RPCRT4!NdrServerCall2+0x1fbd
00000000`01dbf760 000007fe`fdd62a35 RPCRT4!RpcBindingCopy+0x5df
00000000`01dbf8a0 00000000`7739b68b RPCRT4!RpcBindingCopy+0x195
00000000`01dbf930 00000000`7739feff ntdll!TpSetTimer+0x39b
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\kernel32.dll - 
00000000`01dbf9c0 00000000`7727652d ntdll!RtlValidateHeap+0x4af
00000000`01dbfcc0 00000000`773ac521 kernel32!BaseThreadInitThunk+0xd
00000000`01dbfcf0 00000000`00000000 ntdll!RtlUserThreadStart+0x21

And, the registers at the time of crash,

0:015> r
rax=**0000000000000005** rbx=0000000000e85c90 rcx=0000000000010399
rdx=000007fef261f988 rsi=0000000000e85c40 rdi=0000000001dbec60
rip=000007fef25a53e7 rsp=0000000001dbebe0 rbp=00000000000103aa
 r8=0000000001dbe6c8  r9=00000000000103aa r10=0000000000000000
r11=0000000000000246 r12=0000000000e85d70 r13=0000000000000002
r14=0000000000e85c7c r15=0000000000e85ec0
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010200

And, the code fragment:

PDRVLINE pLine = (PDRVLINE) hdLine;

*lphdCall = (HDRVCALL)hdLine;

typedef TUISPICREATEDIALOGINSTANCEPARAMS PARAMS;

pLine->htCall = htCall; <========= ********OFFENDING CODE************

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"TSP_ATSPMod.tsp";
lParams->lpParams = lParams + 1;
lParams->dwSize = lLength;

lstrcpyW((LPWSTR)(lParams + 1), lpszDestAddress);
(*pLine->pfnEventProc)(pLine->htLine, 0, LINE_CREATEDIALOGINSTANCE, (DWORD)lParams, 0, 0);

It seems we cannot cast hdLine to PDRVLINE.

Any idea?

PS: Using Windows 7 x64 on VMWare.

2

There are 2 answers

0
Jimson James On BEST ANSWER

At last MSDN to the rescue: As per MSDN, the first parameter of the LINEEVENT call for this event needs to be an HPROVIDER. But if you look closely, MSDN says,

hProvider The ProviderHandle supplied to the service provider as a parameter to TSPI_providerEnumDevices.

So, you have to save the HPROVIDER hProvider passed to TSPI_providerEnumDevices first and use it here.

The working code is,

PDRVLINE pLine = (PDRVLINE) ghProvider;    
...
(pDI->lpfnEventProc)((HTAPILINE)ghProvider, 0, LINE_CREATEDIALOGINSTANCE, (DWORD)lParams, 0, 0);

Also make sure the method TUISPI_providerGenericDialog is exported correctly.

2
SpaghettiCook On

Have you had progress? I think I see now what you are trying to do. You want to send the LINE_CREATEDIALOGINSTANCE in response to a TSPI_lineMakeCall command in order to find out which user is requesting the makecall. Is that correct?

If so, I think you should still handle one problem at the time. If you could momentarily assume the user info and process the makecall request you would still have to solve the invalid typecast first. In order to solve this look at what you will the linehandle with at the TSPI_lineOpen code. In the MakeCall function you only get back what you provided the Telephony Service with in the third parameter of the TSPI_lineOpen

Parameters

dwDeviceID Identifies the line device to be opened.

htLine The TAPI handle for the line device to be used in subsequent calls to the LINEEVENT callback procedure to identify the device.

lphdLine A pointer to an HDRVLINE where the service provider fills in its handle for the line device.

dwTSPIVersion The TSPI version. lpfnEventProc A pointer to the LINEEVENT callback procedure supplied by TAPI that the service provider calls to report subsequent events on the line.

If that works correctly please look at the string pointer you put in the lParams struct. Is that scope correct? I would create a static string and point the variable to that like this

static WCHAR szUIDLLName[] = L"TSP_ATSPMod.tsp";
lParams->lpszUIDLLName = szUIDLLName;

Third and finally, I am confused about how you call the callback function. According to the LINE_CREATEDIALOGINSTANCE documentation you are correct. However if you look at the Line_Event callback function the last three params should really be DWORD_PTR which make sense if you want to compile for 64 bit.

This all is really more comment than answer. Please let me know if any of it makes sense. This solution to the differing context process of the user and the TSP is new to me and I would love to make it work for you because I will probably be wanting to use it to some day.