summaryrefslogtreecommitdiffstats
path: root/private/tapi/dev/sp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/tapi/dev/sp/atsp32/atsp.c2630
-rw-r--r--private/tapi/dev/sp/atsp32/atsp.h204
-rw-r--r--private/tapi/dev/sp/atsp32/atsp.rc45
-rw-r--r--private/tapi/dev/sp/atsp32/atsp32.def42
-rw-r--r--private/tapi/dev/sp/atsp32/depend.mk3
-rw-r--r--private/tapi/dev/sp/atsp32/dialogs.dlg22
-rw-r--r--private/tapi/dev/sp/atsp32/makefile29
-rw-r--r--private/tapi/dev/sp/atsp32/makefile.def67
-rw-r--r--private/tapi/dev/sp/atsp32/resource.h7
-rw-r--r--private/tapi/dev/sp/atsp32/sources54
-rw-r--r--private/tapi/dev/sp/dirs26
-rw-r--r--private/tapi/dev/sp/esp.new/dirs26
-rw-r--r--private/tapi/dev/sp/esp.new/espidl.acf5
-rw-r--r--private/tapi/dev/sp/esp.new/espidl.idl66
-rw-r--r--private/tapi/dev/sp/esp.new/exe/esp.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/esp.new/exe/espexe.c3351
-rw-r--r--private/tapi/dev/sp/esp.new/exe/espexe.def13
-rw-r--r--private/tapi/dev/sp/esp.new/exe/espexe.h410
-rw-r--r--private/tapi/dev/sp/esp.new/exe/espexe.rc251
-rw-r--r--private/tapi/dev/sp/esp.new/exe/makefile11
-rw-r--r--private/tapi/dev/sp/esp.new/exe/resource.h67
-rw-r--r--private/tapi/dev/sp/esp.new/exe/sources58
-rw-r--r--private/tapi/dev/sp/esp.new/makefil071
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/devspec.h200
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/esp.c11878
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/esp.h653
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/esp.rc38
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/esp32.def113
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/intrface.h67
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/line.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/makefile11
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/phone.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/sources60
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/vars.c445
-rw-r--r--private/tapi/dev/sp/esp.new/tsp/vars.h76
-rw-r--r--private/tapi/dev/sp/esp.new/ui/espui.c788
-rw-r--r--private/tapi/dev/sp/esp.new/ui/espui.def16
-rw-r--r--private/tapi/dev/sp/esp.new/ui/espui.rc32
-rw-r--r--private/tapi/dev/sp/esp.new/ui/makefile11
-rw-r--r--private/tapi/dev/sp/esp.new/ui/sources56
-rw-r--r--private/tapi/dev/sp/esp/esp.c9641
-rw-r--r--private/tapi/dev/sp/esp/esp.def117
-rw-r--r--private/tapi/dev/sp/esp/esp.h631
-rw-r--r--private/tapi/dev/sp/esp/esp.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/esp/esp.rc224
-rw-r--r--private/tapi/dev/sp/esp/esp32.def117
-rw-r--r--private/tapi/dev/sp/esp/espexe.c67
-rw-r--r--private/tapi/dev/sp/esp/espexe.def6
-rw-r--r--private/tapi/dev/sp/esp/espexe.rc57
-rw-r--r--private/tapi/dev/sp/esp/line.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/esp/makefile29
-rw-r--r--private/tapi/dev/sp/esp/makefile.def46
-rw-r--r--private/tapi/dev/sp/esp/phone.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/esp/resource.h60
-rw-r--r--private/tapi/dev/sp/esp/sources58
-rw-r--r--private/tapi/dev/sp/esp/vars.c605
-rw-r--r--private/tapi/dev/sp/esp/vars.h95
-rw-r--r--private/tapi/dev/sp/esp/widget.c885
-rw-r--r--private/tapi/dev/sp/esp/win31.mak60
-rw-r--r--private/tapi/dev/sp/hmtsp/depend.mk3
-rw-r--r--private/tapi/dev/sp/hmtsp/hmtsp.c1160
-rw-r--r--private/tapi/dev/sp/hmtsp/hmtsp.def36
-rw-r--r--private/tapi/dev/sp/hmtsp/hmtsp.h50
-rw-r--r--private/tapi/dev/sp/hmtsp/hmtsp.rc47
-rw-r--r--private/tapi/dev/sp/hmtsp/hmtsprc.h18
-rw-r--r--private/tapi/dev/sp/hmtsp/makefile29
-rw-r--r--private/tapi/dev/sp/hmtsp/makefile.def64
-rw-r--r--private/tapi/dev/sp/hmtsp/makefile.old96
-rw-r--r--private/tapi/dev/sp/hmtsp/sources58
-rw-r--r--private/tapi/dev/sp/kmddsp/kmddsp.c4792
-rw-r--r--private/tapi/dev/sp/kmddsp/kmddsp.def107
-rw-r--r--private/tapi/dev/sp/kmddsp/kmddsp.h152
-rw-r--r--private/tapi/dev/sp/kmddsp/kmddsp.rc17
-rw-r--r--private/tapi/dev/sp/kmddsp/makefile6
-rw-r--r--private/tapi/dev/sp/kmddsp/sources53
-rw-r--r--private/tapi/dev/sp/kmesp/dirs25
-rw-r--r--private/tapi/dev/sp/kmesp/exe/kmesp.c1927
-rw-r--r--private/tapi/dev/sp/kmesp/exe/kmesp.def11
-rw-r--r--private/tapi/dev/sp/kmesp/exe/kmesp.h246
-rw-r--r--private/tapi/dev/sp/kmesp/exe/kmesp.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/kmesp/exe/kmesp.rc164
-rw-r--r--private/tapi/dev/sp/kmesp/exe/makefile6
-rw-r--r--private/tapi/dev/sp/kmesp/exe/resource.h49
-rw-r--r--private/tapi/dev/sp/kmesp/exe/sources48
-rw-r--r--private/tapi/dev/sp/kmesp/sys/intrface.h138
-rw-r--r--private/tapi/dev/sp/kmesp/sys/makefile7
-rw-r--r--private/tapi/dev/sp/kmesp/sys/sources34
-rw-r--r--private/tapi/dev/sp/kmesp/sys/stubmp.c1465
-rw-r--r--private/tapi/dev/sp/kmesp/sys/stubmp.h109
-rw-r--r--private/tapi/dev/sp/kmesp/sys/stubmp.ini4
-rw-r--r--private/tapi/dev/sp/kmesp/sys/stubmp.src2
-rw-r--r--private/tapi/dev/sp/makefile27
-rw-r--r--private/tapi/dev/sp/pdisp32/makefile6
-rw-r--r--private/tapi/dev/sp/pdisp32/pdisp.c1594
-rw-r--r--private/tapi/dev/sp/pdisp32/pdisp.h62
-rw-r--r--private/tapi/dev/sp/pdisp32/pdisp.rc45
-rw-r--r--private/tapi/dev/sp/pdisp32/pdisp32.def31
-rw-r--r--private/tapi/dev/sp/pdisp32/pdisprc.h18
-rw-r--r--private/tapi/dev/sp/pdisp32/sources54
-rw-r--r--private/tapi/dev/sp/remotesp/dialogs.dlg16
-rw-r--r--private/tapi/dev/sp/remotesp/line.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/remotesp/makefile29
-rw-r--r--private/tapi/dev/sp/remotesp/makefile.def77
-rw-r--r--private/tapi/dev/sp/remotesp/phone.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/remotesp/remotesp.c7677
-rw-r--r--private/tapi/dev/sp/remotesp/remotesp.def126
-rw-r--r--private/tapi/dev/sp/remotesp/remotesp.h388
-rw-r--r--private/tapi/dev/sp/remotesp/remotesp.icobin0 -> 766 bytes
-rw-r--r--private/tapi/dev/sp/remotesp/remotesp.rc23
-rw-r--r--private/tapi/dev/sp/remotesp/resource.h7
-rw-r--r--private/tapi/dev/sp/remotesp/sources58
-rw-r--r--private/tapi/dev/sp/repeater/app/makefile29
-rw-r--r--private/tapi/dev/sp/repeater/app/repapp.c1093
-rw-r--r--private/tapi/dev/sp/repeater/app/repapp.rc37
-rw-r--r--private/tapi/dev/sp/repeater/app/resource.h22
-rw-r--r--private/tapi/dev/sp/repeater/app/sources56
-rw-r--r--private/tapi/dev/sp/repeater/dirs4
-rw-r--r--private/tapi/dev/sp/repeater/new/debug.c180
-rw-r--r--private/tapi/dev/sp/repeater/new/debug.h25
-rw-r--r--private/tapi/dev/sp/repeater/new/depend.mk7
-rw-r--r--private/tapi/dev/sp/repeater/new/logger.c945
-rw-r--r--private/tapi/dev/sp/repeater/new/logger.h317
-rw-r--r--private/tapi/dev/sp/repeater/new/makefile29
-rw-r--r--private/tapi/dev/sp/repeater/new/makefile.def51
-rw-r--r--private/tapi/dev/sp/repeater/new/rep16.def122
-rw-r--r--private/tapi/dev/sp/repeater/new/rep16.mak80
-rw-r--r--private/tapi/dev/sp/repeater/new/repeater.c6251
-rw-r--r--private/tapi/dev/sp/repeater/new/repeater.def122
-rw-r--r--private/tapi/dev/sp/repeater/new/repeater.h177
-rw-r--r--private/tapi/dev/sp/repeater/new/repeater.rc19
-rw-r--r--private/tapi/dev/sp/repeater/new/repeater.txt87
-rw-r--r--private/tapi/dev/sp/repeater/new/sources53
-rw-r--r--private/tapi/dev/sp/repeater/new/tsp3216.h10
-rw-r--r--private/tapi/dev/sp/repeater/setup/makefile29
-rw-r--r--private/tapi/dev/sp/repeater/setup/resource.h22
-rw-r--r--private/tapi/dev/sp/repeater/setup/setup.cpp779
-rw-r--r--private/tapi/dev/sp/repeater/setup/setup.rc46
-rw-r--r--private/tapi/dev/sp/repeater/setup/sources55
-rw-r--r--private/tapi/dev/sp/tsp1632/makefile25
-rw-r--r--private/tapi/dev/sp/tsp1632/script/makefile16
-rw-r--r--private/tapi/dev/sp/tsp1632/script/subthk.mk49
-rw-r--r--private/tapi/dev/sp/tsp1632/script/tapi32.inc11
-rw-r--r--private/tapi/dev/sp/tsp1632/script/tapi32.thk31
-rw-r--r--private/tapi/dev/sp/tsp1632/script/tapicbid.inc17
-rw-r--r--private/tapi/dev/sp/tsp1632/script/tapifthk.inc1
-rw-r--r--private/tapi/dev/sp/tsp1632/script/tapifthk.thk587
-rw-r--r--private/tapi/dev/sp/tsp1632/script/tapithk.inc1234
-rw-r--r--private/tapi/dev/sp/tsp1632/script/tapithk.thk309
-rw-r--r--private/tapi/dev/sp/tsp1632/script/types.thk102
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/debug.c174
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/debug.h25
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/depend.mk9
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/makefile29
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/makefile.def50
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.c2369
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.def125
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.h53
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632s/depend.mk9
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632s/makefile29
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632s/makefile.def51
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632s/tpiint32.asm844
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.def125
-rw-r--r--private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.rc24
-rw-r--r--private/tapi/dev/sp/tsp3216/dirs25
-rw-r--r--private/tapi/dev/sp/tsp3216/makefile25
-rw-r--r--private/tapi/dev/sp/tsp3216/script/debug/makefile3
-rw-r--r--private/tapi/dev/sp/tsp3216/script/makefile14
-rw-r--r--private/tapi/dev/sp/tsp3216/script/retail/makefile3
-rw-r--r--private/tapi/dev/sp/tsp3216/script/subthk.mk52
-rw-r--r--private/tapi/dev/sp/tsp3216/script/tapi32.inc11
-rw-r--r--private/tapi/dev/sp/tsp3216/script/tapi32.thk76
-rw-r--r--private/tapi/dev/sp/tsp3216/script/tapicbid.inc17
-rw-r--r--private/tapi/dev/sp/tsp3216/script/tapifthk.inc1
-rw-r--r--private/tapi/dev/sp/tsp3216/script/tapifthk.thk563
-rw-r--r--private/tapi/dev/sp/tsp3216/script/tapithk.inc1234
-rw-r--r--private/tapi/dev/sp/tsp3216/script/tapithk.thk288
-rw-r--r--private/tapi/dev/sp/tsp3216/script/types.thk102
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/debug.c135
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/debug.h25
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/depend.mk11
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/makefile29
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/makefile.def56
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/sources47
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/tpiint32.old760
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.c1282
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.def130
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.h49
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.mak177
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.rc24
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/debug.c176
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/debug.h25
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/depend.mk11
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/makefile29
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/makefile.def49
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216.h10
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.c3659
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.def132
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.h55
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.mak89
-rw-r--r--private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.rc19
200 files changed, 82099 insertions, 0 deletions
diff --git a/private/tapi/dev/sp/atsp32/atsp.c b/private/tapi/dev/sp/atsp32/atsp.c
new file mode 100644
index 000000000..0141d18fc
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/atsp.c
@@ -0,0 +1,2630 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ atsp.c
+
+Notes:
+
+--*/
+
+
+#include "atsp.h"
+
+
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ ghInst = hDLL;
+
+#if DBG
+ {
+ HKEY hKey;
+ DWORD dwDataSize, dwDataType;
+ char szAtsp32DebugLevel[] = "Atsp32DebugLevel";
+
+
+ RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ gszAtspKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof (DWORD);
+ gdwDebugLevel=0;
+
+ RegQueryValueEx(
+ hKey,
+ szAtsp32DebugLevel,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwDebugLevel,
+ &dwDataSize
+ );
+
+ RegCloseKey (hKey);
+ }
+#endif
+
+ }
+
+ return TRUE;
+}
+
+
+void
+CommThread(
+ PDRVLINE pLine
+ )
+{
+ char buf[4];
+ DWORD dwThreadID = GetCurrentThreadId(), dwNumBytes;
+ HANDLE hComm = pLine->hComm, hEvent;
+ LPOVERLAPPED pOverlapped = &pLine->Overlapped;
+
+
+ DBGOUT((
+ 3,
+ "CommThread (id=%d): enter, port=%s",
+ dwThreadID,
+ pLine->szComm
+ ));
+
+ hEvent = pOverlapped->hEvent;
+ buf[0] = buf[1] = '.';
+
+
+ //
+ // Loop waiting for i/o to complete (either the Write done in
+ // TSPI_lineMakeCall or the Reads done to retrieve status info).
+ // Note that TSPI_lineDrop or TSPI_lineCloseCall may set the
+ // event to alert us that they're tearing down the call, in
+ // which case we just exit.
+ //
+
+ for (;;)
+ {
+ if (WaitForSingleObject (hEvent, ATSP_TIMEOUT) == WAIT_OBJECT_0)
+ {
+ if (pLine->bDropInProgress == TRUE)
+ {
+ DBGOUT((2, "CommThread (id=%d): drop in progress"));
+ goto CommThread_exit;
+ }
+
+ GetOverlappedResult (hComm, pOverlapped, &dwNumBytes, FALSE);
+ ResetEvent (hEvent);
+ }
+ else
+ {
+ DBGOUT((2, "CommThread (id=%d): wait timeout"));
+ SetCallState (pLine, LINECALLSTATE_IDLE, 0);
+ goto CommThread_exit;
+ }
+
+ buf[1] &= 0x7f; // nuke the parity bit
+
+ DBGOUT((
+ 3,
+ "CommThread (id=%d): read '%c'",
+ dwThreadID,
+ (buf[1] == '\r' ? '.' : buf[1])
+ ));
+
+ switch ((buf[0] << 8) + buf[1])
+ {
+ case 'CT': // "CONNECT"
+ case 'OK': // "OK"
+
+ SetCallState (pLine, LINECALLSTATE_CONNECTED, 0);
+ goto CommThread_exit;
+
+ case 'SY': // "BUSY"
+ case 'OR': // "ERROR"
+ case 'NO': // "NO ANSWER", "NO DIALTONE", "NO CARRIER"
+
+ SetCallState (pLine, LINECALLSTATE_IDLE, 0);
+ goto CommThread_exit;
+
+ default:
+
+ break;
+ }
+
+ buf[0] = buf[1];
+
+ ZeroMemory (pOverlapped, sizeof (OVERLAPPED) - sizeof (HANDLE));
+ ReadFile (hComm, &buf[1], 1, &dwNumBytes, pOverlapped);
+ }
+
+CommThread_exit:
+
+ CloseHandle (hEvent);
+ DBGOUT((3, "CommThread (id=%d): exit", dwThreadID));
+ ExitThread (0);
+}
+
+
+//
+// We get a slough of C4047 (different levels of indrection) warnings down
+// below in the initialization of FUNC_PARAM structs as a result of the
+// real func prototypes having params that are types other than DWORDs,
+// so since these are known non-interesting warnings just turn them off
+//
+
+#pragma warning (disable:4047)
+
+
+//
+// --------------------------- TAPI_lineXxx funcs -----------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+{
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdLine, hdLine }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineClose",
+ 1,
+ params,
+ };
+#endif
+
+ Prolog (&info);
+ DrvFree ((PDRVLINE) hdLine);
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+{
+ PDRVLINE pLine = (PDRVLINE) hdCall;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdCall, hdCall }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineCloseCall",
+ 1,
+ params
+ };
+#endif
+
+
+ //
+ // Note that in TAPI 2.0 TSPI_lineCloseCall can get called
+ // without TSPI_lineDrop ever being called, so we need to
+ // be prepared for either case.
+ //
+
+ Prolog (&info);
+ DropActiveCall (pLine);
+ pLine->htCall = NULL;
+ return (Epilog (&info, 0));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdLine, hdLine },
+ { "dwMediaModes", dwMediaModes },
+ { gszlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineConditionalMediaDetection",
+ 3,
+ params
+ };
+#endif
+
+
+ //
+ // This func is really a no-op for us, since we don't look
+ // for incoming calls (though we do say we support them to
+ // make apps happy)
+ //
+
+ Prolog (&info);
+ return (Epilog (&info, 0));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ PDRVLINE pLine = (PDRVLINE) hdCall;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszdwRequestID, dwRequestID },
+ { gszhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { gszdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineDrop",
+ 4,
+ params
+ };
+#endif
+
+
+ Prolog (&info);
+ DropActiveCall (pLine);
+ SetCallState (pLine, LINECALLSTATE_IDLE, 0);
+ (*gpfnCompletionProc)(dwRequestID, 0);
+ return (Epilog (&info, dwRequestID));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+{
+
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszdwDeviceID, dwDeviceID },
+ { "dwAddressID", dwAddressID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpAddressCaps", lpAddressCaps }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetAddressCaps",
+ 5,
+ params
+ };
+#endif
+
+ LONG lResult = 0;
+
+
+ Prolog (&info);
+
+ if (dwAddressID != 0)
+ {
+ lResult = LINEERR_INVALADDRESSID;
+ }
+
+ lpAddressCaps->dwNeededSize =
+ lpAddressCaps->dwUsedSize = sizeof(LINEADDRESSCAPS);
+
+ lpAddressCaps->dwLineDeviceID = dwDeviceID;
+ lpAddressCaps->dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
+ lpAddressCaps->dwCallInfoStates = LINECALLINFOSTATE_MEDIAMODE |
+ LINECALLINFOSTATE_APPSPECIFIC;
+ lpAddressCaps->dwCallerIDFlags =
+ lpAddressCaps->dwCalledIDFlags =
+ lpAddressCaps->dwRedirectionIDFlags =
+ lpAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwCallStates = LINECALLSTATE_IDLE |
+ LINECALLSTATE_OFFERING |
+ LINECALLSTATE_ACCEPTED |
+ LINECALLSTATE_DIALTONE |
+ LINECALLSTATE_DIALING |
+ LINECALLSTATE_CONNECTED |
+ LINECALLSTATE_PROCEEDING |
+ LINECALLSTATE_DISCONNECTED |
+ LINECALLSTATE_UNKNOWN;
+ lpAddressCaps->dwDialToneModes = LINEDIALTONEMODE_UNAVAIL;
+ lpAddressCaps->dwBusyModes = LINEBUSYMODE_UNAVAIL;
+ lpAddressCaps->dwSpecialInfo = LINESPECIALINFO_UNAVAIL;
+ lpAddressCaps->dwDisconnectModes = LINEDISCONNECTMODE_NORMAL |
+ LINEDISCONNECTMODE_BUSY |
+ LINEDISCONNECTMODE_NOANSWER |
+ LINEDISCONNECTMODE_UNAVAIL |
+ LINEDISCONNECTMODE_NODIALTONE;
+ lpAddressCaps->dwMaxNumActiveCalls = 1;
+ lpAddressCaps->dwAddrCapFlags = LINEADDRCAPFLAGS_DIALED;
+ lpAddressCaps->dwCallFeatures = LINECALLFEATURE_ACCEPT |
+ LINECALLFEATURE_ANSWER |
+ LINECALLFEATURE_DROP |
+ LINECALLFEATURE_SETCALLPARAMS;
+ lpAddressCaps->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { "lpAddressStatus", lpAddressStatus }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetAddressStatus",
+ 3,
+ params
+ };
+#endif
+
+ LONG lResult = 0;
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ Prolog (&info);
+
+ lpAddressStatus->dwNeededSize =
+ lpAddressStatus->dwUsedSize = sizeof(LINEADDRESSSTATUS);
+
+ lpAddressStatus->dwNumActiveCalls = (pLine->htCall ? 1 : 0);
+ lpAddressStatus->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdCall, hdCall },
+ { "lpdwAddressID", lpdwAddressID }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetCallAddressID",
+ 2,
+ params
+ };
+#endif
+
+
+ //
+ // We only support 1 address (id=0)
+ //
+
+ Prolog (&info);
+ *lpdwAddressID = 0;
+ return (Epilog (&info, 0));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpLineInfo
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdCall, hdCall },
+ { "lpLineInfo", lpLineInfo }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetCallInfo",
+ 2,
+ params
+ };
+#endif
+ LONG lResult = 0;
+ PDRVLINE pLine = (PDRVLINE) hdCall;
+
+
+ Prolog (&info);
+
+ lpLineInfo->dwNeededSize =
+ lpLineInfo->dwUsedSize = sizeof(LINECALLINFO);
+
+ lpLineInfo->dwBearerMode = LINEBEARERMODE_VOICE;
+ lpLineInfo->dwMediaMode = pLine->dwMediaMode;
+ lpLineInfo->dwCallStates = LINECALLSTATE_IDLE |
+ LINECALLSTATE_DIALTONE |
+ LINECALLSTATE_DIALING |
+ LINECALLSTATE_CONNECTED |
+ LINECALLSTATE_PROCEEDING |
+ LINECALLSTATE_DISCONNECTED |
+ LINECALLSTATE_UNKNOWN;
+ lpLineInfo->dwOrigin = LINECALLORIGIN_OUTBOUND;
+ lpLineInfo->dwReason = LINECALLREASON_DIRECT;
+ lpLineInfo->dwCallerIDFlags =
+ lpLineInfo->dwCalledIDFlags =
+ lpLineInfo->dwConnectedIDFlags =
+ lpLineInfo->dwRedirectionIDFlags =
+ lpLineInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpLineStatus
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdCall, hdCall },
+ { "lpLineStatus", lpLineStatus }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetCallStatus",
+ 2,
+ params
+ };
+#endif
+ LONG lResult = 0;
+ PDRVLINE pLine = (PDRVLINE) hdCall;
+
+
+ Prolog (&info);
+
+ lpLineStatus->dwNeededSize =
+ lpLineStatus->dwUsedSize = sizeof(LINECALLSTATUS);
+
+ lpLineStatus->dwCallState = pLine->dwCallState;
+
+ if (pLine->dwCallState != LINECALLSTATE_IDLE)
+ {
+ lpLineStatus->dwCallFeatures = LINECALLFEATURE_DROP;
+ }
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpLineDevCaps", lpLineDevCaps }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetDevCaps",
+ 4,
+ params
+ };
+#endif
+
+ LONG lResult = 0;
+ static WCHAR szProviderInfo[] = L"AT-compatible modem service provider";
+
+ #define PROVIDER_INFO_SIZE (37 * sizeof (WCHAR))
+
+ Prolog (&info);
+
+ lpLineDevCaps->dwNeededSize = sizeof (LINEDEVCAPS) + PROVIDER_INFO_SIZE +
+ (MAX_DEV_NAME_LENGTH + 1) * sizeof (WCHAR);
+
+ if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwNeededSize)
+ {
+ #define LINECONFIG_SIZE (2 * (MAX_DEV_NAME_LENGTH + 1) + 40)
+
+ char szLineConfig[LINECONFIG_SIZE], szLineN[16], *p;
+ HKEY hKey;
+ DWORD dwDataSize, dwDataType;
+
+
+ lpLineDevCaps->dwUsedSize = lpLineDevCaps->dwNeededSize;
+
+ lpLineDevCaps->dwProviderInfoSize = PROVIDER_INFO_SIZE;
+ lpLineDevCaps->dwProviderInfoOffset = sizeof(LINEDEVCAPS);
+
+ lstrcpyW ((WCHAR *)(lpLineDevCaps + 1), szProviderInfo);
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszAtspKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = LINECONFIG_SIZE;
+ wsprintf (szLineN, "Line%d", dwDeviceID - gdwLineDeviceIDBase);
+ lstrcpy (szLineConfig, gszDefLineConfigParams);
+
+ RegQueryValueEx(
+ hKey,
+ szLineN,
+ 0,
+ &dwDataType,
+ (LPBYTE) szLineConfig,
+ &dwDataSize
+ );
+
+ RegCloseKey (hKey);
+
+ for (p = szLineConfig; *p != ','; p++);
+ *p = 0;
+
+ lpLineDevCaps->dwLineNameSize = (lstrlen (szLineConfig) + 1) *
+ sizeof (WCHAR);
+ lpLineDevCaps->dwLineNameOffset = sizeof(LINEDEVCAPS) +
+ PROVIDER_INFO_SIZE;
+
+ MultiByteToWideChar(
+ CP_ACP,
+ MB_PRECOMPOSED,
+ szLineConfig,
+ -1,
+ (WCHAR *) ((LPBYTE) (lpLineDevCaps + 1) + PROVIDER_INFO_SIZE),
+ lpLineDevCaps->dwLineNameSize
+ );
+ }
+ else
+ {
+ lpLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS);
+ }
+
+ lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII;
+ lpLineDevCaps->dwAddressModes = LINEADDRESSMODE_ADDRESSID;
+ lpLineDevCaps->dwNumAddresses = 1;
+ lpLineDevCaps->dwBearerModes = LINEBEARERMODE_VOICE;
+ lpLineDevCaps->dwMaxRate = 9600;
+ lpLineDevCaps->dwMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE |
+ LINEMEDIAMODE_DATAMODEM;
+ lpLineDevCaps->dwDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP |
+ LINEDEVCAPFLAGS_DIALBILLING |
+ LINEDEVCAPFLAGS_DIALQUIET |
+ LINEDEVCAPFLAGS_DIALDIALTONE;
+ lpLineDevCaps->dwMaxNumActiveCalls = 1;
+ lpLineDevCaps->dwRingModes = 1;
+ lpLineDevCaps->dwLineFeatures = LINEFEATURE_MAKECALL;
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { gszhdCall, hdCall },
+ { "dwSelect", dwSelect },
+ { "lpDeviceID", lpDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass },
+ { "hTargetProcess", hTargetProcess }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetID",
+ 7,
+ params
+ };
+#endif
+
+ DWORD dwNeededSize = sizeof(VARSTRING) + sizeof (DWORD);
+ LONG lResult = 0;
+ PDRVLINE pLine = (dwSelect == LINECALLSELECT_CALL ?
+ (PDRVLINE) hdCall : (PDRVLINE) hdLine);
+
+
+ Prolog (&info);
+
+ if (lstrcmpiW (lpszDeviceClass, L"tapi/line") == 0)
+ {
+ if (lpDeviceID->dwTotalSize < dwNeededSize)
+ {
+ lpDeviceID->dwUsedSize = 3*sizeof(DWORD);
+ }
+ else
+ {
+ lpDeviceID->dwUsedSize = dwNeededSize;
+
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof(DWORD);
+ lpDeviceID->dwStringOffset = sizeof(VARSTRING);
+
+ *((LPDWORD)(lpDeviceID + 1)) = pLine->dwDeviceID;
+ }
+
+ lpDeviceID->dwNeededSize = dwNeededSize;
+ }
+ else if (lstrcmpiW (lpszDeviceClass, L"comm/datamodem") == 0)
+ {
+ dwNeededSize += (strlen (pLine->szComm) + 1) * sizeof (WCHAR);
+
+ if (lpDeviceID->dwTotalSize < dwNeededSize)
+ {
+ lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
+ }
+ else
+ {
+ HANDLE hCommDup = NULL;
+
+
+ if (!pLine->htCall)
+ {
+ DBGOUT((1, "TSPI_lineGetID32: error, no active call"));
+
+ lResult = LINEERR_OPERATIONFAILED;
+
+ goto TSPI_lineGetID_epilog;
+ }
+
+ if (!DuplicateHandle(
+ GetCurrentProcess(),
+ pLine->hComm,
+ hTargetProcess,
+ &hCommDup,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS
+ ))
+ {
+ DBGOUT((
+ 1,
+ "TSPI_lineGetID: DupHandle failed, err=%ld",
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+
+ goto TSPI_lineGetID_epilog;
+ }
+
+ lpDeviceID->dwUsedSize = dwNeededSize;
+
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = dwNeededSize - sizeof(VARSTRING);
+ lpDeviceID->dwStringOffset = sizeof(VARSTRING);
+
+ *((HANDLE *)(lpDeviceID + 1)) = hCommDup;
+
+ lstrcpy(
+ ((char *)(lpDeviceID + 1)) + sizeof (HANDLE),
+ pLine->szComm
+ );
+
+ MultiByteToWideChar(
+ CP_ACP,
+ 0,
+ pLine->szComm,
+ -1,
+ ((WCHAR *)(lpDeviceID + 1)) + sizeof (HANDLE),
+ 256
+ );
+ }
+
+ lpDeviceID->dwNeededSize = dwNeededSize;
+ }
+ else
+ {
+ lResult = LINEERR_NODEVICE;
+ }
+
+TSPI_lineGetID_epilog:
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdLine, hdLine },
+ { "lpLineDevStatus", lpLineDevStatus }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetLineDevStatus",
+ 2,
+ params
+ };
+#endif
+
+ LONG lResult = 0;
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ Prolog (&info);
+
+ lpLineDevStatus->dwUsedSize =
+ lpLineDevStatus->dwNeededSize = sizeof (LINEDEVSTATUS);
+
+ lpLineDevStatus->dwNumActiveCalls = (pLine->htCall ? 1 : 0);
+ //lpLineDevStatus->dwLineFeatures =
+ lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
+ LINEDEVSTATUSFLAGS_INSERVICE;
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdLine, hdLine },
+ { "lpdwNumAddressIDs", lpdwNumAddressIDs }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineGetNumAddressIDs",
+ 2,
+ params
+ };
+#endif
+
+ LONG lResult = 0;
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ //
+ // We only support 1 address (id=0)
+ //
+
+ Prolog (&info);
+ *lpdwNumAddressIDs = 1;
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ char szCommands[64], szCommand[64], szDestAddress[128];
+ DWORD dwThreadID, dwNumBytes, dwError;
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszdwRequestID, dwRequestID },
+ { gszhdLine, hdLine },
+ { "htCall", htCall },
+ { "lphdCall", lphdCall },
+ { "lpszDestAddress", szDestAddress },
+ { "dwCountryCode", dwCountryCode },
+ { gszlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineMakeCall",
+ 7,
+ params
+ };
+#endif
+
+
+ if (lpszDestAddress)
+ {
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDestAddress,
+ -1,
+ (LPSTR) szDestAddress,
+ 128,
+ NULL,
+ NULL
+ );
+ }
+
+ Prolog (&info);
+
+
+ //
+ // Check to see if there's already another call
+ //
+
+ if (pLine->htCall)
+ {
+ (*gpfnCompletionProc)(dwRequestID, LINEERR_CALLUNAVAIL);
+ goto TSPI_lineMakeCall_return;
+ }
+
+
+ //
+ // Since we don't support TSPI_lineDial, fail if app tries
+ // to pass a NULL lpszDestAddress (implying that app just
+ // wants to go offhook)
+ //
+
+ if (lpszDestAddress == NULL)
+ {
+ (*gpfnCompletionProc)(dwRequestID, LINEERR_INVALADDRESS);
+ goto TSPI_lineMakeCall_return;
+ }
+
+
+ //
+ // Get the line's config info
+ //
+
+ {
+ HKEY hKey;
+ DWORD dwDataSize, dwDataType;
+ char szLineN[8], *pszConfig, *p, *p2;
+
+
+ wsprintf(
+ szLineN,
+ "Line%d",
+ ((PDRVLINE) hdLine)->dwDeviceID - gdwLineDeviceIDBase
+ );
+
+ dwDataSize = 256;
+
+ pszConfig = DrvAlloc (dwDataSize);
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszAtspKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ RegQueryValueEx(
+ hKey,
+ szLineN,
+ 0,
+ &dwDataType,
+ (LPBYTE) pszConfig,
+ &dwDataSize
+ );
+
+ pszConfig[dwDataSize] = '\0'; // *pszConfig = "MyLine,COM1,L0"
+
+ RegCloseKey (hKey);
+
+
+ //
+ // szComm
+ //
+
+ for (p = pszConfig; *p != ','; p++);
+ p++; // *p = "COM1,L0"
+ for (p2 = p; *p2 != ','; p2++);
+ *p2 = 0; // *p = "COM1"
+
+ lstrcpy (pLine->szComm, p);
+
+
+ //
+ // szCommands
+ //
+
+ p2++; // *p2 = "L0"
+ lstrcpy (szCommands, p2);
+
+ DrvFree (pszConfig);
+ }
+
+
+ //
+ // Open the port
+ //
+
+ if ((pLine->hComm = CreateFile(
+ pLine->szComm,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, //FILE_SHARE_READ | FILE_SHARE_WRITE, // BUGBUG
+ NULL, // no security attrs
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL // no template file
+
+ )) == INVALID_HANDLE_VALUE)
+ {
+ DBGOUT((
+ 3,
+ "TSPI_lineMakeCall: CreateFile(%s) failed, err=%ld",
+ pLine->szComm,
+ GetLastError()
+ ));
+
+ (*gpfnCompletionProc)(dwRequestID, LINEERR_RESOURCEUNAVAIL);
+ goto TSPI_lineMakeCall_return;
+ }
+
+
+ //
+ // Setup up the modem command string. If there's an initial 'T'
+ // or 'P' (for Tone or Pulse) in the dest address then disregard
+ // it. Also if it's a voice call add the semi colon so we return
+ // to cmd mode.
+ //
+
+ {
+ char *p = (char *) szDestAddress;
+
+
+ if (*p == 'T' || *p == 'P')
+ {
+ p++;
+ }
+
+ if (lpCallParams &&
+ lpCallParams->dwMediaMode != LINEMEDIAMODE_INTERACTIVEVOICE)
+ {
+ wsprintf (szCommand, "AT%sDT%s\r", szCommands, p);
+ }
+ else
+ {
+ wsprintf (szCommand, "AT%sDT%s;\r", szCommands, p);
+ }
+ }
+
+
+ //
+ // Init the data structure & tell tapi our handle to the call
+ //
+
+ pLine->htCall = htCall;
+ pLine->bDropInProgress = FALSE;
+ pLine->dwMediaMode = (lpCallParams ? lpCallParams->dwMediaMode :
+ LINEMEDIAMODE_INTERACTIVEVOICE);
+
+ *lphdCall = (HDRVCALL) pLine;
+
+
+ //
+ // Do an overlapped write, the comm thread will deal with the results
+ //
+
+ pLine->Overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
+
+ if (!WriteFile(
+ pLine->hComm,
+ szCommand,
+ lstrlen (szCommand),
+ &dwNumBytes,
+ &pLine->Overlapped
+ )
+
+ && (dwError = GetLastError()) != ERROR_IO_PENDING)
+ {
+ DBGOUT((
+ 1,
+ "TSPI_lineMakeCall: WriteFile(%s) failed, error=%d",
+ pLine->szComm,
+ dwError
+ ));
+
+ pLine->htCall = NULL;
+ CloseHandle (pLine->hComm);
+ CloseHandle (pLine->Overlapped.hEvent);
+ (*gpfnCompletionProc)(dwRequestID, LINEERR_OPERATIONFAILED);
+ goto TSPI_lineMakeCall_return;
+ }
+
+
+ //
+ // Complete the requests & set the initial call state
+ //
+
+ (*gpfnCompletionProc)(dwRequestID, 0);
+ SetCallState (pLine, LINECALLSTATE_DIALING, 0);
+
+
+ //
+ // Spin the comm thread to handle the results of the Write above
+ //
+
+ {
+ HANDLE hCommThread;
+
+
+ if (!(hCommThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE) CommThread,
+ pLine,
+ 0,
+ &dwThreadID
+ )))
+ {
+ DBGOUT((
+ 1,
+ "TSPI_lineMakeCall: CreateThread failed, err=%ld",
+ GetLastError()
+ ));
+
+ GetOverlappedResult(
+ pLine->hComm,
+ &pLine->Overlapped,
+ &dwNumBytes,
+ TRUE
+ );
+
+ SetCallState (pLine, LINECALLSTATE_IDLE, 0);
+ CloseHandle (pLine->hComm);
+ CloseHandle (pLine->Overlapped.hEvent);
+ goto TSPI_lineMakeCall_return;
+ }
+
+ CloseHandle (hCommThread);
+ }
+
+
+TSPI_lineMakeCall_return:
+
+ return (Epilog (&info, dwRequestID));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszdwDeviceID, dwDeviceID },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwTSPIVersion", lpdwTSPIVersion }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineNegotiateTSPIVersion",
+ 4,
+ params
+ };
+#endif
+
+ Prolog (&info);
+ *lpdwTSPIVersion = 0x00020000;
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+{
+ LONG lResult;
+ PDRVLINE pLine;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszdwDeviceID, dwDeviceID },
+ { "htLine", htLine },
+ { "lphdLine", lphdLine },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpfnEventProc", lpfnEventProc }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineOpen",
+ 5,
+ params
+ };
+#endif
+
+
+ Prolog (&info);
+
+ if ((pLine = DrvAlloc (sizeof (DRVLINE))))
+ {
+ pLine->htLine = htLine;
+ pLine->pfnEventProc = lpfnEventProc;
+ pLine->dwDeviceID = dwDeviceID;
+
+ *lphdLine = (HDRVLINE) pLine;
+
+ lResult = 0;
+ }
+ else
+ {
+ lResult = LINEERR_NOMEM;
+ }
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+{
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { gszhdLine, hdLine },
+ { "dwMediaModes", dwMediaModes }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_lineSetDefaultMediaDetection",
+ 2,
+ params
+ };
+#endif
+
+
+ //
+ // This func is really a no-op for us, since we don't look
+ // for incoming calls (though we do say we support them to
+ // make apps happy)
+ //
+
+ Prolog (&info);
+ return (Epilog (&info, 0));
+}
+
+
+//
+// ------------------------- TSPI_providerXxx funcs ---------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // Although this func is never called by TAPI v2.0, we export
+ // it so that the Telephony Control Panel Applet knows that it
+ // can configure this provider via lineConfigProvider(),
+ // otherwise Telephon.cpl will not consider it configurable
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerGenericDialogData(
+ DWORD dwObjectID,
+ DWORD dwObjectType,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { "dwObjectID", dwObjectID },
+ { "dwObjectType", dwObjectType },
+ { "lpParams", lpParams },
+ { "dwSize", dwSize }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_providerGenericDialogData",
+ 4,
+ params
+ };
+#endif
+
+
+ Prolog (&info);
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc,
+ LPDWORD lpdwTSPIOptions
+ )
+{
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { "dwTSPIVersion", dwTSPIVersion },
+ { gszdwPermanentProviderID, dwPermanentProviderID },
+ { "dwLineDeviceIDBase", dwLineDeviceIDBase },
+ { "dwPhoneDeviceIDBase", dwPhoneDeviceIDBase },
+ { "dwNumLines", dwNumLines },
+ { "dwNumPhones", dwNumPhones },
+ { "lpfnCompletionProc", lpfnCompletionProc }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_providerInit",
+ 7,
+ params
+ };
+#endif
+
+ Prolog (&info);
+ gdwLineDeviceIDBase = dwLineDeviceIDBase;
+ gpfnCompletionProc = lpfnCompletionProc;
+ *lpdwTSPIOptions = LINETSPIOPTION_NONREENTRANT;
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // Although this func is never called by TAPI v2.0, we export
+ // it so that the Telephony Control Panel Applet knows that it
+ // can add this provider via lineAddProvider(), otherwise
+ // Telephon.cpl will not consider it installable
+ //
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // Although this func is never called by TAPI v2.0, we export
+ // it so that the Telephony Control Panel Applet knows that it
+ // can remove this provider via lineRemoveProvider(), otherwise
+ // Telephon.cpl will not consider it removable
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID
+ )
+{
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { "dwTSPIVersion", dwTSPIVersion },
+ { gszdwPermanentProviderID, dwPermanentProviderID }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_providerShutdown",
+ 2,
+ params
+ };
+#endif
+
+
+ Prolog (&info);
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+{
+ HKEY hKey;
+ DWORD dwNumLines, dwDataType, dwDataSize;
+
+
+ //
+ // Retrieve the number of devices we're
+ // configured for from our registry section
+ //
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszAtspKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof(dwNumLines);
+ dwNumLines = 0;
+
+ RegQueryValueEx(
+ hKey,
+ gszNumLines,
+ 0,
+ &dwDataType,
+ (LPBYTE) &dwNumLines,
+ &dwDataSize
+ );
+
+ RegCloseKey (hKey);
+
+ *lpdwNumLines = dwNumLines;
+ *lpdwNumPhones = 0;
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerUIIdentify(
+ LPWSTR lpszUIDLLName
+ )
+{
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { "lpsUIDLLName", lpszUIDLLName }
+ };
+ FUNC_INFO info =
+ {
+ "TSPI_providerUIIdentify",
+ 1,
+ params
+ };
+#endif
+
+
+ Prolog (&info);
+ lstrcpyW(lpszUIDLLName, L"atsp32.tsp");
+ return (Epilog (&info, lResult));
+}
+
+
+//
+// ---------------------------- TUISPI_xxx funcs ------------------------------
+//
+
+LONG
+TSPIAPI
+TUISPI_lineConfigDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ char szDeviceClass[128];
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { "lpfnUIDLLCallback", lpfnUIDLLCallback },
+ { gszdwDeviceID, dwDeviceID },
+ { gszhwndOwner, hwndOwner },
+ { "lpszDeviceClass", szDeviceClass }
+ };
+ FUNC_INFO info =
+ {
+ "TUISPI_lineConfigDialog",
+ 4,
+ params
+ };
+#endif
+
+
+ if (lpszDeviceClass)
+ {
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDeviceClass,
+ -1,
+ (LPSTR) szDeviceClass,
+ 128,
+ NULL,
+ NULL
+ );
+ }
+
+ Prolog (&info);
+
+ DialogBoxParam(
+ ghInst,
+ MAKEINTRESOURCE(IDD_DIALOG1),
+ hwndOwner,
+ (DLGPROC) ConfigDlgProc,
+ 0
+ );
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerConfig(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ LONG lResult = 0;
+#if DBG
+ FUNC_PARAM params[] =
+ {
+ { "lpfnUIDLLCallback", lpfnUIDLLCallback },
+ { gszhwndOwner, hwndOwner },
+ { gszdwPermanentProviderID, dwPermanentProviderID }
+ };
+ FUNC_INFO info =
+ {
+ "TUISPI_providerConfig",
+ 3,
+ params
+ };
+#endif
+
+
+ Prolog (&info);
+
+ DialogBoxParam(
+ ghInst,
+ MAKEINTRESOURCE(IDD_DIALOG1),
+ hwndOwner,
+ (DLGPROC) ConfigDlgProc,
+ 0
+ );
+
+ return (Epilog (&info, lResult));
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerInstall(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ LONG lResult;
+
+
+ if ((lResult = ProviderInstall ("atsp32.tsp", TRUE)) == 0)
+ {
+ DialogBoxParam(
+ ghInst,
+ MAKEINTRESOURCE(IDD_DIALOG1),
+ hwndOwner,
+ (DLGPROC) ConfigDlgProc,
+ 0
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerRemove(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ HKEY hKey;
+ char szSoftwareMsft[] = "Software\\Microsoft", szATSP[] = "ATSP";
+
+
+ //
+ // Clean up our registry section
+ //
+
+ RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ szSoftwareMsft,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ RegDeleteKeyA (hKey, szATSP);
+ RegCloseKey (hKey);
+ return 0;
+}
+
+
+#pragma warning (default:4047)
+
+
+//
+// ---------------------- Misc private support routines -----------------------
+//
+
+void
+PASCAL
+EnableChildren(
+ HWND hwnd,
+ BOOL bEnable
+ )
+{
+ int i;
+ static int aiControlIDs[] =
+ {
+ IDC_DEVICES,
+ IDC_NAME,
+ IDC_PORT,
+ IDC_COMMANDS,
+ IDC_REMOVE,
+ 0
+ };
+
+
+ for (i = 0; aiControlIDs[i]; i++)
+ {
+ EnableWindow (GetDlgItem (hwnd, aiControlIDs[i]), bEnable);
+ }
+}
+
+
+void
+PASCAL
+SelectDevice(
+ HWND hwnd,
+ int iDevice
+ )
+{
+ SendDlgItemMessage (hwnd, IDC_DEVICES, LB_SETCURSEL, iDevice, 0);
+ PostMessage(hwnd, WM_COMMAND, IDC_DEVICES | (LBN_SELCHANGE << 16), 0);
+}
+
+
+BOOL
+CALLBACK
+ConfigDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ static HKEY hAtspKey;
+
+ DWORD dwDataSize;
+ DWORD dwDataType;
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ char *pBuf;
+ DWORD i, iNumLines;
+
+
+ //
+ // Create or open our configuration key in the registry. If the
+ // create fails it may well be that the current user does not
+ // have write access to this portion of the registry, so we'll
+ // just show a "read only" dialog and not allow user to make any
+ // changes
+ //
+
+ {
+ LONG lResult;
+ DWORD dwDisposition;
+
+
+ if ((lResult = RegCreateKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszAtspKey,
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ &hAtspKey,
+ &dwDisposition
+
+ )) != ERROR_SUCCESS)
+ {
+ DBGOUT((
+ 3,
+ "RegCreateKeyEx(%s,ALL_ACCESS) failed, err=%d",
+ gszAtspKey,
+ lResult
+ ));
+
+ if ((lResult = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszAtspKey,
+ 0,
+ KEY_QUERY_VALUE,
+ &hAtspKey
+
+ )) != ERROR_SUCCESS)
+ {
+ DBGOUT((
+ 3,
+ "RegOpenKeyEx(%s,ALL_ACCESS) failed, err=%d",
+ gszAtspKey,
+ lResult
+ ));
+
+ EndDialog (hwnd, 0);
+ return FALSE;
+ }
+
+ {
+ int i;
+ static int aiControlIDs[] =
+ {
+ IDC_NAME,
+ IDC_PORT,
+ IDC_COMMANDS,
+ IDC_ADD,
+ IDC_REMOVE,
+ IDOK,
+ 0
+ };
+
+
+ for (i = 0; aiControlIDs[i]; i++)
+ {
+ EnableWindow(
+ GetDlgItem (hwnd, aiControlIDs[i]),
+ FALSE
+ );
+ }
+ }
+ }
+ }
+
+
+ //
+ // Retrieve our configuration info from the registry
+ //
+
+ dwDataSize = sizeof(iNumLines);
+ iNumLines = 0;
+
+ RegQueryValueEx(
+ hAtspKey,
+ gszNumLines,
+ 0,
+ &dwDataType,
+ (LPBYTE) &iNumLines,
+ &dwDataSize
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_NAME,
+ EM_LIMITTEXT,
+ MAX_DEV_NAME_LENGTH,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMMANDS,
+ EM_LIMITTEXT,
+ MAX_DEV_NAME_LENGTH,
+ 0
+ );
+
+ pBuf = DrvAlloc (256);
+
+ for (i = 0; i < iNumLines; i++)
+ {
+ char *p, *p2, szLineN[8];
+ PDRVLINECONFIG pLineConfig = DrvAlloc (sizeof(DRVLINECONFIG));
+ LONG lResult;
+
+
+ wsprintf (szLineN, "Line%d", i);
+
+ dwDataSize = 256;
+
+ lResult = RegQueryValueEx(
+ hAtspKey,
+ szLineN,
+ 0,
+ &dwDataType,
+ (LPBYTE) pBuf,
+ &dwDataSize
+ );
+
+
+ //
+ // If there was a problem, use the default config
+ //
+
+ if (0 != lResult)
+ {
+ lstrcpy (pBuf, gszDefLineConfigParams);
+ }
+
+ for (p = pBuf; *p != ','; p++);
+ *p = 0;
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) pBuf
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_SETITEMDATA,
+ i,
+ (LPARAM) pLineConfig
+ );
+
+ p++;
+ for (p2 = p; *p2 != ','; p2++);
+ *p2 = 0;
+
+ lstrcpy (pLineConfig->szPort, p);
+
+ p = p2 + 1;
+
+ lstrcpy (pLineConfig->szCommands, p);
+ }
+
+ DrvFree (pBuf);
+
+
+ //
+ // Fill up the various controls with configuration options
+ //
+
+ {
+ static char *aszPorts[] = { "COM1","COM2","COM3",NULL };
+
+ for (i = 0; aszPorts[i]; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_PORT,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) aszPorts[i]
+ );
+ }
+ }
+
+ if (iNumLines == 0)
+ {
+ EnableChildren (hwnd, FALSE);
+ }
+ else
+ {
+ SelectDevice (hwnd, 0);
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ int iSelection;
+ PDRVLINECONFIG pLineConfig;
+
+
+ iSelection = SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ pLineConfig = (PDRVLINECONFIG) SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_GETITEMDATA,
+ (WPARAM) iSelection,
+ 0
+ );
+
+ switch (LOWORD((DWORD)wParam))
+ {
+ case IDC_DEVICES:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ char buf[MAX_DEV_NAME_LENGTH + 1];
+
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_GETTEXT,
+ iSelection,
+ (LPARAM) buf
+ );
+
+ SetDlgItemText (hwnd, IDC_NAME, buf);
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_PORT,
+ LB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLineConfig->szPort
+ );
+
+ SetDlgItemText (hwnd, IDC_COMMANDS, pLineConfig->szCommands);
+ }
+
+ break;
+
+ case IDC_NAME:
+
+ if ((HIWORD(wParam) == EN_CHANGE) && (iSelection != LB_ERR))
+ {
+ char buf[MAX_DEV_NAME_LENGTH + 1];
+
+
+ GetDlgItemText (hwnd, IDC_NAME, buf, MAX_DEV_NAME_LENGTH);
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_DELETESTRING,
+ iSelection,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_INSERTSTRING,
+ iSelection,
+ (LPARAM) buf
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_SETCURSEL,
+ iSelection,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_SETITEMDATA,
+ iSelection,
+ (LPARAM) pLineConfig
+ );
+ }
+
+ break;
+
+ case IDC_PORT:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ iSelection = SendDlgItemMessage(
+ hwnd,
+ IDC_PORT,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_PORT,
+ LB_GETTEXT,
+ iSelection,
+ (LPARAM) pLineConfig->szPort
+ );
+ }
+
+ break;
+
+ case IDC_COMMANDS:
+
+ if ((HIWORD(wParam) == EN_CHANGE) && (iSelection != LB_ERR))
+ {
+ GetDlgItemText(
+ hwnd,
+ IDC_COMMANDS,
+ pLineConfig->szCommands,
+ 63
+ );
+ }
+
+ break;
+
+ case IDC_ADD:
+ {
+ int iNumLines, i = 2;
+ char szLineName[32];
+ PDRVLINECONFIG pLineConfig = DrvAlloc (sizeof(DRVLINECONFIG));
+
+
+ iNumLines = SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_GETCOUNT,
+ 0,
+ 0
+ );
+
+ lstrcpy (pLineConfig->szPort, "COM1");
+
+ lstrcpy (szLineName, "my new line");
+
+find_unique_line_name:
+
+ if (SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_FINDSTRING,
+ (WPARAM) -1,
+ (LPARAM) szLineName
+
+ ) != LB_ERR)
+ {
+ wsprintf (szLineName, "my new line%d", i++);
+ goto find_unique_line_name;
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) szLineName
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_SETITEMDATA,
+ iNumLines,
+ (LPARAM) pLineConfig
+ );
+
+ EnableChildren (hwnd, TRUE);
+
+ SelectDevice (hwnd, iNumLines);
+
+ SetFocus (GetDlgItem (hwnd, IDC_NAME));
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_NAME,
+ EM_SETSEL,
+ 0,
+ (LPARAM) -1
+ );
+
+ break;
+ }
+ case IDC_REMOVE:
+ {
+ int iNumLines;
+
+
+ DrvFree (pLineConfig);
+
+ iNumLines = SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_DELETESTRING,
+ iSelection,
+ 0
+ );
+
+ if (iNumLines == 0)
+ {
+ SetDlgItemText (hwnd, IDC_NAME, "");
+ SetDlgItemText (hwnd, IDC_COMMANDS, "");
+
+ EnableChildren (hwnd, FALSE);
+ }
+ else
+ {
+ SelectDevice (hwnd, 0);
+ }
+
+ break;
+ }
+ case IDOK:
+ {
+ int i, iNumLines;
+ char *pBuf;
+
+
+ //
+ // Update the num lines & num phones values
+ //
+
+ pBuf = DrvAlloc (256);
+
+ iNumLines = SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_GETCOUNT,
+ 0,
+ 0
+ );
+
+ RegSetValueEx(
+ hAtspKey,
+ gszNumLines,
+ 0,
+ REG_DWORD,
+ (LPBYTE) &iNumLines,
+ sizeof(DWORD)
+ );
+
+
+ //
+ // For each installed device save it's config info
+ //
+
+ for (i = 0; i < iNumLines; i++)
+ {
+ char szLineN[8];
+ PDRVLINECONFIG pLineConfig;
+
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_GETTEXT,
+ i,
+ (LPARAM) pBuf
+ );
+
+ pLineConfig = (PDRVLINECONFIG) SendDlgItemMessage(
+ hwnd,
+ IDC_DEVICES,
+ LB_GETITEMDATA,
+ i,
+ 0
+ );
+
+ wsprintf(
+ pBuf + strlen (pBuf),
+ ",%s,%s",
+ pLineConfig->szPort,
+ pLineConfig->szCommands
+ );
+
+ wsprintf (szLineN, "Line%d", i);
+
+ RegSetValueEx(
+ hAtspKey,
+ szLineN,
+ 0,
+ REG_SZ,
+ (LPBYTE) pBuf,
+ lstrlen (pBuf) + 1
+ );
+
+ DrvFree (pLineConfig);
+ }
+
+ DrvFree (pBuf);
+
+ // fall thru to EndDialog...
+ }
+ case IDCANCEL:
+
+ RegCloseKey (hAtspKey);
+ EndDialog (hwnd, 0);
+ break;
+
+ } // switch (LOWORD((DWORD)wParam))
+
+ break;
+ }
+ } // switch (msg)
+
+ return FALSE;
+}
+
+
+LPVOID
+PASCAL
+DrvAlloc(
+ DWORD dwSize
+ )
+{
+ return (LocalAlloc (LPTR, dwSize));
+}
+
+
+VOID
+PASCAL
+DrvFree(
+ LPVOID lp
+ )
+{
+ LocalFree (lp);
+}
+
+
+void
+PASCAL
+SetCallState(
+ PDRVLINE pLine,
+ DWORD dwCallState,
+ DWORD dwCallStateMode
+ )
+{
+ if (dwCallState != pLine->dwCallState)
+ {
+ pLine->dwCallState = dwCallState;
+ pLine->dwCallStateMode = dwCallStateMode;
+
+ (*pLine->pfnEventProc)(
+ pLine->htLine,
+ pLine->htCall,
+ LINE_CALLSTATE,
+ dwCallState,
+ dwCallStateMode,
+ pLine->dwMediaMode
+ );
+ }
+}
+
+
+#if DBG
+
+void
+PASCAL
+Prolog(
+ PFUNC_INFO pInfo
+ )
+{
+ DWORD i;
+
+
+ DBGOUT((3, "%s: enter", pInfo->lpszFuncName));
+
+ for (i = 0; i < pInfo->dwNumParams; i++)
+ {
+ if (pInfo->aParams[i].dwVal &&
+ pInfo->aParams[i].lpszVal[3] == 'z') // lpszVal = "lpsz..."
+ {
+ DBGOUT((
+ 3,
+ "%s%s=x%lx, '%s'",
+ gszTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal,
+ pInfo->aParams[i].dwVal
+ ));
+ }
+ else
+ {
+ DBGOUT((
+ 3,
+ "%s%s=x%lx",
+ gszTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal
+ ));
+ }
+ }
+}
+
+
+LONG
+PASCAL
+Epilog(
+ PFUNC_INFO pInfo,
+ LONG lResult
+ )
+{
+ DBGOUT((3, "%s: returning x%x", pInfo->lpszFuncName, lResult));
+
+ return lResult;
+}
+
+
+void
+CDECL
+DebugOutput(
+ DWORD dwDbgLevel,
+ LPCSTR lpszFormat,
+ ...
+ )
+{
+ if (dwDbgLevel <= gdwDebugLevel)
+ {
+ char buf[128] = "ATSP32: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ wvsprintf (&buf[8], lpszFormat, ap);
+
+ lstrcat (buf, "\n");
+
+ OutputDebugString (buf);
+
+ va_end(ap);
+ }
+}
+
+#endif
+
+
+LONG
+PASCAL
+ProviderInstall(
+ char *pszProviderName,
+ BOOL bNoMultipleInstance
+ )
+{
+ LONG lResult;
+
+
+ //
+ // If only one installation instance of this provider is
+ // allowed then we want to check the provider list to see
+ // if the provider is already installed
+ //
+
+ if (bNoMultipleInstance)
+ {
+ LONG (WINAPI *pfnGetProviderList)();
+ DWORD dwTotalSize, i;
+ HINSTANCE hTapi32;
+ LPLINEPROVIDERLIST pProviderList;
+ LPLINEPROVIDERENTRY pProviderEntry;
+
+
+ //
+ // Load Tapi32.dll & get a pointer to the lineGetProviderList
+ // func. We don't want to statically link because this module
+ // plays the part of both core SP & UI DLL, and we don't want
+ // to incur the performance hit of automatically loading
+ // Tapi32.dll when running as a core SP within Tapisrv.exe's
+ // context.
+ //
+
+ if (!(hTapi32 = LoadLibrary ("tapi32.dll")))
+ {
+ DBGOUT((
+ 1,
+ "LoadLibrary(tapi32.dll) failed, err=%d",
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+ goto ProviderInstall_return;
+ }
+
+ if (!((FARPROC) pfnGetProviderList = GetProcAddress(
+ hTapi32,
+ (LPCSTR) "lineGetProviderList"
+ )))
+ {
+ DBGOUT((
+ 1,
+ "GetProcAddr(lineGetProviderList) failed, err=%d",
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+ goto ProviderInstall_unloadTapi32;
+ }
+
+
+ //
+ // Loop until we get the full provider list
+ //
+
+ dwTotalSize = sizeof (LINEPROVIDERLIST);
+
+ goto ProviderInstall_allocProviderList;
+
+ProviderInstall_getProviderList:
+
+ if ((lResult = (*pfnGetProviderList)(0x00020000, pProviderList)) != 0)
+ {
+ goto ProviderInstall_freeProviderList;
+ }
+
+ if (pProviderList->dwNeededSize > pProviderList->dwTotalSize)
+ {
+ dwTotalSize = pProviderList->dwNeededSize;
+
+ LocalFree (pProviderList);
+
+ProviderInstall_allocProviderList:
+
+ if (!(pProviderList = LocalAlloc (LPTR, dwTotalSize)))
+ {
+ lResult = LINEERR_NOMEM;
+ goto ProviderInstall_unloadTapi32;
+ }
+
+ pProviderList->dwTotalSize = dwTotalSize;
+
+ goto ProviderInstall_getProviderList;
+ }
+
+
+ //
+ // Inspect the provider list entries to see if this provider
+ // is already installed
+ //
+
+ pProviderEntry = (LPLINEPROVIDERENTRY) (((LPBYTE) pProviderList) +
+ pProviderList->dwProviderListOffset);
+
+ for (i = 0; i < pProviderList->dwNumProviders; i++)
+ {
+ char *pszInstalledProviderName = ((char *) pProviderList) +
+ pProviderEntry->dwProviderFilenameOffset,
+ *p;
+
+
+ //
+ // Make sure pszInstalledProviderName points at <filename>
+ // and not <path>\filename by walking backeards thru the
+ // string searching for last '\\'
+ //
+
+ p = pszInstalledProviderName +
+ lstrlen (pszInstalledProviderName) - 1;
+
+ for (; *p != '\\' && p != pszInstalledProviderName; p--);
+
+ pszInstalledProviderName =
+ (p == pszInstalledProviderName ? p : p + 1);
+
+ if (lstrcmpiA (pszInstalledProviderName, pszProviderName) == 0)
+ {
+ lResult = LINEERR_NOMULTIPLEINSTANCE;
+ goto ProviderInstall_freeProviderList;
+ }
+
+ pProviderEntry++;
+ }
+
+
+ //
+ // If here then the provider isn't currently installed,
+ // so do whatever configuration stuff is necessary and
+ // indicate SUCCESS
+ //
+
+ lResult = 0;
+
+
+ProviderInstall_freeProviderList:
+
+ LocalFree (pProviderList);
+
+ProviderInstall_unloadTapi32:
+
+ FreeLibrary (hTapi32);
+ }
+ else
+ {
+ //
+ // Do whatever configuration stuff is necessary and return SUCCESS
+ //
+
+ lResult = 0;
+ }
+
+ProviderInstall_return:
+
+ return lResult;
+}
+
+
+void
+PASCAL
+DropActiveCall(
+ PDRVLINE pLine
+ )
+{
+ if (pLine->hComm)
+ {
+ DWORD dwNumBytes, dwError;
+ OVERLAPPED overlapped;
+
+
+ pLine->bDropInProgress = TRUE;
+
+ SetEvent (pLine->Overlapped.hEvent);
+
+ ZeroMemory (&overlapped, sizeof (OVERLAPPED));
+
+ overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
+
+ if (pLine->dwMediaMode != LINEMEDIAMODE_INTERACTIVEVOICE)
+ {
+ if (!WriteFile(
+ pLine->hComm,
+ "+++\r", 4,
+ &dwNumBytes,
+ &overlapped
+ ))
+ {
+ if ((dwError = GetLastError()) == ERROR_IO_PENDING)
+ {
+ GetOverlappedResult(
+ pLine->hComm,
+ &overlapped,
+ &dwNumBytes,
+ TRUE
+ );
+
+ ResetEvent (overlapped.hEvent);
+ }
+ else
+ {
+ }
+ }
+ }
+
+ if (!WriteFile (pLine->hComm, "ATH\r", 4, &dwNumBytes, &overlapped))
+ {
+ if ((dwError = GetLastError()) == ERROR_IO_PENDING)
+ {
+ GetOverlappedResult(
+ pLine->hComm,
+ &overlapped,
+ &dwNumBytes,
+ TRUE
+ );
+ }
+ else
+ {
+ }
+ }
+
+ CloseHandle (overlapped.hEvent);
+ CloseHandle (pLine->hComm);
+ pLine->hComm = NULL;
+ }
+}
diff --git a/private/tapi/dev/sp/atsp32/atsp.h b/private/tapi/dev/sp/atsp32/atsp.h
new file mode 100644
index 000000000..000963a6b
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/atsp.h
@@ -0,0 +1,204 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ atsp.h
+
+Notes:
+
+--*/
+
+#include <windows.h>
+#include "tapi.h"
+#include "tspi.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include "resource.h"
+
+
+#define MAX_DEV_NAME_LENGTH 63
+#define ATSP_TIMEOUT 60000 // milliseconds
+
+
+typedef struct _DRVLINE
+{
+ HTAPILINE htLine;
+
+ LINEEVENT pfnEventProc;
+
+ DWORD dwDeviceID;
+
+ char szComm[8];
+
+ HTAPICALL htCall;
+
+ DWORD dwCallState;
+
+ DWORD dwCallStateMode;
+
+ DWORD dwMediaMode;
+
+ HANDLE hComm;
+
+ BOOL bDropInProgress;
+
+ OVERLAPPED Overlapped;
+
+} DRVLINE, FAR *PDRVLINE;
+
+
+typedef struct _DRVLINECONFIG
+{
+ char szPort[8];
+
+ char szCommands[64];
+
+} DRVLINECONFIG, FAR *PDRVLINECONFIG;
+
+
+typedef struct _ASYNC_REQUEST
+{
+ DWORD dwRequestID;
+
+ DWORD dwCommand;
+
+ char szCommand[32];
+
+ struct _ASYNC_REQUEST *pNext;
+
+} ASYNC_REQUEST, *PASYNC_REQUEST;
+
+
+#if DBG
+
+typedef struct _FUNC_PARAM
+{
+ char *lpszVal;
+
+ DWORD dwVal;
+
+} FUNC_PARAM, *PFUNC_PARAM;
+
+#endif
+
+typedef struct _FUNC_INFO
+{
+
+#if DBG
+
+ char *lpszFuncName;
+
+ DWORD dwNumParams;
+
+ PFUNC_PARAM aParams;
+
+#endif
+
+ LONG lResult;
+
+} FUNC_INFO, *PFUNC_INFO;
+
+
+DWORD gdwLineDeviceIDBase;
+DWORD gdwPermanentProviderID;
+HANDLE ghInst;
+ASYNC_COMPLETION gpfnCompletionProc;
+
+char gszAtspKey[] = "Software\\Microsoft\\ATSP";
+char gszNumLines[] = "NumLines";
+char gszDefLineConfigParams[] = "my new line,COM1,L0";
+
+#if DBG
+
+char gszTab[] = " ";
+char gszhdLine[] = "hdLine";
+char gszhdCall[] = "hdCall";
+char gszdwSize[] = "dwSize";
+char gszhwndOwner[] = "hwndOwner";
+char gszdwDeviceID[] = "dwDeviceID";
+char gszdwRequestID[] = "dwRequestID";
+char gszlpCallParams[] = "lpCallParams";
+char gszdwPermanentProviderID[] = "dwPermanentProviderID";
+
+DWORD gdwDebugLevel = 0;
+
+void
+CDECL
+DebugOutput(
+ DWORD dwLevel,
+ LPCSTR lpszFormat,
+ ...
+ );
+
+#define DBGOUT(arg) DebugOutput arg
+
+LONG
+PASCAL
+Epilog(
+ PFUNC_INFO pInfo,
+ LONG lResult
+ );
+
+void
+PASCAL
+Prolog(
+ PFUNC_INFO pInfo
+ );
+
+#else
+
+#define DBGOUT(arg)
+
+#define Epilog(pAsyncRequestInfo, lResult) (lResult)
+
+#define Prolog(pAsyncRequestInfo)
+
+#endif
+
+
+LPVOID
+PASCAL
+DrvAlloc(
+ DWORD dwSize
+ );
+
+VOID
+PASCAL
+DrvFree(
+ LPVOID lp
+ );
+
+void
+PASCAL
+SetCallState(
+ PDRVLINE pLine,
+ DWORD dwCallState,
+ DWORD dwCallStateMode
+ );
+
+BOOL
+CALLBACK
+ConfigDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+LONG
+PASCAL
+ProviderInstall(
+ char *pszProviderName,
+ BOOL bNoMultipleInstance
+ );
+
+void
+PASCAL
+DropActiveCall(
+ PDRVLINE pLine
+ );
diff --git a/private/tapi/dev/sp/atsp32/atsp.rc b/private/tapi/dev/sp/atsp32/atsp.rc
new file mode 100644
index 000000000..115761219
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/atsp.rc
@@ -0,0 +1,45 @@
+#include "windows.h"
+#include "resource.h"
+
+IDD_DIALOG1 DIALOG 6, 18, 176, 128
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "ATSP Configuration"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Installed lines:", 101, 4, 6, 54, 8
+ LISTBOX IDC_DEVICES, 4, 16, 120, 30, WS_VSCROLL | WS_TABSTOP
+
+ GROUPBOX "Line properties", 103, 4, 46, 120, 76
+
+ LTEXT "Name:", 113, 7, 64, 26, 8
+ EDITTEXT IDC_NAME, 38, 62, 80, 12, ES_AUTOHSCROLL
+
+ LTEXT "Port:", 104, 7, 81, 19, 8
+ LISTBOX IDC_PORT, 38, 80, 44, 26, WS_VSCROLL | WS_TABSTOP
+
+ LTEXT "Extra", 105, 7, 101, 25, 8
+ LTEXT "settings:", 114, 7, 109, 30, 8
+ EDITTEXT IDC_COMMANDS, 38, 104, 80, 12, ES_AUTOHSCROLL
+
+ PUSHBUTTON "Add", IDC_ADD, 130, 16, 40, 14
+ PUSHBUTTON "Remove", IDC_REMOVE, 130, 35, 40, 14
+ PUSHBUTTON "OK", IDOK, 130, 55, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 130, 74, 40, 14
+END
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) 32bit AT-Compatible Modem Service Provider"
+#define VER_INTERNALNAME_STR "atsp32"
+#define VER_ORIGINALFILENAME_STR "ATSP32.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/atsp32/atsp32.def b/private/tapi/dev/sp/atsp32/atsp32.def
new file mode 100644
index 000000000..a991154ad
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/atsp32.def
@@ -0,0 +1,42 @@
+LIBRARY ATSP32
+PROTMODE
+CODE PRELOAD FIXED
+DATA PRELOAD FIXED
+
+
+EXPORTS
+
+ TSPI_lineClose
+ TSPI_lineCloseCall
+ TSPI_lineConditionalMediaDetection
+ TSPI_lineDrop
+ TSPI_lineGetAddressCaps
+ TSPI_lineGetAddressStatus
+ TSPI_lineGetCallAddressID
+ TSPI_lineGetCallInfo
+ TSPI_lineGetCallStatus
+ TSPI_lineGetDevCaps
+ TSPI_lineGetID
+ TSPI_lineGetLineDevStatus
+ TSPI_lineGetNumAddressIDs
+ TSPI_lineMakeCall
+ TSPI_lineNegotiateTSPIVersion
+ TSPI_lineOpen
+ TSPI_lineSetDefaultMediaDetection
+
+ TSPI_providerConfig
+ TSPI_providerInit
+ TSPI_providerInstall
+ TSPI_providerRemove
+ TSPI_providerShutdown
+ TSPI_providerEnumDevices
+
+ TSPI_providerGenericDialogData
+ TSPI_providerUIIdentify
+
+ TUISPI_lineConfigDialog
+ TUISPI_providerConfig
+ TUISPI_providerInstall
+ TUISPI_providerRemove
+
+ ConfigDlgProc
diff --git a/private/tapi/dev/sp/atsp32/depend.mk b/private/tapi/dev/sp/atsp32/depend.mk
new file mode 100644
index 000000000..1163364ff
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/depend.mk
@@ -0,0 +1,3 @@
+.\atsp.obj: ..\atsp.c ..\atsp.h ..\resource.h
+
+.\atsp.res: ..\atsp.rc ..\resource.h
diff --git a/private/tapi/dev/sp/atsp32/dialogs.dlg b/private/tapi/dev/sp/atsp32/dialogs.dlg
new file mode 100644
index 000000000..5809e0054
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/dialogs.dlg
@@ -0,0 +1,22 @@
+#include "resource.h"
+
+100 DIALOG 6, 18, 184, 111
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "ATSP32 Device Configuration"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Installed devices:", 101, 8, 8, 61, 8
+ LISTBOX IDC_DEVICES, 72, 7, 104, 20, WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Device", 111, 8, 27, 168, 63
+ LTEXT "Description:", 102, 16, 41, 45, 8
+ EDITTEXT IDC_DESCRIPTION, 72, 40, 96, 9, ES_AUTOHSCROLL
+ LTEXT "Port:", 103, 16, 57, 20, 8
+ LISTBOX IDC_PORT, 72, 56, 96, 11, LBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Commands:", 104, 16, 73, 47, 8
+ EDITTEXT IDC_COMMANDS, 72, 72, 96, 10, ES_AUTOHSCROLL
+ PUSHBUTTON "Add", IDC_ADD, 8, 94, 40, 14
+ PUSHBUTTON "Remove", IDC_REMOVE, 50, 94, 40, 14
+ PUSHBUTTON "OK", IDOK, 93, 94, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 136, 94, 40, 14
+END
diff --git a/private/tapi/dev/sp/atsp32/makefile b/private/tapi/dev/sp/atsp32/makefile
new file mode 100644
index 000000000..707a71e8b
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# atsp32 Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/atsp32/makefile.def b/private/tapi/dev/sp/atsp32/makefile.def
new file mode 100644
index 000000000..0b6f58439
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/makefile.def
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# atsp32.tsp Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..\..
+
+WANT_C932=1
+#WANT_C1032=1
+IS_32 = TRUE
+WIN32=1
+IS_OEM = TRUE
+
+BUILDDLL=1
+DLLENTRY=DllMain
+
+DEPENDNAME=..\depend.mk
+
+CLEANLIST=*.tsp
+
+TARGETS=atsp32.tsp
+
+SRCDIR=..
+
+BUILD_COFF=1
+
+
+L32EXE=atsp32.tsp # Name of exe.
+L32DEF=..\atsp32.def # Our def file.
+L32MAP=atsp32.map # Our map file.
+L32SYM=atsp32.sym # Our sym file.
+L32LIBS=\
+ $(W32LIBID)\kernel32.lib \
+ $(W32LIBID)\user32.lib \
+ $(W32LIBID)\gdi32.lib \
+ $(W32LIBID)\advapi32.lib \
+ $(ROOT)\dev\tools\c932\lib\msvcrt.lib \
+ $(ROOT)\dev\tools\c932\lib\rpcrt4.lib
+
+
+
+L32RES=atsp.res # Resource file.
+
+
+#-----------------------------------------------------------------------
+# Object files
+#-----------------------------------------------------------------------
+L32OBJS = atsp.obj
+
+
+L32FLAGS=$(L32FLAGS)
+
+
+!include $(ROOT)\dev\master.mk
+
+INCLUDE=..;..\..\..\client;..\..\..\server;$(INCLUDE)
+
+#CFLAGS=$(CFLAGS) -DWIN32=100 -DWIN_32=100 -Od -Fc -GD
+CFLAGS=$(CFLAGS) -DWIN32=100 -DWIN_32=100 -Ox
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
+
diff --git a/private/tapi/dev/sp/atsp32/resource.h b/private/tapi/dev/sp/atsp32/resource.h
new file mode 100644
index 000000000..1c54fcb2d
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/resource.h
@@ -0,0 +1,7 @@
+#define IDD_DIALOG1 101
+#define IDC_DEVICES 1001
+#define IDC_NAME 1002
+#define IDC_PORT 1003
+#define IDC_COMMANDS 1004
+#define IDC_ADD 1005
+#define IDC_REMOVE 1006
diff --git a/private/tapi/dev/sp/atsp32/sources b/private/tapi/dev/sp/atsp32/sources
new file mode 100644
index 000000000..023525573
--- /dev/null
+++ b/private/tapi/dev/sp/atsp32/sources
@@ -0,0 +1,54 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=atsp32
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=TSP
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib
+
+DLLBASE=0x61000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+SOURCES=atsp.c \
+ atsp.rc
+
+C_DEFINES=-DTAPI_NT=1
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/dirs b/private/tapi/dev/sp/dirs
new file mode 100644
index 000000000..467867ebb
--- /dev/null
+++ b/private/tapi/dev/sp/dirs
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989-92 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=\
+ atsp32 \
+ esp.new \
+ kmddsp
diff --git a/private/tapi/dev/sp/esp.new/dirs b/private/tapi/dev/sp/esp.new/dirs
new file mode 100644
index 000000000..f304d7bc5
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/dirs
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989-92 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=\
+ tsp \
+ exe \
+ ui
diff --git a/private/tapi/dev/sp/esp.new/espidl.acf b/private/tapi/dev/sp/esp.new/espidl.acf
new file mode 100644
index 000000000..be47cd031
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/espidl.acf
@@ -0,0 +1,5 @@
+[implicit_handle(handle_t hEsp)]
+interface esp
+{
+
+}
diff --git a/private/tapi/dev/sp/esp.new/espidl.idl b/private/tapi/dev/sp/esp.new/espidl.idl
new file mode 100644
index 000000000..eb0e8d03e
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/espidl.idl
@@ -0,0 +1,66 @@
+[ uuid(2F5F6521-CA47-1068-B31A-00DD010662DB),
+ version(1.0),
+#ifdef __midl
+ ms_union,
+#endif // __midl
+ pointer_default(unique)
+]
+
+interface esp
+
+{
+
+long
+ESPAttach(
+ [in] long lProcessID,
+ [out] long *phShutdownEvent,
+ [out] long *phDebugOutputEvent,
+ [out] long *phWidgetEventsEvent
+ );
+
+void
+ESPSetOptions(
+ [in] long lDebugOptions,
+ [in] long lCompletionMode
+ );
+
+void
+ESPCompleteRequest(
+ [in] long lAsyncReqInfo,
+ [in] long lResult
+ );
+
+long
+ESPEvent(
+ [in] long htDevice,
+ [in] long htCall,
+ [in] long dwMsg,
+ [in] long dwParam1,
+ [in] long dwParam2,
+ [in] long dwParam3
+ );
+
+void
+ESPGetDebugOutput(
+ [out, length_is(*plSize), size_is(*plSize)] char pBuffer[],
+ [in, out] long *plSize
+ );
+
+void
+ESPGetWidgetEvents(
+ [out, length_is(*plSize), size_is(*plSize)] char pBuffer[],
+ [in, out] long *plSize
+ );
+
+long
+ESPStartPBXThread(
+ [in, length_is(lSize), size_is(lSize)] char pBuffer[],
+ [in] long lSize
+ );
+
+long
+ESPStopPBXThread(
+ [in] long dummy
+ );
+
+}
diff --git a/private/tapi/dev/sp/esp.new/exe/esp.ico b/private/tapi/dev/sp/esp.new/exe/esp.ico
new file mode 100644
index 000000000..516eb3f84
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/esp.ico
Binary files differ
diff --git a/private/tapi/dev/sp/esp.new/exe/espexe.c b/private/tapi/dev/sp/esp.new/exe/espexe.c
new file mode 100644
index 000000000..97c95e9e9
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/espexe.c
@@ -0,0 +1,3351 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ espexe.c
+
+Abstract:
+
+
+
+Author:
+
+ Dan Knudson (DanKn) 15-Sep-1995
+
+Revision History:
+
+--*/
+
+
+#include "espexe.h"
+
+
+int
+WINAPI
+WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow
+ )
+{
+ MSG msg;
+ HACCEL hAccel;
+
+
+ ghInstance = hInstance;
+
+ ghwndMain = CreateDialog(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG1),
+ (HWND)NULL,
+ (DLGPROC) MainWndProc
+ );
+
+ if (!ghwndMain)
+ {
+ }
+
+ hAccel = LoadAccelerators(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDR_ACCELERATOR1)
+ );
+
+ while (GetMessage (&msg, (HWND) NULL, 0, 0))
+ {
+ if (!TranslateAccelerator (ghwndMain, hAccel, &msg))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+
+ DestroyWindow (ghwndMain);
+
+ DestroyAcceleratorTable (hAccel);
+
+ return 0;
+}
+
+
+void
+ESPServiceThread(
+ LPVOID pParams
+ )
+{
+ HANDLE hInitEvent;
+
+
+ ShowStr ("ESPServiceThread: enter");
+
+ hInitEvent = CreateEvent(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ FALSE, // auto-reset
+ FALSE, // non-signaled
+ "ESPevent"
+ );
+
+ while (1)
+ {
+ HANDLE ahEvents[3];
+
+
+wait_for_esp_to_init:
+
+ gbESPLoaded = FALSE;
+
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON1), FALSE);
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON2), FALSE);
+
+
+ //
+ //
+ //
+
+ {
+ DWORD dwUsedSize;
+ RPC_STATUS status;
+
+ #define CNLEN 25 // computer name length
+ #define UNCLEN CNLEN+2 // \\computername
+ #define PATHLEN 260 // Path
+ #define MAXPROTSEQ 20 // protocol sequence "ncacn_np"
+
+ unsigned char pszNetworkAddress[UNCLEN+1];
+ unsigned char * pszUuid = NULL;
+ unsigned char * pszOptions = NULL;
+ unsigned char * pszStringBinding = NULL;
+
+
+ pszNetworkAddress[0] = '\0';
+
+ status = RpcStringBindingCompose(
+ pszUuid,
+ "ncalrpc",
+ pszNetworkAddress,
+ "esplpc",
+ pszOptions,
+ &pszStringBinding
+ );
+
+ if (status)
+ {
+ ShowStr(
+ "RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
+ status,
+ pszNetworkAddress
+ );
+ }
+
+ status = RpcBindingFromStringBinding(
+ pszStringBinding,
+ &hEsp
+ );
+
+ if (status)
+ {
+ ShowStr(
+ "RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
+ status,
+ pszStringBinding
+ );
+ }
+
+ RpcStringFree (&pszStringBinding);
+ }
+
+ ShowStr ("ESPServiceThread: waiting for esp init event");
+
+ WaitForSingleObject (hInitEvent, INFINITE);
+
+
+ RpcTryExcept
+ {
+ ESPAttach(
+ (long) GetCurrentProcessId(),
+ (long *) ahEvents, // &hShutdownEvent
+ (long *) ahEvents + 1, // &hDebugOutputEvent
+ (long *) ahEvents + 2 // &hWidgetEventsEvent
+ );
+ }
+ RpcExcept (1)
+ {
+ // BUGBUG
+ }
+ RpcEndExcept
+
+ gbESPLoaded = TRUE;
+
+ UpdateESPOptions();
+
+ gbPBXThreadRunning = FALSE;
+ EnableMenuItem (ghMenu, IDM_PBXSTART, MF_BYCOMMAND | MF_ENABLED);
+
+ ShowStr ("ESPServiceThread: esp init event signaled, attached to esp");
+
+ gpWidgets = NULL;
+
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON1), TRUE);
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON2), TRUE);
+
+
+ //
+ //
+ //
+
+ {
+ DWORD dwBufSize = 50 * sizeof (WIDGETEVENT);
+ char *buf = MyAlloc (dwBufSize);
+
+
+ while (1)
+ {
+ switch (WaitForMultipleObjects (3, ahEvents, FALSE, INFINITE))
+ {
+ case WAIT_OBJECT_0+1:
+ {
+ DWORD dwSize;
+
+get_debug_output:
+ dwSize = dwBufSize - 1;
+
+ RpcTryExcept
+ {
+ ESPGetDebugOutput (buf, &dwSize);
+ }
+ RpcExcept (1)
+ {
+ break; // BUGBUG
+ }
+ RpcEndExcept
+
+ buf[dwSize] = 0;
+
+ xxxShowStr (buf);
+
+ if (dwSize == (dwBufSize - 1))
+ {
+ char *newBuf;
+
+
+ if ((newBuf = MyAlloc (2*dwBufSize)))
+ {
+ MyFree (buf);
+ buf = newBuf;
+ dwBufSize *= 2;
+ }
+
+ goto get_debug_output;
+ }
+
+ break;
+ }
+ case WAIT_OBJECT_0+2:
+ {
+ DWORD dwSize, i, dwNumEvents;
+ PWIDGETEVENT pEvent;
+
+get_widget_events:
+ dwSize = dwBufSize;
+
+ RpcTryExcept
+ {
+ ESPGetWidgetEvents (buf, &dwSize);
+ }
+ RpcExcept (1)
+ {
+ break; // BUGBUG
+ }
+ RpcEndExcept
+
+ dwNumEvents = dwSize / sizeof (WIDGETEVENT);
+
+ pEvent = (PWIDGETEVENT) buf;
+
+ for (i = 0; i < dwNumEvents; i++)
+ {
+ ProcessWidgetEvent (pEvent++);
+ }
+
+ if (dwSize == dwBufSize)
+ {
+ goto get_widget_events;
+ }
+
+ break;
+ }
+ default:
+
+ RpcBindingFree (&hEsp);
+
+ SaveIniFileSettings();
+
+ CloseHandle (ahEvents[0]);
+ CloseHandle (ahEvents[1]);
+ CloseHandle (ahEvents[2]);
+
+ MyFree (buf);
+
+ SendMessage (ghwndList1, LB_RESETCONTENT, 0, 0);
+
+ while (gpWidgets)
+ {
+ PMYWIDGET pNextWidget = gpWidgets->pNext;
+
+
+ MyFree (gpWidgets);
+ gpWidgets = pNextWidget;
+ }
+
+ // BUGBUG disable lots of menuitems, etc.
+
+ EnableMenuItem(
+ ghMenu,
+ IDM_PBXSTART,
+ MF_BYCOMMAND | MF_GRAYED
+ );
+
+ EnableMenuItem(
+ ghMenu,
+ IDM_PBXSTOP,
+ MF_BYCOMMAND | MF_GRAYED
+ );
+
+ if (gbAutoClose)
+ {
+ gbESPLoaded = FALSE;
+ PostMessage (ghwndMain, WM_CLOSE, 0, 0);
+ goto ESPServiceThread_exit;
+ }
+
+ goto wait_for_esp_to_init;
+
+ } // switch (WaitForMultipleObjects (...))
+
+ } // while (1)
+ }
+
+ } // while (1)
+
+ESPServiceThread_exit:
+
+ CloseHandle (hInitEvent);
+
+ ExitThread (0);
+}
+
+
+BOOL
+CALLBACK
+MainWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ static int icyButton, icyBorder, cyWnd;
+ static BOOL bCaptured = FALSE;
+ static LONG xCapture, cxVScroll;
+ static HFONT hFont;
+ static HICON hIcon;
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ char buf[64];
+ RECT rect;
+
+
+ //
+ // Init some globals
+ //
+
+ hIcon = LoadIcon (ghInstance, MAKEINTRESOURCE(IDI_ICON1));
+
+ ghwndMain = hwnd;
+ ghwndList1 = GetDlgItem (hwnd, IDC_LIST1);
+ ghwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ ghwndEdit = GetDlgItem (hwnd, IDC_EDIT1);
+ ghMenu = GetMenu (hwnd);
+
+ icyBorder = GetSystemMetrics (SM_CYFRAME);
+ GetWindowRect (GetDlgItem (hwnd, IDC_BUTTON1), &rect);
+ icyButton = (rect.bottom - rect.top) + icyBorder + 3;
+ cxVScroll = 2*GetSystemMetrics (SM_CXVSCROLL);
+
+ gbPBXThreadRunning = FALSE;
+
+ EnableMenuItem (ghMenu, IDM_PBXSTART, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem (ghMenu, IDM_PBXSTOP, MF_BYCOMMAND | MF_GRAYED);
+
+
+ //
+ //
+ //
+
+ {
+ typedef struct _XXX
+ {
+ DWORD dwDefValue;
+
+ LPCSTR pszValueName;
+
+ LPDWORD pdwValue;
+
+ } XXX, *PXXX;
+
+ XXX axxx[] =
+ {
+ { DEF_SPI_VERSION, "TSPIVersion", &gdwTSPIVersion },
+ { 0, "AutoClose", &gbAutoClose },
+ { DEF_NUM_LINES, "NumLines", &gdwNumLines },
+ { DEF_NUM_ADDRS_PER_LINE, "NumAddrsPerLine", &gdwNumAddrsPerLine },
+ { DEF_NUM_CALLS_PER_ADDR, "NumCallsPerAddr", &gdwNumCallsPerAddr },
+ { DEF_NUM_PHONES, "NumPhones", &gdwNumPhones },
+ { DEF_DEBUG_OPTIONS, "DebugOutput", &gdwDebugOptions },
+ { DEF_COMPLETION_MODE, "Completion", &gdwCompletionMode },
+ { 0, "DisableUI", &gbDisableUI },
+ { 1, "AutoGatherGenerateMsgs", &gbAutoGatherGenerateMsgs },
+ { 0, NULL, NULL },
+ };
+ DWORD i;
+
+ for (i = 0; axxx[i].pszValueName; i++)
+ {
+ *(axxx[i].pdwValue) = (DWORD) GetProfileInt(
+ szMySection,
+ axxx[i].pszValueName,
+ (int) axxx[i].dwDefValue
+ );
+ }
+
+ for (i = 0; i < 6; i++)
+ {
+ if (gdwDebugOptions & (0x1 << i))
+ {
+ CheckMenuItem(
+ ghMenu,
+ IDM_SHOWFUNCENTRY + i,
+ MF_BYCOMMAND | MF_CHECKED
+ );
+ }
+ }
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SYNCCOMPL + gdwCompletionMode,
+ MF_BYCOMMAND | MF_CHECKED
+ );
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_AUTOCLOSE,
+ MF_BYCOMMAND | (gbAutoClose ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_AUTOGATHERGENERATEMSGS,
+ MF_BYCOMMAND |
+ (gbAutoGatherGenerateMsgs ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_DISABLEUI,
+ MF_BYCOMMAND | (gbDisableUI ? MF_CHECKED : MF_UNCHECKED)
+ );
+ }
+
+
+ //
+ // Set control fonts
+ //
+
+ {
+ HWND hwndCtrl = GetDlgItem (hwnd, IDC_BUTTON1);
+ hFont = CreateFont(
+ 13, 5, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 34, "MS Sans Serif"
+ );
+
+ do
+ {
+ SendMessage(
+ hwndCtrl,
+ WM_SETFONT,
+ (WPARAM) hFont,
+ 0
+ );
+
+ } while ((hwndCtrl = GetNextWindow (hwndCtrl, GW_HWNDNEXT)));
+ }
+
+
+ //
+ // Read in control size ratios
+ //
+
+ cxWnd = GetProfileInt (szMySection, "cxWnd", 100);
+ cxList1 = GetProfileInt (szMySection, "cxList1", 25);
+
+
+ //
+ // Send self WM_SIZE to position child controls correctly
+ //
+
+ GetProfileString(
+ szMySection,
+ "Left",
+ "0",
+ buf,
+ 63
+ );
+
+ if (strcmp (buf, "max") == 0)
+ {
+ ShowWindow (hwnd, SW_SHOWMAXIMIZED);
+ }
+ else if (strcmp (buf, "min") == 0)
+ {
+ ShowWindow (hwnd, SW_SHOWMINIMIZED);
+ }
+ else
+ {
+ int left, top, right, bottom;
+ int cxScreen = GetSystemMetrics (SM_CXSCREEN);
+ int cyScreen = GetSystemMetrics (SM_CYSCREEN);
+
+
+ left = GetProfileInt (szMySection, "Left", 0);
+ top = GetProfileInt (szMySection, "Top", 3*cyScreen/4);
+ right = GetProfileInt (szMySection, "Right", cxScreen);
+ bottom = GetProfileInt (szMySection, "Bottom", cyScreen);
+
+ SetWindowPos(
+ hwnd,
+ HWND_TOP,
+ left,
+ top,
+ right - left,
+ bottom - top,
+ SWP_SHOWWINDOW
+ );
+
+ GetClientRect (hwnd, &rect);
+
+ SendMessage(
+ hwnd,
+ WM_SIZE,
+ 0,
+ MAKELONG((rect.right-rect.left),(rect.bottom-rect.top))
+ );
+
+ ShowWindow (hwnd, SW_SHOW);
+ }
+
+
+ //
+ // Start the service thread
+ //
+
+ {
+ DWORD dwThreadID;
+ HANDLE hThread;
+
+
+ hThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE) ESPServiceThread,
+ NULL,
+ 0,
+ &dwThreadID
+ );
+
+ SetThreadPriority (hThread, THREAD_PRIORITY_ABOVE_NORMAL);
+
+ CloseHandle (hThread);
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ UINT uiCtrlID = (UINT) LOWORD((DWORD)wParam);
+
+
+ switch (uiCtrlID)
+ {
+ case IDM_INSTALL:
+ case IDM_UNINSTALL:
+ {
+ BOOL bESPInstalled = FALSE;
+ LONG lResult;
+ DWORD i;
+ FARPROC pfnLineGetProviderList, pfnLineAddProvider,
+ pfnLineRemoveProvider;
+ HINSTANCE hTapi32;
+ LINEPROVIDERLIST providerList, *pProviderList;
+ LPLINEPROVIDERENTRY pProviderEntry;
+
+
+ if (!(hTapi32 = LoadLibrary ("tapi32.dll")))
+ {
+ ShowStr(
+ "LoadLibrary(tapi32.dll) failed, err=%d",
+ GetLastError()
+ );
+
+ break;
+ }
+
+ if (!(pfnLineAddProvider = GetProcAddress(
+ hTapi32,
+ "lineAddProvider"
+ )) ||
+
+ !(pfnLineGetProviderList = GetProcAddress(
+ hTapi32,
+ "lineGetProviderList"
+ )) ||
+
+ !(pfnLineRemoveProvider = GetProcAddress(
+ hTapi32,
+ "lineRemoveProvider"
+ )))
+ {
+ ShowStr(
+ "GetProcAddr(tapi32,lineAddProvider) failed, err=%d",
+ GetLastError()
+ );
+
+ goto install_free_tapi32;
+ }
+
+ providerList.dwTotalSize = sizeof (LINEPROVIDERLIST);
+
+ if ((lResult = (*pfnLineGetProviderList)(0x20000, &providerList)))
+ {
+ ShowStr(
+ "ESP (Un)Install: error, lineGetProviderList returned x%x",
+ lResult
+ );
+
+ goto install_free_tapi32;
+ }
+
+ pProviderList = MyAlloc (providerList.dwNeededSize);
+
+ pProviderList->dwTotalSize = providerList.dwNeededSize;
+
+ if ((lResult = (*pfnLineGetProviderList)(0x20000, pProviderList)))
+ {
+ ShowStr(
+ "ESP (Un)Install: error, lineGetProviderList returned x%x",
+ lResult
+ );
+
+ goto install_free_provider_list;
+ }
+
+ pProviderEntry = (LPLINEPROVIDERENTRY) (((LPBYTE) pProviderList) +
+ pProviderList->dwProviderListOffset);
+
+ for (i = 0; i < pProviderList->dwNumProviders; i++)
+ {
+ int j;
+ char *pszProviderName = (char *) (((LPBYTE) pProviderList) +
+ pProviderEntry->dwProviderFilenameOffset);
+
+
+ //
+ // Convert the string to lower case, then see if it
+ // contains "esp32.tsp"
+ //
+
+ for (j = 0; pszProviderName[j]; j++)
+ {
+ pszProviderName[j] |= 0x20;
+ }
+
+ if (strstr (pszProviderName, "esp32.tsp"))
+ {
+ bESPInstalled = TRUE;
+ break;
+ }
+
+ pProviderEntry++;
+ }
+
+ if (uiCtrlID == IDM_INSTALL)
+ {
+ if (bESPInstalled)
+ {
+ ShowStr ("ESP Install: already installed");
+ }
+ else
+ {
+ DWORD dwPermanentProviderID;
+
+
+ if ((lResult = (*pfnLineAddProvider)(
+ "esp32.tsp",
+ hwnd,
+ &dwPermanentProviderID
+
+ )) == 0)
+ {
+ ShowStr(
+ "ESP Install: success, ProviderID=%d",
+ dwPermanentProviderID
+ );
+ }
+ else
+ {
+ ShowStr(
+ "ESP Install: error, lineAddProvider returned x%x",
+ lResult
+ );
+ }
+ }
+ }
+ else // IDM_UNINSTALL
+ {
+ if (bESPInstalled)
+ {
+ if ((lResult = (*pfnLineRemoveProvider)(
+ pProviderEntry->dwPermanentProviderID,
+ hwnd
+
+ )) == 0)
+ {
+ ShowStr ("ESP Uninstall: success");
+ }
+ else
+ {
+ ShowStr(
+ "ESP Uninstall: error, lineRemoveProvider " \
+ "returned x%x",
+ lResult
+ );
+ }
+ }
+ else
+ {
+ ShowStr ("ESP Uninstall: not installed");
+ }
+ }
+
+install_free_provider_list:
+
+ MyFree (pProviderList);
+
+install_free_tapi32:
+
+ FreeLibrary (hTapi32);
+
+ break;
+ }
+ case IDM_AUTOCLOSE:
+ {
+ gbAutoClose = (gbAutoClose ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_AUTOCLOSE,
+ MF_BYCOMMAND | (gbAutoClose ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ SaveIniFileSettings();
+ break;
+ }
+ case IDM_AUTOGATHERGENERATEMSGS:
+ {
+ gbAutoGatherGenerateMsgs =
+ (gbAutoGatherGenerateMsgs ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_AUTOGATHERGENERATEMSGS,
+ MF_BYCOMMAND |
+ (gbAutoGatherGenerateMsgs ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ SaveIniFileSettings();
+ break;
+ }
+ case IDM_DISABLEUI:
+ {
+ gbDisableUI = (gbDisableUI ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_DISABLEUI,
+ MF_BYCOMMAND | (gbDisableUI ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ SaveIniFileSettings();
+ break;
+ }
+ case IDM_DEFAULTS:
+ {
+ EVENT_PARAM params[] =
+ {
+ { "TSPI Version", PT_ORDINAL, gdwTSPIVersion, aVersions },
+ { "Num lines", PT_DWORD, gdwNumLines, 0 },
+ { "Num addrs per line", PT_DWORD, gdwNumAddrsPerLine, 0 },
+ { "Num calls per addr", PT_DWORD, gdwNumCallsPerAddr, 0 },
+ { "Num phones", PT_DWORD, gdwNumPhones, 0 },
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 5, "Default values", 0, params };
+
+
+ if (DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ hwnd,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) == IDOK)
+ {
+ char *aszValueNames[] =
+ {
+ "TSPIVersion",
+ "NumLines",
+ "NumAddrsPerLine",
+ "NumCallsPerAddr",
+ "NumPhones",
+ NULL
+ };
+ LPDWORD lpdwValues[] =
+ {
+ &gdwTSPIVersion,
+ &gdwNumLines,
+ &gdwNumAddrsPerLine,
+ &gdwNumCallsPerAddr,
+ &gdwNumPhones
+ };
+ int i;
+ BOOL bValuesChanged = FALSE;
+
+
+ for (i = 0; aszValueNames[i]; i++)
+ {
+ char buf[16];
+
+ if (*(lpdwValues[i]) != params[i].dwValue)
+ {
+ *(lpdwValues[i]) = params[i].dwValue;
+
+ wsprintf (buf, "%d", params[i].dwValue);
+
+ WriteProfileString(
+ szMySection,
+ aszValueNames[i],
+ buf
+ );
+
+ bValuesChanged = TRUE;
+ }
+ }
+
+ if (bValuesChanged && gbESPLoaded)
+ {
+ MessageBox(
+ hwnd,
+ "New values will not take effect until provider is" \
+ " shutdown and reinitialized",
+ "ESP Defaults",
+ MB_OK
+ );
+ }
+ }
+
+ break;
+ }
+ case IDC_BUTTON1:
+ {
+ LONG lSel;
+ EVENT_PARAM params[] =
+ {
+ { "htLine", PT_DWORD, 0, 0 },
+ { "htCall", PT_DWORD, 0, 0 },
+ { "dwMsg", PT_ORDINAL, 0, aLineMsgs },
+ { "dwParam1", PT_DWORD, 0, 0 },
+ { "dwParam2", PT_DWORD, 0, 0 },
+ { "dwParam3", PT_DWORD, 0, 0 },
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 6, "Line event", 0, params };
+
+
+ lSel = SendMessage (ghwndList1, LB_GETCURSEL, 0, 0);
+
+ if (lSel != LB_ERR)
+ {
+ PMYWIDGET pWidget;
+
+
+ pWidget = (PMYWIDGET) SendMessage(
+ ghwndList1,
+ LB_GETITEMDATA,
+ lSel,
+ 0
+ );
+
+ if (pWidget->dwWidgetType == WIDGETTYPE_LINE)
+ {
+ params[0].dwValue =
+ params[0].dwDefValue = pWidget->htXxx;
+ }
+ else if (pWidget->dwWidgetType == WIDGETTYPE_CALL)
+ {
+ params[1].dwValue =
+ params[1].dwDefValue = pWidget->htXxx;
+
+ do
+ {
+ pWidget = pWidget->pPrev;
+ }
+ while (pWidget->dwWidgetType != WIDGETTYPE_LINE);
+
+ params[0].dwValue =
+ params[0].dwDefValue = pWidget->htXxx;
+ }
+ }
+
+ if (DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ hwnd,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) == IDOK)
+ {
+ ESPEvent(
+ params[0].dwValue,
+ params[1].dwValue,
+ params[2].dwValue,
+ params[3].dwValue,
+ params[4].dwValue,
+ params[5].dwValue
+ );
+ }
+
+ break;
+ }
+ case IDC_BUTTON2:
+ {
+ LONG lSel;
+ EVENT_PARAM params[] =
+ {
+ { "htPhone", PT_DWORD, 0, 0 },
+ { "dwMsg", PT_ORDINAL, 0, aPhoneMsgs },
+ { "dwParam1", PT_DWORD, 0, 0 },
+ { "dwParam2", PT_DWORD, 0, 0 },
+ { "dwParam3", PT_DWORD, 0, 0 },
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 5, "Phone event", 0, params };
+
+
+ lSel = SendMessage (ghwndList1, LB_GETCURSEL, 0, 0);
+
+ if (lSel != LB_ERR)
+ {
+ PMYWIDGET pWidget;
+
+
+ pWidget = (PMYWIDGET) SendMessage(
+ ghwndList1,
+ LB_GETITEMDATA,
+ lSel,
+ 0
+ );
+
+ if (pWidget->dwWidgetType == WIDGETTYPE_PHONE)
+ {
+ params[0].dwValue =
+ params[0].dwDefValue = pWidget->htXxx;
+ }
+ }
+
+ if (DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ hwnd,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) == IDOK)
+ {
+ ESPEvent(
+ params[0].dwValue,
+ 0,
+ params[1].dwValue,
+ params[2].dwValue,
+ params[3].dwValue,
+ params[4].dwValue
+ );
+ }
+
+ break;
+ }
+ case IDC_ENTER:
+ {
+ HWND hwndFocus = GetFocus();
+
+
+ if (hwndFocus == ghwndList1)
+ {
+ goto show_widget_dialog;
+ }
+ else if (hwndFocus == ghwndList2)
+ {
+ goto complete_pending_request;
+ }
+
+ break;
+ }
+ case IDC_LIST1:
+ {
+ if (HIWORD(wParam) == LBN_DBLCLK)
+ {
+ LONG lSel;
+
+show_widget_dialog:
+
+ lSel = SendMessage (ghwndList1, LB_GETCURSEL, 0, 0);
+
+ if (lSel != LB_ERR)
+ {
+ //
+ // Determine the widget type, & put up the
+ // appropriate properties dlg
+ //
+
+ PMYWIDGET pWidget;
+
+
+ pWidget = (PMYWIDGET) SendMessage(
+ ghwndList1,
+ LB_GETITEMDATA,
+ lSel,
+ 0
+ );
+
+ switch (pWidget->dwWidgetType)
+ {
+ case WIDGETTYPE_LINE:
+ {
+ char szTitle[32];
+ EVENT_PARAM params[] =
+ {
+ { "<under construction>", PT_DWORD, 0, 0 }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, szTitle, 0, params };
+
+
+ wsprintf(
+ szTitle,
+ "Line%d properties",
+ pWidget->dwWidgetID
+ );
+
+ if (DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ hwnd,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) == IDOK)
+ {
+ }
+
+ break;
+ }
+ case WIDGETTYPE_CALL:
+ {
+ char szTitle[32];
+ EVENT_PARAM params[] =
+ {
+ { "Call state", PT_ORDINAL, pWidget->dwCallState, aCallStates },
+ { "Call state mode", PT_DWORD, 0, 0 }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 2, szTitle, 0, params };
+
+
+ wsprintf(
+ szTitle,
+ "Call x%x properties",
+ pWidget->hdXxx
+ );
+
+ if (DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ hwnd,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) == IDOK)
+ {
+ if (params[0].dwValue != pWidget->dwCallState)
+ {
+ ESPEvent(
+ 0,
+ pWidget->hdXxx,
+ LINE_CALLSTATE,
+ params[0].dwValue,
+ params[1].dwValue,
+ 0
+ );
+ }
+ }
+
+ break;
+ }
+ case WIDGETTYPE_PHONE:
+ {
+ char szTitle[32];
+ EVENT_PARAM params[] =
+ {
+ { "<under construction>", PT_DWORD, 0, 0 }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, szTitle, 0, params };
+
+
+ wsprintf(
+ szTitle,
+ "Phone%d properties",
+ pWidget->dwWidgetID
+ );
+
+ if (DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ hwnd,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) == IDOK)
+ {
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case IDC_LIST2:
+ {
+ if (HIWORD(wParam) == LBN_DBLCLK)
+ {
+ LONG lSel;
+
+complete_pending_request:
+
+ lSel = SendMessage (ghwndList2, LB_GETCURSEL, 0, 0);
+
+ if (lSel != LB_ERR)
+ {
+ LONG lResult = 0, pAsyncReqInfo;
+
+
+ if (gdwDebugOptions & MANUAL_RESULTS)
+ {
+ EVENT_PARAM params[] =
+ {
+ { "lResult", PT_ORDINAL, 0, aLineErrs }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, "Completing request", 0, params };
+
+
+ if (DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ hwnd,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) != IDOK)
+ {
+ break;
+ }
+
+ lResult = (LONG) params[0].dwValue;
+ }
+
+ pAsyncReqInfo = SendMessage(
+ ghwndList2,
+ LB_GETITEMDATA,
+ (WPARAM) lSel,
+ 0
+ );
+
+ SendMessage(
+ ghwndList2,
+ LB_DELETESTRING,
+ (WPARAM) lSel,
+ 0
+ );
+
+ ESPCompleteRequest (pAsyncReqInfo, lResult);
+ }
+ }
+
+ break;
+ }
+ case IDC_PREVCTRL:
+ {
+ HWND hwndPrev = GetNextWindow (GetFocus (), GW_HWNDPREV);
+
+
+ if (!hwndPrev)
+ {
+ hwndPrev = GetDlgItem (hwnd, IDC_LIST2);
+ }
+
+ SetFocus (hwndPrev);
+ break;
+ }
+ case IDC_NEXTCTRL:
+ {
+ HWND hwndNext = GetNextWindow (GetFocus (), GW_HWNDNEXT);
+
+
+ if (!hwndNext)
+ {
+ hwndNext = GetDlgItem (hwnd, IDC_BUTTON1);
+ }
+
+ SetFocus (hwndNext);
+ break;
+ }
+ case IDC_BUTTON4: // "Clear"
+
+ SetWindowText (ghwndEdit, "");
+ break;
+
+ case IDM_PBXCONFIG:
+
+ DialogBox(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG4),
+ hwnd,
+ (DLGPROC) PBXConfigDlgProc,
+ );
+
+ break;
+
+ case IDM_PBXSTART:
+ {
+ DWORD dwTID, aPBXSettings[2];
+
+
+ aPBXSettings[0] = (gPBXSettings[0].dwNumber ?
+ gPBXSettings[0].dwTime / gPBXSettings[0].dwNumber : 0);
+
+ aPBXSettings[1] = (gPBXSettings[1].dwNumber ?
+ gPBXSettings[1].dwTime / gPBXSettings[1].dwNumber : 0);
+
+ if (ESPStartPBXThread ((char *) aPBXSettings, 2 * sizeof(DWORD))
+ == 0)
+ {
+ gbPBXThreadRunning = TRUE;
+
+ EnableMenuItem(
+ ghMenu,
+ IDM_PBXSTART,
+ MF_BYCOMMAND | MF_GRAYED
+ );
+
+ EnableMenuItem(
+ ghMenu,
+ IDM_PBXSTOP,
+ MF_BYCOMMAND | MF_ENABLED
+ );
+ }
+
+ break;
+ }
+ case IDM_PBXSTOP:
+
+ if (ESPStopPBXThread (0) == 0)
+ {
+ gbPBXThreadRunning = FALSE;
+
+ EnableMenuItem(
+ ghMenu,
+ IDM_PBXSTOP,
+ MF_BYCOMMAND | MF_GRAYED
+ );
+
+ EnableMenuItem(
+ ghMenu,
+ IDM_PBXSTART,
+ MF_BYCOMMAND | MF_ENABLED
+ );
+ }
+ break;
+
+ case IDM_USAGE:
+
+ DialogBox(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG5),
+ (HWND) hwnd,
+ (DLGPROC) HelpDlgProc
+ );
+
+ break;
+
+ case IDM_ABOUT:
+
+ DialogBox(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG2),
+ (HWND) hwnd,
+ (DLGPROC) AboutDlgProc
+ );
+
+ break;
+
+ case IDC_EDIT1:
+
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ //
+ // Watch to see if the edit control is full, & if so
+ // purge the top half of the text to make room for more
+ //
+
+ int length = GetWindowTextLength (ghwndEdit);
+
+
+ if (length > 20000)
+ {
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)0 ,
+ (LPARAM) 10000
+ );
+
+ SendMessage(
+ ghwndEdit,
+ EM_REPLACESEL,
+ 0,
+ (LPARAM) (char far *) ""
+ );
+
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)0xfffffffd,
+ (LPARAM)0xfffffffe
+ );
+ }
+
+ UpdateESPOptions();
+ }
+ break;
+
+ case IDM_SYNCCOMPL:
+ case IDM_ASYNCCOMPL:
+ case IDM_SYNCASYNCCOMPL:
+ case IDM_MANUALCOMPL:
+
+ if ((uiCtrlID - IDM_SYNCCOMPL) != gdwCompletionMode)
+ {
+ CheckMenuItem(
+ ghMenu,
+ IDM_SYNCCOMPL + gdwCompletionMode,
+ MF_BYCOMMAND | MF_UNCHECKED
+ );
+
+ gdwCompletionMode = uiCtrlID - IDM_SYNCCOMPL;
+
+ CheckMenuItem(
+ ghMenu,
+ uiCtrlID,
+ MF_BYCOMMAND | MF_CHECKED
+ );
+
+ UpdateESPOptions();
+ }
+
+ break;
+
+ case IDM_SHOWFUNCENTRY:
+ case IDM_SHOWFUNCPARAMS:
+ case IDM_SHOWFUNCEXIT:
+ case IDM_SHOWEVENTS:
+ case IDM_SHOWCOMPLETIONS:
+ case IDM_MANUALRESULTS:
+ {
+ DWORD dwBitField = 0x1 << (uiCtrlID - IDM_SHOWFUNCENTRY);
+
+ gdwDebugOptions ^= dwBitField;
+
+ CheckMenuItem(
+ ghMenu,
+ uiCtrlID,
+ MF_BYCOMMAND | (gdwDebugOptions & dwBitField ?
+ MF_CHECKED : MF_UNCHECKED)
+ );
+
+ UpdateESPOptions();
+
+ break;
+ }
+ case IDM_SHOWALL:
+ case IDM_SHOWNONE:
+ {
+ int i;
+
+ gdwDebugOptions = (uiCtrlID == IDM_SHOWALL ? 0xffffffff : 0);
+
+ for (i = 0; i < 5; i++)
+ {
+ CheckMenuItem(
+ ghMenu,
+ IDM_SHOWFUNCENTRY + i,
+ MF_BYCOMMAND | (uiCtrlID == IDM_SHOWALL ?
+ MF_CHECKED : MF_UNCHECKED)
+ );
+
+ UpdateESPOptions();
+ }
+
+ break;
+ }
+ case IDM_EXIT:
+
+ goto do_wm_close;
+ break;
+
+ } // switch (LOWORD((DWORD)wParam))
+
+ break;
+ }
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+
+ BeginPaint (hwnd, &ps);
+
+ if (IsIconic (hwnd))
+ {
+ DrawIcon (ps.hdc, 0, 0, hIcon);
+ }
+ else
+ {
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+#ifdef WIN32
+ MoveToEx (ps.hdc, 0, 0, NULL);
+#else
+ MoveTo (ps.hdc, 0, 0);
+#endif
+ LineTo (ps.hdc, 5000, 0);
+
+#ifdef WIN32
+ MoveToEx (ps.hdc, 0, icyButton - 4, NULL);
+#else
+ MoveTo (ps.hdc, 0, icyButton - 4);
+#endif
+ LineTo (ps.hdc, 5000, icyButton - 4);
+ }
+
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ case WM_SIZE:
+ {
+ if (wParam != SIZE_MINIMIZED)
+ {
+ LONG width = (LONG)LOWORD(lParam);
+
+
+ //
+ // Adjust globals based on new size
+ //
+
+ cxWnd = (cxWnd ? cxWnd : 1); // avoid div by 0
+
+ cxList1 = (cxList1 * width) / cxWnd;
+ cxWnd = width;
+ cyWnd = ((int)HIWORD(lParam)) - icyButton;
+
+
+ //
+ // Now reposition the child windows
+ //
+
+ SetWindowPos(
+ ghwndList1,
+ GetNextWindow (ghwndList1, GW_HWNDPREV),
+ 0,
+ icyButton,
+ (int) cxList1,
+ 2*cyWnd/3,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndList2,
+ GetNextWindow (ghwndList2, GW_HWNDPREV),
+ 0,
+ icyButton + 2*cyWnd/3 + icyBorder,
+ (int) cxList1,
+ cyWnd/3 - icyBorder,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndEdit,
+ GetNextWindow (ghwndEdit, GW_HWNDPREV),
+ (int) cxList1 + icyBorder,
+ icyButton,
+ (int)width - ((int)cxList1 + icyBorder),
+ cyWnd,
+ SWP_SHOWWINDOW
+ );
+
+ InvalidateRect (hwnd, NULL, TRUE);
+ }
+ break;
+ }
+ case WM_MOUSEMOVE:
+ {
+ LONG x = (LONG)((short)LOWORD(lParam));
+ int y = (int)((short)HIWORD(lParam));
+ int cxList1New;
+
+
+ if (((y > icyButton) && (x > cxList1)) || bCaptured)
+ {
+ SetCursor(
+ LoadCursor ((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_SIZEWE))
+ );
+ }
+
+ if (bCaptured)
+ {
+ x = (x < cxVScroll ? cxVScroll : x);
+ x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x);
+
+ cxList1New = (int) (cxList1 + x - xCapture);
+
+ SetWindowPos(
+ ghwndList1,
+ GetNextWindow (ghwndList1, GW_HWNDPREV),
+ 0,
+ icyButton,
+ cxList1New,
+ 2*cyWnd/3,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndList2,
+ GetNextWindow (ghwndList2, GW_HWNDPREV),
+ 0,
+ icyButton + 2*cyWnd/3 + icyBorder,
+ cxList1New,
+ cyWnd/3 - icyBorder,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndEdit,
+ GetNextWindow (ghwndEdit, GW_HWNDPREV),
+ (int) cxList1New + icyBorder,
+ icyButton,
+ (int)cxWnd - (cxList1New + icyBorder),
+ cyWnd,
+ SWP_SHOWWINDOW
+ );
+ }
+
+ break;
+ }
+ case WM_LBUTTONDOWN:
+ {
+ if (((int)((short)HIWORD(lParam)) > icyButton) &&
+ ((int)((short)LOWORD(lParam)) > cxList1))
+ {
+ xCapture = (LONG)LOWORD(lParam);
+
+ SetCapture (hwnd);
+
+ bCaptured = TRUE;
+ }
+
+ break;
+ }
+ case WM_LBUTTONUP:
+ {
+ if (bCaptured)
+ {
+ POINT p;
+ LONG x;
+
+ GetCursorPos (&p);
+ MapWindowPoints (HWND_DESKTOP, hwnd, &p, 1);
+ x = (LONG) p.x;
+
+ ReleaseCapture();
+
+ x = (x < cxVScroll ? cxVScroll : x);
+ x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x);
+
+ cxList1 = cxList1 + (x - xCapture);
+
+ bCaptured = FALSE;
+
+ InvalidateRect (hwnd, NULL, TRUE);
+ }
+
+ break;
+ }
+ case WM_CLOSE:
+
+do_wm_close:
+
+ if (!gbESPLoaded)
+ {
+ SaveIniFileSettings();
+ DestroyIcon (hIcon);
+ DeleteObject (hFont);
+ PostQuitMessage (0);
+ }
+
+ break;
+
+ } // switch (msg)
+
+ return FALSE;
+}
+
+
+void
+UpdateSummary(
+ HWND hwnd,
+ PPBXSETTING pPBXSettings
+ )
+{
+ int i, j;
+
+
+ SendDlgItemMessage (hwnd, IDC_LIST4, LB_RESETCONTENT, 0, 0);
+
+ for (i = 0, j= 0; i < NUM_PBXSETTINGS; i++)
+ {
+ if (pPBXSettings[i].dwNumber)
+ {
+ char buf[64];
+
+
+ wsprintf(
+ buf, "%s %s per %s",
+ aPBXNumbers[pPBXSettings[i].dwNumber].pszVal,
+ pPBXSettings[i].pszEvent,
+ aPBXTimes[pPBXSettings[i].dwTime].pszVal
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST4,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) buf
+ );
+
+ SendDlgItemMessage (hwnd, IDC_LIST4, LB_SETITEMDATA, j, i);
+
+ j++;
+ }
+ }
+}
+
+
+BOOL
+CALLBACK
+PBXConfigDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ static PBXSETTING pbxSettings[NUM_PBXSETTINGS];
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ int i, j;
+
+
+ //
+ // Mkae a local copy of the global PBX settings
+ //
+
+ for (i = 0; i < NUM_PBXSETTINGS; i++)
+ {
+
+ pbxSettings[i].pszEvent = gPBXSettings[i].pszEvent;
+
+ //
+ // For Number & time fields convert from values to indexes
+ //
+
+ for (j = 0; aPBXNumbers[j].pszVal; j++)
+ {
+ if (gPBXSettings[i].dwNumber == aPBXNumbers[j].dwVal)
+ {
+ pbxSettings[i].dwNumber = j;
+ }
+ }
+
+ for (j = 0; aPBXTimes[j].pszVal; j++)
+ {
+ if (gPBXSettings[i].dwTime == aPBXTimes[j].dwVal)
+ {
+ pbxSettings[i].dwTime = j;
+ }
+ }
+ }
+
+ if (gbPBXThreadRunning)
+ {
+ EnableWindow (GetDlgItem (hwnd, IDC_RESET), FALSE);
+ }
+ else
+ {
+ for (i = 0; aPBXNumbers[i].pszVal; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) aPBXNumbers[i].pszVal
+ );
+ }
+
+ for (i = 0; i < NUM_PBXSETTINGS; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) pbxSettings[i].pszEvent
+ );
+ }
+
+ for (i = 0; aPBXTimes[i].pszVal; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST3,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) aPBXTimes[i].pszVal
+ );
+ }
+ }
+
+ UpdateSummary (hwnd, pbxSettings);
+
+ break;
+ }
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_LIST1:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ LONG lSelSetting, lSelNumber;
+
+
+ lSelSetting = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ lSelNumber = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ pbxSettings[lSelSetting].dwNumber = lSelNumber;
+
+ UpdateSummary (hwnd, pbxSettings);
+ }
+
+ break;
+
+ case IDC_LIST2:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ LONG lSelSetting;
+
+
+ lSelSetting = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_SETCURSEL,
+ pbxSettings[lSelSetting].dwNumber,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST3,
+ LB_SETCURSEL,
+ pbxSettings[lSelSetting].dwTime,
+ 0
+ );
+
+ UpdateSummary (hwnd, pbxSettings);
+ }
+
+ break;
+
+ case IDC_LIST3:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ LONG lSelSetting, lSelTime;
+
+
+ lSelSetting = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ lSelTime = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST3,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ pbxSettings[lSelSetting].dwTime = lSelTime;
+
+ UpdateSummary (hwnd, pbxSettings);
+ }
+
+ break;
+
+ case IDC_LIST4:
+
+ if ((HIWORD(wParam) == LBN_SELCHANGE) && !gbPBXThreadRunning)
+ {
+ LONG lSel, lEntryToSel;
+
+
+ lSel = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST4,
+ LB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ lEntryToSel = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST4,
+ LB_GETITEMDATA,
+ lSel,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_SETCURSEL,
+ pbxSettings[lEntryToSel].dwNumber,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETCURSEL,
+ lEntryToSel,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST3,
+ LB_SETCURSEL,
+ pbxSettings[lEntryToSel].dwTime,
+ 0
+ );
+ }
+
+ break;
+
+ case IDC_RESET:
+
+ memset (pbxSettings, 0, NUM_PBXSETTINGS * sizeof(PBXSETTING));
+
+ UpdateSummary (hwnd, pbxSettings);
+
+ break;
+
+ case IDOK:
+ {
+ int i;
+
+ // convert from indexes to values
+
+ for (i = 0; i < NUM_PBXSETTINGS; i++)
+ {
+ gPBXSettings[i].dwNumber =
+ aPBXNumbers[pbxSettings[i].dwNumber].dwVal;
+ gPBXSettings[i].dwTime =
+ aPBXTimes[pbxSettings[i].dwTime].dwVal;
+ }
+
+ // drop thru to IDM_CANCEL code
+
+ }
+ case IDCANCEL:
+
+ EndDialog (hwnd, 0);
+ break;
+ }
+
+ break;
+
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ } // switch (msg)
+
+ return FALSE;
+}
+
+
+BOOL
+CALLBACK
+AboutDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ EndDialog (hwnd, 0);
+ break;
+ }
+ break;
+
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+CALLBACK
+HelpDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ static char szUsageText[] =
+
+ "ABSTRACT:\r\n" \
+ " ESP is a TAPI Service Provider that supports\r\n" \
+ "multiple virtual line and phone devices. It is\r\n" \
+ "configurable, requires no special hardware,\r\n" \
+ "and implements the entire Telephony Service\r\n" \
+ "Provider Interface (including Win95 TAPI\r\n" \
+ "extensions). ESP will work in both Windows 3.1/\r\n" \
+ "TAPI 1.0 and Windows95/TAPI 1.1 systems.\r\n" \
+
+ "\r\nGETTING STARTED:\r\n" \
+ " 1. Choose 'File/Install' to install ESP.\r\n" \
+ " 2. Start a TAPI application and try to make\r\n" \
+ "a call on one of ESP's line devices (watch for\r\n" \
+ "messages appearing in the ESP window).\r\n" \
+ " *. Choose 'File/Uninstall' to uninstall ESP.\r\n" \
+
+ "\r\nMORE INFO:\r\n" \
+ " * Double-click on a line, call, or phone\r\n" \
+ "widget (in upper-left listbox) to view/modify\r\n" \
+ "properties. The 'hd'widget field is the driver\r\n" \
+ "handle; the 'ht' field is the TAPI handle.\r\n" \
+ " * Press the 'LEvt' or 'PEvt' button to\r\n" \
+ "indicate a line or phone event to TAPI.DLL.\r\n" \
+ "Press the 'Call+' button to indicate an incoming\r\n" \
+ " call.\r\n" \
+ " * Choose 'Options/Default values...' to\r\n" \
+ "modify provider paramters (SPI version, etc.)\r\n" \
+ " * All parameter values displayed in\r\n" \
+ "hexadecimal unless specified otherwise (strings\r\n" \
+ "displayed by contents).\r\n" \
+ " * Choose 'Options/Complete async requests/Xxx'\r\n" \
+ "to specify async requests completion behavior.\r\n" \
+ "Manually-completed requests appear in lower-left\r\n" \
+ "listbox.";
+
+ SetDlgItemText (hwnd, IDC_EDIT1, szUsageText);
+
+ break;
+ }
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ EndDialog (hwnd, 0);
+ break;
+ }
+ break;
+
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+void
+ProcessWidgetEvent(
+ PWIDGETEVENT pEvent
+ )
+{
+ char buf[64];
+ long lIndex = 0xfffffffe;
+ PMYWIDGET pWidget = gpWidgets;
+
+
+ switch (pEvent->dwWidgetType)
+ {
+ case WIDGETTYPE_ASYNCREQUEST:
+ {
+ wsprintf (buf, "ReqID=x%x", pEvent->dwWidgetID);
+
+ // BUGBUG want to incl the req type at some point (str table lookup)
+
+ lIndex = SendMessage (ghwndList2, LB_ADDSTRING, 0, (LPARAM) buf);
+
+ SendMessage(
+ ghwndList2,
+ LB_SETITEMDATA,
+ (WPARAM) lIndex,
+ (LPARAM) pEvent->pAsyncReqInfo
+ );
+
+ return;
+ }
+ case WIDGETTYPE_LINE:
+ {
+ for (lIndex = 0;; lIndex++)
+ {
+ if ((pWidget->dwWidgetType == WIDGETTYPE_LINE) &&
+ (pWidget->dwWidgetID == pEvent->dwWidgetID))
+ {
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+
+ if (pEvent->htXxx == 0)
+ {
+ PMYWIDGET pWidget2 = pWidget->pNext;
+
+
+ // line closing so nuke all following calls (listbox & widg list)
+
+ while (pWidget2->dwWidgetType == WIDGETTYPE_CALL)
+ {
+ pWidget->pNext = pWidget2->pNext;
+
+ MyFree (pWidget2);
+
+ pWidget2 = pWidget->pNext;
+
+ SendMessage(
+ ghwndList1,
+ LB_DELETESTRING,
+ (WPARAM) lIndex + 1,
+ (LPARAM) 0
+ );
+ }
+
+ if (pWidget2)
+ {
+ pWidget2->pPrev = pWidget;
+ }
+
+ wsprintf (buf, "Line%d (CLOSED)", pEvent->dwWidgetID);
+
+ }
+ else
+ {
+ wsprintf (buf, "Line%d, hd=x%x, ht=x%x",
+ pEvent->dwWidgetID,
+ pEvent->hdXxx,
+ pEvent->htXxx
+ );
+ }
+
+ pWidget->hdXxx = pEvent->hdXxx;
+ pWidget->htXxx = pEvent->htXxx;
+
+ break;
+ }
+ case WIDGETTYPE_CALL:
+ {
+ long lIndexLine = 0;
+ PMYWIDGET pLine = NULL;
+
+
+ for (lIndex = 0; pWidget; lIndex++)
+ {
+ if ((pWidget->dwWidgetType == WIDGETTYPE_LINE) &&
+ (pWidget->dwWidgetID == pEvent->dwWidgetID))
+ {
+ pLine = pWidget;
+ lIndexLine = lIndex;
+ }
+
+ if ((pWidget->dwWidgetType == WIDGETTYPE_CALL) &&
+ (pWidget->hdXxx == pEvent->hdXxx))
+ {
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+
+ if (pWidget)
+ {
+ //
+ // Found call in list
+ //
+
+ if (pEvent->htXxx)
+ {
+ //
+ // Update the call's listbox entry
+ //
+
+ int i;
+
+
+ for (i = 0; pEvent->dwCallState != aCallStates[i].dwVal; i++);
+
+ wsprintf(
+ buf,
+ " hdCall=x%x, ht=x%x, %s Addr=%d",
+ pEvent->hdXxx,
+ pEvent->htXxx,
+ aCallStates[i].pszVal,
+ pEvent->dwCallAddressID
+ );
+
+ pWidget->dwCallState = pEvent->dwCallState;
+ }
+ else
+ {
+ //
+ // Call was destroyed, so remove it from the listbox &
+ // widget lists and nuke the data structure
+ //
+
+ SendMessage(
+ ghwndList1,
+ LB_DELETESTRING,
+ (WPARAM) lIndex,
+ (LPARAM) 0
+ );
+
+ pWidget->pPrev->pNext = pWidget->pNext;
+
+ if (pWidget->pNext)
+ {
+ pWidget->pNext->pPrev = pWidget->pPrev;
+ }
+
+ MyFree (pWidget);
+
+ return;
+ }
+ }
+ else if (pEvent->htXxx)
+ {
+ //
+ // Call wasn't in the list, but it's valid so add it to
+ // listbox & widget lists
+ //
+
+ int i;
+
+
+ pWidget = MyAlloc (sizeof (MYWIDGET));
+
+ memcpy (pWidget, pEvent, sizeof (WIDGETEVENT));
+
+ if ((pWidget->pNext = pLine->pNext))
+ {
+ pWidget->pNext->pPrev = pWidget;
+ }
+
+ pWidget->pPrev = pLine;
+ pLine->pNext = pWidget;
+
+ for (i = 0; pEvent->dwCallState != aCallStates[i].dwVal; i++);
+
+ wsprintf(
+ buf,
+ " hdCall=x%x, ht=x%x, %s Addr=%d",
+ pEvent->hdXxx,
+ pEvent->htXxx,
+ aCallStates[i].pszVal,
+ pEvent->dwCallAddressID
+ );
+
+ SendMessage(
+ ghwndList1,
+ LB_INSERTSTRING,
+ (WPARAM) lIndexLine + 1,
+ (LPARAM) buf
+ );
+
+ SendMessage(
+ ghwndList1,
+ LB_SETITEMDATA,
+ (WPARAM) lIndexLine + 1,
+ (LPARAM) pWidget
+ );
+
+ return;
+ }
+
+ break;
+ }
+ case WIDGETTYPE_PHONE:
+ {
+ for (lIndex = 0;; lIndex++)
+ {
+ if ((pWidget->dwWidgetType == WIDGETTYPE_PHONE) &&
+ (pWidget->dwWidgetID == pEvent->dwWidgetID))
+ {
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+
+ if (pEvent->htXxx == 0)
+ {
+ wsprintf (buf, "Phone%d (CLOSED)", pEvent->dwWidgetID);
+ }
+ else
+ {
+ wsprintf (buf, "Phone%d, hd=x%x, ht=x%x",
+ pEvent->dwWidgetID,
+ pEvent->hdXxx,
+ pEvent->htXxx
+ );
+ }
+
+ pWidget->hdXxx = pEvent->hdXxx;
+ pWidget->htXxx = pEvent->htXxx;
+
+ break;
+ }
+ case WIDGETTYPE_STARTUP:
+ {
+ //
+ // Build widget list for "static" devices
+ //
+
+ DWORD i, j;
+ PMYWIDGET pWidget, pLastWidget = NULL;
+
+
+ for (i = 0; i < pEvent->dwNumLines; i++)
+ {
+ pWidget = MyAlloc (sizeof (MYWIDGET));
+
+ pWidget->dwWidgetID = i + pEvent->dwLineDeviceIDBase;
+ pWidget->dwWidgetType = WIDGETTYPE_LINE;
+
+ if ((pWidget->pPrev = pLastWidget))
+ {
+ pLastWidget->pNext = pWidget;
+ }
+ else
+ {
+ gpWidgets = pWidget;
+ }
+
+ pLastWidget = pWidget;
+
+ wsprintf (buf, "Line%d (CLOSED)", pWidget->dwWidgetID);
+
+ SendMessage (ghwndList1, LB_ADDSTRING, 0, (LPARAM) buf);
+ SendMessage (ghwndList1, LB_SETITEMDATA, i, (LPARAM) pWidget);
+ }
+
+ for (j = 0; j < pEvent->dwNumPhones; j++)
+ {
+ pWidget = MyAlloc (sizeof (MYWIDGET));
+
+ pWidget->dwWidgetID = j + pEvent->dwPhoneDeviceIDBase;
+ pWidget->dwWidgetType = WIDGETTYPE_PHONE;
+
+ if ((pWidget->pPrev = pLastWidget))
+ {
+ pLastWidget->pNext = pWidget;
+ }
+ else
+ {
+ gpWidgets = pWidget;
+ }
+
+ pLastWidget = pWidget;
+
+ wsprintf (buf, "Phone%d (CLOSED)", pWidget->dwWidgetID);
+
+ SendMessage (ghwndList1, LB_ADDSTRING, 0, (LPARAM) buf);
+ SendMessage (ghwndList1, LB_SETITEMDATA, i + j, (LPARAM) pWidget);
+ }
+
+ return;
+ }
+ } // switch (pEvent->dwWidgetType)
+
+
+ //
+ // Update the widget's listbox entry given the index &
+ // description filled in above
+ //
+
+ SendMessage (ghwndList1, LB_DELETESTRING, (WPARAM) lIndex, (LPARAM) 0);
+ SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM) lIndex, (LPARAM) buf);
+ SendMessage (ghwndList1, LB_SETITEMDATA, (WPARAM) lIndex, (LPARAM)pWidget);
+}
+
+
+void
+UpdateESPOptions(
+ void
+ )
+{
+ if (gbESPLoaded)
+ {
+ RpcTryExcept
+ {
+ ESPSetOptions(
+ (long) gdwDebugOptions,
+ (long) gdwCompletionMode
+ );
+ }
+ RpcExcept (1)
+ {
+ // BUGBUG
+ }
+ RpcEndExcept
+ }
+}
+
+
+void
+SaveIniFileSettings(
+ void
+ )
+{
+ RECT rect;
+
+
+ GetWindowRect (ghwndMain, &rect);
+
+ {
+ typedef struct _YYY
+ {
+ LPCSTR pszValueName;
+
+ DWORD dwValue;
+
+ } YYY, *PYYY;
+
+ YYY ayyy[] =
+ {
+ { "Left", (DWORD) rect.left },
+ { "Top", (DWORD) rect.top },
+ { "Right", (DWORD) rect.right },
+ { "Bottom", (DWORD) rect.bottom },
+ { "cxWnd", (DWORD) cxWnd },
+ { "cxList1", (DWORD) cxList1 },
+ { "AutoClose", (DWORD) gbAutoClose },
+ { "DebugOutput", (DWORD) gdwDebugOptions },
+ { "Completion", (DWORD) gdwCompletionMode },
+ { "TSPIVersion", (DWORD) gdwTSPIVersion },
+ { "NumLines", (DWORD) gdwNumLines },
+ { "NumAddrsPerLine", (DWORD) gdwNumAddrsPerLine },
+ { "NumCallsPerAddr", (DWORD) gdwNumCallsPerAddr },
+ { "NumPhones", (DWORD) gdwNumPhones },
+ { "AutoGatherGenerateMsgs", (DWORD) gbAutoGatherGenerateMsgs },
+ { "DisableUI", (DWORD) gbDisableUI },
+ { NULL, (DWORD) 0 }
+ };
+ DWORD i = (IsIconic (ghwndMain) ? 6 : 0); // don't chg pos if iconic
+
+
+ for (i = 0; ayyy[i].pszValueName; i++)
+ {
+ char buf[16];
+
+
+ wsprintf (buf, "%d", ayyy[i].dwValue);
+
+ WriteProfileString (szMySection, ayyy[i].pszValueName, buf);
+ }
+ }
+}
+
+
+void
+xxxShowStr(
+ char *psz
+ )
+{
+ SendMessage (ghwndEdit, EM_SETSEL, (WPARAM)0xfffffffd, (LPARAM)0xfffffffe);
+ SendMessage (ghwndEdit, EM_REPLACESEL, 0, (LPARAM) psz);
+ SendMessage (ghwndEdit, EM_SCROLLCARET, 0, 0);
+}
+
+
+void
+ShowStr(
+ char *pszFormat,
+ ...
+ )
+{
+ char buf[256];
+ va_list ap;
+
+
+ va_start(ap, pszFormat);
+
+ wvsprintf (buf, pszFormat, ap);
+
+ strcat (buf, "\r\n");
+
+ xxxShowStr (buf);
+
+ va_end(ap);
+}
+
+
+LPVOID
+MyAlloc(
+ size_t numBytes
+ )
+{
+ LPVOID p = (LPVOID) LocalAlloc (LPTR, numBytes);
+
+
+ if (!p)
+ {
+ ShowStr ("Error: MyAlloc () failed");
+ }
+
+ return p;
+}
+
+
+void
+MyFree(
+ LPVOID p
+ )
+{
+#if DBG
+
+ //
+ // Fill the buf to free with 0x5a's to facilitate debugging
+ //
+
+ memset (p, 0x5a, (size_t) LocalSize (LocalHandle (p)));
+
+#endif
+
+ LocalFree (p);
+}
+
+
+void
+__RPC_FAR *
+__RPC_API
+midl_user_allocate(
+ size_t len
+ )
+{
+ return NULL;
+}
+
+
+void
+__RPC_API
+midl_user_free(
+ void __RPC_FAR * ptr
+ )
+{
+}
+
+
+BOOL
+ScanForDWORD(
+ char far *pBuf,
+ LPDWORD lpdw
+ )
+{
+ char c;
+ BOOL bValid = FALSE;
+ DWORD d = 0;
+
+ while ((c = *pBuf))
+ {
+ if ((c >= '0') && (c <= '9'))
+ {
+ c -= '0';
+ }
+ else if ((c >= 'a') && (c <= 'f'))
+ {
+ c -= ('a' - 10);
+ }
+ else if ((c >= 'A') && (c <= 'F'))
+ {
+ c -= ('A' - 10);
+ }
+ else
+ {
+ break;
+ }
+
+ bValid = TRUE;
+
+ d *= 16;
+
+ d += (DWORD) c;
+
+ pBuf++;
+ }
+
+ if (bValid)
+ {
+ *lpdw = d;
+ }
+
+ return bValid;
+}
+
+
+BOOL
+CALLBACK
+ValuesDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ DWORD i;
+
+ static HWND hwndCombo, hwndList1, hwndList2;
+ static LONG lLastSel;
+ static char szComboText[MAX_STRING_PARAM_SIZE];
+ static PEVENT_PARAM_HEADER pParamsHeader;
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ hwndList1 = GetDlgItem (hwnd, IDC_LIST1);
+ hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ hwndCombo = GetDlgItem (hwnd, IDC_COMBO1);
+
+ lLastSel = -1;
+ pParamsHeader = (PEVENT_PARAM_HEADER) lParam;
+
+
+ //
+ // Limit the max text length for the combobox's edit field
+ // (NOTE: A combobox ctrl actually has two child windows: a
+ // edit ctrl & a listbox. We need to get the hwnd of the
+ // child edit ctrl & send it the LIMITTEXT msg.)
+ //
+
+ {
+ HWND hwndChild = GetWindow (hwndCombo, GW_CHILD);
+
+
+ while (hwndChild)
+ {
+ char buf[8];
+
+
+ GetClassName (hwndChild, buf, 7);
+
+ if (_stricmp (buf, "edit") == 0)
+ {
+ break;
+ }
+
+ hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
+ }
+
+ SendMessage(
+ hwndChild,
+ EM_LIMITTEXT,
+ (WPARAM) MAX_STRING_PARAM_SIZE - 1,
+ 0
+ );
+ }
+
+
+ //
+ // Misc other init
+ //
+
+ SetWindowText (hwnd, pParamsHeader->pszDlgTitle);
+
+ for (i = 0; i < pParamsHeader->dwNumParams; i++)
+ {
+ SendMessage(
+ hwndList1,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pParamsHeader->aParams[i].szName
+ );
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ if (lLastSel != -1)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ //
+ // Save val of currently selected param
+ //
+
+ i = GetDlgItemText(
+ hwnd,
+ IDC_COMBO1,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendMessage (hwndCombo, CB_GETCURSEL, 0, 0);
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD) 0;
+ }
+ else // "Valid string"
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].buf[MAX_STRING_PARAM_SIZE-1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!ScanForDWORD(
+ buf,
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+ // Drop thru to IDCANCEL cleanup code
+
+ case IDCANCEL:
+
+ EndDialog (hwnd, (int)LOWORD(wParam));
+ break;
+
+ case IDC_LIST1:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ char buf[MAX_STRING_PARAM_SIZE] = "";
+ LPCSTR lpstr = buf;
+ LONG lSel = SendMessage (hwndList1, LB_GETCURSEL, 0, 0);
+
+
+ if (lLastSel != -1)
+ {
+ //
+ // Save the old param value
+ //
+
+ i = GetWindowText(
+ hwndCombo,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendMessage (hwndCombo, CB_GETCURSEL, 0,0);
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue =
+ (DWORD)0;
+ }
+ else // "Valid string" or no sel
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].buf[MAX_STRING_PARAM_SIZE - 1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!ScanForDWORD(
+ buf,
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+
+ SendMessage (hwndList2, LB_RESETCONTENT, 0, 0);
+ SendMessage (hwndCombo, CB_RESETCONTENT, 0, 0);
+
+ switch (pParamsHeader->aParams[lSel].dwType)
+ {
+ case PT_STRING:
+ {
+ char * aszOptions[] =
+ {
+ "NUL (dwXxxSize=0)",
+ "Valid string"
+ };
+
+
+ for (i = 0; i < 2; i++)
+ {
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) aszOptions[i]
+ );
+ }
+
+ if (pParamsHeader->aParams[lSel].dwValue == 0)
+ {
+ i = 0;
+ buf[0] = 0;
+ }
+ else
+ {
+ i = 1;
+ lpstr = (LPCSTR) pParamsHeader->aParams[lSel].dwValue;
+ }
+
+ SendMessage (hwndCombo, CB_SETCURSEL, (WPARAM) i, 0);
+
+ break;
+ }
+ case PT_DWORD:
+ {
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "0000000"
+ );
+
+ if (pParamsHeader->aParams[lSel].dwDefValue)
+ {
+ //
+ // Add the default val string to the combo
+ //
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwDefValue
+ );
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) buf
+ );
+ }
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "ffffffff"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_ORDINAL:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].pszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue ==
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_FLAGS:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].pszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue &
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select all"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ } //switch
+
+ SetWindowText (hwndCombo, lpstr);
+
+ lLastSel = lSel;
+ }
+ break;
+
+ case IDC_LIST2:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ //
+ // BUGBUG in the PT_ORDINAL case we should compare the
+ // currently selected item(s) against the previous DWORD
+ // val and figure out which item we need to deselect,
+ // if any, in order to maintain a mutex of values
+ //
+
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].pLookup;
+ char buf[16];
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendMessage (hwndList2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) MyAlloc ((size_t)lSelCount * sizeof(int));
+
+ SendMessage(
+ hwndList2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_FLAGS)
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+ }
+ else // if (.dwType == PT_ORDINAL)
+ {
+ if (lSelCount == 1)
+ {
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ else if (lSelCount == 2)
+ {
+ //
+ // Figure out which item we need to de-select, since
+ // we're doing ordinals & only want 1 item selected
+ // at a time
+ //
+
+ GetWindowText (hwndCombo, buf, 16);
+
+ if (ScanForDWORD (buf, &dwValue))
+ {
+ if (pLookup[ai[0]].dwVal == dwValue)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[0]
+ );
+
+ dwValue = pLookup[ai[1]].dwVal;
+ }
+ else
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[1]
+ );
+
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ else if (lSelCount > 2)
+ {
+ //
+ // Determine previous selection & de-select all the
+ // latest selections
+ //
+
+ GetDlgItemText (hwnd, IDC_COMBO1, buf, 16);
+
+ if (ScanForDWORD (buf, &dwValue))
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ if (pLookup[ai[i]].dwVal != dwValue)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[i]
+ );
+ }
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ }
+
+ MyFree (ai);
+ wsprintf (buf, "%08lx", dwValue);
+ SetWindowText (hwndCombo, buf);
+ }
+ break;
+
+ case IDC_COMBO1:
+
+ switch (HIWORD(wParam))
+ {
+ case CBN_SELCHANGE:
+ {
+ LONG lSel = SendMessage (hwndCombo, CB_GETCURSEL, 0, 0);
+
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_ORDINAL:
+
+ //
+ // The only option here is "select none"
+ //
+
+ strcpy (szComboText, "00000000");
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+ break;
+
+ case PT_FLAGS:
+ {
+ BOOL bSelect = (lSel ? TRUE : FALSE);
+
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) bSelect,
+ (LPARAM) -1
+ );
+
+ if (bSelect)
+ {
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].pLookup;
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendMessage (hwndList2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) MyAlloc(
+ (size_t)lSelCount * sizeof(int)
+ );
+
+ SendMessage(
+ hwndList2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+
+ MyFree (ai);
+ wsprintf (szComboText, "%08lx", dwValue);
+
+ }
+ else
+ {
+ strcpy (szComboText, "00000000");
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+ }
+ case PT_STRING:
+
+ if (lSel == 1)
+ {
+ strncpy(
+ szComboText,
+ pParamsHeader->aParams[lLastSel].buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ szComboText[MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ else
+ {
+ szComboText[0] = 0;
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+
+ case PT_DWORD:
+
+ break;
+
+ } // switch
+ break;
+ }
+ case CBN_EDITCHANGE:
+ {
+ //
+ // If user entered text in the edit field then copy the
+ // text to our buffer
+ //
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_STRING)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ GetWindowText (hwndCombo, buf, MAX_STRING_PARAM_SIZE);
+
+ strncpy(
+ pParamsHeader->aParams[lLastSel].buf,
+ buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ pParamsHeader->aParams[lLastSel].buf
+ [MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ break;
+ }
+ } // switch
+
+ } // switch
+
+ break;
+ }
+ case WM_USER+55:
+
+ SetWindowText (hwndCombo, szComboText);
+ break;
+
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/private/tapi/dev/sp/esp.new/exe/espexe.def b/private/tapi/dev/sp/esp.new/exe/espexe.def
new file mode 100644
index 000000000..ed1eea8b6
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/espexe.def
@@ -0,0 +1,13 @@
+NAME ESPEXE
+STUB 'WINSTUB.EXE'
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE MULTIPLE
+HEAPSIZE 2048
+STACKSIZE 16384
+
+EXPORTS
+ MainWndProc
+ PBXConfigDlgProc
+ AboutDlgProc
+ HelpDlgProc
+ ValuesDlgProc
diff --git a/private/tapi/dev/sp/esp.new/exe/espexe.h b/private/tapi/dev/sp/esp.new/exe/espexe.h
new file mode 100644
index 000000000..a2209be92
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/espexe.h
@@ -0,0 +1,410 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ espexe.h
+
+Abstract:
+
+
+
+Author:
+
+ Dan Knudson (DanKn) 15-Sep-1995
+
+Revision History:
+
+--*/
+
+
+#include "windows.h"
+#include "tapi.h"
+#include "tspi.h"
+#include "..\tsp\intrface.h"
+#include "resource.h"
+#include "espidl.h"
+
+
+#define MAX_STRING_PARAM_SIZE 32
+
+#define PT_DWORD 1
+#define PT_FLAGS 2
+#define PT_STRING 3
+#define PT_ORDINAL 4
+
+typedef struct _MYWIDGET
+{
+ DWORD dwWidgetID;
+
+ DWORD dwWidgetType;
+
+ DWORD hdXxx;
+
+ DWORD htXxx;
+
+ DWORD dwCallState;
+
+ DWORD dwCallAddressID;
+
+ struct _MYWIDGET *pPrev;
+
+ struct _MYWIDGET *pNext;
+
+} MYWIDGET, *PMYWIDGET;
+
+
+typedef struct _LOOKUP
+{
+ DWORD dwVal;
+
+ char far *pszVal;
+
+} LOOKUP, *PLOOKUP;
+
+
+typedef struct _PBXSETTING
+{
+ DWORD dwNumber;
+
+ LPCSTR pszEvent;
+
+ DWORD dwTime;
+
+} PBXSETTING, *PPBXSETTING;
+
+
+typedef struct _EVENT_PARAM
+{
+ char far *szName;
+
+ DWORD dwType;
+
+ DWORD dwValue;
+
+ union
+ {
+ PLOOKUP pLookup;
+
+ char far *buf;
+
+ LPVOID ptr;
+
+ DWORD dwDefValue;
+
+ };
+
+} EVENT_PARAM, far *PEVENT_PARAM;
+
+
+typedef struct _EVENT_PARAM_HEADER
+{
+ DWORD dwNumParams;
+
+ LPSTR pszDlgTitle;
+
+ DWORD dwEventType;
+
+ PEVENT_PARAM aParams;
+
+} EVENT_PARAM_HEADER, far *PEVENT_PARAM_HEADER;
+
+
+
+LOOKUP aPBXNumbers[] =
+{
+ { 0, "0" },
+ { 1, "1" },
+ { 2, "2" },
+ { 5, "5" },
+ { 10, "10" },
+ { 20, "20" },
+ { 50, "50" },
+ { 100, "100" },
+ { 200, "200" },
+ { 500, "500" },
+ { 1000, "1000" },
+ { 0, NULL }
+};
+
+
+LOOKUP aPBXTimes[] =
+{
+ { 1000, "second" },
+ { 60000, "minute" },
+ { 3600000, "hour" },
+ { 86400000, "day" },
+ { 604800000, "week" },
+ { 0, NULL }
+};
+
+
+#define NUM_PBXSETTINGS 2
+
+
+PBXSETTING gPBXSettings[NUM_PBXSETTINGS] =
+{
+ { 0, "incoming calls", 0 },
+ { 0, "disconnections", 0 }
+};
+
+
+LOOKUP aCallStates[] =
+{
+ { LINECALLSTATE_IDLE ,"IDLE" },
+ { LINECALLSTATE_OFFERING ,"OFFERING" },
+ { LINECALLSTATE_ACCEPTED ,"ACCEPTED" },
+ { LINECALLSTATE_DIALTONE ,"DIALTONE" },
+ { LINECALLSTATE_DIALING ,"DIALING" },
+ { LINECALLSTATE_RINGBACK ,"RINGBACK" },
+ { LINECALLSTATE_BUSY ,"BUSY" },
+ { LINECALLSTATE_SPECIALINFO ,"SPECIALINFO" },
+ { LINECALLSTATE_CONNECTED ,"CONNECTED" },
+ { LINECALLSTATE_PROCEEDING ,"PROCEEDING" },
+ { LINECALLSTATE_ONHOLD ,"ONHOLD" },
+ { LINECALLSTATE_CONFERENCED ,"CONFERENCED" },
+ { LINECALLSTATE_ONHOLDPENDCONF ,"ONHOLDPENDCONF" },
+ { LINECALLSTATE_ONHOLDPENDTRANSFER ,"ONHOLDPENDTRANSFER" },
+ { LINECALLSTATE_DISCONNECTED ,"DISCONNECTED" },
+ { LINECALLSTATE_UNKNOWN ,"UNKNOWN" },
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP aLineErrs[] =
+{
+ { 0 ,"<SUCCESS>" },
+ { LINEERR_ALLOCATED ,"ALLOCATED" },
+ { LINEERR_BADDEVICEID ,"BADDEVICEID" },
+ { LINEERR_BEARERMODEUNAVAIL ,"BEARERMODEUNAVAIL" },
+ { LINEERR_CALLUNAVAIL ,"CALLUNAVAIL" },
+ { LINEERR_COMPLETIONOVERRUN ,"COMPLETIONOVERRUN" },
+ { LINEERR_CONFERENCEFULL ,"CONFERENCEFULL" },
+ { LINEERR_DIALBILLING ,"DIALBILLING" },
+ { LINEERR_DIALDIALTONE ,"DIALDIALTONE" },
+ { LINEERR_DIALPROMPT ,"DIALPROMPT" },
+ { LINEERR_DIALQUIET ,"DIALQUIET" },
+ { LINEERR_INCOMPATIBLEAPIVERSION ,"INCOMPATIBLEAPIVERSION" },
+ { LINEERR_INCOMPATIBLEEXTVERSION ,"INCOMPATIBLEEXTVERSION" },
+ { LINEERR_INIFILECORRUPT ,"INIFILECORRUPT" },
+ { LINEERR_INUSE ,"INUSE" },
+ { LINEERR_INVALADDRESS ,"INVALADDRESS" },
+ { LINEERR_INVALADDRESSID ,"INVALADDRESSID" },
+ { LINEERR_INVALADDRESSMODE ,"INVALADDRESSMODE" },
+ { LINEERR_INVALADDRESSSTATE ,"INVALADDRESSSTATE" },
+ { LINEERR_INVALAPPHANDLE ,"INVALAPPHANDLE" },
+ { LINEERR_INVALAPPNAME ,"INVALAPPNAME" },
+ { LINEERR_INVALBEARERMODE ,"INVALBEARERMODE" },
+ { LINEERR_INVALCALLCOMPLMODE ,"INVALCALLCOMPLMODE" },
+ { LINEERR_INVALCALLHANDLE ,"INVALCALLHANDLE" },
+ { LINEERR_INVALCALLPARAMS ,"INVALCALLPARAMS" },
+ { LINEERR_INVALCALLPRIVILEGE ,"INVALCALLPRIVILEGE" },
+ { LINEERR_INVALCALLSELECT ,"INVALCALLSELECT" },
+ { LINEERR_INVALCALLSTATE ,"INVALCALLSTATE" },
+ { LINEERR_INVALCALLSTATELIST ,"INVALCALLSTATELIST" },
+ { LINEERR_INVALCARD ,"INVALCARD" },
+ { LINEERR_INVALCOMPLETIONID ,"INVALCOMPLETIONID" },
+ { LINEERR_INVALCONFCALLHANDLE ,"INVALCONFCALLHANDLE" },
+ { LINEERR_INVALCONSULTCALLHANDLE ,"INVALCONSULTCALLHANDLE" },
+ { LINEERR_INVALCOUNTRYCODE ,"INVALCOUNTRYCODE" },
+ { LINEERR_INVALDEVICECLASS ,"INVALDEVICECLASS" },
+ { LINEERR_INVALDEVICEHANDLE ,"INVALDEVICEHANDLE" },
+ { LINEERR_INVALDIALPARAMS ,"INVALDIALPARAMS" },
+ { LINEERR_INVALDIGITLIST ,"INVALDIGITLIST" },
+ { LINEERR_INVALDIGITMODE ,"INVALDIGITMODE" },
+ { LINEERR_INVALDIGITS ,"INVALDIGITS" },
+ { LINEERR_INVALEXTVERSION ,"INVALEXTVERSION" },
+ { LINEERR_INVALGROUPID ,"INVALGROUPID" },
+ { LINEERR_INVALLINEHANDLE ,"INVALLINEHANDLE" },
+ { LINEERR_INVALLINESTATE ,"INVALLINESTATE" },
+ { LINEERR_INVALLOCATION ,"INVALLOCATION" },
+ { LINEERR_INVALMEDIALIST ,"INVALMEDIALIST" },
+ { LINEERR_INVALMEDIAMODE ,"INVALMEDIAMODE" },
+ { LINEERR_INVALMESSAGEID ,"INVALMESSAGEID" },
+ { LINEERR_INVALPARAM ,"INVALPARAM" },
+ { LINEERR_INVALPARKID ,"INVALPARKID" },
+ { LINEERR_INVALPARKMODE ,"INVALPARKMODE" },
+ { LINEERR_INVALPOINTER ,"INVALPOINTER" },
+ { LINEERR_INVALPRIVSELECT ,"INVALPRIVSELECT" },
+ { LINEERR_INVALRATE ,"INVALRATE" },
+ { LINEERR_INVALREQUESTMODE ,"INVALREQUESTMODE" },
+ { LINEERR_INVALTERMINALID ,"INVALTERMINALID" },
+ { LINEERR_INVALTERMINALMODE ,"INVALTERMINALMODE" },
+ { LINEERR_INVALTIMEOUT ,"INVALTIMEOUT" },
+ { LINEERR_INVALTONE ,"INVALTONE" },
+ { LINEERR_INVALTONELIST ,"INVALTONELIST" },
+ { LINEERR_INVALTONEMODE ,"INVALTONEMODE" },
+ { LINEERR_INVALTRANSFERMODE ,"INVALTRANSFERMODE" },
+ { LINEERR_LINEMAPPERFAILED ,"LINEMAPPERFAILED" },
+ { LINEERR_NOCONFERENCE ,"NOCONFERENCE" },
+ { LINEERR_NODEVICE ,"NODEVICE" },
+ { LINEERR_NODRIVER ,"NODRIVER" },
+ { LINEERR_NOMEM ,"NOMEM" },
+ { LINEERR_NOREQUEST ,"NOREQUEST" },
+ { LINEERR_NOTOWNER ,"NOTOWNER" },
+ { LINEERR_NOTREGISTERED ,"NOTREGISTERED" },
+ { LINEERR_OPERATIONFAILED ,"OPERATIONFAILED" },
+ { LINEERR_OPERATIONUNAVAIL ,"OPERATIONUNAVAIL" },
+ { LINEERR_RATEUNAVAIL ,"RATEUNAVAIL" },
+ { LINEERR_RESOURCEUNAVAIL ,"RESOURCEUNAVAIL" },
+ { LINEERR_REQUESTOVERRUN ,"REQUESTOVERRUN" },
+ { LINEERR_STRUCTURETOOSMALL ,"STRUCTURETOOSMALL" },
+ { LINEERR_TARGETNOTFOUND ,"TARGETNOTFOUND" },
+ { LINEERR_TARGETSELF ,"TARGETSELF" },
+ { LINEERR_UNINITIALIZED ,"UNINITIALIZED" },
+ { LINEERR_USERUSERINFOTOOBIG ,"USERUSERINFOTOOBIG" },
+ { LINEERR_REINIT ,"REINIT" },
+ { LINEERR_ADDRESSBLOCKED ,"ADDRESSBLOCKED" },
+ { LINEERR_BILLINGREJECTED ,"BILLINGREJECTED" },
+ { LINEERR_INVALFEATURE ,"INVALFEATURE" },
+ { LINEERR_NOMULTIPLEINSTANCE ,"NOMULTIPLEINSTANCE" },
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP aLineMsgs[] =
+{
+ { LINE_ADDRESSSTATE ,"ADDRESSSTATE" },
+ { LINE_CALLDEVSPECIFIC ,"CALLDEVSPECIFIC" },
+ { LINE_CALLDEVSPECIFICFEATURE ,"CALLDEVSPECIFICFEATURE" },
+ { LINE_CREATEDIALOGINSTANCE ,"CREATEDIALOGINSTANCE" },
+ { LINE_CLOSE ,"CLOSE" },
+ { LINE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINE_DEVSPECIFICFEATURE ,"DEVSPECIFICFEATURE" },
+ { LINE_GATHERDIGITS ,"GATHERDIGITS" },
+ { LINE_GENERATE ,"GENERATE" },
+ { LINE_LINEDEVSTATE ,"LINEDEVSTATE" },
+ { LINE_MONITORDIGITS ,"MONITORDIGITS" },
+ { LINE_MONITORMEDIA ,"MONITORMEDIA" },
+ { LINE_MONITORTONE ,"MONITORTONE" },
+ { LINE_SENDDIALOGINSTANCEDATA ,"SENDDIALOGINSTANCEDATA" },
+ { LINE_REMOVE ,"REMOVE" },
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP aPhoneMsgs[] =
+{
+ { PHONE_BUTTON ,"BUTTON" },
+ { PHONE_CLOSE ,"CLOSE" },
+ { PHONE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { PHONE_STATE ,"STATE" },
+ { PHONE_REMOVE ,"REMOVE" },
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP aVersions[] =
+{
+ { 0x00010003 ,"1.0" },
+ { 0x00010004 ,"1.4" },
+ { 0x00020000 ,"2.0" },
+ { 0xffffffff ,"" }
+};
+
+
+BOOL gbESPLoaded = FALSE;
+ gbPBXThreadRunning,
+ gbAutoClose,
+ gbDisableUI;
+LONG cxList1,
+ cxWnd;
+HWND ghwndMain,
+ ghwndList1,
+ ghwndList2,
+ ghwndEdit;
+DWORD gdwTSPIVersion,
+ gdwNumLines,
+ gdwNumAddrsPerLine,
+ gdwNumCallsPerAddr,
+ gdwNumPhones,
+ gdwDebugOptions,
+ gdwCompletionMode,
+ gbAutoGatherGenerateMsgs;
+HMENU ghMenu;
+HINSTANCE ghInstance;
+PMYWIDGET gpWidgets;
+
+char szMySection[] = "ESP32";
+
+BOOL
+CALLBACK
+MainWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+BOOL
+CALLBACK
+PBXConfigDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+BOOL
+CALLBACK
+AboutDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+BOOL
+CALLBACK
+HelpDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+void
+ProcessWidgetEvent(
+ PWIDGETEVENT pEvent
+ );
+
+void
+UpdateESPOptions(
+ void
+ );
+
+void
+SaveIniFileSettings(
+ void
+ );
+
+void
+xxxShowStr(
+ char *psz
+ );
+
+void
+ShowStr(
+ char *pszFormat,
+ ...
+ );
+
+LPVOID
+MyAlloc(
+ size_t numBytes
+ );
+
+void
+MyFree(
+ LPVOID p
+ );
+
+BOOL
+CALLBACK
+ValuesDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
diff --git a/private/tapi/dev/sp/esp.new/exe/espexe.rc b/private/tapi/dev/sp/esp.new/exe/espexe.rc
new file mode 100644
index 000000000..eeda5ab8f
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/espexe.rc
@@ -0,0 +1,251 @@
+//Microsoft App Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifdef WIN32
+#include "windows.h"
+#else
+#include "afxres.h"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+//////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // APSTUDIO_INVOKED
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 292, 217
+STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU |
+ WS_THICKFRAME | WS_CLIPCHILDREN
+CAPTION "ESP: The Economical Service Provider"
+MENU IDR_MENU2
+FONT 6, "Courier"
+BEGIN
+ PUSHBUTTON "LEvt",IDC_BUTTON1,1,1,16,16,WS_DISABLED
+ PUSHBUTTON "PEvt",IDC_BUTTON2,19,1,16,16,WS_DISABLED
+ PUSHBUTTON "Call+",IDC_BUTTON3,37,1,16,16,WS_DISABLED
+ PUSHBUTTON "Clear",IDC_BUTTON4,55,1,16,16
+ EDITTEXT IDC_EDIT1,129,19,117,195,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL | 0x1000
+ LISTBOX IDC_LIST1,62,17,65,197,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+ LISTBOX IDC_LIST2,0,0,0,0,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+END
+
+IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 185, 69
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "About ESPExe"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,69,50,50,14
+ LTEXT "ESP v2.0",38,88,12,70,7
+ LTEXT "Copyright (c) 1995 Microsoft Corporation",70,24,30,160,
+ 12
+ ICON IDI_ICON1,IDC_STATIC1,60,5,18,20
+END
+
+IDD_DIALOG3 DIALOG DISCARDABLE 0, 0, 205, 192
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Parameters:",55,4,6,42,7
+ LISTBOX IDC_LIST1,4,16,100,148,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Value:",56,116,6,30,7
+ COMBOBOX IDC_COMBO1,116,16,80,47,CBS_SIMPLE | CBS_AUTOHSCROLL |
+ CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Options:",57,116,66,40,9
+ LISTBOX IDC_LIST2,116,75,80,89,LBS_MULTIPLESEL |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",IDOK,116,171,36,14
+ PUSHBUTTON "Cancel",IDCANCEL,160,171,37,14
+END
+
+
+IDD_DIALOG4 DIALOG 6, 18, 192, 138
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU |
+ WS_CLIPCHILDREN
+CAPTION "PBX Simulation"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LISTBOX IDC_LIST1, 4, 18, 50, 40, WS_VSCROLL | WS_TABSTOP
+ LISTBOX IDC_LIST2, 60, 18, 70, 40, WS_VSCROLL | WS_TABSTOP
+ LISTBOX IDC_LIST3, 136, 18, 50, 40, WS_VSCROLL | WS_TABSTOP
+ LISTBOX IDC_LIST4, 4, 72, 182, 40, WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Reset", IDC_RESET, 16, 119, 40, 14
+ PUSHBUTTON "OK", IDOK, 74, 119, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 134, 119, 40, 14
+ LTEXT "Number...", 107, 4, 9, 39, 8
+ LTEXT "of Events...", 108, 60, 9, 49, 8
+ LTEXT "per Time", 109, 136, 9, 33, 8
+ LTEXT "Summary", 110, 5, 62, 34, 8
+END
+
+
+IDD_DIALOG5 DIALOG 6, 18, 192, 173
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU |
+ WS_CLIPCHILDREN
+CAPTION "Using ESPExe"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "OK", IDOK, 66, 157, 60, 14
+ EDITTEXT IDC_EDIT1, 4, 4, 184, 150, ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
+END
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU2 MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Install", IDM_INSTALL
+ MENUITEM "&Uninstall", IDM_UNINSTALL
+ MENUITEM SEPARATOR
+ MENUITEM "&Dump globals", IDM_DUMPGLOBALS
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_EXIT
+ END
+ POPUP "&Options"
+ BEGIN
+ MENUITEM "&Default values...", IDM_DEFAULTS
+ MENUITEM SEPARATOR
+ MENUITEM "Disable UI (for faster auto-testing)",IDM_DISABLEUI
+ MENUITEM SEPARATOR
+ MENUITEM "&Outgoing call state progress...", IDM_OUTCALLSTATEPROG
+ MENUITEM SEPARATOR
+ POPUP "D&ebug Output"
+ BEGIN
+ MENUITEM "Show function &entry", IDM_SHOWFUNCENTRY
+ MENUITEM "Show &parameters", IDM_SHOWFUNCPARAMS
+ MENUITEM "Show function e&xit", IDM_SHOWFUNCEXIT
+ MENUITEM "Show event &notifications", IDM_SHOWEVENTS
+ MENUITEM "Show &completion notifications", IDM_SHOWCOMPLETIONS
+ MENUITEM SEPARATOR
+ MENUITEM "Show &all", IDM_SHOWALL
+ MENUITEM "Show n&one", IDM_SHOWNONE
+ END
+ MENUITEM "Debug&Break() on function entry", IDM_DEBUGBREAK
+ MENUITEM SEPARATOR
+
+ POPUP "Complete async requests"
+ BEGIN
+ MENUITEM "Synchronously", IDM_SYNCCOMPL
+ MENUITEM "Asynchronously", IDM_ASYNCCOMPL
+ MENUITEM "Sync and Async", IDM_SYNCASYNCCOMPL
+ MENUITEM "Manually", IDM_MANUALCOMPL
+ END
+ MENUITEM "User-specified request results", IDM_MANUALRESULTS
+ MENUITEM SEPARATOR
+ MENUITEM "PBX simulation config...", IDM_PBXCONFIG
+ MENUITEM "PBX simulation start", IDM_PBXSTART
+ MENUITEM "PBX simulation stop", IDM_PBXSTOP
+ MENUITEM SEPARATOR
+ MENUITEM "Automatic GATHER/GENERATE msgs", IDM_AUTOGATHERGENERATEMSGS
+ MENUITEM SEPARATOR
+ MENUITEM "Close &window on shutdown", IDM_AUTOCLOSE
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Using ESP...", IDM_USAGE
+ MENUITEM SEPARATOR
+ MENUITEM "&About...", IDM_ABOUT
+ END
+END
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+IDI_ICON1 ICON DISCARDABLE "ESP.ICO"
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ VK_F1, IDM_USAGE, VIRTKEY
+ VK_TAB, IDC_PREVCTRL, VIRTKEY, SHIFT
+ VK_TAB, IDC_NEXTCTRL, VIRTKEY
+ VK_RETURN, IDC_ENTER, VIRTKEY
+END
+
+
+#ifndef APSTUDIO_INVOKED
+////////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+// /////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Economical Service Provider Application"
+#define VER_INTERNALNAME_STR "espexe"
+#define VER_ORIGINALFILENAME_STR "ESPEXE.EXE"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
+
+// /////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/private/tapi/dev/sp/esp.new/exe/makefile b/private/tapi/dev/sp/esp.new/exe/makefile
new file mode 100644
index 000000000..23524cb99
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/makefile
@@ -0,0 +1,11 @@
+!ifndef NTMAKEENV
+NTMAKEENV=.
+!endif
+
+
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/tapi/dev/sp/esp.new/exe/resource.h b/private/tapi/dev/sp/esp.new/exe/resource.h
new file mode 100644
index 000000000..ab20242b8
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/resource.h
@@ -0,0 +1,67 @@
+//{{NO_DEPENDENCIES}}
+// App Studio generated include file.
+// Used by ESP.RC
+//
+#define IDR_MENU1 101
+#define IDD_DIALOG1 102
+#define IDD_DIALOG2 103
+#define IDI_ICON1 104
+#define IDD_DIALOG3 105
+#define IDD_DIALOG4 106
+#define IDD_DIALOG5 107
+#define IDR_ACCELERATOR1 108
+#define IDC_LIST1 1000
+#define IDC_LIST2 1001
+#define IDC_LIST3 1002
+#define IDC_EDIT1 1003
+#define IDC_STATIC1 1004
+#define IDC_BUTTON1 1005
+#define IDC_BUTTON2 1006
+#define IDC_BUTTON3 1007
+#define IDC_BUTTON4 1009
+#define IDC_COMBO1 1010
+#define IDC_F1HELP 1011
+#define IDC_PREVCTRL 1012
+#define IDC_NEXTCTRL 1013
+#define IDC_ENTER 1014
+#define IDC_LIST4 1015
+#define IDC_RESET 1016
+#define IDM_ABOUT 40000
+#define IDM_EXIT 40001
+#define IDM_SHOWFUNCENTRY 40002
+#define IDM_SHOWFUNCPARAMS 40003
+#define IDM_SHOWFUNCEXIT 40004
+#define IDM_SHOWEVENTS 40005
+#define IDM_SHOWCOMPLETIONS 40006
+#define IDM_MANUALRESULTS 40007
+#define IDM_DEBUGBREAK 40008
+#define IDM_SHOWALL 40009
+#define IDM_SHOWNONE 40010
+#define IDM_OUTCALLSTATEPROG 40011
+#define IDM_AUTOCLOSE 40012
+#define IDM_INSTALL 40013
+#define IDM_UNINSTALL 40014
+#define IDM_USAGE 40015
+#define IDM_DUMPGLOBALS 40016
+#define IDM_SYNCCOMPL 40017
+#define IDM_ASYNCCOMPL 40018
+#define IDM_SYNCASYNCCOMPL 40019
+#define IDM_MANUALCOMPL 40020
+#define IDM_DEFAULTS 40021
+#define IDM_DISABLEUI 40022
+#define IDM_PBXCONFIG 40023
+#define IDM_PBXSTART 40024
+#define IDM_PBXSTOP 40025
+#define IDM_AUTOGATHERGENERATEMSGS 40026
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE 109
+#define _APS_NEXT_COMMAND_VALUE 40027
+#define _APS_NEXT_CONTROL_VALUE 1017
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/private/tapi/dev/sp/esp.new/exe/sources b/private/tapi/dev/sp/esp.new/exe/sources
new file mode 100644
index 000000000..93eed7442
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/exe/sources
@@ -0,0 +1,58 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+Notes:
+
+ Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=espexe
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=PROGRAM
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+USE_CRTDLL=1
+
+SOURCES=espexe.c \
+ espidl_c.c \
+ espexe.rc
+
+C_DEFINES=-DTAPI_NT=1
+
+UMTYPE=windows
+
+UMENTRY=winmain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/esp.new/makefil0 b/private/tapi/dev/sp/esp.new/makefil0
new file mode 100644
index 000000000..caa8b1f9c
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/makefil0
@@ -0,0 +1,71 @@
+#
+# this is the midl compile phase of the build process.
+#
+# The following is where you put the name of your .idl file without
+# the .idl extension:
+#
+
+
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.plt
+
+SDKINC = $(BASEDIR)\public\sdk\inc
+SDKCRTINC = $(BASEDIR)\public\sdk\inc\crt
+INCS = -I$(SDKINC) -I$(SDKCRTINC)
+
+CPP = -cpp_cmd "$(MIDL_CPP)" $(MIDL_FLAGS) $(C_DEFINES) $(NET_C_DEFINES)
+
+!else
+
+FLAGS = -D_X86_ -Di386 -D_WCHAR_T_DEFINED
+CPP = -cpp_cmd "cl" -cpp_opt "-E $(FLAGS) $(INCS) $(C_DEFINES)"
+
+HEADER_TARGETS =
+
+!endif
+
+
+
+IDL_NAME = espidl
+
+CLIENT_TARGETS = exe\$(IDL_NAME)_c.c \
+
+SERVER_TARGETS = tsp\$(IDL_NAME)_s.c
+
+EXTRN_DEPENDS =
+
+
+#
+# Define Products and Dependencies
+#
+
+all: $(CLIENT_TARGETS) $(SERVER_TARGETS) $(EXTRN_DEPENDS)
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+clean: delete_source all
+
+delete_source:
+ -erase $(CLIENT_TARGETS) $(SERVER_TARGETS)
+
+#
+# MIDL COMPILE
+#
+
+$(CLIENT_TARGETS) : $(IDL_NAME).idl $(EXTRN_DEPENDS)
+ midl -Oi -server none -oldnames -error allocation -error ref -ms_ext -c_ext $(CPP) $(IDL_NAME).idl $(INCS)
+ IF EXIST $(IDL_NAME)_c.c copy $(IDL_NAME)_c.c .\exe
+ IF EXIST $(IDL_NAME)_c.c del $(IDL_NAME)_c.c
+
+ IF EXIST $(IDL_NAME).h copy $(IDL_NAME).h .\exe
+
+
+$(SERVER_TARGETS) : $(IDL_NAME).idl $(EXTRN_DEPENDS)
+ midl -client none -oldnames -error stub_data -error allocation -error ref -ms_ext -c_ext $(CPP) $(IDL_NAME).idl $(INCS)
+ IF EXIST $(IDL_NAME)_s.c copy $(IDL_NAME)_s.c .\tsp
+ IF EXIST $(IDL_NAME)_s.c del $(IDL_NAME)_s.c
+
+ IF EXIST $(IDL_NAME).h copy $(IDL_NAME).h .\tsp
+ IF EXIST $(IDL_NAME).h del $(IDL_NAME).h
diff --git a/private/tapi/dev/sp/esp.new/tsp/devspec.h b/private/tapi/dev/sp/esp.new/tsp/devspec.h
new file mode 100644
index 000000000..2c8134663
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/devspec.h
@@ -0,0 +1,200 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ devspec.h
+
+Abstract:
+
+ This module contains the line/phoneDevSpecific interface
+ definitions for tapi apps to pass data to esp32.tsp,
+ i.e. msgs the app wants esp32.tsp to indicate
+
+Author:
+
+ Dan Knudson (DanKn) 25-Apr-1996
+
+Revision History:
+
+
+Notes:
+
+
+--*/
+
+
+#define ESPDEVSPECIFIC_KEY ((DWORD) 'DPSE')
+
+#define ESP_DEVSPEC_MSG 1
+#define ESP_DEVSPEC_RESULT 2
+
+
+//
+// The following structure is used when an app wants to tell esp to
+// indicate a certain message, i.e. LINE_ADDRESSSTATE. Note that
+// the fields must be filled in with values that are valid at the
+// SPI level, which are not necessarily the same as those at the
+// API level. (Consult the win32 sdk for more info.) For example,
+// there is no LINE_CALLDEVSPECIFIC message defined a the API level,
+// but it is used at the SPI level to denote that TAPI should pass
+// the corresponding call handle (rather than the line handle) to
+// apps in the hDevice parameter of the LINE_DEVSPECIFIC message
+//
+
+typedef struct _ESPDEVSPECMSG
+{
+ DWORD dwMsg;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+
+} ESPDEVSPECMSG, *PESPDEVSPECMSG;
+
+
+//
+// The following structure is used when an app wants to tell esp how
+// to complete next request. (Bear in mind that esp may override the
+// app's request if it encounters an "internal" error somewhere along
+// the way.) Valid values for the "lResult" field are 0 or any of
+// the LINEERR_XXX / PHONEERR_XXX constants defined in tapi.h. Valid
+// values for the "dwCompletionType" field are any of the ESP_RESULT_XXX
+// values defined below.
+//
+// This operation allows for testing the following scenarios for
+// synchronous telephony APIs:
+//
+// 1. Service provider's TSPI_xxx function returns success.
+// App recives success result
+//
+// 2. Service provider's TSPI_xxx function returns error.
+// App recives error result
+//
+// This operation allows for testing the following scenarios for
+// ASYNCHRONOUS telephony APIs (in each case, app recieves a request
+// id from the API, then later a LINE/PHONE_REPLY msg with a matching
+// request id (dwParam1) and result (dwParam2)):
+//
+// 1. Service provider's TSPI_xxx func calls tapi's completion proc
+// with success result
+//
+// 2. Service provider's worker thread calls tapi's completion proc
+// with success result
+//
+// 3. Service provider's TSPI_xxx function returns error
+//
+// 4. Service provider's TSPI_xxx func calls tapi's completion proc
+// with error result
+//
+// 5. Service provider's worker thread calls tapi's completion proc
+// with error result
+//
+
+typedef struct _ESPDEVSPECRESULT
+{
+ LONG lResult; // 0, LINEERR_XXX, PHONEERR_XXX
+ DWORD dwCompletionType; // ESP_RESULT_XXX
+
+} ESPDEVSPECRESULT, *PESPDEVSPECRESULT;
+
+#define ESP_RESULT_RETURNRESULT 0
+#define ESP_RESULT_CALLCOMPLPROCSYNC 1
+#define ESP_RESULT_CALLCOMPLPROCASYNC 2
+
+
+//
+// The following structure is the device specific information
+// "wrapper". The app must initialize the dwKey & dwType fields
+// to create a valid header and fill in the appropriate
+// union substructure before passing the info to esp32.tsp via
+// line/phoneDevSpecific.
+//
+// If esp32.tsp detects an invalid parameter(s) it will return an
+// OPERATIONFAILED error, and spit out relevant debug information
+// in the espexe.exe window.
+//
+
+typedef struct _ESPDEVSPECIFICINFO
+{
+ DWORD dwKey; // App must init this to ESPDEVSPECIFIC_KEY
+ DWORD dwType; // App must init this to ESP_DEVSPEC_MSG, ...
+
+ union
+ {
+
+ ESPDEVSPECMSG EspMsg;
+ ESPDEVSPECRESULT EspResult;
+
+ } u;
+
+} ESPDEVSPECIFICINFO, *PESPDEVSPECIFICINFO;
+
+
+/*
+
+//
+// Example: if an app wanted esp32.tsp to indicate a
+// LINE_LINEDEVSTATE\RENINIT msg it would do
+// the following
+//
+
+{
+ LONG lResult;
+ HLINE hLine;
+ ESPDEVSPECIFICINFO info;
+
+
+ // do a lineInitialize, lineNegotiateAPIVersion, lineOpen, etc...
+
+ info.dwKey = ESPDEVSPECIFIC_KEY;
+ info.dwType = ESP_DEVSPEC_MSG;
+
+ // make sure to use the SPI (not API) msg params here (not
+ // necessarily the same)
+
+ info.u.EspMsg.dwMsg = LINE_LINEDEVSTATE;
+ info.u.EspMsg.dwParam1 = LINEDEVSTATE_REINIT;
+ info.u.EspMsg.dwParam2 = 0;
+ info.u.EspMsg.dwParam3 = 0;
+
+ lResult = lineDevSpecific (hLine, 0, NULL, &info, sizeof (info));
+
+ // some time later a LINE_LINEDEVSTATE\REINIT msg will show up
+}
+
+
+//
+// Example: if an app wanted esp32.tsp to fail a request
+// to lineMakeCall asynchronously with the error
+// LINEERR_CALLUNAVAIL it would do the following
+// (ESP's worker thread would complete the request
+// in this case)
+//
+
+{
+ LONG lResult, lResult2;
+ HCALL hCall;
+ HLINE hLine;
+ ESPDEVSPECIFICINFO info;
+
+
+ // do a lineInitialize, lineNegotiateAPIVersion, lineOpen, etc...
+
+ info.dwKey = ESPDEVSPECIFIC_KEY;
+ info.dwType = ESP_DEVSPEC_RESULT;
+
+ info.u.EspResult.lResult = LINEERR_CALLUNAVAIL;
+ info.u.EspResult.dwCompletionType = ESP_RESULT_CALLCOMPLPROCASYNC;
+
+ lResult = lineDevSpecific (hLine, 0, NULL, &info, sizeof (info));
+
+ lResult2 = lineMakeCall (hLine, &hCall, "555-1212", 1, NULL);
+
+ // some time later a LINE_REPLY will show for for both the DevSpecific
+ // & MakeCall requests. the LINE_REPLY for the MakeCall will have
+ // dwParam1 = lResult2, and dwParam2 = LINEERR_CALLUNAVAIL
+}
+
+
+*/
diff --git a/private/tapi/dev/sp/esp.new/tsp/esp.c b/private/tapi/dev/sp/esp.new/tsp/esp.c
new file mode 100644
index 000000000..682166e1e
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/esp.c
@@ -0,0 +1,11878 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ esp.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 18-Sep-1995
+
+Revision History:
+
+
+Notes:
+
+ 1. Regarding the SP filling in structures with variable length fields
+ (dwXxxSize/dwXxxOffset) : "The SP's variable size fields start
+ immediately after the fixed part of the data structure. The order
+ of filling of the variable size fields owned by the SP is not
+ specified. The SP can fill them in any order it desires. Filling
+ should be contiguous, starting at the beginning of the variable
+ part." (Taken from Chapter 2 of the SPI Programmer's Guide.)
+
+--*/
+
+
+#include "stdarg.h"
+#include "stdio.h"
+#include "stdlib.h"
+//#include "malloc.h"
+#include "string.h"
+#include "esp.h"
+#include "devspec.h"
+#include "vars.h"
+
+
+#define MAX_NUM_PARKED_CALLS 16
+
+LONG glNextRequestResult = 0;
+DWORD gdwNextRequestCompletionType;
+DWORD gdwDevSpecificRequestID;
+DWORD gdwCallID = 1;
+BOOL gbExitPBXThread;
+BOOL gbDisableUI;
+BOOL gbAutoGatherGenerateMsgs;
+BOOL gbManualResults = FALSE;
+BOOL gbInteractWithDesktop = FALSE;
+DWORD gdwCallInstance = 0;
+WCHAR gszProviderInfo[] = L"ESP v2.0";
+HANDLE ghPBXThread = NULL;
+PDRVCALL gaParkedCalls[MAX_NUM_PARKED_CALLS];
+
+static WCHAR *aszDeviceClasses[] =
+{
+ L"tapi/line",
+ L"tapi/phone",
+ L"wave",
+ L"wave/in",
+ L"wave/out",
+ L"comm",
+ L"comm/datamodem",
+ (WCHAR *) NULL
+};
+
+
+BOOL
+PASCAL
+IsValidDrvCall(
+ PDRVCALL pCall,
+ LPDWORD pdwCallInstance
+ );
+
+BOOL
+CALLBACK
+ValuesDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+LONG
+PASCAL
+CreateIncomingCall(
+ LPCWSTR lpszDestAddress,
+ LPLINECALLPARAMS lpCallParams,
+ PDRVCALL pOutgoingCall,
+ BOOL *pbValidESPAddress,
+ PDRVLINE *ppIncomingLine,
+ PDRVCALL *ppIncomingCall
+ );
+
+LONG
+PASCAL
+TransferCall(
+ PFUNC_INFO pInfo,
+ PDRVCALL pCall,
+ DWORD dwValidCurrentCallStates,
+ DWORD dwNewCallState,
+ LPCWSTR lpszDestAddress
+ );
+
+
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ static BOOL bLoadedByTapisrv;
+ static HANDLE hInitEvent;
+
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ UINT uiResult;
+
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ OutputDebugString ("ESP: DllMain: _CRT_INIT() failed\n\r");
+ }
+
+ ghInstance = hDLL;
+
+
+ //
+ // Grab ini file settings
+ //
+#if DBG
+
+ {
+ HKEY hKey;
+ DWORD dwDataSize, dwDataType;
+ TCHAR szTelephonyKey[] =
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony",
+ szEsp32DebugLevel[] = "Esp32DebugLevel";
+
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ szTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof (DWORD);
+ gdwDebugLevel=0;
+
+ RegQueryValueEx(
+ hKey,
+ szEsp32DebugLevel,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwDebugLevel,
+ &dwDataSize
+ );
+
+ RegCloseKey (hKey);
+ }
+
+#endif
+ //
+ // Determine whether we're being loaded by tapisrv or some
+ // other process (i.e. telephony ctrl panel)- this will tell
+ // us whether we need to go thru all the necessary init or not
+ //
+
+ {
+ char *pszProcessName;
+ STARTUPINFO si;
+
+
+ GetStartupInfoA (&si);
+
+ pszProcessName = si.lpTitle + (lstrlenA (si.lpTitle) - 1);
+
+ for (; pszProcessName != si.lpTitle; pszProcessName--)
+ {
+ if (*pszProcessName == '\\')
+ {
+ pszProcessName++;
+ break;
+ }
+ }
+
+ bLoadedByTapisrv = (lstrcmpiA (pszProcessName, "tapisrv.exe") == 0
+ ? TRUE : FALSE);
+ }
+
+ if (bLoadedByTapisrv)
+ {
+ {
+ typedef struct _XXX
+ {
+ DWORD dwDefValue;
+
+ LPCSTR pszValueName;
+
+ LPDWORD pdwValue;
+
+ } XXX, *PXXX;
+
+ XXX axxx[] =
+ {
+ { DEF_SPI_VERSION,
+ "TSPIVersion",
+ &gESPGlobals.dwSPIVersion },
+ { DEF_NUM_LINES,
+ "NumLines",
+ &gESPGlobals.dwNumLines },
+ { DEF_NUM_ADDRS_PER_LINE,
+ "NumAddrsPerLine",
+ &gESPGlobals.dwNumAddressesPerLine },
+ { DEF_NUM_CALLS_PER_ADDR,
+ "NumCallsPerAddr",
+ &gESPGlobals.dwNumCallsPerAddress },
+ { DEF_NUM_PHONES,
+ "NumPhones",
+ &gESPGlobals.dwNumPhones },
+ { DEF_DEBUG_OPTIONS,
+ "DebugOutput",
+ &gESPGlobals.dwDebugOptions },
+ { DEF_COMPLETION_MODE,
+ "Completion",
+ &gESPGlobals.dwCompletionMode },
+ { 0,
+ "DisableUI",
+ &gbDisableUI },
+ { 1,
+ "AutoGatherGenerateMsgs",
+ &gbAutoGatherGenerateMsgs },
+ { 0,
+ NULL,
+ NULL },
+ };
+ DWORD i;
+
+
+ for (i = 0; axxx[i].pszValueName; i++)
+ {
+ *(axxx[i].pdwValue) = (DWORD) GetProfileInt(
+ "ESP32",
+ axxx[i].pszValueName,
+ (int) axxx[i].dwDefValue
+ );
+
+ }
+ }
+
+
+ //
+ //
+ //
+
+ InitializeCriticalSection (&gESPGlobals.CallListCritSec);
+ InitializeCriticalSection (&gESPGlobals.PhoneCritSec);
+ InitializeCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
+
+ if (gbDisableUI)
+ {
+ //
+ // Don't bother doing all the stuff to sync/start up espexe.
+ // However, we do want to make sure that we're not wasting
+ // time spewing dbg output nor completing async requests in
+ // any way other than inline (synchronously), since we're
+ // not real smart about cleaning up pending async requests
+ // when a call or line is closed/destroyed.
+ //
+
+ gESPGlobals.dwDebugOptions = 0;
+ gESPGlobals.dwCompletionMode =
+ COMPLETE_ASYNC_EVENTS_SYNCHRONOUSLY;
+ gbAutoGatherGenerateMsgs = FALSE; //TRUE;
+ }
+ else
+ {
+ //
+ // Check to see if tapisrv has the "interact with
+ // desktop" privilege enabled
+ //
+
+ {
+ SC_HANDLE hSCManager, hTapisrvSvc;
+
+
+ if ((hSCManager = OpenSCManager(
+ NULL,
+ NULL,
+ GENERIC_READ
+ )))
+ {
+ if ((hTapisrvSvc = OpenService(
+ hSCManager,
+ "tapisrv",
+ SERVICE_QUERY_CONFIG
+ )))
+ {
+ DWORD dwNeededSize;
+ QUERY_SERVICE_CONFIG config;
+
+
+ if (!QueryServiceConfig(
+ hTapisrvSvc,
+ &config,
+ sizeof (QUERY_SERVICE_CONFIG),
+ &dwNeededSize
+ ))
+ {
+ QUERY_SERVICE_CONFIG *pConfig;
+
+
+ config.dwServiceType = 0;
+
+ if (GetLastError() ==
+ ERROR_INSUFFICIENT_BUFFER)
+ {
+ if ((pConfig = DrvAlloc (dwNeededSize)))
+ {
+ if (QueryServiceConfig(
+ hTapisrvSvc,
+ pConfig,
+ dwNeededSize,
+ &dwNeededSize
+ ))
+ {
+ config.dwServiceType =
+ pConfig->dwServiceType;
+ }
+
+ DrvFree (pConfig);
+ }
+ }
+ }
+
+ gbInteractWithDesktop = (BOOL)
+ (config.dwServiceType &
+ SERVICE_INTERACTIVE_PROCESS);
+
+ CloseServiceHandle (hTapisrvSvc);
+ }
+
+ CloseServiceHandle (hSCManager);
+ }
+ }
+
+ if (!gbInteractWithDesktop)
+ {
+ gESPGlobals.dwDebugOptions &= ~MANUAL_RESULTS;
+ }
+
+
+ //
+ //
+ //
+
+ InitializeCriticalSection (&gESPGlobals.DebugBufferCritSec);
+ InitializeCriticalSection (&gESPGlobals.EventBufferCritSec);
+
+ gESPGlobals.dwDebugBufferTotalSize = 2048;
+ gESPGlobals.dwDebugBufferUsedSize = 0;
+
+ gESPGlobals.pDebugBuffer =
+ gESPGlobals.pDebugBufferIn =
+ gESPGlobals.pDebugBufferOut = DrvAlloc(
+ gESPGlobals.dwDebugBufferTotalSize
+ );
+
+ gESPGlobals.dwEventBufferTotalSize = 40 * sizeof (WIDGETEVENT);
+ gESPGlobals.dwEventBufferUsedSize = 0;
+
+ gESPGlobals.pEventBuffer =
+ gESPGlobals.pEventBufferIn =
+ gESPGlobals.pEventBufferOut = DrvAlloc(
+ gESPGlobals.dwEventBufferTotalSize
+ );
+
+
+ //
+ // Create the events used to sync up w/ espexe, and
+ // start espexe if it's not already running
+ //
+
+ ghDebugOutputEvent = CreateEvent(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ TRUE, // manual reset
+ FALSE, // non-signaled
+ NULL // unnamed
+ );
+
+ ghWidgetEventsEvent = CreateEvent(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ TRUE, // manual reset
+ FALSE, // non-signaled
+ NULL // unnamed
+ );
+
+ ghShutdownEvent = CreateEvent(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ FALSE, // auto reset
+ FALSE, // non-signaled
+ NULL // unnamed
+ );
+
+
+ //
+ // Enable rpc server interface
+ //
+
+ {
+ RPC_STATUS status;
+ unsigned char * pszSecurity = NULL;
+ unsigned int cMaxCalls = 20;
+
+
+ status = RpcServerUseProtseqEp(
+ "ncalrpc",
+ cMaxCalls,
+ "esplpc",
+ pszSecurity // Security descriptor
+ );
+
+ DBGOUT((3, "RpcServerUseProtseqEp(lrpc) ret'd %d", status));
+
+ if (status)
+ {
+ }
+
+ status = RpcServerRegisterIf(
+ esp_ServerIfHandle, // interface to register
+ NULL, // MgrTypeUuid
+ NULL // MgrEpv; null means use default
+ );
+
+ DBGOUT((3, "RpcServerRegisterIf ret'd %d", status));
+
+ if (status)
+ {
+ }
+ }
+
+
+ if ((hInitEvent = OpenEvent(
+ EVENT_ALL_ACCESS,
+ FALSE, "ESPevent"
+ )))
+ {
+ SetEvent (hInitEvent);
+ }
+ else
+ {
+ hInitEvent = CreateEvent(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ FALSE, // auto reset
+ TRUE, // signaled
+ "ESPevent"
+ );
+
+ DBGOUT((3, "Starting espexe..."));
+
+ if ((uiResult = WinExec ("espexe.exe", SW_SHOW)) < 32)
+ {
+ DBGOUT((
+ 1,
+ "WinExec(espexe.exe) failed, err=%d",
+ uiResult
+ ));
+
+ gESPGlobals.dwDebugOptions = 0;
+ gESPGlobals.dwCompletionMode =
+ COMPLETE_ASYNC_EVENTS_SYNCHRONOUSLY;
+ }
+#if DBG
+ else
+ {
+ DBGOUT((3, "started espexe"));
+ }
+#endif
+ }
+ }
+ }
+
+ break;
+ }
+ case DLL_PROCESS_DETACH:
+
+ if (bLoadedByTapisrv)
+ {
+ if (gbDisableUI == FALSE)
+ {
+ SetEvent (ghShutdownEvent);
+
+ //
+ // Unregister out rpc server interface
+ //
+
+ {
+ RPC_STATUS status;
+
+
+ status = RpcServerUnregisterIf(
+ esp_ServerIfHandle, // interface to register
+ NULL, // MgrTypeUuid
+ 0 // wait for calls to complete
+ );
+
+ DBGOUT((3, "RpcServerUntegisterIf ret'd %d", status));
+ }
+
+ CloseHandle (ghDebugOutputEvent);
+ CloseHandle (ghWidgetEventsEvent);
+ CloseHandle (ghShutdownEvent);
+ CloseHandle (hInitEvent);
+
+ DeleteCriticalSection (&gESPGlobals.DebugBufferCritSec);
+ DeleteCriticalSection (&gESPGlobals.EventBufferCritSec);
+
+ DrvFree (gESPGlobals.pDebugBuffer);
+ DrvFree (gESPGlobals.pEventBuffer);
+ }
+
+ DeleteCriticalSection (&gESPGlobals.CallListCritSec);
+ DeleteCriticalSection (&gESPGlobals.PhoneCritSec);
+ DeleteCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
+ }
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ OutputDebugString ("ESP: DllMain: _CRT_INIT() failed\n\r");
+ }
+
+ break;
+
+ default:
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ OutputDebugString ("ESP: DllMain: _CRT_INIT() failed\n\r");
+ }
+
+ break;
+ }
+
+ return TRUE;
+}
+
+
+void
+AsyncEventQueueServiceThread(
+ LPVOID pParams
+ )
+{
+ while (1)
+ {
+ WaitForSingleObject (gESPGlobals.hAsyncEventsPendingEvent, INFINITE);
+
+ while (1)
+ {
+ PASYNC_REQUEST_INFO pAsyncReqInfo;
+
+
+ EnterCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
+
+ if (gESPGlobals.dwNumUsedQueueEntries == 0)
+ {
+ ResetEvent (gESPGlobals.hAsyncEventsPendingEvent);
+ LeaveCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
+ break;
+ }
+
+ pAsyncReqInfo = (PASYNC_REQUEST_INFO)
+ (*gESPGlobals.pAsyncRequestQueueOut);
+
+ gESPGlobals.pAsyncRequestQueueOut++;
+
+ if (gESPGlobals.pAsyncRequestQueueOut ==
+ (gESPGlobals.pAsyncRequestQueue +
+ gESPGlobals.dwNumTotalQueueEntries))
+ {
+ gESPGlobals.pAsyncRequestQueueOut =
+ gESPGlobals.pAsyncRequestQueue;
+ }
+
+ gESPGlobals.dwNumUsedQueueEntries--;
+
+ LeaveCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
+
+ if (pAsyncReqInfo->pfnPostProcessProc)
+ {
+ (*(pAsyncReqInfo->pfnPostProcessProc))(
+ pAsyncReqInfo,
+ ASYNC
+ );
+ }
+ else
+ {
+ DoCompletion (pAsyncReqInfo, ASYNC);
+ }
+
+ DrvFree (pAsyncReqInfo);
+ }
+
+ if (gESPGlobals.bProviderShutdown)
+ {
+ break;
+ }
+ }
+
+ ExitThread (0);
+}
+
+
+void
+PBXThread(
+ LPVOID pParams
+ )
+{
+ DWORD *pPBXSettings = (LPDWORD) pParams,
+ dwTickCount, dwElapsedTime,
+ dwTimePerNewCall = pPBXSettings[0], dwLastNewCallTickCount,
+ dwTimePerDisconnect = pPBXSettings[1], dwLastDisconnectTickCount;
+
+/*
+ DWORD dwTickCount, dwElapsedTime,
+ dwLastNewCallTickCount, dwLastDisconnectTickCount,
+ dwTimePerNewCall = (gPBXSettings[0].dwNumber ?
+ gPBXSettings[0].dwTime / gPBXSettings[0].dwNumber : 0),
+ dwTimePerDisconnect = (gPBXSettings[1].dwNumber ?
+ gPBXSettings[1].dwTime / gPBXSettings[1].dwNumber : 0);
+*/
+
+ ShowStr (TRUE, "PBXThread: enter");
+
+ // BUGBUG acct for 49.7 day tick count wrap
+
+ dwTickCount =
+ dwLastNewCallTickCount =
+ dwLastDisconnectTickCount = GetTickCount();
+
+ ShowStr(
+ TRUE,
+ "dwTimePerNewCall = %d, dwTimePerDisconnect = %d",
+ dwTimePerNewCall,
+ dwTimePerDisconnect
+ );
+
+ while (1)
+ {
+ Sleep (1000);
+
+ if (gbExitPBXThread)
+ {
+ break;
+ }
+
+ dwTickCount += 1000;
+
+ if (dwTimePerNewCall)
+ {
+ dwElapsedTime = dwTickCount - dwLastNewCallTickCount;
+
+ while (dwElapsedTime >= dwTimePerNewCall)
+ {
+ //
+ // Generate new call (random line, random media mode)
+ //
+
+ DWORD i = rand(), j;
+
+
+ for (j = 0; j < gESPGlobals.dwInitialNumLines; j++)
+ {
+ PDRVLINE pLine = GetLineFromID(
+ i % gESPGlobals.dwInitialNumLines +
+ gESPGlobals.dwLineDeviceIDBase
+ );
+
+
+ if (pLine->dwMediaModes)
+ {
+ DWORD dwMediaMode;
+ PDRVCALL pCall;
+
+
+ for(
+ dwMediaMode =
+ (LINEMEDIAMODE_INTERACTIVEVOICE << i % 13);
+ dwMediaMode <= LAST_LINEMEDIAMODE;
+ dwMediaMode <<= 1
+ )
+ {
+ if (pLine->dwMediaModes & dwMediaMode)
+ {
+ goto PBXThread_allocCall;
+ }
+ }
+
+ for(
+ dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
+ dwMediaMode <= LAST_LINEMEDIAMODE;
+ dwMediaMode <<= 1
+ )
+ {
+ if (pLine->dwMediaModes & dwMediaMode)
+ {
+ break;
+ }
+ }
+
+PBXThread_allocCall:
+ if (AllocCall (pLine, NULL, NULL, &pCall) == 0)
+ {
+ pCall->dwMediaMode = dwMediaMode;
+
+ SendLineEvent(
+ pLine,
+ NULL,
+ LINE_NEWCALL,
+ (DWORD) pCall,
+ (DWORD) &pCall->htCall,
+ 0
+ );
+
+ if (!pCall->htCall)
+ {
+ FreeCall (pCall, pCall->dwCallInstance);
+ continue;
+ }
+
+ SetCallState(
+ pCall,
+ pCall->dwCallInstance,
+ 0xffffffff,
+ LINECALLSTATE_OFFERING,
+ 0,
+ FALSE
+ );
+
+ break;
+ }
+
+ }
+
+ i++;
+ }
+
+ dwElapsedTime -= dwTimePerNewCall;
+
+ dwLastNewCallTickCount = dwTickCount;
+ }
+ }
+
+ if (dwTimePerDisconnect)
+ {
+ dwElapsedTime = dwTickCount - dwLastDisconnectTickCount;
+
+ while (dwElapsedTime >= dwTimePerDisconnect)
+ {
+ //
+ // Disconnect a random (non-idle) call (random disconnect mode)
+ //
+
+ DWORD i = rand(), j, k;
+
+
+ for (j = 0; j < gESPGlobals.dwInitialNumLines; j++)
+ {
+ DWORD dwInitialAddrID =
+ i % gESPGlobals.dwNumAddressesPerLine,
+ dwLastAddrID =
+ gESPGlobals.dwNumAddressesPerLine;
+ PDRVLINE pLine = GetLineFromID(
+ i % gESPGlobals.dwInitialNumLines +
+ gESPGlobals.dwLineDeviceIDBase
+ );
+
+PBXThread_findCallToDisconnect:
+
+ for (
+ k = dwInitialAddrID;
+ k < dwLastAddrID;
+ k++
+ )
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (pLine->aAddrs[k].dwNumCalls)
+ {
+ PDRVCALL pCall = pLine->aAddrs[k].pCalls;
+
+ while (pCall &&
+ pCall->dwCallState == LINECALLSTATE_IDLE)
+ {
+ pCall = pCall->pNext;
+ }
+
+ if (pCall)
+ {
+ DWORD dwDisconnectMode =
+ LINEDISCONNECTMODE_NORMAL;
+
+
+ // BUGBUG disconnectMode depends on curr state
+
+ SetCallState(
+ pCall,
+ pCall->dwCallInstance,
+ 0xffffffff,
+ LINECALLSTATE_DISCONNECTED,
+ dwDisconnectMode,
+ FALSE
+ );
+
+ SetCallState(
+ pCall,
+ pCall->dwCallInstance,
+ 0xffffffff,
+ LINECALLSTATE_IDLE,
+ 0,
+ FALSE
+ );
+
+ LeaveCriticalSection(
+ &gESPGlobals.CallListCritSec
+ );
+
+ goto PBXThread_droppedCall;
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ if (dwInitialAddrID != 0)
+ {
+ dwLastAddrID = dwInitialAddrID;
+ dwInitialAddrID = 0;
+ goto PBXThread_findCallToDisconnect;
+ }
+
+ i++;
+ }
+
+PBXThread_droppedCall:
+
+ dwElapsedTime -= dwTimePerDisconnect;
+
+ dwLastDisconnectTickCount = dwTickCount;
+ }
+ }
+ }
+
+ DrvFree (pPBXSettings);
+
+ ShowStr (TRUE, "PBXThread: exit");
+
+ ExitThread (0);
+}
+
+
+void
+PASCAL
+InsertVarData(
+ LPVOID lpXxx,
+ LPDWORD pdwXxxSize,
+ LPVOID pData,
+ DWORD dwDataSize
+ )
+{
+ DWORD dwAlignedSize, dwUsedSize;
+ LPVARSTRING lpVarString = (LPVARSTRING) lpXxx;
+
+
+ if (dwDataSize != 0)
+ {
+ //
+ // Align var data on 64-bit boundaries
+ //
+
+ if ((dwAlignedSize = dwDataSize) & 7)
+ {
+ dwAlignedSize += 8;
+ dwAlignedSize &= 0xfffffff8;
+
+ }
+
+
+ //
+ // The following if statement should only be TRUE the first time
+ // we're inserting data into a given structure that does not have
+ // an even number of DWORD fields
+ //
+
+ if ((dwUsedSize = lpVarString->dwUsedSize) & 7)
+ {
+ dwUsedSize += 8;
+ dwUsedSize &= 0xfffffff8;
+
+ lpVarString->dwNeededSize += dwUsedSize - lpVarString->dwUsedSize;
+ }
+
+ lpVarString->dwNeededSize += dwAlignedSize;
+
+ if ((dwUsedSize + dwAlignedSize) <= lpVarString->dwTotalSize)
+ {
+ CopyMemory(
+ ((LPBYTE) lpVarString) + dwUsedSize,
+ pData,
+ dwDataSize
+ );
+
+ *pdwXxxSize = dwDataSize;
+ pdwXxxSize++; // pdwXxxSize = pdwXxxOffset
+ *pdwXxxSize = dwUsedSize;
+
+ lpVarString->dwUsedSize = dwUsedSize + dwAlignedSize;
+ }
+
+ }
+}
+
+
+void
+PASCAL
+InsertVarDataString(
+ LPVOID lpXxx,
+ LPDWORD pdwXxxSize,
+ WCHAR *psz
+ )
+{
+ DWORD dwRealSize = (lstrlenW (psz) + 1) * sizeof (WCHAR),
+ dwAlignedSize;
+ LPVARSTRING lpVarString = (LPVARSTRING) lpXxx;
+
+
+ if (dwRealSize % 4)
+ {
+ dwAlignedSize = dwRealSize - (dwRealSize % 4) + 4;
+ }
+ else
+ {
+ dwAlignedSize = dwRealSize;
+ }
+
+ lpVarString->dwNeededSize += dwAlignedSize;
+
+ if ((lpVarString->dwUsedSize + dwAlignedSize) <= lpVarString->dwTotalSize)
+ {
+ CopyMemory(
+ ((LPBYTE) lpVarString) + lpVarString->dwUsedSize,
+ psz,
+ dwRealSize
+ );
+
+ *pdwXxxSize = dwRealSize;
+ pdwXxxSize++;
+ *pdwXxxSize = lpVarString->dwUsedSize;
+
+ lpVarString->dwUsedSize += dwAlignedSize;
+ }
+}
+
+
+//
+// We get a slough of C4047 (different levels of indrection) warnings down
+// below in the initialization of FUNC_PARAM structs as a result of the
+// real func prototypes having params that are types other than DWORDs,
+// so since these are known non-interesting warnings just turn them off
+//
+
+#pragma warning (disable:4047)
+
+
+//
+// --------------------------- TSPI_lineXxx funcs -----------------------------
+//
+
+void
+FAR
+PASCAL
+TSPI_lineAccept_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ pAsyncReqInfo->lResult = SetCallState(
+ pCall,
+ dwCallInstThen,
+ LINECALLSTATE_OFFERING,
+ LINECALLSTATE_ACCEPTED,
+ 0,
+ TRUE
+ );
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAccept(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineAccept";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_lineAccept_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam2))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineAddToConference_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwConfCallInstThen = pAsyncReqInfo->dwParam3,
+ dwConsultCallInstThen = pAsyncReqInfo->dwParam4,
+ dwConfCallInstNow;
+ PDRVCALL pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+ PDRVCALL pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
+
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pConfCall, &dwConfCallInstNow) &&
+ dwConfCallInstNow == dwConfCallInstThen)
+ {
+ if ((pAsyncReqInfo->lResult = SetCallState(
+ pConsultCall,
+ dwConsultCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_CONFERENCED,
+ 0,
+ TRUE
+
+ )) == 0)
+ {
+ pConsultCall->pConfParent = pConfCall;
+ pConsultCall->pNextConfChild = pConfCall->pNextConfChild;
+
+ pConfCall->pNextConfChild = pConsultCall;
+ }
+ }
+ else
+ {
+ pAsyncReqInfo->lResult == LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HDRVCALL hdConsultCall
+ )
+{
+ static char szFuncName[] = "lineAddToConference";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { "hdConfCall", hdConfCall },
+ { "hdConsultCall", hdConsultCall }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 3,
+ params,
+ TSPI_lineAddToConference_postProcess
+ };
+ PDRVCALL pConfCall = (PDRVCALL) hdConfCall;
+ PDRVCALL pConsultCall = (PDRVCALL) hdConsultCall;
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall(
+ (PDRVCALL) hdConfCall,
+ &info.pAsyncReqInfo->dwParam3
+ ) &&
+
+ IsValidDrvCall(
+ (PDRVCALL) hdConsultCall,
+ &info.pAsyncReqInfo->dwParam4
+ ))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdConfCall;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdConsultCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineAnswer_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ pAsyncReqInfo->lResult = SetCallState(
+ pCall,
+ dwCallInstThen,
+ LINECALLSTATE_OFFERING | LINECALLSTATE_ACCEPTED,
+ LINECALLSTATE_CONNECTED,
+ 0,
+ TRUE
+ );
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAnswer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineAnswer";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_lineAnswer_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam2))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineBlindTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ static char szFuncName[] = "lineBlindTransfer";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ info.lResult = TransferCall(
+ &info,
+ (PDRVCALL) hdCall,
+ LINECALLSTATE_CONNECTED | LINECALLSTATE_ONHOLD,
+ LINECALLSTATE_OFFERING,
+ lpszDestAddress
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+{
+ static char szFuncName[] = "lineClose";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 1, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ //
+ // This is more of a "command" than a request, in that TAPI.DLL is
+ // going to consider the line closed whether we like it or not.
+ // Therefore we want to free up the line even if the user chooses
+ // to return an error.
+ //
+
+ Prolog (&info);
+
+ pLine->htLine = (HTAPILINE) NULL;
+ pLine->dwMediaModes = 0;
+
+ WriteEventBuffer (pLine->dwDeviceID, WIDGETTYPE_LINE, 0, 0, 0, 0);
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+{
+ DWORD dwCallInst;
+ static char szFuncName[] = "lineCloseCall";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 1, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ //
+ // This is more of a "command" than a request, in that TAPI.DLL is
+ // going to consider the call closed whether we like it or not.
+ // Therefore we want to free up the call even if the user chooses
+ // to return an error.
+ //
+
+ Prolog (&info);
+
+ if (IsValidDrvCall (pCall, &dwCallInst))
+ {
+ WriteEventBuffer(
+ ((PDRVLINE) pCall->pLine)->dwDeviceID, // BUGBUG: AV potential
+ WIDGETTYPE_CALL,
+ (DWORD) pCall,
+ 0,
+ 0,
+ 0
+ );
+
+ FreeCall (pCall, dwCallInst);
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPDWORD lpdwCompletionID,
+ DWORD dwCompletionMode,
+ DWORD dwMessageID
+ )
+{
+ static char szFuncName[] = "lineCompleteCall";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpdwCompletionID", lpdwCompletionID },
+ { "dwCompletionMode", dwCompletionMode },
+ { "dwMessageID", dwMessageID }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 5, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ if (dwMessageID >= MAX_NUM_COMPLETION_MESSAGES)
+ {
+ info.lResult = LINEERR_INVALMESSAGEID;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineCompleteTransfer_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1,
+ dwConsultCallInstThen = pAsyncReqInfo->dwParam2,
+ dwConfCallInstThen = pAsyncReqInfo->dwParam6,
+ dwCallInstNow, dwConsultCallInstNow, dwConfCallInstNow;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
+ pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam4,
+ pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam5;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen &&
+ IsValidDrvCall (pConsultCall, &dwConsultCallInstNow) &&
+ dwConsultCallInstNow == dwConsultCallInstThen)
+ {
+ if (pConfCall)
+ {
+ if (IsValidDrvCall (pConfCall, &dwConfCallInstNow) &&
+ dwConfCallInstNow == dwConfCallInstThen)
+ {
+ pConfCall->pNextConfChild = pCall;
+ pCall->pNextConfChild = pConsultCall;
+ pCall->pConfParent = pConfCall;
+ pConsultCall->pConfParent = pConfCall;
+ }
+ else
+ {
+ pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+ }
+ else
+ {
+ pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
+
+ if (pConfCall)
+ {
+ FreeCall (pConfCall, dwConfCallInstThen);
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if (pConfCall)
+ {
+ if (SetCallState(
+ pConfCall,
+ dwConfCallInstNow,
+ 0xffffffff, // BUGBUG specify valid call states
+ LINECALLSTATE_CONNECTED,
+ 0,
+ TRUE
+
+ ) == 0)
+ {
+ SetCallState(
+ pCall,
+ dwCallInstNow,
+ 0xffffffff, // BUGBUG specify valid call states
+ LINECALLSTATE_CONFERENCED,
+ 0,
+ TRUE
+ );
+
+ SetCallState(
+ pConsultCall,
+ dwConsultCallInstNow,
+ 0xffffffff, // BUGBUG specify valid call states
+ LINECALLSTATE_CONFERENCED,
+ 0,
+ TRUE
+ );
+ }
+ }
+ else
+ {
+ SetCallState(
+ pCall,
+ dwCallInstNow,
+ 0xffffffff, // BUGBUG specify valid call states
+ LINECALLSTATE_IDLE,
+ 0,
+ TRUE
+ );
+
+ SetCallState(
+ pConsultCall,
+ dwConsultCallInstNow,
+ 0xffffffff, // BUGBUG specify valid call states
+ LINECALLSTATE_IDLE,
+ 0,
+ TRUE
+ );
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCompleteTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVCALL hdConsultCall,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ DWORD dwTransferMode
+ )
+{
+ static char szFuncName[] = "lineCompleteTransfer";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "hdConsultCall", hdConsultCall },
+ { "htConfCall", htConfCall },
+ { "lphdConfCall", lphdConfCall },
+ { "dwTransferMode", dwTransferMode, aTransferModes }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 6,
+ params,
+ TSPI_lineCompleteTransfer_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall(
+ (PDRVCALL) hdCall,
+ &info.pAsyncReqInfo->dwParam1
+ ) &&
+
+ IsValidDrvCall(
+ (PDRVCALL) hdConsultCall,
+ &info.pAsyncReqInfo->dwParam2
+ ))
+ {
+ info.pAsyncReqInfo->dwParam3 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) hdConsultCall;
+
+ if (dwTransferMode == LINETRANSFERMODE_CONFERENCE)
+ {
+ LONG lResult;
+ PDRVCALL pConfCall;
+ PDRVLINE pLine = ((PDRVCALL) hdCall)->pLine; // BUGBUG: AV
+
+
+ if ((lResult = AllocCall(
+ pLine,
+ htConfCall,
+ NULL,
+ &pConfCall
+
+ )) == 0)
+ {
+ *lphdConfCall = (HDRVCALL) pConfCall;
+ info.pAsyncReqInfo->dwParam5 = (DWORD) pConfCall;
+ info.pAsyncReqInfo->dwParam6 = pConfCall->dwCallInstance;
+ }
+ else
+ {
+ info.lResult = lResult;
+ }
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ static char szFuncName[] = "lineConditionalMediaDetection";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwMediaModes", dwMediaModes, aMediaModes },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineDevSpecific_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ LPVOID lpParams = pAsyncReqInfo->dwParam1;
+ DWORD dwSize = pAsyncReqInfo->dwParam2;
+
+
+ if (pAsyncReqInfo->lResult == 0 && dwSize >= 22)
+ {
+ lstrcpyA (lpParams, "ESP dev specific info");
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineDevSpecific";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "lpParams", lpParams },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 6,
+ params
+ };
+ PESPDEVSPECIFICINFO pInfo = (PESPDEVSPECIFICINFO) lpParams;
+
+
+ if (Prolog (&info))
+ {
+ if (dwSize >= sizeof (ESPDEVSPECIFICINFO) &&
+ pInfo->dwKey == ESPDEVSPECIFIC_KEY)
+ {
+ switch (pInfo->dwType)
+ {
+ case ESP_DEVSPEC_MSG:
+
+ switch (pInfo->u.EspMsg.dwMsg)
+ {
+ case LINE_ADDRESSSTATE:
+ case LINE_CLOSE:
+ case LINE_DEVSPECIFIC:
+ case LINE_DEVSPECIFICFEATURE:
+ case LINE_LINEDEVSTATE:
+
+ SendLineEvent(
+ (PDRVLINE) hdLine,
+ NULL,
+ pInfo->u.EspMsg.dwMsg,
+ pInfo->u.EspMsg.dwParam1,
+ pInfo->u.EspMsg.dwParam2,
+ pInfo->u.EspMsg.dwParam3
+ );
+
+ break;
+
+ case LINE_CALLDEVSPECIFIC:
+ case LINE_CALLDEVSPECIFICFEATURE:
+ case LINE_CALLINFO:
+ case LINE_MONITORDIGITS:
+ case LINE_MONITORMEDIA:
+
+ if (hdCall)
+ {
+ SendLineEvent(
+ (PDRVLINE) hdLine,
+ (PDRVCALL) hdCall,
+ pInfo->u.EspMsg.dwMsg,
+ pInfo->u.EspMsg.dwParam1,
+ pInfo->u.EspMsg.dwParam2,
+ pInfo->u.EspMsg.dwParam3
+ );
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+
+ break;
+
+ case LINE_GATHERDIGITS:
+
+ if (hdCall)
+ {
+ DWORD dwEndToEndID = 0;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ if ((dwEndToEndID =
+ pCall->dwGatherDigitsEndToEndID))
+ {
+ pCall->dwGatherDigitsEndToEndID = 0;
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (dwEndToEndID)
+ {
+ SendLineEvent(
+ (PDRVLINE) hdLine,
+ (PDRVCALL) hdCall,
+ LINE_GATHERDIGITS,
+ pInfo->u.EspMsg.dwParam1,
+ dwEndToEndID,
+ 0
+ );
+ }
+ else if (info.lResult == LINEERR_OPERATIONFAILED)
+ {
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: attempt to " \
+ "send GATHERDIGITS msg with no " \
+ "lineGatherDigits request pending"
+ );
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+
+ break;
+
+ case LINE_GENERATE:
+
+ if (hdCall)
+ {
+ DWORD dwEndToEndID = 0, *pdwXxxEndToEndID;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ pdwXxxEndToEndID = (pInfo->u.EspMsg.dwParam3 ?
+ &pCall->dwGenerateToneEndToEndID :
+ &pCall->dwGenerateDigitsEndToEndID
+ );
+
+ if ((dwEndToEndID = *pdwXxxEndToEndID))
+ {
+ *pdwXxxEndToEndID = 0;
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (dwEndToEndID)
+ {
+ SendLineEvent(
+ (PDRVLINE) hdLine,
+ (PDRVCALL) hdCall,
+ LINE_GENERATE,
+ pInfo->u.EspMsg.dwParam1,
+ dwEndToEndID,
+ 0
+ );
+ }
+ else if (info.lResult == LINEERR_OPERATIONFAILED)
+ {
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: attempt to " \
+ "send GENERATE msg with no " \
+ "lineGenerateXxx request pending"
+ );
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+
+ break;
+
+ case LINE_MONITORTONE:
+
+ if (hdCall)
+ {
+ DWORD dwToneListID = 0;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ if ((dwToneListID =
+ pCall->dwMonitorToneListID))
+ {
+ pCall->dwMonitorToneListID = 0;
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (dwToneListID)
+ {
+ SendLineEvent(
+ (PDRVLINE) hdLine,
+ (PDRVCALL) hdCall,
+ LINE_MONITORTONE,
+ pInfo->u.EspMsg.dwParam1,
+ dwToneListID,
+ 0
+ );
+ }
+ else if (info.lResult == LINEERR_OPERATIONFAILED)
+ {
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: attempt to " \
+ "send MONITORTONE msg with no " \
+ "lineMonitorTone request pending"
+ );
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+
+ break;
+
+ case LINE_CALLSTATE:
+ {
+ DWORD dwCallInst;
+
+
+ if (hdCall &&
+ IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInst))
+ {
+ LONG lResult;
+
+
+ // BUGBUG changing to/from conf state cause ptr probs?
+ // BUGBUG check for bad call state vals
+
+ if ((lResult = SetCallState(
+ (PDRVCALL) hdCall,
+ dwCallInst,
+ 0xffffffff,
+ pInfo->u.EspMsg.dwParam1,
+ pInfo->u.EspMsg.dwParam2,
+ TRUE
+
+ )) != 0)
+ {
+ info.lResult = lResult;
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+
+ break;
+ }
+ case LINE_CREATE: // BUGBUG
+
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: no support " \
+ "for indicating LINE_CREATE yet"
+ );
+
+ info.lResult = LINEERR_OPERATIONFAILED;
+ break;
+
+ case LINE_NEWCALL: // BUGBUG
+
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: no support " \
+ "for indicating LINE_NEWCALL yet"
+ );
+
+ info.lResult = LINEERR_OPERATIONFAILED;
+ break;
+
+ default:
+
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: unrecognized " \
+ "ESPDEVSPECIFICINFO.u.EspMsg.dwMsg (=x%x)",
+ pInfo->u.EspMsg.dwMsg
+ );
+
+ info.lResult = LINEERR_OPERATIONFAILED;
+ break;
+ }
+
+ break;
+
+ case ESP_DEVSPEC_RESULT:
+ {
+ DWORD dwResult = pInfo->u.EspResult.lResult;
+
+
+ if (dwResult != 0 &&
+ (dwResult < LINEERR_ALLOCATED ||
+ dwResult > PHONEERR_REINIT ||
+ (dwResult > LINEERR_DIALVOICEDETECT &&
+ dwResult < PHONEERR_ALLOCATED)))
+ {
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: invalid request" \
+ "result value (x%x)",
+ dwResult
+ );
+
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ else if (pInfo->u.EspResult.dwCompletionType >
+ ESP_RESULT_CALLCOMPLPROCASYNC)
+ {
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: invalid request" \
+ "completion type (x%x)",
+ pInfo->u.EspResult.dwCompletionType
+ );
+
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ else
+ {
+ glNextRequestResult = (LONG) dwResult;
+ gdwNextRequestCompletionType =
+ pInfo->u.EspResult.dwCompletionType;
+ gdwDevSpecificRequestID = dwRequestID;
+ }
+
+ break;
+ }
+ default:
+
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_lineDevSpecific: unrecognized " \
+ "ESPDEVSPECIFICINFO.dwType (=x%x)",
+ pInfo->dwType
+ );
+
+ info.lResult = LINEERR_OPERATIONFAILED;
+ break;
+ }
+ }
+ else
+ {
+ info.pAsyncReqInfo->dwParam1 = lpParams;
+ info.pAsyncReqInfo->dwParam2 = dwSize;
+
+ info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
+ TSPI_lineDevSpecific_postProcess;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDevSpecificFeature(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwFeature,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineDevSpecificFeature";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwFeature", dwFeature },
+ { "lpParams", lpParams },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 5,
+ params,
+ TSPI_lineDevSpecific_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ info.pAsyncReqInfo->dwParam1 = lpParams;
+ info.pAsyncReqInfo->dwParam2 = dwSize;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDial(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ static char szFuncName[] = "lineDial";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineDrop_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ //
+ // We need to make sure pCall is pointing at a valid call
+ // structure because it's possible that tapi immediately
+ // followed the drop request with a closeCall request
+ // (without waiting for the result from the drop)
+ //
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_IDLE,
+ 0,
+ TRUE
+
+ ) == 0)
+ {
+ if (pCall->pConfParent)
+ {
+ //
+ // Call is a conf child, so remove from conf list
+ //
+
+ PDRVCALL pCall2 = pCall->pConfParent;
+
+
+ while (pCall2 && (pCall2->pNextConfChild != pCall))
+ {
+ pCall2 = pCall2->pNextConfChild;
+ }
+
+ if (pCall2)
+ {
+ pCall2->pNextConfChild = pCall->pNextConfChild;
+ }
+
+ pCall->pConfParent = NULL;
+ }
+ else if (pCall->pNextConfChild)
+ {
+ //
+ // Call is a conf parent, so IDLE-ize all children &
+ // remove them from list
+ //
+
+ PDRVCALL pConfChild = pCall->pNextConfChild;
+
+
+ pCall->pNextConfChild = NULL;
+
+ while (pConfChild)
+ {
+ PDRVCALL pNextConfChild = pConfChild->pNextConfChild;
+
+
+ pConfChild->pConfParent =
+ pConfChild->pNextConfChild = NULL;
+
+ SetCallState(
+ pConfChild,
+ pConfChild->dwCallInstance,
+ 0xffffffff,
+ LINECALLSTATE_IDLE,
+ 0,
+ TRUE
+ );
+
+ pConfChild = pNextConfChild;
+ }
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineDrop";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_lineDrop_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam2))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineForward_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwConsultCallInstThen = pAsyncReqInfo->dwParam2;
+ PDRVCALL pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState(
+ pConsultCall,
+ dwConsultCallInstThen,
+ 0xffffffff, // BUGBUG specify valid call states
+ LINECALLSTATE_CONNECTED,
+ 0,
+ TRUE
+ );
+ }
+ else
+ {
+ FreeCall (pConsultCall, dwConsultCallInstThen);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineForward(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD bAllAddresses,
+ DWORD dwAddressID,
+ LPLINEFORWARDLIST const lpForwardList,
+ DWORD dwNumRingsNoAnswer,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ static char szFuncName[] = "lineForward";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "bAllAddresses", bAllAddresses },
+ { "dwAddressID", dwAddressID },
+ { "lpForwardList", lpForwardList },
+ { "dwNumRingsNoAnswer", dwNumRingsNoAnswer },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 9,
+ params,
+ TSPI_lineForward_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (bAllAddresses ||
+ dwAddressID < gESPGlobals.dwNumAddressesPerLine)
+ {
+ if (lpForwardList)
+ {
+ LONG lResult;
+ PDRVCALL pConsultCall;
+
+
+ if ((lResult = AllocCall(
+ (PDRVLINE) hdLine,
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+
+ )) == 0)
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) pConsultCall;
+ info.pAsyncReqInfo->dwParam2 = pConsultCall->dwCallInstance;
+
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+ }
+ else
+ {
+ info.lResult = lResult;
+ }
+ }
+ else
+ {
+ info.pAsyncReqInfo->pfnPostProcessProc = NULL;
+ *lphdConsultCall = (HDRVCALL) NULL;
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALADDRESSID;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGatherDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitModes,
+ LPWSTR lpsDigits,
+ DWORD dwNumDigits,
+ LPCWSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+{
+ static char szFuncName[] = "lineGatherDigits";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwEndToEndID", dwEndToEndID },
+ { "dwDigitModes", dwDigitModes, aDigitModes },
+ { "lpsDigits", lpsDigits },
+ { "dwNumDigits", dwNumDigits },
+ { "lpszTerminationDigits", lpszTerminationDigits },
+ { "dwFirstDigitTimeout", dwFirstDigitTimeout },
+ { "dwInterDigitTimeout", dwInterDigitTimeout }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 8, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ DWORD dwReason = 0;
+ HTAPILINE htLine;
+ HTAPICALL htCall;
+
+
+ if (Prolog (&info))
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ htLine = ((PDRVLINE) pCall->pLine)->htLine;
+ htCall = pCall->htCall;
+
+ if (lpsDigits)
+ {
+ lstrcpynW (lpsDigits, L"1234567890", dwNumDigits);
+
+ if (dwNumDigits == 10)
+ {
+ lpsDigits[9] = L'0';
+ }
+ }
+
+ if (gbAutoGatherGenerateMsgs)
+ {
+ if (lpsDigits)
+ {
+ dwReason = (dwNumDigits > 10 ? LINEGATHERTERM_INTERTIMEOUT
+ : LINEGATHERTERM_BUFFERFULL);
+ }
+ }
+ else
+ {
+ DWORD dwEndToEndIDTmp = dwEndToEndID;
+
+
+ if ((dwEndToEndID = pCall->dwGatherDigitsEndToEndID))
+ {
+ dwReason = LINEGATHERTERM_CANCEL;
+ }
+
+ pCall->dwGatherDigitsEndToEndID = (lpsDigits ?
+ dwEndToEndIDTmp : 0);
+ }
+ }
+ else
+ {
+ htLine = (HTAPILINE) (htCall = (HTAPICALL) NULL);
+ dwReason = (lpsDigits ? LINEGATHERTERM_CANCEL : 0);
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (dwReason)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ htLine,
+ htCall,
+ LINE_GATHERDIGITS,
+ dwReason,
+ dwEndToEndID,
+ 0
+ );
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGenerateDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitMode,
+ LPCWSTR lpszDigits,
+ DWORD dwDuration
+ )
+{
+ static char szFuncName[] = "lineGenerateDigits";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwEndToEndID", dwEndToEndID },
+ { "dwDigitMode", dwDigitMode, aDigitModes },
+ { "lpszDigits", lpszDigits },
+ { "dwDuration", dwDuration }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 5, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ HTAPILINE htLine;
+ HTAPICALL htCall;
+ DWORD dwReason = 0;
+
+
+ if (Prolog (&info))
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ htLine = ((PDRVLINE) pCall->pLine)->htLine;
+ htCall = pCall->htCall;
+
+ if (gbAutoGatherGenerateMsgs)
+ {
+ dwReason = (lpszDigits ? LINEGENERATETERM_DONE : 0);
+ }
+ else
+ {
+ DWORD dwEndToEndIDTmp = dwEndToEndID;
+
+
+ if ((dwEndToEndID = pCall->dwGenerateDigitsEndToEndID))
+ {
+ dwReason = LINEGENERATETERM_CANCEL;
+ }
+
+ pCall->dwGenerateDigitsEndToEndID = (lpszDigits ?
+ dwEndToEndIDTmp : 0);
+ }
+ }
+ else
+ {
+ htLine = (HTAPILINE) (htCall = (HTAPICALL) NULL);
+ dwReason = (lpszDigits ? LINEGENERATETERM_CANCEL : 0);
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (dwReason)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ htLine,
+ htCall,
+ LINE_GENERATE,
+ dwReason,
+ dwEndToEndID,
+ 0
+ );
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGenerateTone(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwToneMode,
+ DWORD dwDuration,
+ DWORD dwNumTones,
+ LPLINEGENERATETONE const lpTones
+ )
+{
+ static char szFuncName[] = "lineGenerateTone";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwEndToEndID", dwEndToEndID },
+ { "dwToneMode", dwToneMode, aToneModes },
+ { "dwDuration", dwDuration },
+ { "dwNumTones", dwNumTones },
+ { "lpTones", lpTones }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 6, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ HTAPILINE htLine;
+ HTAPICALL htCall;
+ DWORD dwReason = 0;
+
+
+ if (Prolog (&info))
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ htLine = ((PDRVLINE) pCall->pLine)->htLine;
+ htCall = pCall->htCall;
+
+ if (gbAutoGatherGenerateMsgs)
+ {
+ dwReason = (dwToneMode ? LINEGENERATETERM_DONE : 0);
+ }
+ else
+ {
+ DWORD dwEndToEndIDTmp = dwEndToEndID;
+
+
+ if ((dwEndToEndID = pCall->dwGenerateToneEndToEndID))
+ {
+ dwReason = LINEGENERATETERM_CANCEL;
+ }
+
+ pCall->dwGenerateToneEndToEndID = (dwToneMode ?
+ dwEndToEndIDTmp : 0);
+ }
+ }
+ else
+ {
+ htLine = (HTAPILINE) (htCall = (HTAPICALL) NULL);
+ dwReason = (dwToneMode ? LINEGENERATETERM_CANCEL : 0);
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (dwReason)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ htLine,
+ htCall,
+ LINE_GENERATE,
+ dwReason,
+ dwEndToEndID,
+ 0
+ );
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+{
+ static char szFuncName[] = "lineGetAddressCaps";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwAddressID", dwAddressID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpAddressCaps", lpAddressCaps }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 5, params };
+ DWORD dwUsedSize;
+ PDRVLINE pLine = GetLineFromID (dwDeviceID);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ if (dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
+ {
+ info.lResult = LINEERR_INVALADDRESSID;
+ return (Epilog (&info));
+ }
+
+ //lpAddressCaps->dwTotalSize
+ //lpAddressCaps->dwNeededSize
+ //lpAddressCaps->dwUsedSize
+ //lpAddressCaps->dwLineDeviceID
+ //
+ //lpAddressCaps->dwAddressOffset
+
+ {
+ WCHAR buf[20];
+
+
+ wsprintfW (buf, L"%d#%d", dwDeviceID, dwAddressID);
+
+ InsertVarDataString(
+ lpAddressCaps,
+ &lpAddressCaps->dwAddressSize,
+ buf
+ );
+ }
+
+ //lpAddressCaps->dwDevSpecificSize
+ //lpAddressCaps->dwDevSpecificOffset
+ //lpAddressCaps->dwAddressSharing
+ //lpAddressCaps->dwAddressStates
+ //lpAddressCaps->dwCallInfoStates
+ //lpAddressCaps->dwCallerIDFlags
+ //lpAddressCaps->dwCalledIDFlags
+ //lpAddressCaps->dwConnectedIDFlags
+ //lpAddressCaps->dwRedirectionIDFlags
+ //lpAddressCaps->dwRedirectingIDFlags
+ //lpAddressCaps->dwCallStates
+ //lpAddressCaps->dwDialToneModes
+ //lpAddressCaps->dwBusyModes
+ //lpAddressCaps->dwSpecialInfo
+ //lpAddressCaps->dwDisconnectModes
+ lpAddressCaps->dwMaxNumActiveCalls = gESPGlobals.dwNumCallsPerAddress;
+ //lpAddressCaps->dwMaxNumOnHoldCalls
+ //lpAddressCaps->dwMaxNumOnHoldPendingCalls
+ //lpAddressCaps->dwMaxNumConference
+ //lpAddressCaps->dwMaxNumTransConf
+ lpAddressCaps->dwAddrCapFlags = AllAddrCaps1_0;
+ lpAddressCaps->dwCallFeatures = AllCallFeatures1_0;
+ //lpAddressCaps->dwRemoveFromConfCaps
+ //lpAddressCaps->dwRemoveFromConfState
+ //lpAddressCaps->dwTransferModes
+ //lpAddressCaps->dwParkModes
+ //lpAddressCaps->dwForwardModes
+ //lpAddressCaps->dwMaxForwardEntries
+ //lpAddressCaps->dwMaxSpecificEntries
+ //lpAddressCaps->dwMinFwdNumRings
+ //lpAddressCaps->dwMaxFwdNumRings
+ //lpAddressCaps->dwMaxCallCompletions
+ //lpAddressCaps->dwCallCompletionConds
+ //lpAddressCaps->dwCallCompletionModes
+ lpAddressCaps->dwNumCompletionMessages = MAX_NUM_COMPLETION_MESSAGES;
+ //lpAddressCaps->dwCompletionMsgTextEntrySize
+ //lpAddressCaps->dwCompletionMsgTextSize
+ //lpAddressCaps->dwCompletionMsgTextOffset
+
+ if (dwTSPIVersion >= 0x00010004)
+ {
+ lpAddressCaps->dwCallFeatures = AllCallFeatures1_4;
+
+ lpAddressCaps->dwAddressFeatures = AllAddrFeatures1_0;
+
+ if (dwTSPIVersion >= 0x00020000)
+ {
+ lpAddressCaps->dwAddrCapFlags = AllAddrCaps2_0;
+ lpAddressCaps->dwCallFeatures = AllCallFeatures2_0;
+ lpAddressCaps->dwAddressFeatures = AllAddrFeatures2_0;
+
+ //lpAddressCaps->dwPredictiveAutoTransferStates
+ //lpAddressCaps->dwNumCallTreatments
+ //lpAddressCaps->dwCallTreatmentListSize
+ //lpAddressCaps->dwCallTreatmentListOffset
+ //lpAddressCaps->dwDeviceClassesSize
+ //lpAddressCaps->dwDeviceClassesOffset
+ //lpAddressCaps->dwMaxCallDataSize
+ lpAddressCaps->dwCallFeatures2 = AllCallFeaturesTwo;
+ //lpAddressCaps->dwMaxNoAnswerTimeout
+ //lpAddressCaps->dwConnectedModes
+ //lpAddressCaps->dwOfferingModes
+ lpAddressCaps->dwAvailableMediaModes = AllMediaModes1_4;
+ }
+ }
+
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCWSTR lpsAddress,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineGetAddressID";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "lpdwAddressID", lpdwAddressID },
+ { "dwAddressMode", dwAddressMode },
+ { "lpsAddress", lpsAddress },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 5, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+{
+ static char szFuncName[] = "lineGetAddressStatus";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { "lpAddressStatus", lpAddressStatus }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ if (dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
+ {
+ info.lResult = LINEERR_INVALADDRESSID;
+ return (Epilog (&info));
+ }
+
+ //lpAddressStatus->dwNeededSize
+ //lpAddressStatus->dwUsedSize
+ //lpAddressStatus->dwNumInUse
+
+ if (pLine->aAddrs[dwAddressID].dwNumCalls != 0)
+ {
+ PDRVCALL pCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ for(
+ pCall = pLine->aAddrs[dwAddressID].pCalls;
+ pCall != NULL;
+ pCall = pCall->pNext
+ )
+ {
+ switch (pCall->dwCallState)
+ {
+ case LINECALLSTATE_IDLE:
+
+ continue;
+
+ case LINECALLSTATE_ONHOLD:
+
+ lpAddressStatus->dwNumOnHoldCalls++;
+ continue;
+
+ case LINECALLSTATE_ONHOLDPENDCONF:
+ case LINECALLSTATE_ONHOLDPENDTRANSFER:
+
+ lpAddressStatus->dwNumOnHoldPendCalls++;
+ continue;
+
+ default:
+
+ lpAddressStatus->dwNumActiveCalls++;
+ continue;
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ lpAddressStatus->dwAddressFeatures = (gESPGlobals.dwSPIVersion > 0x10004 ?
+ AllAddrFeatures1_0 : AllAddrFeatures2_0);
+ //lpAddressStatus->dwNumRingsNoAnswer
+ //lpAddressStatus->dwForwardNumEntries
+ //lpAddressStatus->dwForwardSize
+ //lpAddressStatus->dwForwardOffset
+ //lpAddressStatus->dwTerminalModesSize
+ //lpAddressStatus->dwTerminalModesOffset
+ //lpAddressStatus->dwDevSpecificSize
+ //lpAddressStatus->dwDevSpecificOffset
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+{
+ static char szFuncName[] = "lineGetCallAddressID";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "lpdwAddressID", lpdwAddressID }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (Prolog (&info))
+ {
+ *lpdwAddressID = ((PDRVCALL) hdCall)->dwAddressID;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+{
+ static char szFuncName[] = "lineGetCallInfo";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "lpCallInfo", lpCallInfo }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ DWORD dwUsedSize;
+
+
+ if (Prolog (&info))
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ //lpCallInfo->dwNeededSize
+ //lpCallInfo->dwUsedSize
+ lpCallInfo->dwLineDeviceID = ((PDRVLINE) pCall->pLine)->dwDeviceID;
+ lpCallInfo->dwAddressID = pCall->dwAddressID;
+ lpCallInfo->dwBearerMode = pCall->dwBearerMode;
+ //lpCallInfo->dwRate
+ lpCallInfo->dwMediaMode = pCall->dwMediaMode;
+ lpCallInfo->dwAppSpecific = pCall->dwAppSpecific;
+ lpCallInfo->dwCallID = pCall->dwCallID;
+ //lpCallInfo->dwRelatedCallID
+ //lpCallInfo->dwCallParamFlags
+ //lpCallInfo->dwCallStates
+
+ CopyMemory(
+ &lpCallInfo->DialParams,
+ &pCall->DialParams,
+ sizeof(LINEDIALPARAMS)
+ );
+
+ //lpCallInfo->dwOrigin
+ //lpCallInfo->dwReason
+ //lpCallInfo->dwCompletionID
+ //lpCallInfo->dwCountryCode
+ //lpCallInfo->dwTrunk
+ //lpCallInfo->dwCallerIDFlags
+ //lpCallInfo->dwCallerIDSize
+ //lpCallInfo->dwCallerIDOffset
+ //lpCallInfo->dwCallerIDNameSize
+ //lpCallInfo->dwCallerIDNameOffset
+ //lpCallInfo->dwCalledIDFlags
+ //lpCallInfo->dwCalledIDSize
+ //lpCallInfo->dwCalledIDOffset
+ //lpCallInfo->dwCalledIDNameSize
+ //lpCallInfo->dwCalledIDNameOffset
+ //lpCallInfo->dwConnectedIDFlags
+ //lpCallInfo->dwConnectedIDSize
+ //lpCallInfo->dwConnectedIDOffset
+ //lpCallInfo->dwConnectedIDNameSize
+ //lpCallInfo->dwConnectedIDNameOffset
+ //lpCallInfo->dwRedirectionIDFlags
+ //lpCallInfo->dwRedirectionIDSize
+ //lpCallInfo->dwRedirectionIDOffset
+ //lpCallInfo->dwRedirectionIDNameSize
+ //lpCallInfo->dwRedirectionIDNameOffset
+ //lpCallInfo->dwRedirectingIDFlags
+ //lpCallInfo->dwRedirectingIDSize
+ //lpCallInfo->dwRedirectingIDOffset
+ //lpCallInfo->dwRedirectingIDNameSize
+ //lpCallInfo->dwRedirectingIDNameOffset
+ //lpCallInfo->dwDisplaySize
+ //lpCallInfo->dwDisplayOffset
+ //lpCallInfo->dwUserUserInfoSize
+ //lpCallInfo->dwUserUserInfoOffset
+ //lpCallInfo->dwHighLevelCompSize
+ //lpCallInfo->dwHighLevelCompOffset
+ //lpCallInfo->dwLowLevelCompSize
+ //lpCallInfo->dwLowLevelCompOffset
+ //lpCallInfo->dwChargingInfoSize
+ //lpCallInfo->dwChargingInfoOffset
+ //lpCallInfo->dwTerminalModesSize
+ //lpCallInfo->dwTerminalModesOffset
+ //lpCallInfo->dwDevSpecificSize
+ //lpCallInfo->dwDevSpecificOffset
+
+ if (gESPGlobals.dwSPIVersion >= 0x00020000)
+ {
+ lpCallInfo->dwCallTreatment = pCall->dwTreatment;
+
+ InsertVarData(
+ lpCallInfo,
+ &lpCallInfo->dwCallDataSize,
+ pCall->pCallData,
+ pCall->dwCallDataSize
+ );
+
+ InsertVarData(
+ lpCallInfo,
+ &lpCallInfo->dwSendingFlowspecSize,
+ pCall->pSendingFlowspec,
+ pCall->dwSendingFlowspecSize
+ );
+
+ InsertVarData(
+ lpCallInfo,
+ &lpCallInfo->dwReceivingFlowspecSize,
+ pCall->pReceivingFlowspec,
+ pCall->dwReceivingFlowspecSize
+ );
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+{
+ DWORD dwCallState, dwCallStateMode;
+ static char szFuncName[] = "lineGetCallStatus";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "lpCallStatus", lpCallStatus }
+ };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ dwCallState = pCall->dwCallState;
+ dwCallStateMode = pCall->dwCallStateMode;
+
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (info.lResult == 0)
+ {
+ //lpCallStatus->dwNeededSize
+ //lpCallStatus->dwUsedSize
+ lpCallStatus->dwCallState = dwCallState;
+ lpCallStatus->dwCallStateMode = dwCallStateMode;
+
+
+ //
+ // If the call is IDLE we won't let apps do anything with it,
+ // otherwise they can do anything they want to (all valid
+ // 1.0/1.4 LINECALLFEATURE_XXX flags)
+ //
+
+ switch (dwCallState)
+ {
+ case LINECALLSTATE_IDLE:
+
+ lpCallStatus->dwCallFeatures = 0;
+ break;
+
+ default:
+
+ lpCallStatus->dwCallFeatures =
+ (gESPGlobals.dwSPIVersion == 0x10003 ?
+ AllCallFeatures1_0 : AllCallFeatures1_4);
+ break;
+ }
+
+ //lpCallStatus->dwDevSpecificSize
+ //lpCallStatus->dwDevSpecificOffset
+
+ if (gESPGlobals.dwSPIVersion >= 0x00020000)
+ {
+ switch (dwCallState)
+ {
+ case LINECALLSTATE_IDLE:
+
+ lpCallStatus->dwCallFeatures = LINECALLFEATURE_SETCALLDATA;
+ break;
+
+ default:
+
+ lpCallStatus->dwCallFeatures = AllCallFeatures2_0;
+ lpCallStatus->dwCallFeatures2 = AllCallFeaturesTwo;
+ break;
+ }
+
+ //lpCallStatus->dwCallFeatures2
+ //lpCallStatus->tStateEntryTime
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+{
+ static char szFuncName[] = "lineGetDevCaps";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpLineDevCaps", lpLineDevCaps }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+ PDRVLINE pLine = GetLineFromID (dwDeviceID);
+ WCHAR buf[32];
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ InsertVarDataString(
+ lpLineDevCaps,
+ &lpLineDevCaps->dwProviderInfoSize,
+ gszProviderInfo
+ );
+
+ InsertVarDataString(
+ lpLineDevCaps,
+ &lpLineDevCaps->dwSwitchInfoSize,
+ L"ESP switch info"
+ );
+
+ lpLineDevCaps->dwPermanentLineID =
+ (gESPGlobals.dwPermanentProviderID << 16) |
+ (dwDeviceID - gESPGlobals.dwLineDeviceIDBase);
+
+ wsprintfW (buf, L"ESP Line %d", dwDeviceID);
+
+ InsertVarDataString(
+ lpLineDevCaps,
+ &lpLineDevCaps->dwLineNameSize,
+ buf
+ );
+
+ lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII;
+ lpLineDevCaps->dwAddressModes = LINEADDRESSMODE_ADDRESSID |
+ LINEADDRESSMODE_DIALABLEADDR;
+ lpLineDevCaps->dwNumAddresses = gESPGlobals.dwNumAddressesPerLine;
+ lpLineDevCaps->dwBearerModes = AllBearerModes1_0;
+ lpLineDevCaps->dwMaxRate = 0x00100000;
+ lpLineDevCaps->dwMediaModes = AllMediaModes1_0;
+ //lpLineDevCaps->dwGenerateToneModes
+ //lpLineDevCaps->dwGenerateToneMaxNumFreq
+ //lpLineDevCaps->dwGenerateDigitModes
+ //lpLineDevCaps->dwMonitorToneMaxNumFreq
+ //lpLineDevCaps->dwMonitorToneMaxNumEntries
+ //lpLineDevCaps->dwMonitorDigitModes
+ //lpLineDevCaps->dwGatherDigitsMinTimeout
+ //lpLineDevCaps->dwGatherDigitsMaxTimeout
+ //lpLineDevCaps->dwMedCtlDigitMaxListSize
+ //lpLineDevCaps->dwMedCtlMediaMaxListSize
+ //lpLineDevCaps->dwMedCtlToneMaxListSize;
+ //lpLineDevCaps->dwMedCtlCallStateMaxListSize
+ //lpLineDevCaps->dwDevCapFlags
+ lpLineDevCaps->dwMaxNumActiveCalls = gESPGlobals.dwNumAddressesPerLine *
+ gESPGlobals.dwNumCallsPerAddress;
+ //lpLineDevCaps->dwAnswerMode
+ //lpLineDevCaps->dwRingModes
+ //lpLineDevCaps->dwLineStates
+ //lpLineDevCaps->dwUUIAcceptSize
+ //lpLineDevCaps->dwUUIAnswerSize
+ //lpLineDevCaps->dwUUIMakeCallSize
+ //lpLineDevCaps->dwUUIDropSize
+ //lpLineDevCaps->dwUUISendUserUserInfoSize
+ //lpLineDevCaps->dwUUICallInfoSize
+ //lpLineDevCaps->MinDialParams
+ //lpLineDevCaps->MaxDialParams
+ //lpLineDevCaps->DefaultDialParams
+ //lpLineDevCaps->dwNumTerminals
+ //lpLineDevCaps->dwTerminalCapsSize
+ //lpLineDevCaps->dwTerminalCapsOffset
+ //lpLineDevCaps->dwTerminalTextEntrySize
+ //lpLineDevCaps->dwTerminalTextSize;
+ //lpLineDevCaps->dwTerminalTextOffset
+ //lpLineDevCaps->dwDevSpecificSize
+ //lpLineDevCaps->dwDevSpecificOffset
+
+ if (dwTSPIVersion >= 0x00010004)
+ {
+ lpLineDevCaps->dwBearerModes = AllBearerModes1_4;
+ lpLineDevCaps->dwMediaModes = AllMediaModes1_4;
+
+ lpLineDevCaps->dwLineFeatures = AllLineFeatures1_0;
+
+ if (dwTSPIVersion >= 0x00020000)
+ {
+ lpLineDevCaps->dwBearerModes = AllBearerModes2_0;
+
+ lpLineDevCaps->dwLineFeatures = AllLineFeatures2_0;
+
+ //lpLineDevCaps->dwSettableDevStatus
+ //lpLineDevCaps->dwDeviceClassesSize
+ //lpLineDevCaps->dwDeviceClassesOffset
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevConfig(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ static char szFuncName[] = "lineGetDevConfig";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpDeviceConfig", lpDeviceConfig },
+ { "lpszDeviceClass", lpszDeviceClass }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+
+
+ if (Prolog (&info))
+ {
+ // BUGBUG TSPI_lineGetDevConfig: fill in dev config
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPLINEEXTENSIONID lpExtensionID
+ )
+{
+ static char szFuncName[] = "lineGetExtensionID";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpExtensionID", lpExtensionID }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+
+
+ if (Prolog (&info))
+ {
+ // BUGBUG TSPI_lineGetExtensionID: fill in ext id
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetIcon(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ static char szFuncName[] = "lineGetIcon";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass },
+ { "lphIcon", lphIcon }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+
+
+ if (Prolog (&info))
+ {
+ if (lpszDeviceClass &&
+ lstrcmpiW (lpszDeviceClass, L"tapi/InvalidDeviceClass") == 0)
+ {
+ info.lResult = LINEERR_INVALDEVICECLASS;
+ }
+ else
+ {
+ *lphIcon = gESPGlobals.hIconLine;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+{
+ static char szFuncName[] = "lineGetID";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "dwSelect", dwSelect, aCallSelects },
+ { "lpDeviceID", lpDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass },
+ { "hTargetProcess", hTargetProcess }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 7, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ DWORD i, dwDeviceID, dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ for (i = 0; aszDeviceClasses[i]; i++)
+ {
+ if (lstrcmpiW (lpszDeviceClass, aszDeviceClasses[i]) == 0)
+ {
+ break;
+ }
+ }
+
+ if (!aszDeviceClasses[i])
+ {
+ info.lResult = LINEERR_NODEVICE;
+ return (Epilog (&info));
+ }
+
+ if (dwSelect == LINECALLSELECT_ADDRESS &&
+ dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
+ {
+ info.lResult = LINEERR_INVALADDRESSID;
+ return (Epilog (&info));
+ }
+
+ if (lpDeviceID->dwTotalSize < dwNeededSize)
+ {
+ lpDeviceID->dwNeededSize = dwNeededSize;
+ lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
+
+ return (Epilog (&info));
+ }
+
+ if (i == 0)
+ {
+ if (dwSelect == LINECALLSELECT_CALL)
+ {
+ dwDeviceID = ((PDRVLINE) pCall->pLine)->dwDeviceID;
+ }
+ else
+ {
+ dwDeviceID = pLine->dwDeviceID;
+ }
+ }
+ else
+ {
+// BUGBUG TSPI_lineGetID: if (gbShowLineGetIDDlg)
+// {
+// }
+// else
+// {
+ dwDeviceID = 0;
+// }
+ }
+
+ lpDeviceID->dwNeededSize =
+ lpDeviceID->dwUsedSize = dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof(DWORD);
+ lpDeviceID->dwStringOffset = sizeof(VARSTRING);
+
+ *((LPDWORD)(lpDeviceID + 1)) = dwDeviceID;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+{
+ static char szFuncName[] = "lineGetLineDevStatus";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "lpLineDevStatus", lpLineDevStatus }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ DWORD dwTotalSize, dwNeededSize;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ //lpLineDevStatus->dwNeededSize
+ //lpLineDevStatus->dwUsedSize
+ //lpLineDevStatus->dwNumOpens tapi fills this in
+ //lpLineDevStatus->dwOpenMediaModes tapi fills this in
+
+
+ //
+ // Safely determine the # of active, on hold, & onhold pending
+ // conference/transfer calls on this line
+ //
+
+ {
+ DWORD i;
+ PDRVCALL pCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ for (i = 0; i < gESPGlobals.dwNumAddressesPerLine; i++)
+ {
+ for(
+ pCall = pLine->aAddrs[i].pCalls;
+ pCall != NULL;
+ pCall = pCall->pNext
+ )
+ {
+ switch (pCall->dwCallState)
+ {
+ case LINECALLSTATE_IDLE:
+
+ continue;
+
+ case LINECALLSTATE_ONHOLD:
+
+ lpLineDevStatus->dwNumOnHoldCalls++;
+ continue;
+
+ case LINECALLSTATE_ONHOLDPENDCONF:
+ case LINECALLSTATE_ONHOLDPENDTRANSFER:
+
+ lpLineDevStatus->dwNumOnHoldPendCalls++;
+ continue;
+
+ default:
+
+ lpLineDevStatus->dwNumActiveCalls++;
+ continue;
+ }
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ lpLineDevStatus->dwLineFeatures = AllLineFeatures1_0;
+ //lpLineDevStatus->dwNumCallCompletions
+ //lpLineDevStatus->dwRingMode
+ //lpLineDevStatus->dwSignalLevel
+ //lpLineDevStatus->dwBatteryLevel
+ //lpLineDevStatus->dwRoamMode
+ lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
+ LINEDEVSTATUSFLAGS_INSERVICE;
+ //lpLineDevStatus->dwTerminalModesSize
+ //lpLineDevStatus->dwTerminalModesOffset
+ //lpLineDevStatus->dwDevSpecificSize
+ //lpLineDevStatus->dwDevSpecificOffset
+
+ if (gESPGlobals.dwSPIVersion >= 0x20000)
+ {
+ lpLineDevStatus->dwLineFeatures = AllLineFeatures2_0;
+
+ lpLineDevStatus->dwAvailableMediaModes = AllMediaModes1_4;
+
+ //lpLineDevStatus->dwAppInfoSize; tapi fills this in
+ //lpLineDevStatus->dwAppInfoOffset; tapi fills this in
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+{
+ static char szFuncName[] = "lineGetNumAddressIDs";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "lpdwNumAddressIDs", lpdwNumAddressIDs }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (Prolog (&info))
+ {
+ *lpdwNumAddressIDs = gESPGlobals.dwNumAddressesPerLine;
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineHold_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ pAsyncReqInfo->lResult = SetCallState(
+ pCall,
+ dwCallInstThen,
+ LINECALLSTATE_CONNECTED,
+ LINECALLSTATE_ONHOLD,
+ 0,
+ TRUE
+ );
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static char szFuncName[] = "lineHold";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 2,
+ params,
+ TSPI_lineHold_postProcess
+
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam2))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineMakeCall_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD bDestAddress = pAsyncReqInfo->dwParam3,
+ bValidLineID = pAsyncReqInfo->dwParam4,
+ dwCallInstThen = pAsyncReqInfo->dwParam6,
+ dwCallInstNow;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1,
+ pDestCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
+ PDRVLINE pDestLine = (PDRVLINE) pAsyncReqInfo->dwParam5;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if (bDestAddress)
+ {
+ if (bValidLineID && !pDestCall)
+ {
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_BUSY,
+ LINEBUSYMODE_UNAVAIL,
+ TRUE
+ );
+ }
+ else
+ {
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_DIALING,
+ 0,
+ FALSE
+ );
+
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_RINGBACK,
+ 0,
+ TRUE
+ );
+ }
+
+ if (pDestCall)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen)
+ {
+ SendLineEvent(
+ pDestLine,
+ NULL,
+ LINE_NEWCALL,
+ (DWORD) pDestCall,
+ (DWORD) &pDestCall->htCall,
+ 0
+ );
+
+ if (pDestCall->htCall != NULL)
+ {
+ SetCallState(
+ pDestCall,
+ pDestCall->dwCallInstance,
+ 0xffffffff,
+ LINECALLSTATE_OFFERING,
+ 0,
+ TRUE
+ );
+ }
+ else
+ {
+ FreeCall (pDestCall, pDestCall->dwCallInstance);
+ }
+ }
+ else
+ {
+ FreeCall (pDestCall, pDestCall->dwCallInstance);
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+ }
+ else
+ {
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_DIALTONE,
+ 0,
+ TRUE
+ );
+ }
+ }
+ else
+ {
+ FreeCall (pCall, dwCallInstThen);
+
+ if (pDestCall)
+ {
+ FreeCall (pDestCall, pDestCall->dwCallInstance);
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ static char szFuncName[] = "lineMakeCall";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "htCall", htCall },
+ { "lphdCall", lphdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 7,
+ params,
+ TSPI_lineMakeCall_postProcess
+
+ };
+
+ if (Prolog (&info))
+ {
+ BOOL bValidLineID = FALSE;
+ LONG lResult;
+ PDRVCALL pCall, pDestCall;
+ PDRVLINE pLine = (PDRVLINE) hdLine, pDestLine;
+
+
+ if ((lResult = AllocCall (pLine, htCall, lpCallParams, &pCall)) == 0)
+ {
+ *lphdCall = (HDRVCALL) pCall;
+
+ CreateIncomingCall(
+ lpszDestAddress,
+ lpCallParams,
+ pCall,
+ &bValidLineID,
+ &pDestLine,
+ &pDestCall
+ );
+
+ info.pAsyncReqInfo->dwParam1 = pCall;
+ info.pAsyncReqInfo->dwParam2 = pDestCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) lpszDestAddress;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) bValidLineID;
+ info.pAsyncReqInfo->dwParam5 = pDestLine;
+ info.pAsyncReqInfo->dwParam6 = pCall->dwCallInstance;
+ }
+ else
+ {
+ info.lResult = lResult;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorDigits(
+ HDRVCALL hdCall,
+ DWORD dwDigitModes
+ )
+{
+ static char szFuncName[] = "lineMonitorDigits";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwDigitModes", dwDigitModes, aDigitModes }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorMedia(
+ HDRVCALL hdCall,
+ DWORD dwMediaModes
+ )
+{
+ static char szFuncName[] = "lineMonitorMedia";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwMediaModes", dwMediaModes, aMediaModes }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorTones(
+ HDRVCALL hdCall,
+ DWORD dwToneListID,
+ LPLINEMONITORTONE const lpToneList,
+ DWORD dwNumEntries
+ )
+{
+ static char szFuncName[] = "lineMonitorTones";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwToneListID", dwToneListID },
+ { "lpToneList", lpToneList },
+ { "dwNumEntries", dwNumEntries }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (Prolog (&info))
+ {
+ DWORD dwLastToneListID = 0;
+ HTAPICALL htCall;
+ HTAPILINE htLine;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ htLine = ((PDRVLINE) pCall->pLine)->htLine;
+ htCall = pCall->htCall;
+
+ if (gbAutoGatherGenerateMsgs)
+ {
+ dwLastToneListID = dwToneListID;
+ }
+ else
+ {
+ dwLastToneListID = pCall->dwMonitorToneListID;
+ pCall->dwMonitorToneListID = dwToneListID;
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (dwLastToneListID)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ htLine,
+ htCall,
+ LINE_MONITORTONE,
+ 0,
+ dwLastToneListID,
+ 0
+ );
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ static char szFuncName[] = "lineNegotiateExtVersion";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwExtVersion", lpdwExtVersion }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 5, params };
+
+
+ if (Prolog (&info))
+ {
+ if (dwLowVersion == 0 ||
+ dwHighVersion == 0xffffffff ||
+ dwLowVersion > dwHighVersion)
+ {
+ info.lResult = LINEERR_INCOMPATIBLEEXTVERSION;
+ }
+ else
+ {
+ *lpdwExtVersion = dwHighVersion;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ static char szFuncName[] = "lineNegotiateTSPIVersion";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwTSPIVersion", lpdwTSPIVersion }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+
+
+ if (Prolog (&info))
+ {
+ *lpdwTSPIVersion = gESPGlobals.dwSPIVersion;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+{
+ static char szFuncName[] = "lineOpen";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "htLine", htLine },
+ { "lphdLine", lphdLine },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpfnEventProc", lpfnEventProc }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 5, params };
+ PDRVLINE pLine;
+
+
+ if (Prolog (&info))
+ {
+ if ((pLine = GetLineFromID (dwDeviceID)))
+ {
+ pLine->htLine = htLine;
+
+ *lphdLine = (HDRVLINE) pLine;
+
+ WriteEventBuffer(
+ pLine->dwDeviceID,
+ WIDGETTYPE_LINE,
+ (DWORD) pLine,
+ (DWORD) htLine,
+ 0,
+ 0
+ );
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_linePark_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2,
+ dwParkIndex = pAsyncReqInfo->dwParam4;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1,
+ pParkedCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
+ pDestCall;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ pDestCall = pCall->pDestCall;
+ pCall->pDestCall = NULL;
+
+ pParkedCall->bConnectedToDestCall =
+ pCall->bConnectedToDestCall;
+
+ pAsyncReqInfo->lResult = SetCallState(
+ pCall,
+ dwCallInstThen,
+ LINECALLSTATE_CONNECTED | LINECALLSTATE_ONHOLD,
+ LINECALLSTATE_IDLE,
+ 0,
+ TRUE
+ );
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pDestCall, NULL))
+ {
+ pDestCall->pDestCall = pParkedCall;
+ pParkedCall->pDestCall = pDestCall;
+ }
+
+// BUGBUG TSPI_linePark: what if dest call state chg while buddy parked???
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+ else
+ {
+ //
+ // Clean up parked call
+ //
+
+ if (pParkedCall->pSendingFlowspec)
+ {
+ DrvFree (pParkedCall->pSendingFlowspec);
+ }
+
+ if (pParkedCall->pReceivingFlowspec)
+ {
+ DrvFree (pParkedCall->pReceivingFlowspec);
+ }
+
+ if (pParkedCall->pCallData)
+ {
+ DrvFree (pParkedCall->pCallData);
+ }
+
+ DrvFree (pParkedCall);
+
+ gaParkedCalls[dwParkIndex] = NULL;
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePark(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwParkMode,
+ LPCWSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+{
+ static char szFuncName[] = "linePark";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "dwParkMode", dwParkMode },
+ { "lpszDirAddress", lpszDirAddress },
+ { "lpNonDirAddress", lpNonDirAddress }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 5, params, NULL };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (Prolog (&info))
+ {
+ if (dwParkMode == LINEPARKMODE_DIRECTED)
+ {
+ info.lResult = TransferCall(
+ &info,
+ pCall,
+ LINECALLSTATE_CONNECTED | LINECALLSTATE_ONHOLD,
+ LINECALLSTATE_ONHOLD,
+ lpszDirAddress
+ );
+ }
+ else
+ {
+ //
+ // First check to see if buf is big enough to return parked addr
+ //
+
+ if (lpNonDirAddress->dwTotalSize <
+ (sizeof (VARSTRING) + 9 * sizeof(WCHAR))) // L"9999#123"
+ {
+ lpNonDirAddress->dwNeededSize = sizeof (VARSTRING) +
+ 9 * sizeof(WCHAR);
+
+ info.lResult = LINEERR_STRUCTURETOOSMALL;
+
+ return (Epilog (&info));
+ }
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL) == FALSE)
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ else if (pCall->dwCallState != LINECALLSTATE_CONNECTED &&
+ pCall->dwCallState != LINECALLSTATE_ONHOLD)
+ {
+ info.lResult = LINEERR_INVALCALLSTATE;
+ }
+ else
+ {
+ DWORD i;
+
+
+ for (i = 0; i < MAX_NUM_PARKED_CALLS; i++)
+ {
+ if (gaParkedCalls[i] == NULL)
+ {
+ break;
+ }
+ }
+
+ if (i < MAX_NUM_PARKED_CALLS)
+ {
+ //
+ // Create a new call struct, dup-ing all the info of
+ // the existing call, & stick it in the parking place
+ //
+
+ DWORD dwStringSize;
+ PDRVCALL pParkedCall;
+
+
+ if ((pParkedCall = DrvAlloc (sizeof (DRVCALL))))
+ {
+ char buf[16];
+
+
+ CopyMemory(
+ &pParkedCall->dwMediaMode,
+ &pCall->dwMediaMode,
+ 8 * sizeof (DWORD) + sizeof (LINEDIALPARAMS)
+ );
+
+ if (pCall->pSendingFlowspec &&
+ (pParkedCall->pSendingFlowspec =
+ DrvAlloc (pCall->dwSendingFlowspecSize)))
+
+ {
+ pParkedCall->dwSendingFlowspecSize =
+ pCall->dwSendingFlowspecSize;
+ }
+
+ if (pCall->pReceivingFlowspec &&
+ (pParkedCall->pReceivingFlowspec =
+ DrvAlloc (pCall->dwReceivingFlowspecSize)))
+
+ {
+ pParkedCall->dwReceivingFlowspecSize =
+ pCall->dwReceivingFlowspecSize;
+ }
+
+ if (pCall->pCallData &&
+ (pParkedCall->pCallData =
+ DrvAlloc (pCall->dwCallDataSize)))
+ {
+ pParkedCall->dwCallDataSize =
+ pCall->dwCallDataSize;
+ }
+
+ pParkedCall->dwCallInstance = gdwCallInstance++;
+ pParkedCall->dwCallID = pCall->dwCallID;
+
+ gaParkedCalls[i] = pParkedCall;
+
+ wsprintf (buf, "9999#%d", i);
+
+ dwStringSize = (DWORD) MultiByteToWideChar(
+ GetACP(),
+ MB_PRECOMPOSED,
+ (LPCSTR) buf,
+ lstrlenA (buf) + 1,
+ (LPWSTR) (lpNonDirAddress + 1),
+ 9
+ ) * sizeof (WCHAR);
+
+ lpNonDirAddress->dwNeededSize += dwStringSize;
+ lpNonDirAddress->dwUsedSize += dwStringSize;
+
+ lpNonDirAddress->dwStringFormat = STRINGFORMAT_UNICODE;
+ lpNonDirAddress->dwStringSize = dwStringSize;
+ lpNonDirAddress->dwStringOffset = sizeof (VARSTRING);
+
+ info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
+ TSPI_linePark_postProcess;
+
+ info.pAsyncReqInfo->dwParam1 = pCall;
+ info.pAsyncReqInfo->dwParam2 = pCall->dwCallInstance;
+ info.pAsyncReqInfo->dwParam3 = pParkedCall;
+ info.pAsyncReqInfo->dwParam4 = i;
+ }
+ else
+ {
+ info.lResult = LINEERR_NOMEM;
+ }
+ }
+ else
+ {
+ ShowStr(
+ TRUE,
+ "TSPI_linePark (undirected): no available " \
+ "parking spaces"
+ );
+
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_linePickup_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_OFFERING,
+ 0,
+ TRUE
+ );
+ }
+ else
+ {
+ FreeCall (pCall, dwCallInstThen);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePickup(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ LPCWSTR lpszGroupID
+ )
+{
+ static char szFuncName[] = "linePickup";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { "htCall", htCall },
+ { "lphdCall", lphdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "lpszGroupID", lpszGroupID }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 7,
+ params,
+ TSPI_linePickup_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ LONG lResult;
+ PDRVCALL pCall;
+
+
+ if ((lResult = AllocCall(
+ (PDRVLINE) hdLine,
+ htCall,
+ NULL,
+ &pCall
+
+ )) == 0)
+ {
+ // BUGBUG deal w/ addr id
+
+ *lphdCall = (HDRVCALL) pCall;
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) pCall;
+ info.pAsyncReqInfo->dwParam2 = pCall->dwCallInstance;
+ }
+ else
+ {
+ info.lResult = lResult;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_linePrepareAddToConference_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwConfCallInstThen = pAsyncReqInfo->dwParam1,
+ dwConsultCallInstThen = pAsyncReqInfo->dwParam4;
+ PDRVCALL pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam2,
+ pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam3;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState(
+ pConfCall,
+ dwConfCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_ONHOLDPENDCONF,
+ 0,
+ TRUE
+ );
+
+ SetCallState(
+ pConsultCall,
+ dwConsultCallInstThen,
+ 0xffffffff,
+ LINECALLSTATE_DIALTONE,
+ 0,
+ TRUE
+ );
+ }
+ else
+ {
+ FreeCall (pConsultCall, dwConsultCallInstThen);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePrepareAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ PDRVCALL pConsultCall;
+ static char szFuncName[] = "linePrepareAddToConference";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { "hdConfCall", hdConfCall },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 5,
+ params,
+ TSPI_linePrepareAddToConference_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall(
+ (PDRVCALL) hdConfCall,
+ &info.pAsyncReqInfo->dwParam1
+ ))
+ {
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdConfCall;
+
+ if ((lResult = AllocCall(
+ ((PDRVCALL) hdConfCall)->pLine, // BUGBUG: AV potential
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+
+ )) == 0)
+ {
+ info.pAsyncReqInfo->dwParam3 = (DWORD) pConsultCall;
+ info.pAsyncReqInfo->dwParam4 = pConsultCall->dwCallInstance;
+
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+ }
+ else
+ {
+ info.lResult = lResult;
+ }
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineRedirect(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ static char szFuncName[] = "lineRedirect";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (Prolog (&info))
+ {
+ info.lResult = TransferCall(
+ &info,
+ (PDRVCALL) hdCall,
+ LINECALLSTATE_OFFERING,
+ LINECALLSTATE_OFFERING,
+ lpszDestAddress
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineReleaseUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static char szFuncName[] = "lineReleaseUserUserInfo";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 2, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineRemoveFromConference_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ if (pAsyncReqInfo->lResult == 0)
+ {
+
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if ((pAsyncReqInfo->lResult = SetCallState(
+ pCall,
+ dwCallInstThen,
+ LINECALLSTATE_CONFERENCED,
+ LINECALLSTATE_CONNECTED,
+ 0,
+ TRUE
+
+ )) == 0)
+ {
+ PDRVCALL pCall2 = (PDRVCALL) pCall->pConfParent;
+
+
+ while (pCall2 && (pCall2->pNextConfChild != pCall))
+ {
+ pCall2 = pCall2->pNextConfChild;
+ }
+
+ if (pCall2)
+ {
+ pCall2->pNextConfChild = pCall->pNextConfChild;
+ }
+
+ pCall->pConfParent = NULL;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineRemoveFromConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static char szFuncName[] = "lineRemoveFromConference";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 2,
+ params,
+ TSPI_lineRemoveFromConference_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam2))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSecureCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static char szFuncName[] = "lineSecureCall";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 2, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSelectExtVersion(
+ HDRVLINE hdLine,
+ DWORD dwExtVersion
+ )
+{
+ static char szFuncName[] = "lineSelectExtVersion";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwExtVersion", dwExtVersion }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSendUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineSendUserUserInfo";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+{
+ static char szFuncName[] = "lineSetAppSpecific";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwAppSpecific", dwAppSpecific }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (Prolog (&info))
+ {
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ if (pCall->dwAppSpecific != dwAppSpecific)
+ {
+ pCall->dwAppSpecific = dwAppSpecific;
+
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLINFO,
+ LINECALLINFOSTATE_APPSPECIFIC,
+ 0,
+ 0
+ );
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetCallData_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1, dwCallInstNow,
+ dwCallDataSize = pAsyncReqInfo->dwParam4;
+ LPVOID pCallData = (LPVOID) pAsyncReqInfo->dwParam3, pToFree;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen)
+ {
+ pToFree = pCall->pCallData;
+ pCall->pCallData = pCallData;
+ pCall->dwCallDataSize = dwCallDataSize;
+
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLINFO,
+ LINECALLINFOSTATE_CALLDATA,
+ 0,
+ 0
+ );
+ }
+ else
+ {
+ pToFree = NULL;
+ pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ DrvFree (pToFree);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult != 0)
+ {
+ DrvFree (pCallData);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallData(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPVOID lpCallData,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "lineSetCallData";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpCallData", lpCallData },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_lineSetCallData_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall(
+ (PDRVCALL) hdCall,
+ &info.pAsyncReqInfo->dwParam1
+ ))
+ {
+ LPVOID pCallData;
+
+
+ if (dwSize)
+ {
+ if ((pCallData = DrvAlloc (dwSize)))
+ {
+ CopyMemory (pCallData, lpCallData, dwSize);
+ }
+ else
+ {
+ info.lResult = LINEERR_NOMEM;
+ }
+ }
+ else
+ {
+ pCallData = NULL;
+ }
+
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) pCallData;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) dwSize;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetCallParams_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1,
+ dwCallInstNow,
+ dwBearerMode = pAsyncReqInfo->dwParam3,
+ dwMinRate = pAsyncReqInfo->dwParam4,
+ dwMaxRate = pAsyncReqInfo->dwParam5;
+ PDRVCALL pCall = pAsyncReqInfo->dwParam2;
+ LPLINEDIALPARAMS pDialParams = pAsyncReqInfo->dwParam6;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen)
+ {
+ DWORD dwCallInfoStates = 0;
+
+
+ if (pCall->dwBearerMode != dwBearerMode)
+ {
+ pCall->dwBearerMode = dwBearerMode;
+ dwCallInfoStates |= LINECALLINFOSTATE_BEARERMODE;
+ }
+
+ if (pCall->dwMinRate != dwMinRate ||
+ pCall->dwMaxRate != dwMaxRate)
+ {
+ pCall->dwMinRate = dwMinRate;
+ pCall->dwMaxRate = dwMaxRate;
+ dwCallInfoStates |= LINECALLINFOSTATE_RATE;
+ }
+
+ if (pDialParams &&
+ (pCall->DialParams.dwDialPause != pDialParams->dwDialPause ||
+ pCall->DialParams.dwDialSpeed != pDialParams->dwDialSpeed ||
+ pCall->DialParams.dwDigitDuration !=
+ pDialParams->dwDigitDuration ||
+ pCall->DialParams.dwWaitForDialtone !=
+ pDialParams->dwWaitForDialtone))
+ {
+ pCall->DialParams.dwDialPause = pDialParams->dwDialPause;
+ pCall->DialParams.dwDialSpeed = pDialParams->dwDialSpeed;
+ pCall->DialParams.dwDigitDuration =
+ pDialParams->dwDigitDuration;
+ pCall->DialParams.dwWaitForDialtone =
+ pDialParams->dwWaitForDialtone;
+
+ dwCallInfoStates |= LINECALLINFOSTATE_DIALPARAMS;
+ }
+
+ if (dwCallInfoStates)
+ {
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLINFO,
+ dwCallInfoStates,
+ 0,
+ 0
+ );
+ }
+ }
+ else
+ {
+ pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pDialParams)
+ {
+ DrvFree (pDialParams);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallParams(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwBearerMode,
+ DWORD dwMinRate,
+ DWORD dwMaxRate,
+ LPLINEDIALPARAMS const lpDialParams
+ )
+{
+ static char szFuncName[] = "lineSetCallParams";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "dwBearerMode", dwBearerMode, aBearerModes },
+ { "dwMinRate", dwMinRate },
+ { "dwMaxRate", dwMaxRate },
+ { "lpDialParams", lpDialParams }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 6,
+ params,
+ TSPI_lineSetCallParams_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall(
+ (PDRVCALL) hdCall,
+ &info.pAsyncReqInfo->dwParam1
+ ))
+ {
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam3 = dwBearerMode;
+ info.pAsyncReqInfo->dwParam4 = dwMinRate;
+ info.pAsyncReqInfo->dwParam5 = dwMaxRate;
+
+ if (lpDialParams)
+ {
+ LPLINEDIALPARAMS pDialParams;
+
+
+ if ((pDialParams = DrvAlloc (sizeof (LINEDIALPARAMS))))
+ {
+ CopyMemory(
+ pDialParams,
+ lpDialParams,
+ sizeof (LINEDIALPARAMS)
+ );
+
+ info.pAsyncReqInfo->dwParam8 = (DWORD) pDialParams;
+ }
+ else
+ {
+ info.lResult = LINEERR_NOMEM;
+ }
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetCallQualityOfService_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1, dwCallInstNow,
+ dwSendingFlowspecSize = pAsyncReqInfo->dwParam4,
+ dwReceivingFlowspecSize = pAsyncReqInfo->dwParam6;
+ LPVOID pSendingFlowspec = (LPVOID) pAsyncReqInfo->dwParam3,
+ pReceivingFlowspec = (LPVOID) pAsyncReqInfo->dwParam5,
+ pToFree, pToFree2;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen)
+ {
+ pToFree = pCall->pSendingFlowspec;
+ pCall->pSendingFlowspec = pSendingFlowspec;
+ pCall->dwSendingFlowspecSize = dwSendingFlowspecSize;
+
+ pToFree2 = pCall->pReceivingFlowspec;
+ pCall->pReceivingFlowspec = pReceivingFlowspec;
+ pCall->dwReceivingFlowspecSize = dwReceivingFlowspecSize;
+
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLINFO,
+ LINECALLINFOSTATE_QOS,
+ 0,
+ 0
+ );
+ }
+ else
+ {
+ pToFree = pToFree2 = NULL;
+ pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ DrvFree (pToFree);
+ DrvFree (pToFree2);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult != 0)
+ {
+ DrvFree (pSendingFlowspec);
+ DrvFree (pReceivingFlowspec);
+ }
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallQualityOfService(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPVOID lpSendingFlowspec,
+ DWORD dwSendingFlowspecSize,
+ LPVOID lpReceivingFlowspec,
+ DWORD dwReceivingFlowspecSize
+ )
+{
+ static char szFuncName[] = "lineSetCallQualityOfService";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpSendingFlowspec", lpSendingFlowspec },
+ { "dwSendingFlowspecSize", dwSendingFlowspecSize },
+ { "lpReceivingFlowspec", lpReceivingFlowspec },
+ { "dwReceivingFlowspecSize", dwReceivingFlowspecSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 6,
+ params,
+ TSPI_lineSetCallQualityOfService_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam1))
+ {
+ LPVOID pSendingFlowspec, pReceivingFlowspec;
+
+
+ if (dwSendingFlowspecSize)
+ {
+ if ((pSendingFlowspec = DrvAlloc (dwSendingFlowspecSize)))
+ {
+ CopyMemory(
+ pSendingFlowspec,
+ lpSendingFlowspec,
+ dwSendingFlowspecSize
+ );
+ }
+ else
+ {
+ info.lResult = LINEERR_NOMEM;
+ goto TSPI_lineSetCallQualityOfService_epilog;
+ }
+ }
+ else
+ {
+ pSendingFlowspec = NULL;
+ }
+
+ if (dwReceivingFlowspecSize)
+ {
+ if ((pReceivingFlowspec = DrvAlloc (dwReceivingFlowspecSize)))
+ {
+ CopyMemory(
+ pReceivingFlowspec,
+ lpReceivingFlowspec,
+ dwReceivingFlowspecSize
+ );
+ }
+ else
+ {
+ info.lResult = LINEERR_NOMEM;
+
+ if (pSendingFlowspec)
+ {
+ DrvFree (pSendingFlowspec);
+
+ }
+
+ goto TSPI_lineSetCallQualityOfService_epilog;
+ }
+ }
+ else
+ {
+ pReceivingFlowspec = NULL;
+ }
+
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) pSendingFlowspec;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) dwSendingFlowspecSize;
+ info.pAsyncReqInfo->dwParam5 = (DWORD) pReceivingFlowspec;
+ info.pAsyncReqInfo->dwParam6 = (DWORD) dwReceivingFlowspecSize;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+TSPI_lineSetCallQualityOfService_epilog:
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetCallTreatment_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1, dwCallInstNow,
+ dwTreatment = pAsyncReqInfo->dwParam3;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen)
+ {
+ if (pCall->dwTreatment != dwTreatment)
+ {
+ pCall->dwTreatment = dwTreatment;
+
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLINFO,
+ LINECALLINFOSTATE_TREATMENT,
+ 0,
+ 0
+ );
+ }
+ }
+ else
+ {
+ pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallTreatment(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwTreatment
+ )
+{
+ static char szFuncName[] = "lineSetCallTreatment";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "dwTreatment", dwTreatment }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 3,
+ params,
+ TSPI_lineSetCallTreatment_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam1))
+ {
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam3 = dwTreatment;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCurrentLocation(
+ DWORD dwLocation
+ )
+{
+ static char szFuncName[] = "lineSetCurrentLocation";
+ FUNC_PARAM params[] =
+ {
+ { "dwLocation", dwLocation }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 1, params };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+{
+ static char szFuncName[] = "lineSetDefaultMediaDetection";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwMediaModes", dwMediaModes, aMediaModes }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (Prolog (&info))
+ {
+ pLine->dwMediaModes = dwMediaModes;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDevConfig(
+ DWORD dwDeviceID,
+ LPVOID const lpDeviceConfig,
+ DWORD dwSize,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ static char szFuncName[] = "lineSetDevConfig";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpDeviceConfig", lpDeviceConfig },
+ { szdwSize, dwSize },
+ { "lpszDeviceClass", lpszDeviceClass }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetLineDevStatus(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwStatusToChange,
+ DWORD fStatus
+ )
+{
+ static char szFuncName[] = "lineSetLineDevStatus";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwStatusToChange", dwStatusToChange },
+ { "fStatus", fStatus }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaControl(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPLINEMEDIACONTROLDIGIT const lpDigitList,
+ DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA const lpMediaList,
+ DWORD dwMediaNumEntries,
+ LPLINEMEDIACONTROLTONE const lpToneList,
+ DWORD dwToneNumEntries,
+ LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
+ DWORD dwCallStateNumEntries
+ )
+{
+ static char szFuncName[] = "lineSetMediaControl";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "dwSelect", dwSelect, aCallSelects },
+ { "lpDigitList", lpDigitList },
+ { "dwDigitNumEntries", dwDigitNumEntries },
+ { "lpMediaList", lpMediaList },
+ { "dwMediaNumEntries", dwMediaNumEntries },
+ { "lpToneList", lpToneList },
+ { "dwToneNumEntries", dwToneNumEntries },
+ { "lpCallStateList", lpCallStateList },
+ { "dwCallStateNumEntries", dwCallStateNumEntries }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 12, params };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+{
+ static char szFuncName[] = "lineSetMediaMode";
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, szhdCall },
+ { "dwMediaMode", dwMediaMode, aMediaModes }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (Prolog (&info))
+ {
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL))
+ {
+ if (pCall->dwMediaMode != dwMediaMode)
+ {
+ pCall->dwMediaMode = dwMediaMode;
+
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLINFO,
+ LINECALLINFOSTATE_MEDIAMODE,
+ 0,
+ 0
+ );
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetStatusMessages(
+ HDRVLINE hdLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+{
+ static char szFuncName[] = "lineSetStatusMessages";
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwLineStates", dwLineStates, aLineStates },
+ { "dwAddressStates", dwAddressStates, aAddressStates }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetTerminal(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ DWORD dwTerminalModes,
+ DWORD dwTerminalID,
+ DWORD bEnable
+ )
+{
+ static char szFuncName[] = "lineSetTerminal";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "dwSelect", dwSelect, aCallSelects },
+ { "dwTerminalModes", dwTerminalModes, aTerminalModes },
+ { "dwTerminalID", dwTerminalID },
+ { "bEnable", bEnable }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 8, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetupConference_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1,
+ dwConfCallInstThen = pAsyncReqInfo->dwParam4,
+ dwConsultCallInstThen = pAsyncReqInfo->dwParam6;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2,
+ pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
+ pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam5;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (SetCallState(
+ pConfCall,
+ dwConfCallInstThen,
+ 0xffffffff, // BUGBUG specify vald call states
+ LINECALLSTATE_ONHOLDPENDCONF,
+ 0,
+ TRUE
+
+ ) == 0)
+ {
+ if (pCall &&
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff, // BUGBUG specify vald call states
+ LINECALLSTATE_CONFERENCED,
+ 0,
+ TRUE
+
+ ) == 0)
+ {
+ pCall->pConfParent = pConfCall;
+ pConfCall->pNextConfChild = pCall;
+ }
+
+ // The consult call isn't in the conf initially
+
+ SetCallState(
+ pConsultCall,
+ dwConsultCallInstThen,
+ 0xffffffff, // BUGBUG specify vald call states
+ LINECALLSTATE_DIALTONE,
+ 0,
+ TRUE
+ );
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+ else
+ {
+ FreeCall (pConfCall, dwConfCallInstThen);
+ FreeCall (pConsultCall, dwConsultCallInstThen);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetupConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVLINE hdLine,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ static char szFuncName[] = "lineSetupConference";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { szhdLine, hdLine },
+ { "htConfCall", htConfCall },
+ { "lphdConfCall", lphdConfCall },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { "dwNumParties", dwNumParties },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 9,
+ params,
+ TSPI_lineSetupConference_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ LONG lResult;
+ PDRVCALL pConfCall, pConsultCall;
+ PDRVLINE pLine;
+
+
+ //info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (hdCall &&
+ !IsValidDrvCall(
+ (PDRVCALL) hdCall,
+ &info.pAsyncReqInfo->dwParam1
+ ))
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ goto TSPI_lineSetupConference_leaveCritSec;
+ }
+
+ pLine = (hdCall ? (PDRVLINE) ((PDRVCALL) hdCall)->pLine :
+ (PDRVLINE) hdLine);
+
+ if ((lResult = AllocCall(
+ pLine,
+ htConfCall,
+ lpCallParams,
+ &pConfCall
+
+ )) == 0)
+ {
+ if ((lResult = AllocCall(
+ pLine,
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+
+ )) == 0)
+ {
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) pConfCall;
+ info.pAsyncReqInfo->dwParam4 = pConfCall->dwCallInstance;
+ info.pAsyncReqInfo->dwParam5 = (DWORD) pConsultCall;
+ info.pAsyncReqInfo->dwParam6 = pConsultCall->dwCallInstance;
+
+ *lphdConfCall = (HDRVCALL) pConfCall;
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+ }
+ else
+ {
+ FreeCall (pConfCall, pConfCall->dwCallInstance);
+ info.lResult = lResult;
+ }
+ }
+ else
+ {
+ info.lResult = lResult;
+ }
+
+TSPI_lineSetupConference_leaveCritSec:
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetupTransfer_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1,
+ dwConsultCallInstThen = pAsyncReqInfo->dwParam4;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2,
+ pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam3;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if (SetCallState(
+ pConsultCall,
+ dwConsultCallInstThen,
+ 0xffffffff, // BUGBUG specify vald call states
+ LINECALLSTATE_DIALTONE,
+ 0,
+ TRUE
+
+ ) == 0)
+ {
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff, // BUGBUG specify vald call states
+ LINECALLSTATE_ONHOLD,
+ 0,
+ TRUE
+ );
+ }
+ }
+ else
+ {
+ FreeCall (pConsultCall, dwConsultCallInstThen);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetupTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ static char szFuncName[] = "lineSetupTransfer";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 5,
+ params,
+ TSPI_lineSetupTransfer_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam1))
+ {
+ LONG lResult;
+ PDRVCALL pConsultCall;
+
+
+ if ((lResult = AllocCall(
+ ((PDRVCALL) hdCall)->pLine,
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+
+ )) == 0)
+ {
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) pConsultCall;
+ info.pAsyncReqInfo->dwParam4 = pConsultCall->dwCallInstance;
+ }
+ else
+ {
+ info.lResult = lResult;
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSwapHold_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwActiveCallInstThen = pAsyncReqInfo->dwParam1,
+ dwHeldCallInstThen = pAsyncReqInfo->dwParam2,
+ dwActiveCallInstNow, dwHeldCallInstNow;
+ PDRVCALL pActiveCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
+ pHeldCall = (PDRVCALL) pAsyncReqInfo->dwParam4;
+
+
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ if (SetCallState(
+ pActiveCall,
+ dwActiveCallInstThen,
+ 0xffffffff, // BUGBUG specify vald call states
+ LINECALLSTATE_ONHOLD,
+ 0,
+ TRUE
+
+ ) == 0)
+ {
+ SetCallState(
+ pHeldCall,
+ dwHeldCallInstThen,
+ 0xffffffff, // BUGBUG specify vald call states
+ LINECALLSTATE_CONNECTED,
+ 0,
+ TRUE
+ );
+ }
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSwapHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdActiveCall,
+ HDRVCALL hdHeldCall
+ )
+{
+ static char szFuncName[] = "lineSwapHold";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { "hdActiveCall", hdActiveCall },
+ { "hdHeldCall", hdHeldCall }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 3,
+ params,
+ TSPI_lineSwapHold_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall(
+ (PDRVCALL) hdActiveCall,
+ &info.pAsyncReqInfo->dwParam1
+ ) &&
+
+ IsValidDrvCall(
+ (PDRVCALL) hdHeldCall,
+ &info.pAsyncReqInfo->dwParam2
+ ))
+ {
+ info.pAsyncReqInfo->dwParam3 = (DWORD) hdActiveCall;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) hdHeldCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUncompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwCompletionID
+ )
+{
+ static char szFuncName[] = "lineUncompleteCall";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwCompletionID", dwCompletionID }
+ };
+ FUNC_INFO info = { szFuncName, ASYNC, 3, params, NULL };
+
+
+ if (Prolog (&info))
+ {
+ if (dwCompletionID == 0xffffffff)
+ {
+ info.lResult = LINEERR_INVALCOMPLETIONID;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineUnhold_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam1;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
+
+
+ pAsyncReqInfo->lResult == SetCallState(
+ pCall,
+ dwCallInstThen,
+ LINECALLSTATE_ONHOLD,
+ LINECALLSTATE_CONNECTED,
+ 0,
+ TRUE
+ );
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUnhold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static char szFuncName[] = "lineUnhold";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 2,
+ params,
+ TSPI_lineUnhold_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (IsValidDrvCall ((PDRVCALL) hdCall, &info.pAsyncReqInfo->dwParam1))
+ {
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdCall;
+ }
+ else
+ {
+ info.lResult = LINEERR_INVALCALLHANDLE;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineUnpark_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2,
+ dwParkIndex = pAsyncReqInfo->dwParam3,
+ dwCallInstNow;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ //
+ // Make sure there's still a call there to unpark
+ //
+
+ if (gaParkedCalls[dwParkIndex] == NULL)
+ {
+ pAsyncReqInfo->lResult = LINEERR_OPERATIONFAILED;
+ }
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (gaParkedCalls[dwParkIndex] != NULL &&
+ IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen)
+ {
+ //
+ // Copy all the data from the parked call to the new call,
+ // then free the parked call
+ //
+
+ PDRVCALL pParkedCall = gaParkedCalls[dwParkIndex];
+
+
+ gaParkedCalls[dwParkIndex] = NULL;
+
+ CopyMemory(
+ &pCall->dwMediaMode,
+ &pParkedCall->dwMediaMode,
+ 14 * sizeof (DWORD) + sizeof (LINEDIALPARAMS)
+ );
+
+ if ((pCall->pDestCall = pParkedCall->pDestCall))
+ {
+ pCall->pDestCall->pDestCall = pCall;
+ pCall->bConnectedToDestCall =
+ pParkedCall->bConnectedToDestCall;
+ }
+
+ CopyMemory(
+ &pCall->dwGatherDigitsEndToEndID,
+ &pParkedCall->dwGatherDigitsEndToEndID,
+ 5 * sizeof (DWORD)
+ );
+
+
+ //
+ // Reset call state to 0 so SetCallState will do the indication
+ //
+
+ {
+ DWORD dwCallState = pCall->dwCallState;
+
+
+ pCall->dwCallState = 0;
+
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff, // BUGBUG specify valid call states
+ dwCallState,
+ 0,
+ TRUE
+ );
+ }
+
+ pParkedCall->dwKey = INVAL_KEY;
+ DrvFree (pParkedCall);
+ }
+ else
+ {
+ SetCallState(
+ pCall,
+ dwCallInstThen,
+ 0xffffffff, // BUGBUG specify valid call states
+ LINECALLSTATE_IDLE,
+ 0,
+ TRUE
+ );
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+ else
+ {
+ FreeCall (pCall, dwCallInstThen);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUnpark(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress
+ )
+{
+ static char szFuncName[] = "lineUnpark";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { "htCall", htCall },
+ { "lphdCall", lphdCall },
+ { "lpszDestAddress", lpszDestAddress }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 6,
+ params,
+ NULL
+ };
+
+
+ if (Prolog (&info))
+ {
+ //
+ // See if the park addr is valid, & if there's actually a
+ // call parked there now
+ //
+
+ char *pszDestAddress, *p, c;
+ DWORD length, dwParkIndex;
+
+
+ //
+ // Convert dest addr from unicode to ascii
+ //
+
+ length = (lstrlenW (lpszDestAddress) + 1) * sizeof (WCHAR);
+
+ if (!(pszDestAddress = DrvAlloc (length)))
+ {
+ info.lResult = LINEERR_NOMEM;
+ return (Epilog);
+ }
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDestAddress,
+ -1,
+ pszDestAddress,
+ length,
+ NULL,
+ NULL
+ );
+
+ p = pszDestAddress;
+
+
+ //
+ // See if destination address is in the format of "9999#<addr id>"
+ //
+
+ if (*p++ != '9' ||
+ *p++ != '9' ||
+ *p++ != '9' ||
+ *p++ != '9' ||
+ *p++ != '#' ||
+ *p < '0' ||
+ *p > '9')
+ {
+ info.lResult = LINEERR_INVALADDRESS;
+ goto TSPI_lineUnpark_freeDestAddress;
+ }
+
+ for (dwParkIndex = 0; (c = *p); p++)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ dwParkIndex *= 10;
+ dwParkIndex += ((DWORD)(c - '0'));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (c != '\0' || dwParkIndex >= MAX_NUM_PARKED_CALLS)
+ {
+ info.lResult = LINEERR_INVALADDRESS;
+ goto TSPI_lineUnpark_freeDestAddress;
+ }
+
+ if (gaParkedCalls[dwParkIndex] != NULL)
+ {
+ PDRVCALL pCall;
+ LINECALLPARAMS callParams;
+
+
+ ZeroMemory (&callParams, sizeof (LINECALLPARAMS));
+
+ callParams.dwTotalSize = sizeof (LINECALLPARAMS);
+
+ callParams.dwAddressID = dwAddressID;
+ callParams.dwAddressMode = LINEADDRESSMODE_ADDRESSID;
+
+ if ((info.lResult = AllocCall(
+ (PDRVLINE) hdLine,
+ htCall,
+ &callParams,
+ &pCall
+
+ )) == 0)
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) pCall;
+ info.pAsyncReqInfo->dwParam2 = pCall->dwCallInstance;
+ info.pAsyncReqInfo->dwParam3 = dwParkIndex;
+
+ *lphdCall = (HDRVCALL) pCall;
+
+ info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
+ TSPI_lineUnpark_postProcess;
+ }
+ }
+ else
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+
+TSPI_lineUnpark_freeDestAddress:
+
+ DrvFree (pszDestAddress);
+ }
+
+ return (Epilog (&info));
+}
+
+
+
+//
+// -------------------------- TSPI_phoneXxx funcs -----------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_phoneClose(
+ HDRVPHONE hdPhone
+ )
+{
+ static char szFuncName[] = "phoneClose";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 1, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ //
+ // This is more of a "command" than a request, in that TAPI.DLL is
+ // going to consider the phone closed whether we like it or not.
+ // Therefore we want to free up the phone even if the user chooses
+ // to return an error.
+ //
+
+ Prolog (&info);
+
+ pPhone->htPhone = (HTAPIPHONE) NULL;
+
+ WriteEventBuffer (pPhone->dwDeviceID, WIDGETTYPE_PHONE, 0, 0, 0, 0);
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "phoneDevSpecific";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "lpParams", lpParams },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params
+ };
+
+
+ if (Prolog (&info))
+ {
+ PESPDEVSPECIFICINFO pInfo = (PESPDEVSPECIFICINFO) lpParams;
+
+
+ if (dwSize >= sizeof (ESPDEVSPECIFICINFO) &&
+ pInfo->dwKey == ESPDEVSPECIFIC_KEY)
+ {
+ switch (pInfo->dwType)
+ {
+ case ESP_DEVSPEC_MSG:
+
+ switch (pInfo->u.EspMsg.dwMsg)
+ {
+ case PHONE_BUTTON:
+ case PHONE_CLOSE:
+ case PHONE_DEVSPECIFIC:
+ case PHONE_STATE:
+
+ SendPhoneEvent(
+ (PDRVPHONE) hdPhone,
+ pInfo->u.EspMsg.dwMsg,
+ pInfo->u.EspMsg.dwParam1,
+ pInfo->u.EspMsg.dwParam2,
+ pInfo->u.EspMsg.dwParam3
+ );
+
+ break;
+
+ case PHONE_CREATE: // BUGBUG
+
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_phoneDevSpecific: no support " \
+ "for indicating PHONE_CREATE yet"
+ );
+
+ info.lResult = PHONEERR_OPERATIONFAILED;
+ break;
+
+ default:
+
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_phoneDevSpecific: unrecognized " \
+ "ESPDEVSPECIFICINFO.u.EspMsg.dwMsg (=x%x)",
+ pInfo->u.EspMsg.dwMsg
+ );
+
+ info.lResult = PHONEERR_OPERATIONFAILED;
+ break;
+ }
+
+ break;
+
+ case ESP_DEVSPEC_RESULT:
+ {
+ DWORD dwResult = pInfo->u.EspResult.lResult;
+
+
+ if (dwResult != 0 &&
+ (dwResult < LINEERR_ALLOCATED ||
+ dwResult > PHONEERR_REINIT ||
+ (dwResult > LINEERR_DIALVOICEDETECT &&
+ dwResult < PHONEERR_ALLOCATED)))
+ {
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_phoneDevSpecific: invalid request" \
+ "result value (x%x)",
+ dwResult
+ );
+
+ info.lResult = PHONEERR_OPERATIONFAILED;
+ }
+ else if (pInfo->u.EspResult.dwCompletionType >
+ ESP_RESULT_CALLCOMPLPROCASYNC)
+ {
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_phoneDevSpecific: invalid request" \
+ "completion type (x%x)",
+ pInfo->u.EspResult.dwCompletionType
+ );
+
+ info.lResult = PHONEERR_OPERATIONFAILED;
+ }
+ else
+ {
+ glNextRequestResult = (LONG) dwResult;
+ gdwNextRequestCompletionType =
+ pInfo->u.EspResult.dwCompletionType;
+ gdwDevSpecificRequestID = dwRequestID;
+ }
+
+ break;
+ }
+ default:
+
+ ShowStr(
+ TRUE,
+ "ERROR: TSPI_phoneDevSpecific: unrecognized " \
+ "ESPDEVSPECIFICINFO.dwType (=x%x)",
+ pInfo->dwType
+ );
+
+ info.lResult = PHONEERR_OPERATIONFAILED;
+ break;
+ }
+ }
+ else
+ {
+ info.pAsyncReqInfo->dwParam1 = lpParams;
+ info.pAsyncReqInfo->dwParam2 = dwSize;
+
+ info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
+ TSPI_lineDevSpecific_postProcess;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetButtonInfo(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO lpButtonInfo
+ )
+{
+ static char szFuncName[] = "phoneGetButtonInfo";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "lpButtonInfo", lpButtonInfo }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ if (dwButtonLampID == 0)
+ {
+ if (pPhone->pButtonInfo)
+ {
+ if (pPhone->pButtonInfo->dwUsedSize <=
+ lpButtonInfo->dwTotalSize)
+ {
+ CopyMemory(
+ (LPBYTE) &lpButtonInfo->dwNeededSize,
+ (LPBYTE) &pPhone->pButtonInfo->dwNeededSize,
+ pPhone->pButtonInfo->dwUsedSize - sizeof (DWORD)
+ );
+ }
+ else
+ {
+ lpButtonInfo->dwNeededSize =
+ pPhone->pButtonInfo->dwUsedSize;
+ }
+ }
+ }
+ else
+ {
+ info.lResult = PHONEERR_INVALBUTTONLAMPID;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetData(
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID lpData,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "phoneGetData";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwDataID", dwDataID },
+ { "lpData", lpData },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ if (dwDataID != 0)
+ {
+ info.lResult = PHONEERR_INVALDATAID;
+ }
+ else if (pPhone->pData)
+ {
+ CopyMemory(
+ lpData,
+ pPhone->pData,
+ (dwSize > pPhone->dwDataSize ? pPhone->dwDataSize : dwSize)
+ );
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPPHONECAPS lpPhoneCaps
+ )
+{
+ static char szFuncName[] = "phoneGetDevCaps";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpPhoneCaps", lpPhoneCaps }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+ WCHAR buf[32];
+ DWORD dwDummy;
+ PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
+
+
+ if (Prolog (&info))
+ {
+ //lpPhoneCaps->dwNeededSize
+ //lpPhoneCaps->dwUsedSize
+
+ InsertVarDataString(
+ lpPhoneCaps,
+ &lpPhoneCaps->dwProviderInfoSize,
+ gszProviderInfo
+ );
+
+ //lpPhoneCaps->dwPhoneInfoSize
+ //lpPhoneCaps->dwPhoneInfoOffset
+
+ lpPhoneCaps->dwPermanentPhoneID =
+ (gESPGlobals.dwPermanentProviderID << 16) |
+ (dwDeviceID - gESPGlobals.dwPhoneDeviceIDBase);
+
+ wsprintfW (buf, L"ESP Phone %d", dwDeviceID);
+
+ InsertVarDataString(
+ lpPhoneCaps,
+ &lpPhoneCaps->dwPhoneNameSize,
+ buf
+ );
+
+ lpPhoneCaps->dwStringFormat = STRINGFORMAT_ASCII;
+ //lpPhoneCaps->dwPhoneStates
+ lpPhoneCaps->dwHookSwitchDevs = AllHookSwitchDevs;
+ lpPhoneCaps->dwHandsetHookSwitchModes =
+ lpPhoneCaps->dwSpeakerHookSwitchModes =
+ lpPhoneCaps->dwHeadsetHookSwitchModes = AllHookSwitchModes;
+ lpPhoneCaps->dwVolumeFlags = AllHookSwitchDevs;
+ lpPhoneCaps->dwGainFlags = AllHookSwitchDevs;
+ lpPhoneCaps->dwDisplayNumRows = 1;
+ lpPhoneCaps->dwDisplayNumColumns = PHONE_DISPLAY_SIZE_IN_CHARS;
+ lpPhoneCaps->dwNumRingModes = 0xffffffff;
+
+ lpPhoneCaps->dwNumButtonLamps = 1;
+
+ dwDummy = PHONEBUTTONMODE_FEATURE;
+
+ InsertVarData(
+ lpPhoneCaps,
+ &lpPhoneCaps->dwButtonModesSize,
+ (LPVOID) &dwDummy,
+ sizeof (DWORD)
+ );
+
+ dwDummy = PHONEBUTTONFUNCTION_UNKNOWN;
+
+ InsertVarData(
+ lpPhoneCaps,
+ &lpPhoneCaps->dwButtonFunctionsSize,
+ (LPVOID) &dwDummy,
+ sizeof (DWORD)
+ );
+
+ dwDummy = PHONELAMPMODE_OFF;
+
+ InsertVarData(
+ lpPhoneCaps,
+ &lpPhoneCaps->dwLampModesSize,
+ (LPVOID) &dwDummy,
+ sizeof (DWORD)
+ );
+
+
+ lpPhoneCaps->dwNumSetData = 1;
+
+ dwDummy = MAX_VAR_DATA_SIZE;
+
+ InsertVarData(
+ lpPhoneCaps,
+ &lpPhoneCaps->dwSetDataSize,
+ (LPVOID) &dwDummy,
+ sizeof (DWORD)
+ );
+
+ lpPhoneCaps->dwNumGetData = 1;
+
+ InsertVarData(
+ lpPhoneCaps,
+ &lpPhoneCaps->dwGetDataSize,
+ (LPVOID) &dwDummy,
+ sizeof (DWORD)
+ );
+
+ //lpPhoneCaps->dwDevSpecificSize
+ //lpPhoneCaps->dwDevSpecificOffset
+
+ if (gESPGlobals.dwSPIVersion >= 0x00020000)
+ {
+ //lpPhoneCaps->dwDeviceClassesSize
+ //lpPhoneCaps->dwDeviceClassesOffset
+ lpPhoneCaps->dwPhoneFeatures = AllPhoneFeatures;
+ lpPhoneCaps->dwSettableHandsetHookSwitchModes =
+ lpPhoneCaps->dwSettableSpeakerHookSwitchModes =
+ lpPhoneCaps->dwSettableHeadsetHookSwitchModes = AllHookSwitchModes;
+ //lpPhoneCaps->dwMonitoredHandsetHookSwitchModes
+ //lpPhoneCaps->dwMonitoredSpeakerHookSwitchModes
+ //lpPhoneCaps->dwMonitoredHeadsetHookSwitchModes
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDisplay(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDisplay
+ )
+{
+ static char szFuncName[] = "phoneGetDisplay";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpDisplay", lpDisplay }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ static DWORD dwNeededSize = sizeof(VARSTRING) +
+ PHONE_DISPLAY_SIZE_IN_BYTES;
+
+
+ if (lpDisplay->dwTotalSize >= dwNeededSize)
+ {
+ if (pPhone->pDisplay)
+ {
+ CopyMemory(
+ lpDisplay + 1,
+ pPhone->pDisplay,
+ PHONE_DISPLAY_SIZE_IN_BYTES
+ );
+ }
+ else
+ {
+ ZeroMemory (lpDisplay + 1, PHONE_DISPLAY_SIZE_IN_BYTES);
+ }
+
+ lpDisplay->dwUsedSize = dwNeededSize;
+ lpDisplay->dwStringFormat = STRINGFORMAT_ASCII;
+ lpDisplay->dwStringSize = PHONE_DISPLAY_SIZE_IN_BYTES;
+ lpDisplay->dwStringOffset = sizeof (VARSTRING);
+ }
+
+ lpDisplay->dwNeededSize = dwNeededSize;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPPHONEEXTENSIONID lpExtensionID
+ )
+{
+ static char szFuncName[] = "phoneGetExtensionID";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpExtensionID", lpExtensionID }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+
+
+ if (Prolog (&info))
+ {
+ // BUGBUG TSPI_phoneGetExtensionID:
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetGain(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwGain
+ )
+{
+ static char szFuncName[] = "phoneGetGain";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev },
+ { "lpdwGain", lpdwGain }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ switch (dwHookSwitchDev)
+ {
+ case PHONEHOOKSWITCHDEV_HANDSET:
+
+ *lpdwGain = pPhone->dwHandsetGain;
+ break;
+
+ case PHONEHOOKSWITCHDEV_SPEAKER:
+
+ *lpdwGain = pPhone->dwSpeakerGain;
+ break;
+
+ case PHONEHOOKSWITCHDEV_HEADSET:
+
+ *lpdwGain = pPhone->dwHeadsetGain;
+ break;
+
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetHookSwitch(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwHookSwitchDevs
+ )
+{
+ static char szFuncName[] = "phoneGetHookSwitch";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpdwHookSwitchDevs", lpdwHookSwitchDevs }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ *lpdwHookSwitchDevs = 0;
+
+ if (!(pPhone->dwHandsetHookSwitchMode & PHONEHOOKSWITCHMODE_ONHOOK))
+ {
+ *lpdwHookSwitchDevs |= PHONEHOOKSWITCHDEV_HANDSET;
+ }
+
+ if (!(pPhone->dwSpeakerHookSwitchMode & PHONEHOOKSWITCHMODE_ONHOOK))
+ {
+ *lpdwHookSwitchDevs |= PHONEHOOKSWITCHDEV_SPEAKER;
+ }
+
+ if (!(pPhone->dwHeadsetHookSwitchMode & PHONEHOOKSWITCHMODE_ONHOOK))
+ {
+ *lpdwHookSwitchDevs |= PHONEHOOKSWITCHDEV_HEADSET;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetIcon(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ static char szFuncName[] = "phoneGetIcon";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass },
+ { "lphIcon", lphIcon }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+
+
+ if (Prolog (&info))
+ {
+ if (lpszDeviceClass &&
+ lstrcmpiW (lpszDeviceClass, L"tapi/InvalidDeviceClass") == 0)
+ {
+ info.lResult = PHONEERR_INVALDEVICECLASS;
+ }
+ else
+ {
+ *lphIcon = gESPGlobals.hIconPhone;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetID(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+{
+ static char szFuncName[] = "phoneGetID";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpDeviceID", lpDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass }
+ ,{ "hTargetProcess", hTargetProcess }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+ DWORD i, dwDeviceID, dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ for (i = 0; aszDeviceClasses[i]; i++)
+ {
+ if (lstrcmpiW (lpszDeviceClass, aszDeviceClasses[i]) == 0)
+ {
+ break;
+ }
+ }
+
+ if (!aszDeviceClasses[i])
+ {
+ info.lResult = PHONEERR_NODEVICE;
+ return (Epilog (&info));
+ }
+
+ if (lpDeviceID->dwTotalSize < dwNeededSize)
+ {
+ lpDeviceID->dwNeededSize = dwNeededSize;
+ lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
+
+ return (Epilog (&info));
+ }
+
+ if (i == 1)
+ {
+ dwDeviceID = pPhone->dwDeviceID;
+ }
+ else
+ {
+/* BUGBUG TSPI_phoneGetID: if (gbShowLineGetIDDlg)
+ {
+ char szDlgTitle[64];
+ EVENT_PARAM params[] =
+ {
+ { "dwDeviceID", PT_DWORD, gdwDefLineGetIDID, 0 }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, szDlgTitle, 0, params };
+ HWND hwnd;
+
+
+ if (strlen (lpszDeviceClass) > 20)
+ {
+ ((char far *)lpszDeviceClass)[19] = 0;
+ }
+
+ wsprintf(
+ szDlgTitle,
+ "TSPI_phoneGetID: select ID for class '%s'",
+ lpszDeviceClass
+ );
+
+ hwnd = CreateDialogParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) NULL,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ );
+
+ MsgLoopInTAPIClientContext (hwnd);
+
+ dwDeviceID = params[0].dwValue;
+ }
+ else
+ {
+*/
+ dwDeviceID = 0;
+// }
+ }
+
+ lpDeviceID->dwNeededSize =
+ lpDeviceID->dwUsedSize = dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof(DWORD);
+ lpDeviceID->dwStringOffset = sizeof(VARSTRING);
+
+ *((LPDWORD)(lpDeviceID + 1)) = dwDeviceID;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetLamp(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPDWORD lpdwLampMode
+ )
+{
+ static char szFuncName[] = "phoneGetLamp";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "lpdwLampMode", lpdwLampMode }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+
+
+ if (Prolog (&info))
+ {
+ *lpdwLampMode = ((PDRVPHONE) hdPhone)->dwLampMode;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetRing(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwRingMode,
+ LPDWORD lpdwVolume
+ )
+{
+ static char szFuncName[] = "phoneGetRing";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpdwRingMode", lpdwRingMode },
+ { "lpdwVolume", lpdwVolume }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ *lpdwRingMode = pPhone->dwRingMode;
+ *lpdwVolume = pPhone->dwRingVolume;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetStatus(
+ HDRVPHONE hdPhone,
+ LPPHONESTATUS lpPhoneStatus
+ )
+{
+ static char szFuncName[] = "phoneGetStatus";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpPhoneStatus", lpPhoneStatus }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ //lpPhoneStatus->dwStatusFlags;
+ lpPhoneStatus->dwRingMode = pPhone->dwRingMode;
+ lpPhoneStatus->dwRingVolume = pPhone->dwRingVolume;
+ lpPhoneStatus->dwHandsetHookSwitchMode =
+ pPhone->dwHandsetHookSwitchMode;
+ lpPhoneStatus->dwHandsetVolume = pPhone->dwHandsetVolume;
+ lpPhoneStatus->dwHandsetGain = pPhone->dwHandsetGain;
+ lpPhoneStatus->dwSpeakerHookSwitchMode =
+ pPhone->dwSpeakerHookSwitchMode;
+ lpPhoneStatus->dwSpeakerVolume = pPhone->dwSpeakerVolume;
+ lpPhoneStatus->dwSpeakerGain = pPhone->dwSpeakerGain;
+ lpPhoneStatus->dwHeadsetHookSwitchMode =
+ pPhone->dwHeadsetHookSwitchMode;
+ lpPhoneStatus->dwHeadsetVolume = pPhone->dwHeadsetVolume;
+ lpPhoneStatus->dwHeadsetGain = pPhone->dwHeadsetGain;
+
+ // BUGBUG TSPI_phoneGetStatus: copy 0's to display buf if !pDisplay
+
+ InsertVarData(
+ lpPhoneStatus,
+ &lpPhoneStatus->dwDisplaySize,
+ (LPVOID) pPhone->pDisplay,
+ (pPhone->pDisplay ? PHONE_DISPLAY_SIZE_IN_BYTES : 0)
+ );
+
+ InsertVarData(
+ lpPhoneStatus,
+ &lpPhoneStatus->dwLampModesSize,
+ (LPVOID) &pPhone->dwLampMode,
+ sizeof (DWORD)
+ );
+
+ //lpPhoneStatus->dwDevSpecificSize;
+ //lpPhoneStatus->dwDevSpecificOffset;
+
+ if (gESPGlobals.dwSPIVersion >= 0x00020000)
+ {
+ //lpPhoneStatus->
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetVolume(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwVolume
+ )
+{
+ static char szFuncName[] = "phoneGetVolume";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev, aHookSwitchDevs },
+ { "lpdwVolume", lpdwVolume }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (Prolog (&info))
+ {
+ switch (dwHookSwitchDev)
+ {
+ case PHONEHOOKSWITCHDEV_HANDSET:
+
+ *lpdwVolume = pPhone->dwHandsetVolume;
+ break;
+
+ case PHONEHOOKSWITCHDEV_SPEAKER:
+
+ *lpdwVolume = pPhone->dwSpeakerVolume;
+ break;
+
+ case PHONEHOOKSWITCHDEV_HEADSET:
+
+ *lpdwVolume = pPhone->dwHeadsetVolume;
+ break;
+
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ static char szFuncName[] = "phoneNegotiateExtVersion";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwExtVersion", lpdwExtVersion }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 5, params };
+
+
+ if (Prolog (&info))
+ {
+ if (dwLowVersion == 0 ||
+ dwHighVersion == 0xffffffff ||
+ dwLowVersion > dwHighVersion)
+ {
+ info.lResult = PHONEERR_INCOMPATIBLEEXTVERSION;
+ }
+ else
+ {
+ *lpdwExtVersion = dwHighVersion;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ static char szFuncName[] = "phoneNegotiateTSPIVersion";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwTSPIVersion", lpdwTSPIVersion }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+
+
+ if (Prolog (&info))
+ {
+ *lpdwTSPIVersion = gESPGlobals.dwSPIVersion;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneOpen(
+ DWORD dwDeviceID,
+ HTAPIPHONE htPhone,
+ LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion,
+ PHONEEVENT lpfnEventProc
+ )
+{
+ static char szFuncName[] = "phoneOpen";
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "htPhone", htPhone },
+ { "lphdPhone", lphdPhone },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpfnEventProc", lpfnEventProc }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 5, params };
+
+
+ if (Prolog (&info))
+ {
+ PDRVPHONE pPhone;
+
+
+ if (!(pPhone = GetPhoneFromID (dwDeviceID)))
+ {
+ // BUGBUG
+ }
+
+ pPhone->htPhone = htPhone;
+
+ *lphdPhone = (HDRVPHONE) pPhone;
+
+ WriteEventBuffer(
+ pPhone->dwDeviceID,
+ WIDGETTYPE_PHONE,
+ (DWORD) pPhone,
+ (DWORD) htPhone,
+ 0,
+ 0
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSelectExtVersion(
+ HDRVPHONE hdPhone,
+ DWORD dwExtVersion
+ )
+{
+ static char szFuncName[] = "phoneSelectExtVersion";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwExtVersion", dwExtVersion }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetButtonInfo_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+ LPPHONEBUTTONINFO pButtonInfo = (LPPHONEBUTTONINFO)
+ pAsyncReqInfo->dwParam2, pToFree;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.PhoneCritSec);
+
+ pToFree = pPhone->pButtonInfo;
+ pPhone->pButtonInfo = pButtonInfo;
+
+ LeaveCriticalSection (&gESPGlobals.PhoneCritSec);
+
+ DrvFree (pToFree);
+
+ // no msg to send for this one?
+ }
+ else
+ {
+ DrvFree (pButtonInfo);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetButtonInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO const lpButtonInfo
+ )
+{
+ static char szFuncName[] = "phoneSetButtonInfo";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "lpButtonInfo", lpButtonInfo }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_phoneSetButtonInfo_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (dwButtonLampID == 0)
+ {
+ DWORD dwNeededSize;
+ LPPHONEBUTTONINFO pMyButtonInfo;
+
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+
+ dwNeededSize = sizeof (PHONEBUTTONINFO) +
+ lpButtonInfo->dwButtonTextSize +
+ lpButtonInfo->dwDevSpecificSize +
+ 16; // 64-bit align var fields
+
+ if ((pMyButtonInfo = (LPPHONEBUTTONINFO) DrvAlloc (dwNeededSize)))
+ {
+ info.pAsyncReqInfo->dwParam2 = (DWORD) pMyButtonInfo;
+
+ CopyMemory(
+ pMyButtonInfo,
+ lpButtonInfo,
+ (gESPGlobals.dwSPIVersion > 0x00010003 ?
+ sizeof (PHONEBUTTONINFO) : 9 * sizeof (DWORD))
+ );
+
+ pMyButtonInfo->dwTotalSize = dwNeededSize;
+ pMyButtonInfo->dwNeededSize =
+ pMyButtonInfo->dwUsedSize = sizeof (PHONEBUTTONINFO);
+
+ InsertVarData(
+ pMyButtonInfo,
+ &pMyButtonInfo->dwButtonTextSize,
+ ((LPBYTE) lpButtonInfo) +
+ lpButtonInfo->dwButtonTextOffset,
+ lpButtonInfo->dwButtonTextSize
+ );
+
+ InsertVarData(
+ pMyButtonInfo,
+ &pMyButtonInfo->dwDevSpecificSize,
+ ((LPBYTE) lpButtonInfo) +
+ lpButtonInfo->dwDevSpecificOffset,
+ lpButtonInfo->dwDevSpecificSize
+ );
+ }
+ else
+ {
+ info.lResult = PHONEERR_NOMEM;
+ }
+ }
+ else
+ {
+ info.lResult = PHONEERR_INVALBUTTONLAMPID;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetData_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwNewDataSize = pAsyncReqInfo->dwParam3;
+ LPVOID pNewData = (LPVOID) pAsyncReqInfo->dwParam2, pToFree;
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.PhoneCritSec);
+
+ pToFree = pPhone->pData;
+ pPhone->pData = pNewData;
+ pPhone->dwDataSize = dwNewDataSize;
+
+ LeaveCriticalSection (&gESPGlobals.PhoneCritSec);
+
+ DrvFree (pToFree);
+
+ // no msg to send for this one?
+ }
+ else
+ {
+ DrvFree (pNewData);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetData(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID const lpData,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "phoneSetData";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwDataID", dwDataID },
+ { "lpData", lpData },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 5,
+ params,
+ TSPI_phoneSetData_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (dwDataID != 0)
+ {
+ info.lResult = PHONEERR_INVALDATAID;
+ }
+ else
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+
+ if (dwSize)
+ {
+ info.pAsyncReqInfo->dwParam2 = (DWORD) DrvAlloc (dwSize);
+
+ if (info.pAsyncReqInfo->dwParam2 == 0)
+ {
+ info.lResult = PHONEERR_NOMEM;
+ return (Epilog (&info));
+ }
+
+ CopyMemory(
+ (LPVOID) info.pAsyncReqInfo->dwParam2,
+ lpData,
+ dwSize
+ );
+ }
+ else
+ {
+ info.pAsyncReqInfo->dwParam2 = 0;
+ }
+
+ info.pAsyncReqInfo->dwParam3 = (DWORD) dwSize;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetDisplay_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwColumn = pAsyncReqInfo->dwParam2,
+ dwSize = pAsyncReqInfo->dwParam4;
+ WCHAR *pDisplay = (LPVOID) pAsyncReqInfo->dwParam3;
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ EnterCriticalSection (&gESPGlobals.PhoneCritSec);
+
+ if (pPhone->pDisplay ||
+ (pPhone->pDisplay = DrvAlloc (PHONE_DISPLAY_SIZE_IN_BYTES)))
+ {
+ CopyMemory(
+ pPhone->pDisplay + dwColumn,
+ pDisplay,
+ dwSize
+ );
+
+ SendPhoneEvent (pPhone, PHONE_STATE, PHONESTATE_DISPLAY, 0, 0);
+ }
+ else
+ {
+ pAsyncReqInfo->lResult = PHONEERR_NOMEM;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.PhoneCritSec);
+ }
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ DrvFree (pDisplay);
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetDisplay(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRow,
+ DWORD dwColumn,
+ LPCWSTR lpsDisplay,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "phoneSetDisplay";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwRow", dwRow },
+ { "dwColumn", dwColumn },
+ { "lpsDisplay", lpsDisplay },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 6,
+ params,
+ TSPI_phoneSetDisplay_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (dwRow == 0 &&
+ dwColumn < PHONE_DISPLAY_SIZE_IN_CHARS &&
+ dwSize <= PHONE_DISPLAY_SIZE_IN_BYTES &&
+ (dwColumn * sizeof (WCHAR) + dwSize - sizeof (WCHAR)) <
+ PHONE_DISPLAY_SIZE_IN_BYTES)
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) dwColumn;
+
+ if (dwSize)
+ {
+ info.pAsyncReqInfo->dwParam3 = (DWORD) DrvAlloc (dwSize);
+
+ if (info.pAsyncReqInfo->dwParam3 == 0)
+ {
+ info.lResult = PHONEERR_NOMEM;
+ return (Epilog (&info));
+ }
+
+ CopyMemory(
+ (LPVOID) info.pAsyncReqInfo->dwParam3,
+ lpsDisplay,
+ dwSize
+ );
+ }
+ else
+ {
+ info.pAsyncReqInfo->dwParam3 = 0;
+ }
+
+ info.pAsyncReqInfo->dwParam4 = (DWORD) dwSize;
+
+ }
+ else
+ {
+ info.lResult = PHONEERR_INVALPARAM;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetGain_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwHookSwitchDev = pAsyncReqInfo->dwParam2,
+ dwGain = pAsyncReqInfo->dwParam3,
+ *pdwXxxGain, dwPhoneState;
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+
+
+ switch (dwHookSwitchDev)
+ {
+ case PHONEHOOKSWITCHDEV_HANDSET:
+
+ pdwXxxGain = &pPhone->dwHandsetGain;
+ dwPhoneState = PHONESTATE_HANDSETGAIN;
+ break;
+
+ case PHONEHOOKSWITCHDEV_SPEAKER:
+
+ pdwXxxGain = &pPhone->dwSpeakerGain;
+ dwPhoneState = PHONESTATE_SPEAKERGAIN;
+ break;
+
+ default: // case PHONEHOOKSWITCHDEV_HEADSET:
+
+ pdwXxxGain = &pPhone->dwHeadsetGain;
+ dwPhoneState = PHONESTATE_HEADSETGAIN;
+ break;
+ }
+
+ if (*pdwXxxGain != dwGain)
+ {
+ *pdwXxxGain = dwGain;
+ SendPhoneEvent (pPhone, PHONE_STATE, dwPhoneState, 0, 0);
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetGain(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwGain
+ )
+{
+ static char szFuncName[] = "phoneSetGain";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev, aHookSwitchDevs },
+ { "dwGain", dwGain }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_phoneSetGain_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) dwHookSwitchDev;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) dwGain;
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetHookSwitch_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwHookSwitchDevs = pAsyncReqInfo->dwParam2,
+ dwHookSwitchMode = pAsyncReqInfo->dwParam3,
+ dwPhoneStates = 0;
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+
+
+ if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HANDSET &&
+ pPhone->dwHandsetHookSwitchMode != dwHookSwitchMode)
+ {
+ pPhone->dwHandsetHookSwitchMode = dwHookSwitchMode;
+ dwPhoneStates |= PHONESTATE_HANDSETHOOKSWITCH;
+ }
+
+ if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_SPEAKER &&
+ pPhone->dwSpeakerHookSwitchMode != dwHookSwitchMode)
+ {
+ pPhone->dwSpeakerHookSwitchMode = dwHookSwitchMode;
+ dwPhoneStates |= PHONESTATE_SPEAKERHOOKSWITCH;
+ }
+
+ if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HEADSET &&
+ pPhone->dwHeadsetHookSwitchMode != dwHookSwitchMode)
+ {
+ pPhone->dwHeadsetHookSwitchMode = dwHookSwitchMode;
+ dwPhoneStates |= PHONESTATE_HEADSETHOOKSWITCH;
+ }
+
+ if (dwPhoneStates)
+ {
+ SendPhoneEvent(
+ pPhone,
+ PHONE_STATE,
+ dwPhoneStates,
+ dwHookSwitchMode,
+ 0
+ );
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetHookSwitch(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDevs,
+ DWORD dwHookSwitchMode
+ )
+{
+ static char szFuncName[] = "phoneSetHookSwitch";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDevs", dwHookSwitchDevs, aHookSwitchDevs },
+ { "dwHookSwitchMode", dwHookSwitchMode, aHookSwitchModes }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_phoneSetHookSwitch_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) dwHookSwitchDevs;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) dwHookSwitchMode;
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetLamp_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwLampMode = pAsyncReqInfo->dwParam2;
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+
+
+ if (pPhone->dwLampMode != dwLampMode)
+ {
+ pPhone->dwLampMode = dwLampMode;
+ SendPhoneEvent (pPhone, PHONE_STATE, PHONESTATE_LAMP, 0, 0);
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetLamp(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ DWORD dwLampMode
+ )
+{
+ static char szFuncName[] = "phoneSetLamp";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "dwLampMode", dwLampMode, aLampModes }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_phoneSetLamp_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ if (dwButtonLampID == 0)
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) dwLampMode;
+ }
+ else
+ {
+ info.lResult = PHONEERR_INVALBUTTONLAMPID;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetRing_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwRingMode = pAsyncReqInfo->dwParam2,
+ dwRingVolume = pAsyncReqInfo->dwParam3,
+ dwPhoneStates = 0;
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+
+
+ if (pPhone->dwRingMode != dwRingMode)
+ {
+ pPhone->dwRingMode = dwRingMode;
+ dwPhoneStates |= PHONESTATE_RINGMODE;
+ }
+
+ if (pPhone->dwRingVolume != dwRingVolume)
+ {
+ pPhone->dwRingVolume = dwRingVolume;
+ dwPhoneStates |= PHONESTATE_RINGVOLUME;
+ }
+
+ if (dwPhoneStates)
+ {
+ SendPhoneEvent(
+ pPhone,
+ PHONE_STATE,
+ dwPhoneStates,
+ 0,
+ 0
+ );
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetRing(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRingMode,
+ DWORD dwVolume
+ )
+{
+ static char szFuncName[] = "phoneSetRing";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwRingMode", dwRingMode },
+ { "dwVolume", dwVolume }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_phoneSetRing_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) dwRingMode;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) dwVolume;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetStatusMessages(
+ HDRVPHONE hdPhone,
+ DWORD dwPhoneStates,
+ DWORD dwButtonModes,
+ DWORD dwButtonStates
+ )
+{
+ static char szFuncName[] = "phoneSetStatusMessages";
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwPhoneStates", dwPhoneStates, aPhoneStates },
+ { "dwButtonModes", dwButtonModes, aButtonModes },
+ { "dwButtonStates", dwButtonStates, aButtonStates }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+
+
+ if (Prolog (&info))
+ {
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_phoneSetVolume_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ DWORD dwHookSwitchDev = pAsyncReqInfo->dwParam2,
+ dwVolume = pAsyncReqInfo->dwParam3,
+ *pdwXxxVolume, dwPhoneState;
+ PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
+
+
+ switch (dwHookSwitchDev)
+ {
+ case PHONEHOOKSWITCHDEV_HANDSET:
+
+ pdwXxxVolume = &pPhone->dwHandsetVolume;
+ dwPhoneState = PHONESTATE_HANDSETVOLUME;
+ break;
+
+ case PHONEHOOKSWITCHDEV_SPEAKER:
+
+ pdwXxxVolume = &pPhone->dwSpeakerVolume;
+ dwPhoneState = PHONESTATE_SPEAKERVOLUME;
+ break;
+
+ default: // case PHONEHOOKSWITCHDEV_HEADSET:
+
+ pdwXxxVolume = &pPhone->dwHeadsetVolume;
+ dwPhoneState = PHONESTATE_HEADSETVOLUME;
+ break;
+ }
+
+ if (*pdwXxxVolume != dwVolume)
+ {
+ *pdwXxxVolume = dwVolume;
+ SendPhoneEvent (pPhone, PHONE_STATE, dwPhoneState, 0, 0);
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetVolume(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwVolume
+ )
+{
+ static char szFuncName[] = "phoneSetVolume";
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev }, // BUGBUG lookup
+ { "dwVolume", dwVolume }
+ };
+ FUNC_INFO info =
+ {
+ szFuncName,
+ ASYNC,
+ 4,
+ params,
+ TSPI_phoneSetVolume_postProcess
+ };
+
+
+ if (Prolog (&info))
+ {
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdPhone;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) dwHookSwitchDev;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) dwVolume;
+ }
+
+ return (Epilog (&info));
+}
+
+
+
+//
+// ------------------------- TSPI_providerXxx funcs ---------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // 32-bit TAPI never actually calls this function (the corresponding
+ // TUISPI_ func has taken it's place), but the Telephony control
+ // panel applet does look to see if this function is exported to
+ // determine whether or not the provider is configurable
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreateLineDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ static char szFuncName[] = "providerCreateLineDevice";
+ FUNC_PARAM params[] =
+ {
+ { "dwTempID", dwTempID },
+ { szdwDeviceID, dwDeviceID }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (Prolog (&info))
+ {
+ // BUGBUG TSPI_providerCreateLineDevice: alloc new line
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreatePhoneDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ static char szFuncName[] = "providerCreatePhoneDevice";
+ FUNC_PARAM params[] =
+ {
+ { "dwTempID", dwTempID },
+ { szdwDeviceID, dwDeviceID }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+
+
+ if (Prolog (&info))
+ {
+ // BUGBUG TSPI_providerCreatePhoneDevice: alloc new phone
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+{
+ static char szFuncName[] = "providerEnumDevices";
+ FUNC_PARAM params[] =
+ {
+ { szdwPermanentProviderID, dwPermanentProviderID },
+ { "lpdwNumLines", lpdwNumLines },
+ { "lpdwNumPhones", lpdwNumPhones },
+ { "hProvider", hProvider },
+ { "lpfnLineCreateProc", lpfnLineCreateProc },
+ { "lpfnPhoneCreateProc", lpfnPhoneCreateProc }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 6, params };
+
+
+ if (Prolog (&info))
+ {
+ *lpdwNumLines = gESPGlobals.dwNumLines;
+ *lpdwNumPhones = gESPGlobals.dwNumPhones;
+
+ gESPGlobals.pfnLineEvent = lpfnLineCreateProc;
+ gESPGlobals.pfnPhoneEvent = lpfnPhoneCreateProc;
+
+ gESPGlobals.hProvider = hProvider;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerFreeDialogInstance(
+ HDRVDIALOGINSTANCE hdDlgInst
+ )
+{
+ static char szFuncName[] = "providerFreeDialogInstance";
+ FUNC_PARAM params[] =
+ {
+ { "hdDlgInst", hdDlgInst }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 1, params };
+
+
+ Prolog (&info);
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerGenericDialogData(
+ DWORD dwObjectID,
+ DWORD dwObjectType,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ static char szFuncName[] = "providerGenericDialogData";
+ FUNC_PARAM params[] =
+ {
+ { "dwObjectID", dwObjectID },
+ { "dwObjectType", dwObjectType },
+ { "lpszParams", lpParams },
+ { "dwSize", dwSize }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 4, params };
+
+
+ Prolog (&info);
+
+ lstrcpyA (lpParams, "espDlgData");
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc,
+ LPDWORD lpdwTSPIOptions
+ )
+{
+ static char szFuncName[] = "providerInit";
+ FUNC_PARAM params[] =
+ {
+ { "dwTSPIVersion", dwTSPIVersion },
+ { szdwPermanentProviderID, dwPermanentProviderID },
+ { "dwLineDeviceIDBase", dwLineDeviceIDBase },
+ { "dwPhoneDeviceIDBase", dwPhoneDeviceIDBase },
+ { "dwNumLines", dwNumLines },
+ { "dwNumPhones", dwNumPhones },
+ { "lpfnCompletionProc", lpfnCompletionProc }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 7, params };
+ DWORD i, dwNumTotalEntries;
+ PDRVLINE pLine;
+ PDRVPHONE pPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+ //
+ //
+ //
+
+ // BUGBUG zero out he approp gESPGlobals stuff
+
+ gESPGlobals.bProviderShutdown = FALSE;
+
+ ZeroMemory (gaParkedCalls, MAX_NUM_PARKED_CALLS * sizeof (PDRVCALL));
+
+
+ //
+ // Alloc a queue for storing async requests for async completion,
+ // and start a thread to service that queue
+ //
+
+// if (gbDisableUI == FALSE) IF THIS IS UNCOMMENTED MUST MUNGE ERROR CLEANUP
+ {
+ gESPGlobals.dwNumTotalQueueEntries = DEF_NUM_ASYNC_REQUESTS_IN_QUEUE;
+
+ if (!(gESPGlobals.pAsyncRequestQueue = DrvAlloc(
+ gESPGlobals.dwNumTotalQueueEntries * sizeof (DWORD)
+
+ )))
+ {
+ goto TSPI_providerInit_error0;
+ }
+
+ gESPGlobals.pAsyncRequestQueueIn =
+ gESPGlobals.pAsyncRequestQueueOut = gESPGlobals.pAsyncRequestQueue;
+
+ if (!(gESPGlobals.hAsyncEventsPendingEvent = CreateEvent(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ TRUE, // manual reset
+ FALSE, // non-signaled
+ NULL // unnamed
+ )))
+ {
+ goto TSPI_providerInit_error1;
+ }
+
+ if (!(gESPGlobals.hAsyncEventQueueServiceThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ 0, // def stack size
+ (LPTHREAD_START_ROUTINE) AsyncEventQueueServiceThread,
+ NULL, // thread param
+ 0, // creation flags
+ &i // &dwThreadID
+ )))
+ {
+ goto TSPI_providerInit_error2;
+ }
+ }
+
+
+ //
+ // Init sundry globals
+ //
+
+ gESPGlobals.dwPermanentProviderID = dwPermanentProviderID;
+ gESPGlobals.dwLineDeviceIDBase = dwLineDeviceIDBase;
+ gESPGlobals.dwPhoneDeviceIDBase = dwPhoneDeviceIDBase;
+ gESPGlobals.dwInitialNumLines = dwNumLines;
+ gESPGlobals.dwInitialNumPhones = dwNumPhones;
+ gESPGlobals.pfnCompletion = lpfnCompletionProc;
+
+ gESPGlobals.hIconLine = LoadIcon(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(PHONE_ICON) // the id's are reversed
+ );
+
+ gESPGlobals.hIconPhone = LoadIcon(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(LINE_ICON)
+ );
+
+
+ //
+ // Init the line lookup table & crit sec for accessing call lists
+ //
+
+ dwNumTotalEntries = dwNumLines + DEF_NUM_EXTRA_LOOKUP_ENTRIES - 1;
+
+ if (!(gESPGlobals.pLines = DrvAlloc(
+ sizeof (DRVLINETABLE) + sizeof (DRVLINE) * dwNumTotalEntries
+ )))
+ {
+ goto TSPI_providerInit_error3;
+ }
+
+ gESPGlobals.pLines->dwNumTotalEntries = dwNumTotalEntries;
+ gESPGlobals.pLines->dwNumUsedEntries = dwNumLines;
+
+ for (
+ i = dwLineDeviceIDBase, pLine = gESPGlobals.pLines->aLines;
+ i < (dwLineDeviceIDBase + dwNumLines);
+ i++, pLine++
+ )
+ {
+ pLine->dwDeviceID = i;
+
+ if (!(pLine->aAddrs = DrvAlloc(
+ sizeof (DRVADDRESS) * gESPGlobals.dwNumAddressesPerLine
+ )))
+ {
+ goto TSPI_providerInit_error4;
+ }
+ }
+
+
+ //
+ // Init the phone lookup table
+ //
+
+ dwNumTotalEntries = dwNumPhones + DEF_NUM_EXTRA_LOOKUP_ENTRIES - 1;
+
+ if (!(gESPGlobals.pPhones = DrvAlloc(
+ sizeof (DRVPHONETABLE) + dwNumTotalEntries * sizeof(DRVPHONE)
+ )))
+ {
+ goto TSPI_providerInit_error4;
+ }
+
+ gESPGlobals.pPhones->dwNumTotalEntries = dwNumTotalEntries;
+ gESPGlobals.pPhones->dwNumUsedEntries = dwNumPhones;
+
+ for (
+ i = dwPhoneDeviceIDBase, pPhone = gESPGlobals.pPhones->aPhones;
+ i < (dwPhoneDeviceIDBase + dwNumPhones);
+ i++, pPhone++
+ )
+ {
+ pPhone->dwDeviceID = i;
+ }
+
+ if (gbDisableUI == FALSE)
+ {
+ WriteEventBuffer(
+ 0,
+ WIDGETTYPE_STARTUP,
+ dwNumLines,
+ dwNumPhones,
+ dwLineDeviceIDBase,
+ dwPhoneDeviceIDBase
+ );
+ }
+
+ goto TSPI_providerInit_return;
+
+
+TSPI_providerInit_error4:
+
+ for (
+ i = dwLineDeviceIDBase, pLine = gESPGlobals.pLines->aLines;
+ i < (dwLineDeviceIDBase + dwNumLines);
+ i++, pLine++
+ )
+ {
+ if (pLine->aAddrs)
+ {
+ DrvFree (pLine->aAddrs);
+ }
+ }
+
+ DrvFree (gESPGlobals.pLines);
+
+TSPI_providerInit_error3:
+
+ gESPGlobals.bProviderShutdown = TRUE;
+
+ while (WaitForSingleObject(
+ gESPGlobals.hAsyncEventQueueServiceThread,
+ 0
+ ) != WAIT_OBJECT_0)
+ {
+ SetEvent (gESPGlobals.hAsyncEventsPendingEvent);
+ Sleep (0);
+ }
+
+ CloseHandle (gESPGlobals.hAsyncEventQueueServiceThread);
+
+TSPI_providerInit_error2:
+
+ CloseHandle (gESPGlobals.hAsyncEventsPendingEvent);
+
+TSPI_providerInit_error1:
+
+ DrvFree (gESPGlobals.pAsyncRequestQueue);
+
+TSPI_providerInit_error0:
+
+ info.lResult = LINEERR_NOMEM;
+
+TSPI_providerInit_return:
+
+ return (Epilog (&info)); // BUGBUG TSPI_providerInit: return 0 by default
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // 32-bit TAPI never actually calls this function (the corresponding
+ // TUISPI_ func has taken it's place), but the Telephony control
+ // panel applet does look to see if this function is exported to
+ // determine whether or not the provider is installable
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // 32-bit TAPI never actually calls this function (the corresponding
+ // TUISPI_ func has taken it's place), but the Telephony control
+ // panel applet does look to see if this function is exported to
+ // determine whether or not the provider is removeable
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID
+ )
+{
+ static char szFuncName[] = "providerShutdown";
+ FUNC_PARAM params[] =
+ {
+ { "dwTSPIVersion", dwTSPIVersion },
+ { szdwPermanentProviderID, dwPermanentProviderID }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 2, params };
+ LONG lResult;
+ DWORD i;
+
+
+ Prolog (&info);
+
+ DestroyIcon (gESPGlobals.hIconLine);
+ DestroyIcon (gESPGlobals.hIconPhone);
+
+
+ //
+ //
+ //
+
+// if (gbDisableUI == FALSE)
+// {
+ gESPGlobals.bProviderShutdown = TRUE;
+
+ while (WaitForSingleObject(
+ gESPGlobals.hAsyncEventQueueServiceThread,
+ 0
+ ) != WAIT_OBJECT_0)
+ {
+ SetEvent (gESPGlobals.hAsyncEventsPendingEvent);
+ Sleep (0);
+ }
+
+ CloseHandle (gESPGlobals.hAsyncEventQueueServiceThread);
+ CloseHandle (gESPGlobals.hAsyncEventsPendingEvent);
+
+ DrvFree (gESPGlobals.pAsyncRequestQueue);
+// }
+
+
+ //
+ // Free the device tables & call list crit sec
+ //
+
+ {
+ PDRVLINETABLE pTable = gESPGlobals.pLines;
+
+
+ while (pTable)
+ {
+ PDRVLINETABLE pNextTable = pTable->pNext;
+
+
+ for (i = 0; i < pTable->dwNumUsedEntries; i++)
+ {
+ DrvFree (pTable->aLines[i].aAddrs);
+ }
+
+ DrvFree (pTable);
+ pTable = pNextTable;
+ }
+ }
+
+ {
+ PDRVPHONETABLE pTable = gESPGlobals.pPhones;
+
+
+ while (pTable)
+ {
+ PDRVPHONE pPhone = pTable->aPhones;
+ PDRVPHONETABLE pNextTable = pTable->pNext;
+
+
+ for (i = 0; i < pTable->dwNumUsedEntries; i++, pPhone++)
+ {
+ if (pPhone->pData)
+ {
+ DrvFree (pPhone->pData);
+ }
+
+ if (pPhone->pButtonInfo)
+ {
+ DrvFree (pPhone->pButtonInfo);
+ }
+
+ if (pPhone->pDisplay)
+ {
+ DrvFree (pPhone->pDisplay);
+ }
+ }
+
+ DrvFree (pTable);
+ pTable = pNextTable;
+ }
+ }
+
+
+ //
+ //
+ //
+
+ if (ghPBXThread)
+ {
+ ESPStopPBXThread (0);
+ }
+
+
+ //
+ // Clean up any parked calls
+ //
+
+ for (i = 0; i < MAX_NUM_PARKED_CALLS; i++)
+ {
+ if (gaParkedCalls[i])
+ {
+ if (gaParkedCalls[i]->pSendingFlowspec)
+ {
+ DrvFree (gaParkedCalls[i]->pSendingFlowspec);
+ }
+
+ if (gaParkedCalls[i]->pReceivingFlowspec)
+ {
+ DrvFree (gaParkedCalls[i]->pReceivingFlowspec);
+ }
+
+ if (gaParkedCalls[i]->pCallData)
+ {
+ DrvFree (gaParkedCalls[i]->pCallData);
+ }
+
+ DrvFree (gaParkedCalls[i]);
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerUIIdentify(
+ LPWSTR lpszUIDLLName
+ )
+{
+ static char szFuncName[] = "providerUIIdentify";
+ FUNC_PARAM params[] =
+ {
+ { "pszUIDLLName", lpszUIDLLName }
+ };
+ FUNC_INFO info = { szFuncName, SYNC, 1, params };
+
+
+ Prolog (&info);
+
+ wcscpy (lpszUIDLLName, szESPUIDLL);
+
+ return (Epilog (&info));
+}
+
+#pragma warning (default:4047)
+
+//
+// ------------------------ Private support routines --------------------------
+//
+
+
+BOOL
+PASCAL
+IsValidDrvCall(
+ PDRVCALL pCall,
+ LPDWORD pdwCallInstance
+ )
+{
+ try
+ {
+ if (pdwCallInstance)
+ {
+ *pdwCallInstance = pCall->dwCallInstance;
+ }
+
+ if (pCall->dwKey != DRVCALL_KEY)
+ {
+ return FALSE;
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+ShowStr(
+ BOOL bAlertApp,
+ char *format,
+ ...
+ )
+{
+ char buf[256];
+ DWORD dwTotalSize, dwMoveSize, dwMoveSizeWrapped = 0;
+ va_list ap;
+
+
+ if (gbDisableUI == TRUE)
+ {
+ return;
+ }
+
+ va_start(ap, format);
+
+ dwTotalSize = wvsprintf (buf, format, ap);
+ buf[dwTotalSize++] = '\r';
+ buf[dwTotalSize++] = '\n';
+
+ dwMoveSize = dwTotalSize;
+
+ EnterCriticalSection (&gESPGlobals.DebugBufferCritSec);
+
+
+ //
+ // Check to see if there's enough room in the the buffer for the new
+ // data, alloc more if not
+ //
+
+ if (dwMoveSize > (gESPGlobals.dwDebugBufferTotalSize -
+ gESPGlobals.dwDebugBufferUsedSize))
+ {
+ char *pNewDebugBuffer;
+ DWORD dwMoveSize2, dwMoveSizeWrapped2;
+
+
+ if (!(pNewDebugBuffer = DrvAlloc(
+ 2 * gESPGlobals.dwDebugBufferTotalSize
+ )))
+ {
+ LeaveCriticalSection (&gESPGlobals.DebugBufferCritSec);
+ return;
+ }
+
+ if (gESPGlobals.pDebugBufferIn > gESPGlobals.pDebugBufferOut)
+ {
+ dwMoveSize2 = (DWORD) (gESPGlobals.pDebugBufferIn -
+ gESPGlobals.pDebugBufferOut);
+
+ dwMoveSizeWrapped2 = 0;
+ }
+ else
+ {
+ dwMoveSize2 = (DWORD) ((gESPGlobals.pDebugBuffer +
+ gESPGlobals.dwDebugBufferTotalSize) -
+ gESPGlobals.pDebugBufferOut);
+
+ dwMoveSizeWrapped2 = (DWORD) (gESPGlobals.pDebugBufferIn -
+ gESPGlobals.pDebugBuffer);
+ }
+
+ CopyMemory(
+ pNewDebugBuffer,
+ gESPGlobals.pDebugBufferOut,
+ dwMoveSize2
+ );
+
+ if (dwMoveSizeWrapped2)
+ {
+ CopyMemory(
+ pNewDebugBuffer + dwMoveSize2,
+ gESPGlobals.pDebugBuffer,
+ dwMoveSizeWrapped2
+ );
+ }
+
+ DrvFree (gESPGlobals.pDebugBuffer);
+
+ gESPGlobals.pDebugBufferIn = pNewDebugBuffer + dwMoveSize2 +
+ dwMoveSizeWrapped2;
+
+ gESPGlobals.pDebugBuffer =
+ gESPGlobals.pDebugBufferOut = pNewDebugBuffer;
+
+ gESPGlobals.dwDebugBufferTotalSize *= 2;
+ }
+
+ if (gESPGlobals.pDebugBufferIn >= gESPGlobals.pDebugBufferOut)
+ {
+ DWORD dwFreeSize = gESPGlobals.dwDebugBufferTotalSize -
+ (gESPGlobals.pDebugBufferIn - gESPGlobals.pDebugBuffer);
+
+
+ if (dwMoveSize > dwFreeSize)
+ {
+ dwMoveSizeWrapped = dwMoveSize - dwFreeSize;
+
+ dwMoveSize = dwFreeSize;
+ }
+ }
+
+ CopyMemory (gESPGlobals.pDebugBufferIn, buf, dwMoveSize);
+
+ if (dwMoveSizeWrapped != 0)
+ {
+ CopyMemory(
+ gESPGlobals.pDebugBuffer,
+ buf + dwMoveSize,
+ dwMoveSizeWrapped
+ );
+
+ gESPGlobals.pDebugBufferIn = gESPGlobals.pDebugBuffer +
+ dwMoveSizeWrapped;
+ }
+ else
+ {
+ gESPGlobals.pDebugBufferIn += dwMoveSize;
+ }
+
+ gESPGlobals.dwDebugBufferUsedSize += dwTotalSize;
+
+ LeaveCriticalSection (&gESPGlobals.DebugBufferCritSec);
+
+ if (bAlertApp)
+ {
+ SetEvent (ghDebugOutputEvent);
+ }
+
+ va_end(ap);
+}
+
+
+char far *
+GetFlags(
+ DWORD dwFlags,
+ PLOOKUP pLookup
+ )
+{
+ int i;
+ static char buf[256];
+ char far *p = (char far *) NULL;
+
+
+ if (gbDisableUI == TRUE)
+ {
+ return NULL;
+ }
+
+ buf[0] = 0;
+
+ for (i = 0; (dwFlags && (pLookup[i].dwVal != 0xffffffff)); i++)
+ {
+ if (dwFlags & pLookup[i].dwVal)
+ {
+ lstrcatA (buf, pLookup[i].lpszVal);
+ lstrcatA (buf, " ");
+
+ dwFlags = dwFlags & (~pLookup[i].dwVal);
+ }
+ }
+
+ if (buf[0])
+ {
+ if ((p = (char far *) DrvAlloc (lstrlenA (buf) + 1)))
+ {
+ lstrcpyA (p, buf);
+ }
+ }
+
+ return p;
+}
+
+
+void
+ShowLineEvent(
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ if (gESPGlobals.dwDebugOptions & SHOW_EVENT_NOTIFICATIONS)
+ {
+ static DWORD adwLineMsgs[] =
+ {
+ LINE_ADDRESSSTATE,
+ LINE_CALLINFO,
+ LINE_CALLSTATE,
+ LINE_CLOSE,
+ LINE_DEVSPECIFIC,
+ LINE_DEVSPECIFICFEATURE,
+ LINE_GATHERDIGITS,
+ LINE_GENERATE,
+ LINE_LINEDEVSTATE,
+ LINE_MONITORDIGITS,
+ LINE_MONITORMEDIA,
+ LINE_MONITORTONE,
+
+ LINE_CREATE,
+
+ LINE_NEWCALL,
+ LINE_CALLDEVSPECIFIC,
+ LINE_CALLDEVSPECIFICFEATURE,
+
+ LINE_REMOVE,
+
+ 0xffffffff
+ };
+
+ static char *aszLineMsgs[] =
+ {
+ "LINE_ADDRESSSTATE",
+ "LINE_CALLINFO",
+ "LINE_CALLSTATE",
+ "LINE_CLOSE",
+ "LINE_DEVSPECIFIC",
+ "LINE_DEVSPECIFICFEATURE",
+ "LINE_GATHERDIGITS",
+ "LINE_GENERATE",
+ "LINE_LINEDEVSTATE",
+ "LINE_MONITORDIGITS",
+ "LINE_MONITORMEDIA",
+ "LINE_MONITORTONE",
+
+ "LINE_CREATE",
+
+ "LINE_NEWCALL",
+ "LINE_CALLDEVSPECIFIC",
+ "LINE_CALLDEVSPECIFICFEATURE",
+
+ "LINE_REMOVE"
+ };
+
+ int i;
+ char far *lpszParam1 = (char far *) NULL;
+ char far *lpszParam2 = (char far *) NULL;
+ char far *lpszParam3 = (char far *) NULL;
+
+
+ for (i = 0; adwLineMsgs[i] != 0xffffffff; i++)
+ {
+ if (dwMsg == adwLineMsgs[i])
+ {
+ ShowStr(
+ FALSE,
+ "%ssent %s : htLine=x%x, htCall=x%x",
+ szCallUp,
+ aszLineMsgs[i],
+ htLine,
+ htCall
+ );
+
+ break;
+ }
+ }
+
+ if (adwLineMsgs[i] == 0xffffffff)
+ {
+ ShowStr(
+ FALSE,
+ "%ssent <unknown msg id, x%x> : htLine=x%x, htCall=x%x",
+ szCallUp,
+ dwMsg,
+ htLine,
+ htCall
+ );
+ }
+
+ switch (dwMsg)
+ {
+ case LINE_ADDRESSSTATE:
+
+ lpszParam2 = GetFlags (dwParam2, aAddressStates);
+ break;
+
+ case LINE_CALLINFO:
+
+ lpszParam1 = GetFlags (dwParam1, aCallInfoStates);
+ break;
+
+ case LINE_CALLSTATE:
+
+ lpszParam1 = GetFlags (dwParam1, aCallStates);
+ break;
+
+ case LINE_LINEDEVSTATE:
+
+ lpszParam1 = GetFlags (dwParam1, aLineStates);
+ break;
+
+ } // switch
+
+ ShowStr(
+ FALSE,
+ "%s%sdwParam1=x%x, %s",
+ szCallUp,
+ szTab,
+ dwParam1,
+ (lpszParam1 ? lpszParam1 : "")
+ );
+
+ ShowStr(
+ FALSE,
+ "%s%sdwParam2=x%x, %s",
+ szCallUp,
+ szTab,
+ dwParam2,
+ (lpszParam2 ? lpszParam2 : "")
+ );
+
+ ShowStr(
+ TRUE,
+ "%s%sdwParam3=x%x, %s",
+ szCallUp,
+ szTab,
+ dwParam3,
+ (lpszParam3 ? lpszParam3 : "")
+ );
+
+ if (lpszParam1)
+ {
+ DrvFree (lpszParam1);
+ }
+
+ if (lpszParam2)
+ {
+ DrvFree (lpszParam2);
+ }
+
+ if (lpszParam3)
+ {
+ DrvFree (lpszParam3);
+ }
+ }
+}
+
+
+void
+ShowPhoneEvent(
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ if (gESPGlobals.dwDebugOptions & SHOW_EVENT_NOTIFICATIONS)
+ {
+ static DWORD adwPhoneMsgs[] =
+ {
+ PHONE_BUTTON,
+ PHONE_CLOSE,
+ PHONE_DEVSPECIFIC,
+ PHONE_STATE,
+ PHONE_CREATE,
+ PHONE_REMOVE,
+ 0xffffffff
+ };
+
+ static char *aszPhoneMsgs[] =
+ {
+ "PHONE_BUTTON",
+ "PHONE_CLOSE",
+ "PHONE_DEVSPECIFIC",
+ "PHONE_STATE",
+ "PHONE_CREATE",
+ "PHONE_REMOVE"
+ };
+ char far *lpszParam1 = (char far *) NULL;
+ char far *lpszParam2 = (char far *) NULL;
+ char far *lpszParam3 = (char far *) NULL;
+ DWORD i;
+
+
+ for (i = 0; adwPhoneMsgs[i] != 0xffffffff; i++)
+ {
+ if (dwMsg == adwPhoneMsgs[i])
+ {
+ ShowStr(
+ FALSE,
+ "%ssent %s : htPhone=x%x",
+ szCallUp,
+ aszPhoneMsgs[i],
+ htPhone
+ );
+
+ break;
+ }
+ }
+
+ if (adwPhoneMsgs[i] == 0xffffffff)
+ {
+ ShowStr(
+ FALSE,
+ "%ssent <unknown msg id, x%x> : htPhone=x%x",
+ szCallUp,
+ dwMsg,
+ htPhone
+ );
+ }
+
+ switch (dwMsg)
+ {
+ case PHONE_BUTTON:
+
+ lpszParam2 = GetFlags (dwParam2, aButtonModes);
+ lpszParam3 = GetFlags (dwParam3, aButtonStates);
+ break;
+
+ case PHONE_STATE:
+
+ lpszParam1 = GetFlags (dwParam1, aPhoneStates);
+ break;
+
+ } // switch
+
+ ShowStr(
+ FALSE,
+ "%s%sdwParam1=x%x, %s",
+ szCallUp,
+ szTab,
+ dwParam1,
+ (lpszParam1 ? lpszParam1 : "")
+ );
+
+ ShowStr(
+ FALSE,
+ "%s%sdwParam2=x%x, %s",
+ szCallUp,
+ szTab,
+ dwParam2,
+ (lpszParam2 ? lpszParam2 : "")
+ );
+
+ ShowStr(
+ TRUE,
+ "%s%sdwParam3=x%x, %s",
+ szCallUp,
+ szTab,
+ dwParam3,
+ (lpszParam3 ? lpszParam3 : "")
+ );
+
+ if (lpszParam1)
+ {
+ DrvFree (lpszParam1);
+ }
+
+ if (lpszParam2)
+ {
+ DrvFree (lpszParam2);
+ }
+
+ if (lpszParam3)
+ {
+ DrvFree (lpszParam3);
+ }
+ }
+}
+
+
+BOOL
+Prolog(
+ PFUNC_INFO pInfo
+ )
+{
+ BOOL bLineFunc = (pInfo->pszFuncName[1] != 'h');
+ DWORD i, j;
+
+
+ if (gESPGlobals.dwDebugOptions & SHOW_FUNC_ENTRY)
+ {
+ ShowStr (FALSE, "TSPI_%s: enter", pInfo->pszFuncName);
+ }
+
+ if (gESPGlobals.dwDebugOptions & SHOW_PARAMETERS)
+ {
+ for (i = 0; i < pInfo->dwNumParams; i++)
+ {
+ if (pInfo->aParams[i].dwVal &&
+ pInfo->aParams[i].lpszVal[3] == 'z') // "lpszXxx"
+ {
+ ShowStr(
+ FALSE,
+ "%s%s=x%x, '%ws'",
+ szTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal,
+ pInfo->aParams[i].dwVal
+ );
+ }
+ else if (pInfo->aParams[i].pLookup)
+ {
+ char buf[90];
+ PLOOKUP pLookup = pInfo->aParams[i].pLookup;
+
+
+ wsprintf(
+ buf,
+ "%s%s=x%x, ",
+ szTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal
+ );
+
+ for (j = 0; pLookup[j].dwVal != 0xffffffff; j++)
+ {
+ if (pInfo->aParams[i].dwVal & pLookup[j].dwVal)
+ {
+ lstrcatA (buf, pLookup[j].lpszVal);
+ lstrcatA (buf, " ");
+
+ if (lstrlenA (buf) > 60)
+ {
+ ShowStr (FALSE, buf);
+ wsprintfA (buf, "%s%s", szTab, szTab);
+ }
+ }
+ }
+
+ ShowStr (FALSE, buf);
+ }
+ else
+ {
+ ShowStr(
+ FALSE,
+ "%s%s=x%x",
+ szTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal
+ );
+ }
+ }
+ }
+
+ if (gESPGlobals.dwDebugOptions & (SHOW_PARAMETERS | SHOW_FUNC_ENTRY))
+ {
+ SetEvent (ghDebugOutputEvent);
+ }
+
+
+ //
+ //
+ //
+
+ if (gdwDevSpecificRequestID &&
+ glNextRequestResult != 0 &&
+ (pInfo->bAsync == FALSE ||
+ gdwNextRequestCompletionType == ESP_RESULT_RETURNRESULT)
+ )
+ {
+ gdwDevSpecificRequestID = 0;
+ pInfo->lResult = glNextRequestResult;
+ return FALSE;
+ }
+
+
+ if (gESPGlobals.dwDebugOptions & MANUAL_RESULTS)
+ {
+ char szDlgTitle[64];
+ EVENT_PARAM params[] =
+ {
+ { "lResult", PT_ORDINAL, 0, (bLineFunc ? aLineErrs : aPhoneErrs) }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, szDlgTitle, 0, params };
+ HWND hwnd;
+
+
+ wsprintf (szDlgTitle, "TSPI_%s request result", pInfo->pszFuncName);
+
+ DialogBoxParam(
+ ghInstance,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG1),
+ (HWND) NULL,
+ (DLGPROC) ValuesDlgProc,
+ (LPARAM) &paramsHeader
+ );
+
+
+ //
+ // If user selected to synchronously return an error we'll save
+ // the error & return FALSE to indicate to caller that it should
+ // return immediately.
+ //
+
+ if (params[0].dwValue)
+ {
+ pInfo->lResult = (LONG) params[0].dwValue;
+
+ return FALSE;
+ }
+ }
+
+
+ if (pInfo->bAsync)
+ {
+ //
+ // Alloc & init an async request info structure
+ //
+
+ PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO)
+ DrvAlloc (sizeof(ASYNC_REQUEST_INFO));
+
+
+ if ((pInfo->pAsyncReqInfo = pAsyncReqInfo))
+ {
+ pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
+ pInfo->pfnPostProcessProc;
+ pAsyncReqInfo->dwRequestID = pInfo->aParams[0].dwVal;
+
+ pAsyncReqInfo->pszFuncName = pInfo->pszFuncName;
+ }
+ else
+ {
+ pInfo->lResult = (bLineFunc ?
+ LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+LONG
+Epilog(
+ PFUNC_INFO pInfo
+ )
+{
+ if (pInfo->bAsync)
+ {
+ PASYNC_REQUEST_INFO pAsyncReqInfo = pInfo->pAsyncReqInfo;
+
+
+ if (pInfo->lResult == 0)
+ {
+ //
+ //
+ //
+
+ if (gdwDevSpecificRequestID &&
+ pInfo->aParams[0].dwVal != gdwDevSpecificRequestID)
+ {
+ gdwDevSpecificRequestID = 0;
+
+ if (glNextRequestResult != 0)
+ {
+ pAsyncReqInfo->lResult = glNextRequestResult;
+ }
+
+ if (gdwNextRequestCompletionType ==
+ ESP_RESULT_CALLCOMPLPROCASYNC)
+ {
+ goto complete_event_async;
+ }
+ else
+ {
+ goto complete_event_sync;
+ }
+ }
+
+ switch (gESPGlobals.dwCompletionMode)
+ {
+ case COMPLETE_ASYNC_EVENTS_SYNCHRONOUSLY:
+
+ //
+ // We're completing this async request synchronously, so call
+ // the post processing proc (if there is one) or call the
+ // completion routine directly
+ //
+
+complete_event_sync:
+
+ if (pInfo->pAsyncReqInfo->pfnPostProcessProc)
+ {
+ (*((POSTPROCESSPROC) pAsyncReqInfo->pfnPostProcessProc))(
+ pInfo->pAsyncReqInfo,
+ SYNC
+ );
+ }
+ else
+ {
+ DoCompletion (pAsyncReqInfo, SYNC);
+ }
+
+ DrvFree (pAsyncReqInfo);
+
+ break;
+
+ case COMPLETE_ASYNC_EVENTS_ASYNCHRONOUSLY:
+
+ //
+ // Safely add the async request to the queue (careful to
+ // reset pDataIn when we reach the end of the buffer)
+ //
+
+complete_event_async:
+
+ EnterCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
+
+ if (gESPGlobals.dwNumUsedQueueEntries ==
+ gESPGlobals.dwNumTotalQueueEntries)
+ {
+ //
+ // We've max'd out our ring buf, so try to grow it
+ //
+
+ DWORD *pNewAsyncRequestQueue, dwMoveSize;
+
+
+ if (!(pNewAsyncRequestQueue = DrvAlloc(
+ 2 * gESPGlobals.dwNumTotalQueueEntries *
+ sizeof (DWORD)
+ )))
+ {
+ LeaveCriticalSection(
+ &gESPGlobals.AsyncEventQueueCritSec
+ );
+
+ goto complete_event_sync;
+ }
+
+ dwMoveSize = ((gESPGlobals.pAsyncRequestQueue +
+ gESPGlobals.dwNumTotalQueueEntries) -
+ gESPGlobals.pAsyncRequestQueueOut) * sizeof (DWORD);
+
+ CopyMemory(
+ pNewAsyncRequestQueue,
+ gESPGlobals.pAsyncRequestQueueOut,
+ dwMoveSize
+ );
+
+ CopyMemory(
+ ((LPBYTE) pNewAsyncRequestQueue) + dwMoveSize,
+ gESPGlobals.pAsyncRequestQueue,
+ (gESPGlobals.pAsyncRequestQueueOut -
+ gESPGlobals.pAsyncRequestQueue) * sizeof (DWORD)
+ );
+
+ DrvFree (gESPGlobals.pAsyncRequestQueue);
+
+ gESPGlobals.pAsyncRequestQueue =
+ gESPGlobals.pAsyncRequestQueueOut = pNewAsyncRequestQueue;
+
+ gESPGlobals.pAsyncRequestQueueIn = pNewAsyncRequestQueue +
+ gESPGlobals.dwNumTotalQueueEntries;
+
+ gESPGlobals.dwNumTotalQueueEntries *= 2;
+ }
+
+ *(gESPGlobals.pAsyncRequestQueueIn) = (DWORD) pAsyncReqInfo;
+
+ gESPGlobals.pAsyncRequestQueueIn++;
+
+ if (gESPGlobals.pAsyncRequestQueueIn ==
+ (gESPGlobals.pAsyncRequestQueue +
+ gESPGlobals.dwNumTotalQueueEntries))
+ {
+ gESPGlobals.pAsyncRequestQueueIn =
+ gESPGlobals.pAsyncRequestQueue;
+ }
+
+ gESPGlobals.dwNumUsedQueueEntries++;
+
+ if (gESPGlobals.dwNumUsedQueueEntries == 1)
+ {
+ SetEvent (gESPGlobals.hAsyncEventsPendingEvent);
+ }
+
+ LeaveCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
+
+ break;
+
+ case COMPLETE_ASYNC_EVENTS_SYNC_AND_ASYNC:
+ {
+ //
+ // Decide whether to complete this request sync or async,
+ // then jump to the right place
+ //
+
+ static i = 0;
+
+
+ if (i++ % 2)
+ {
+ goto complete_event_sync;
+ }
+ else
+ {
+ goto complete_event_async;
+ }
+
+ break;
+ }
+ case COMPLETE_ASYNC_EVENTS_MANUALLY:
+
+ WriteEventBuffer(
+ (DWORD) pAsyncReqInfo->dwRequestID,
+ WIDGETTYPE_ASYNCREQUEST,
+ (DWORD) pAsyncReqInfo,
+ 0,
+ 0,
+ 0
+ );
+
+ break;
+ }
+
+
+ //
+ // Finally, return the request ID
+ //
+
+ pInfo->lResult = pInfo->aParams[0].dwVal;
+ }
+ else if (pAsyncReqInfo)
+ {
+ DrvFree (pAsyncReqInfo);
+ }
+ }
+
+ if (gESPGlobals.dwDebugOptions & SHOW_FUNC_EXIT)
+ {
+ ShowStr(
+ TRUE,
+ "TSPI_%s: exit, returning x%x",
+ pInfo->pszFuncName,
+ pInfo->lResult
+ );
+ }
+
+ return (pInfo->lResult);
+}
+
+
+void
+PASCAL
+SendLineEvent(
+ PDRVLINE pLine,
+ PDRVCALL pCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ //
+ //
+ //
+
+ (*(gESPGlobals.pfnLineEvent))(
+ pLine->htLine,
+ (pCall ? pCall->htCall : (HTAPICALL) NULL),
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ if (dwMsg == LINE_CALLSTATE)
+ {
+ //PostUpdateWidgetListMsg();
+ }
+
+ ShowLineEvent(
+ pLine->htLine,
+ (pCall ? pCall->htCall : (HTAPICALL) NULL),
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+}
+
+
+void
+PASCAL
+SendPhoneEvent(
+ PDRVPHONE pPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ //
+ //
+ //
+
+ (*(gESPGlobals.pfnPhoneEvent))(
+ pPhone->htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ ShowPhoneEvent(
+ pPhone->htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+}
+
+
+void
+PASCAL
+DoCompletion(
+ PASYNC_REQUEST_INFO pAsyncRequestInfo,
+ BOOL bAsync
+ )
+{
+ (*(gESPGlobals.pfnCompletion))(
+ pAsyncRequestInfo->dwRequestID,
+ pAsyncRequestInfo->lResult
+ );
+
+ if (gESPGlobals.dwDebugOptions & SHOW_COMPLETION_NOTIFICATIONS)
+ {
+ ShowStr(
+ TRUE,
+ "%sTSPI_%s: calling compl proc (%ssync), dwReqID=x%x, lResult = x%x",
+ szCallUp,
+ pAsyncRequestInfo->pszFuncName,
+ (bAsync ? "a" : ""),
+ pAsyncRequestInfo->dwRequestID,
+ pAsyncRequestInfo->lResult
+ );
+ }
+}
+
+
+LONG
+PASCAL
+SetCallState(
+ PDRVCALL pCall,
+ DWORD dwExpectedCallInstance,
+ DWORD dwValidCurrentStates,
+ DWORD dwNewCallState,
+ DWORD dwNewCallStateMode,
+ BOOL bSendStateMsgToExe
+ )
+{
+ LONG lResult = 0;
+ DWORD dwActualCallInstance;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (!IsValidDrvCall (pCall, &dwActualCallInstance) ||
+ dwActualCallInstance != dwExpectedCallInstance)
+ {
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ return LINEERR_INVALCALLHANDLE;
+ }
+
+ if (lResult == 0)
+ {
+ //
+ // Check to see that the call is in a valid (expected) state.
+ // If dwValidCurrentStates == 0xffffffff then we want to chg the
+ // state regardless of the current state.
+ //
+
+ if ((dwValidCurrentStates != 0xffffffff) &&
+ !(dwValidCurrentStates & pCall->dwCallState))
+ {
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ return LINEERR_INVALCALLSTATE;
+ }
+
+
+ //
+ // Only chg the call state if it differs from the existing one
+ //
+
+ if (dwNewCallState != pCall->dwCallState)
+ {
+ pCall->dwCallState = dwNewCallState;
+ pCall->dwCallStateMode = dwNewCallStateMode;
+
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLSTATE,
+ dwNewCallState,
+ dwNewCallStateMode,
+ pCall->dwMediaMode
+ );
+
+ if (bSendStateMsgToExe)
+ {
+ WriteEventBuffer(
+ ((PDRVLINE) pCall->pLine)->dwDeviceID,
+ WIDGETTYPE_CALL,
+ (DWORD) pCall,
+ (DWORD) pCall->htCall,
+ dwNewCallState,
+ pCall->dwAddressID
+ );
+ }
+
+
+ //
+ // If this call has an associated call/endpoint then pass
+ // connected (1st time only) or disconnected msgs to that
+ // call so they know if we've answered or hung up
+ //
+
+ if (pCall->pDestCall)
+ {
+ if (dwNewCallState == LINECALLSTATE_CONNECTED)
+ {
+ if (!pCall->bConnectedToDestCall)
+ {
+ if (IsValidDrvCall (pCall->pDestCall, NULL))
+ {
+ if (SetCallState(
+ pCall->pDestCall,
+ pCall->pDestCall->dwCallInstance,
+ 0xffffffff,
+ LINECALLSTATE_CONNECTED,
+ 0,
+ TRUE
+
+ ) == 0)
+ {
+ // NOTE: use 0x55 to aid in debugging
+ // wild writes
+
+ pCall->bConnectedToDestCall =
+ pCall->pDestCall->bConnectedToDestCall = 0x55;
+ }
+ }
+ else
+ {
+ pCall->pDestCall = NULL;
+ }
+ }
+ }
+ else if (dwNewCallState == LINECALLSTATE_IDLE ||
+ dwNewCallState == LINECALLSTATE_DISCONNECTED)
+ {
+ pCall->pDestCall->pDestCall = NULL;
+
+ SetCallState(
+ pCall->pDestCall,
+ pCall->pDestCall->dwCallInstance,
+ 0xffffffff,
+ LINECALLSTATE_DISCONNECTED,
+ (dwNewCallState == LINECALLSTATE_DISCONNECTED ?
+ dwNewCallStateMode : LINEDISCONNECTMODE_NORMAL),
+ TRUE
+ );
+
+ pCall->pDestCall = NULL;
+ }
+ }
+ }
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ return lResult;
+}
+
+
+void
+PASCAL
+WriteEventBuffer(
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6
+ )
+{
+ WIDGETEVENT event ={dwParam1,dwParam2,dwParam3,dwParam4,dwParam5,dwParam6};
+
+
+ if (gbDisableUI == TRUE)
+ {
+ return;
+ }
+
+ EnterCriticalSection (&gESPGlobals.EventBufferCritSec);
+
+ if ((gESPGlobals.dwEventBufferUsedSize + sizeof (WIDGETEVENT)) >
+ gESPGlobals.dwEventBufferTotalSize)
+ {
+ //
+ // We've max'd out our ring buf, so try to grow it
+ //
+
+ char *pNewEventBuffer;
+ DWORD dwMoveSize;
+
+
+ if (!(pNewEventBuffer = DrvAlloc (
+ 2 * gESPGlobals.dwEventBufferTotalSize
+ )))
+ {
+ LeaveCriticalSection (&gESPGlobals.EventBufferCritSec);
+
+ // log some sort of error
+
+ return;
+ }
+
+ dwMoveSize = (gESPGlobals.pEventBuffer +
+ gESPGlobals.dwEventBufferTotalSize) - gESPGlobals.pEventBufferOut;
+
+ CopyMemory (pNewEventBuffer, gESPGlobals.pEventBufferOut, dwMoveSize);
+
+ CopyMemory(
+ pNewEventBuffer + dwMoveSize,
+ gESPGlobals.pEventBuffer,
+ gESPGlobals.pEventBufferOut - gESPGlobals.pEventBuffer
+ );
+
+ DrvFree (gESPGlobals.pEventBuffer);
+
+ gESPGlobals.pEventBuffer =
+ gESPGlobals.pEventBufferOut = pNewEventBuffer;
+
+ gESPGlobals.pEventBufferIn = pNewEventBuffer +
+ gESPGlobals.dwEventBufferTotalSize;
+
+ gESPGlobals.dwEventBufferTotalSize *= 2;
+ }
+
+ CopyMemory (gESPGlobals.pEventBufferIn, &event, sizeof (WIDGETEVENT));
+
+ gESPGlobals.dwEventBufferUsedSize += sizeof (WIDGETEVENT);
+
+ if ((gESPGlobals.pEventBufferIn += sizeof (WIDGETEVENT)) >=
+ (gESPGlobals.pEventBuffer + gESPGlobals.dwEventBufferTotalSize))
+ {
+ gESPGlobals.pEventBufferIn = gESPGlobals.pEventBuffer;
+ }
+
+ SetEvent (ghWidgetEventsEvent);
+
+ LeaveCriticalSection (&gESPGlobals.EventBufferCritSec);
+}
+
+
+LPVOID
+DrvAlloc(
+ size_t numBytes
+ )
+{
+ LPVOID p = (LPVOID) LocalAlloc (LPTR, numBytes);
+
+
+ if (!p)
+ {
+ ShowStr (TRUE, "Error: DrvAlloc (x%x) failed", (DWORD) numBytes);
+ }
+
+ return p;
+}
+
+
+void
+DrvFree(
+ LPVOID p
+ )
+{
+ if (p)
+ {
+#if DBG
+ //
+ // Fill the buf to free with 0xa5's to facilitate debugging
+ //
+
+ FillMemory (p, LocalSize (LocalHandle (p)), 0xa5);
+#endif
+ LocalFree (p);
+ }
+}
+
+
+PDRVADDRESS
+PASCAL
+FindFreeAddress(
+ PDRVLINE pLine
+ )
+{
+ DWORD i;
+ PDRVADDRESS pAddr = pLine->aAddrs;
+
+
+ for (i = 0; i < gESPGlobals.dwNumAddressesPerLine; i++)
+ {
+ if (pAddr->dwNumCalls < gESPGlobals.dwNumCallsPerAddress)
+ {
+ return pAddr;
+ }
+
+ pAddr++;
+ }
+
+ return NULL;
+}
+
+
+LONG
+PASCAL
+AllocCall(
+ PDRVLINE pLine,
+ HTAPICALL htCall,
+ LPLINECALLPARAMS pCallParams,
+ PDRVCALL *ppCall
+ )
+{
+ LONG lResult = 0;
+ DWORD i;
+ PDRVCALL pCall;
+ PDRVADDRESS pAddr;
+
+
+ if (!(pCall = (PDRVCALL) DrvAlloc (sizeof (DRVCALL))))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ pCall->pLine = pLine;
+ pCall->htCall = htCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (!pCallParams)
+ {
+ if (!(pAddr = FindFreeAddress (pLine)))
+ {
+ lResult = LINEERR_CALLUNAVAIL;
+ goto AllocCall_cleanup;
+ }
+
+ pCall->dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
+ pCall->dwBearerMode = LINEBEARERMODE_VOICE;
+ }
+ else
+ {
+
+AllocCall_findTheAddr:
+
+ if (pCallParams->dwAddressMode == LINEADDRESSMODE_ADDRESSID)
+ {
+ if (pCallParams->dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
+ {
+ lResult = LINEERR_INVALADDRESSID;
+ goto AllocCall_cleanup;
+ }
+
+ if (pCallParams->dwAddressID == 0)
+ {
+ //
+ // App doesn't care which addr to make call on
+ //
+
+ if (!(pAddr = FindFreeAddress (pLine)))
+ {
+ lResult = LINEERR_CALLUNAVAIL;
+ goto AllocCall_cleanup;
+ }
+ }
+ else
+ {
+ //
+ // App wants call on a particular addr
+ //
+
+ pAddr = pLine->aAddrs + pCallParams->dwAddressID;
+
+ if (pAddr->dwNumCalls > gESPGlobals.dwNumCallsPerAddress)
+ {
+ lResult = LINEERR_CALLUNAVAIL;
+ goto AllocCall_cleanup;
+ }
+ }
+ }
+ else // (pCallParams->dwAddressMode == LINEADDRESSMODE_DIALABLEADDR)
+ {
+
+// BUGBUG AllocCall: handle dialable addr
+
+ pCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
+ pCallParams->dwAddressID = 0;
+ goto AllocCall_findTheAddr;
+ }
+
+ pCall->dwMediaMode = pCallParams->dwMediaMode;
+ pCall->dwBearerMode = pCallParams->dwBearerMode;
+ }
+
+
+ //
+ // Call was successfully "made", so do all the common stuff like
+ // adding it to the addr's list, setting the attributes, etc...
+ //
+
+ if ((pCall->pNext = pAddr->pCalls))
+ {
+ pCall->pNext->pPrev = pCall;
+ }
+
+ pAddr->pCalls = pCall;
+
+ pAddr->dwNumCalls++;
+
+ pCall->dwKey = DRVCALL_KEY;
+ pCall->pLine = pLine;
+ pCall->dwAddressID = pAddr - pLine->aAddrs;
+ pCall->dwCallInstance = gdwCallInstance++;
+ pCall->dwCallID = gdwCallID++;
+
+
+AllocCall_cleanup:
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (lResult == 0)
+ {
+ *ppCall = pCall;
+ }
+ else
+ {
+ DrvFree (pCall);
+ }
+
+ return lResult;
+}
+
+
+void
+PASCAL
+FreeCall(
+ PDRVCALL pCall,
+ DWORD dwExpectedCallInstance
+ )
+{
+ DWORD dwActualCallInstance;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwActualCallInstance) &&
+ dwActualCallInstance == dwExpectedCallInstance)
+ {
+ PDRVADDRESS pAddr;
+
+
+ pCall->dwKey = INVAL_KEY;
+
+ pAddr = ((PDRVLINE) pCall->pLine)->aAddrs + pCall->dwAddressID;
+ if (pCall->pNext)
+ {
+ pCall->pNext->pPrev = pCall->pPrev;
+ }
+
+ if (pCall->pPrev)
+ {
+ pCall->pPrev->pNext = pCall->pNext;
+ }
+ else
+ {
+ pAddr->pCalls = pCall->pNext;
+ }
+
+ if (pCall->pDestCall)
+ {
+ pCall->pDestCall->pDestCall = NULL;
+ }
+
+ pAddr->dwNumCalls--;
+ }
+ else
+ {
+ pCall = NULL;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (pCall)
+ {
+ if (pCall->pSendingFlowspec)
+ {
+ DrvFree (pCall->pSendingFlowspec);
+ }
+
+ if (pCall->pReceivingFlowspec)
+ {
+ DrvFree (pCall->pReceivingFlowspec);
+ }
+
+ if (pCall->pCallData)
+ {
+ DrvFree (pCall->pCallData);
+ }
+
+ if (pCall->dwGatherDigitsEndToEndID)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ ((PDRVLINE) pCall->pLine)->htLine,
+ pCall->htCall,
+ LINE_GATHERDIGITS,
+ LINEGATHERTERM_CANCEL,
+ pCall->dwGatherDigitsEndToEndID,
+ 0
+ );
+ }
+
+ if (pCall->dwGenerateDigitsEndToEndID)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ ((PDRVLINE) pCall->pLine)->htLine,
+ pCall->htCall,
+ LINE_GENERATE,
+ LINEGENERATETERM_CANCEL,
+ pCall->dwGenerateDigitsEndToEndID,
+ 0
+ );
+ }
+
+ if (pCall->dwGenerateToneEndToEndID)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ ((PDRVLINE) pCall->pLine)->htLine,
+ pCall->htCall,
+ LINE_GENERATE,
+ LINEGENERATETERM_CANCEL,
+ pCall->dwGenerateToneEndToEndID,
+ 0
+ );
+ }
+
+ if (pCall->dwMonitorToneListID)
+ {
+ (gESPGlobals.pfnLineEvent)(
+ ((PDRVLINE) pCall->pLine)->htLine,
+ pCall->htCall,
+ LINE_MONITORTONE,
+ 0,
+ pCall->dwMonitorToneListID,
+ 0
+ );
+ }
+
+ DrvFree (pCall);
+ }
+}
+
+
+PDRVLINE
+PASCAL
+GetLineFromID(
+ DWORD dwDeviceID
+ )
+{
+ PDRVLINE pLine;
+
+
+ if (dwDeviceID < gESPGlobals.dwLineDeviceIDBase)
+ {
+ pLine = (PDRVLINE) NULL;
+ }
+ else if (dwDeviceID < (gESPGlobals.dwLineDeviceIDBase +
+ gESPGlobals.dwInitialNumLines))
+ {
+ pLine = gESPGlobals.pLines->aLines +
+ (dwDeviceID - gESPGlobals.dwLineDeviceIDBase);
+ }
+ else
+ {
+ // BUGBUG GetLineFromID: find a line created on the fly
+ pLine = (PDRVLINE) NULL;
+ }
+
+ return pLine;
+}
+
+
+PDRVPHONE
+PASCAL
+GetPhoneFromID(
+ DWORD dwDeviceID
+ )
+{
+ PDRVPHONE pPhone;
+
+
+ if (dwDeviceID < (gESPGlobals.dwPhoneDeviceIDBase +
+ gESPGlobals.dwInitialNumPhones))
+ {
+ pPhone = gESPGlobals.pPhones->aPhones +
+ (dwDeviceID - gESPGlobals.dwPhoneDeviceIDBase);
+ }
+ else
+ {
+ // BUGBUG GetPhoneFromID: find a phone created on the fly
+ pPhone = (PDRVPHONE) NULL;
+ }
+
+ return pPhone;
+}
+
+
+long
+ESPAttach(
+ long lProcessID,
+ long *phShutdownEvent,
+ long *phDebugOutputEvent,
+ long *phWidgetEventsEvent
+ )
+{
+ HANDLE hMyProcess, hEspExeProcess;
+
+
+ hMyProcess = GetCurrentProcess();
+
+ hEspExeProcess = OpenProcess(
+ PROCESS_DUP_HANDLE,
+ TRUE,
+ (DWORD) lProcessID
+ );
+
+ if (!DuplicateHandle(
+ hMyProcess,
+ ghDebugOutputEvent,
+ hEspExeProcess,
+ (HANDLE *) phDebugOutputEvent,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ ) ||
+
+ !DuplicateHandle(
+ hMyProcess,
+ ghShutdownEvent,
+ hEspExeProcess,
+ (HANDLE *) phShutdownEvent,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ ) ||
+
+ !DuplicateHandle(
+ hMyProcess,
+ ghWidgetEventsEvent,
+ hEspExeProcess,
+ (HANDLE *) phWidgetEventsEvent,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ ))
+ {
+ DBGOUT((1, "ESPAttach: DupHandle failed, err=%d", GetLastError()));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+void
+ESPSetOptions(
+ long lDebugOptions,
+ long lCompletionMode
+ )
+{
+ gESPGlobals.dwDebugOptions = (DWORD) lDebugOptions;
+ gESPGlobals.dwCompletionMode = (DWORD) lCompletionMode;
+
+ if (!gbInteractWithDesktop)
+ {
+ gESPGlobals.dwDebugOptions &= ~MANUAL_RESULTS;
+ }
+}
+
+
+void
+ESPCompleteRequest(
+ long lAsyncReqInfo,
+ long lResult
+ )
+{
+ PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO) lAsyncReqInfo;
+
+
+ pAsyncReqInfo->lResult = lResult;
+
+ if (pAsyncReqInfo->pfnPostProcessProc)
+ {
+ (*((POSTPROCESSPROC) pAsyncReqInfo->pfnPostProcessProc))(
+ pAsyncReqInfo,
+ ASYNC
+ );
+ }
+ else
+ {
+ DoCompletion (pAsyncReqInfo, ASYNC);
+ }
+
+ DrvFree (pAsyncReqInfo);
+}
+
+
+long
+ESPEvent(
+ long htDevice,
+ long htCall,
+ long dwMsg,
+ long dwParam1,
+ long dwParam2,
+ long dwParam3
+ )
+{
+ switch (dwMsg)
+ {
+ case LINE_CALLSTATE:
+ {
+ DWORD dwCallInst;
+
+// BUGBUG when state == conf or prevState == conf need to add/rem conf list
+
+ try
+ {
+ dwCallInst = ((PDRVCALL) htCall)->dwCallInstance;
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ break;
+ }
+
+ SetCallState(
+ (PDRVCALL) htCall,
+ dwCallInst,
+ 0xffffffff,
+ dwParam1,
+ dwParam2,
+ TRUE
+ );
+
+ break;
+ }
+ case LINE_ADDRESSSTATE:
+ case LINE_CALLDEVSPECIFIC:
+ case LINE_CALLDEVSPECIFICFEATURE:
+ case LINE_CALLINFO:
+ case LINE_CLOSE:
+ case LINE_DEVSPECIFIC:
+ case LINE_DEVSPECIFICFEATURE:
+ case LINE_GATHERDIGITS:
+ case LINE_GENERATE:
+ case LINE_LINEDEVSTATE:
+ case LINE_MONITORDIGITS:
+ case LINE_MONITORMEDIA:
+ case LINE_MONITORTONE:
+ case LINE_REMOVE:
+
+ (*gESPGlobals.pfnLineEvent)(
+ (HTAPILINE) htDevice,
+ (HTAPICALL) htCall,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ ShowLineEvent(
+ (HTAPILINE) htDevice,
+ (HTAPICALL) htCall,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ break;
+
+ case LINE_CREATEDIALOGINSTANCE:
+ {
+ TUISPICREATEDIALOGINSTANCEPARAMS createDlgParams;
+
+
+ ZeroMemory(
+ &createDlgParams,
+ sizeof (TUISPICREATEDIALOGINSTANCEPARAMS)
+ );
+
+ createDlgParams.dwRequestID = dwParam1;
+ createDlgParams.hdDlgInst = (HDRVDIALOGINSTANCE) 0x55;
+ createDlgParams.lpszUIDLLName = szESPUIDLL;
+ createDlgParams.lpParams = "genDlg params";
+ createDlgParams.dwSize = 14;
+
+ (*gESPGlobals.pfnLineEvent)(
+ (HTAPILINE) gESPGlobals.hProvider,
+ (HTAPICALL) NULL,
+ (DWORD) LINE_CREATEDIALOGINSTANCE,
+ (DWORD) &createDlgParams,
+ 0,
+ 0
+ );
+
+ ShowLineEvent(
+ (HTAPILINE) gESPGlobals.hProvider,
+ NULL,
+ LINE_CREATEDIALOGINSTANCE,
+ (DWORD) &createDlgParams,
+ 0,
+ 0
+ );
+
+ break;
+ }
+ case LINE_SENDDIALOGINSTANCEDATA:
+ {
+ char data[] = "dlgInstData";
+
+
+ (*gESPGlobals.pfnLineEvent)(
+ (HTAPILINE) dwParam1,
+ (HTAPICALL) NULL,
+ (DWORD) LINE_SENDDIALOGINSTANCEDATA,
+ (DWORD) data,
+ 12,
+ 0
+ );
+
+ ShowLineEvent(
+ (HTAPILINE) dwParam1,
+ NULL,
+ LINE_CREATEDIALOGINSTANCE,
+ (DWORD) data,
+ 12,
+ 0
+ );
+
+ break;
+ }
+ case PHONE_BUTTON:
+ case PHONE_CLOSE:
+ case PHONE_DEVSPECIFIC:
+ case PHONE_STATE:
+ case PHONE_REMOVE:
+
+ (*gESPGlobals.pfnPhoneEvent)(
+ (HTAPIPHONE) htDevice,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ ShowPhoneEvent(
+ (HTAPIPHONE) htDevice,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ break;
+ }
+
+ return 0;
+}
+
+
+void
+ESPGetDebugOutput(
+ unsigned char *pBuffer,
+ long *plSize
+ )
+{
+ DWORD dwTotalSize, dwMoveSize, dwMoveSizeWrapped;
+
+
+ EnterCriticalSection (&gESPGlobals.DebugBufferCritSec);
+
+ dwMoveSize =
+ dwTotalSize = ((DWORD) *plSize < gESPGlobals.dwDebugBufferUsedSize ?
+ (DWORD)*plSize : gESPGlobals.dwDebugBufferUsedSize);
+
+ if ((DWORD) (gESPGlobals.pDebugBuffer + gESPGlobals.dwDebugBufferTotalSize
+ - gESPGlobals.pDebugBufferOut) > dwTotalSize)
+ {
+ dwMoveSizeWrapped = 0;
+ }
+ else
+ {
+ dwMoveSize = (gESPGlobals.pDebugBuffer +
+ gESPGlobals.dwDebugBufferTotalSize - gESPGlobals.pDebugBufferOut);
+
+ dwMoveSizeWrapped = dwTotalSize - dwMoveSize;
+ }
+
+ CopyMemory(
+ pBuffer,
+ gESPGlobals.pDebugBufferOut,
+ dwMoveSize
+ );
+
+ if (dwMoveSizeWrapped)
+ {
+ CopyMemory(
+ pBuffer + dwMoveSize,
+ gESPGlobals.pDebugBuffer,
+ dwMoveSizeWrapped
+ );
+
+ gESPGlobals.pDebugBufferOut = gESPGlobals.pDebugBuffer +
+ dwMoveSizeWrapped;
+ }
+ else
+ {
+ gESPGlobals.pDebugBufferOut += dwTotalSize;
+ }
+
+ gESPGlobals.dwDebugBufferUsedSize -= dwTotalSize;
+
+ LeaveCriticalSection (&gESPGlobals.DebugBufferCritSec);
+
+ ResetEvent (ghDebugOutputEvent);
+
+ *plSize = (long) dwTotalSize;
+}
+
+
+void
+ESPGetWidgetEvents(
+ unsigned char *pBuffer,
+ long *plSize
+ )
+{
+ DWORD dwTotalSize, dwMoveSize, dwMoveSizeWrapped;
+
+
+ EnterCriticalSection (&gESPGlobals.EventBufferCritSec);
+
+ dwMoveSize =
+ dwTotalSize = ((DWORD) *plSize < gESPGlobals.dwEventBufferUsedSize ?
+ (DWORD)*plSize : gESPGlobals.dwEventBufferUsedSize);
+
+ if ((DWORD) (gESPGlobals.pEventBuffer + gESPGlobals.dwEventBufferTotalSize
+ - gESPGlobals.pEventBufferOut) > dwTotalSize)
+ {
+ dwMoveSizeWrapped = 0;
+ }
+ else
+ {
+ dwMoveSize = (gESPGlobals.pEventBuffer +
+ gESPGlobals.dwEventBufferTotalSize - gESPGlobals.pEventBufferOut);
+
+ dwMoveSizeWrapped = dwTotalSize - dwMoveSize;
+ }
+
+ CopyMemory(
+ pBuffer,
+ gESPGlobals.pEventBufferOut,
+ dwMoveSize
+ );
+
+ if (dwMoveSizeWrapped)
+ {
+ CopyMemory(
+ pBuffer + dwMoveSize,
+ gESPGlobals.pEventBuffer,
+ dwMoveSizeWrapped
+ );
+
+ gESPGlobals.pEventBufferOut = gESPGlobals.pEventBuffer +
+ dwMoveSizeWrapped;
+ }
+ else
+ {
+ gESPGlobals.pEventBufferOut += dwTotalSize;
+ }
+
+ gESPGlobals.dwEventBufferUsedSize -= dwTotalSize;
+
+ LeaveCriticalSection (&gESPGlobals.EventBufferCritSec);
+
+ ResetEvent (ghWidgetEventsEvent);
+
+ *plSize = (long) dwTotalSize;
+}
+
+
+long
+ESPStartPBXThread(
+ unsigned char *pBuffer,
+ long lSize
+ )
+{
+ long *pPBXSettings;
+ DWORD dwThreadID;
+
+ if ((pPBXSettings = DrvAlloc (lSize)))
+ {
+ CopyMemory (pPBXSettings, pBuffer, lSize);
+
+ gbExitPBXThread = FALSE;
+
+ if ((ghPBXThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE) PBXThread,
+ (LPVOID) pPBXSettings,
+ 0,
+ &dwThreadID
+ )))
+ {
+ return 0;
+ }
+
+ DrvFree (pPBXSettings);
+ }
+
+ return -1;
+}
+
+
+long
+ESPStopPBXThread(
+ long lDummy
+ )
+{
+ gbExitPBXThread = TRUE;
+
+ WaitForSingleObject (ghPBXThread, INFINITE);
+
+ CloseHandle (ghPBXThread);
+
+ ghPBXThread = NULL;
+
+ return 0;
+}
+
+
+void
+__RPC_FAR *
+__RPC_API
+midl_user_allocate(
+ size_t len
+ )
+{
+
+
+ return (DrvAlloc (len));
+}
+
+
+void
+__RPC_API
+midl_user_free(
+ void __RPC_FAR * ptr
+ )
+{
+ DrvFree (ptr);
+}
+
+
+#if DBG
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+{
+ if (dwDbgLevel <= gdwDebugLevel)
+ {
+ char buf[128] = "ESP32: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+ wvsprintf (&buf[7], lpszFormat, ap);
+ lstrcatA (buf, "\n");
+ OutputDebugStringA (buf);
+ va_end(ap);
+ }
+}
+#endif
+
+BOOL
+ScanForDWORD(
+ char far *pBuf,
+ LPDWORD lpdw
+ )
+{
+ char c;
+ BOOL bValid = FALSE;
+ DWORD d = 0;
+
+ while ((c = *pBuf))
+ {
+ if ((c >= '0') && (c <= '9'))
+ {
+ c -= '0';
+ }
+ else if ((c >= 'a') && (c <= 'f'))
+ {
+ c -= ('a' - 10);
+ }
+ else if ((c >= 'A') && (c <= 'F'))
+ {
+ c -= ('A' - 10);
+ }
+ else
+ {
+ break;
+ }
+
+ bValid = TRUE;
+
+ d *= 16;
+
+ d += (DWORD) c;
+
+ pBuf++;
+ }
+
+ if (bValid)
+ {
+ *lpdw = d;
+ }
+
+ return bValid;
+}
+
+
+BOOL
+CALLBACK
+ValuesDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ DWORD i;
+
+ static HWND hwndCombo, hwndList1, hwndList2;
+ static LONG lLastSel;
+ static char szComboText[MAX_STRING_PARAM_SIZE];
+ static PEVENT_PARAM_HEADER pParamsHeader;
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ hwndList1 = GetDlgItem (hwnd, IDC_LIST1);
+ hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ hwndCombo = GetDlgItem (hwnd, IDC_COMBO1);
+
+ lLastSel = -1;
+ pParamsHeader = (PEVENT_PARAM_HEADER) lParam;
+
+
+ //
+ // Limit the max text length for the combobox's edit field
+ // (NOTE: A combobox ctrl actually has two child windows: a
+ // edit ctrl & a listbox. We need to get the hwnd of the
+ // child edit ctrl & send it the LIMITTEXT msg.)
+ //
+
+ {
+ HWND hwndChild = GetWindow (hwndCombo, GW_CHILD);
+
+
+ while (hwndChild)
+ {
+ char buf[8];
+
+
+ GetClassName (hwndChild, buf, 7);
+
+ if (_stricmp (buf, "edit") == 0)
+ {
+ break;
+ }
+
+ hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
+ }
+
+ SendMessage(
+ hwndChild,
+ EM_LIMITTEXT,
+ (WPARAM) MAX_STRING_PARAM_SIZE - 1,
+ 0
+ );
+ }
+
+
+ //
+ // Misc other init
+ //
+
+ SetWindowText (hwnd, pParamsHeader->pszDlgTitle);
+
+ for (i = 0; i < pParamsHeader->dwNumParams; i++)
+ {
+ SendMessage(
+ hwndList1,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pParamsHeader->aParams[i].szName
+ );
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ if (lLastSel != -1)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ //
+ // Save val of currently selected param
+ //
+
+ i = GetDlgItemText(
+ hwnd,
+ IDC_COMBO1,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendMessage (hwndCombo, CB_GETCURSEL, 0, 0);
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD) 0;
+ }
+ else // "Valid string"
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].buf[MAX_STRING_PARAM_SIZE-1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!ScanForDWORD(
+ buf,
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+ // Drop thru to IDCANCEL cleanup code
+
+ case IDCANCEL:
+
+ EndDialog (hwnd, (int)LOWORD(wParam));
+ break;
+
+ case IDC_LIST1:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ char buf[MAX_STRING_PARAM_SIZE] = "";
+ LPCSTR lpstr = buf;
+ LONG lSel = SendMessage (hwndList1, LB_GETCURSEL, 0, 0);
+
+
+ if (lLastSel != -1)
+ {
+ //
+ // Save the old param value
+ //
+
+ i = GetWindowText(
+ hwndCombo,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendMessage (hwndCombo, CB_GETCURSEL, 0,0);
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue =
+ (DWORD)0;
+ }
+ else // "Valid string" or no sel
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].buf[MAX_STRING_PARAM_SIZE - 1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!ScanForDWORD(
+ buf,
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+
+ SendMessage (hwndList2, LB_RESETCONTENT, 0, 0);
+ SendMessage (hwndCombo, CB_RESETCONTENT, 0, 0);
+
+ switch (pParamsHeader->aParams[lSel].dwType)
+ {
+ case PT_STRING:
+ {
+ char * aszOptions[] =
+ {
+ "NUL (dwXxxSize=0)",
+ "Valid string"
+ };
+
+
+ for (i = 0; i < 2; i++)
+ {
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) aszOptions[i]
+ );
+ }
+
+ if (pParamsHeader->aParams[lSel].dwValue == 0)
+ {
+ i = 0;
+ buf[0] = 0;
+ }
+ else
+ {
+ i = 1;
+ lpstr = (LPCSTR) pParamsHeader->aParams[lSel].dwValue;
+ }
+
+ SendMessage (hwndCombo, CB_SETCURSEL, (WPARAM) i, 0);
+
+ break;
+ }
+ case PT_DWORD:
+ {
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "0000000"
+ );
+
+ if (pParamsHeader->aParams[lSel].dwDefValue)
+ {
+ //
+ // Add the default val string to the combo
+ //
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwDefValue
+ );
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) buf
+ );
+ }
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "ffffffff"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_ORDINAL:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].lpszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue ==
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_FLAGS:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].lpszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue &
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ SendMessage(
+ hwndCombo,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select all"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ } //switch
+
+ SetWindowText (hwndCombo, lpstr);
+
+ lLastSel = lSel;
+ }
+ break;
+
+ case IDC_LIST2:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ //
+ // BUGBUG in the PT_ORDINAL case we should compare the
+ // currently selected item(s) against the previous DWORD
+ // val and figure out which item we need to deselect,
+ // if any, in order to maintain a mutex of values
+ //
+
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].pLookup;
+ char buf[16];
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendMessage (hwndList2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) DrvAlloc ((size_t)lSelCount * sizeof(int));
+
+ SendMessage(
+ hwndList2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_FLAGS)
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+ }
+ else // if (.dwType == PT_ORDINAL)
+ {
+ if (lSelCount == 1)
+ {
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ else if (lSelCount == 2)
+ {
+ //
+ // Figure out which item we need to de-select, since
+ // we're doing ordinals & only want 1 item selected
+ // at a time
+ //
+
+ GetWindowText (hwndCombo, buf, 16);
+
+ if (ScanForDWORD (buf, &dwValue))
+ {
+ if (pLookup[ai[0]].dwVal == dwValue)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[0]
+ );
+
+ dwValue = pLookup[ai[1]].dwVal;
+ }
+ else
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[1]
+ );
+
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ else if (lSelCount > 2)
+ {
+ //
+ // Determine previous selection & de-select all the
+ // latest selections
+ //
+
+ GetDlgItemText (hwnd, IDC_COMBO1, buf, 16);
+
+ if (ScanForDWORD (buf, &dwValue))
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ if (pLookup[ai[i]].dwVal != dwValue)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[i]
+ );
+ }
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ }
+
+ DrvFree (ai);
+ wsprintf (buf, "%08lx", dwValue);
+ SetWindowText (hwndCombo, buf);
+ }
+ break;
+
+ case IDC_COMBO1:
+
+ switch (HIWORD(wParam))
+ {
+ case CBN_SELCHANGE:
+ {
+ LONG lSel = SendMessage (hwndCombo, CB_GETCURSEL, 0, 0);
+
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_ORDINAL:
+
+ //
+ // The only option here is "select none"
+ //
+
+ strcpy (szComboText, "00000000");
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+ break;
+
+ case PT_FLAGS:
+ {
+ BOOL bSelect = (lSel ? TRUE : FALSE);
+
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) bSelect,
+ (LPARAM) -1
+ );
+
+ if (bSelect)
+ {
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].pLookup;
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendMessage (hwndList2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) DrvAlloc(
+ (size_t)lSelCount * sizeof(int)
+ );
+
+ SendMessage(
+ hwndList2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+
+ DrvFree (ai);
+ wsprintf (szComboText, "%08lx", dwValue);
+
+ }
+ else
+ {
+ strcpy (szComboText, "00000000");
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+ }
+ case PT_STRING:
+
+ if (lSel == 1)
+ {
+ strncpy(
+ szComboText,
+ pParamsHeader->aParams[lLastSel].buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ szComboText[MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ else
+ {
+ szComboText[0] = 0;
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+
+ case PT_DWORD:
+
+ break;
+
+ } // switch
+ break;
+ }
+ case CBN_EDITCHANGE:
+ {
+ //
+ // If user entered text in the edit field then copy the
+ // text to our buffer
+ //
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_STRING)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ GetWindowText (hwndCombo, buf, MAX_STRING_PARAM_SIZE);
+
+ strncpy(
+ pParamsHeader->aParams[lLastSel].buf,
+ buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ pParamsHeader->aParams[lLastSel].buf
+ [MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ break;
+ }
+ } // switch
+
+ } // switch
+
+ break;
+ }
+ case WM_USER+55:
+
+ SetWindowText (hwndCombo, szComboText);
+ break;
+
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+PASCAL
+IsValidESPAddress(
+ LPCWSTR lpszDestAddress,
+ PDRVLINE *ppLine,
+ LPDWORD pdwAddressID
+ )
+{
+ char *pszDestAddress, *p, c;
+ BOOL bResult = FALSE;
+ DWORD length, dwDestLineID, dwAddressID;
+
+
+ if (!lpszDestAddress)
+ {
+ return FALSE;
+ }
+
+
+ //
+ // Convert destination address from unicode to ascii
+ //
+
+ length = (lstrlenW (lpszDestAddress) + 1) * sizeof (WCHAR);
+
+ if (!(pszDestAddress = DrvAlloc (length)))
+ {
+ return FALSE;
+ }
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDestAddress,
+ -1,
+ pszDestAddress,
+ length,
+ NULL,
+ NULL
+ );
+
+ p = pszDestAddress;
+
+
+ //
+ // See if destination address is in the format of either
+ // "<esp line id>" or "<esp line id>#<esp address id>"
+ //
+
+ if (*p < '0' || *p > '9')
+ {
+ goto ISESPAddress_freeAddr;
+ }
+
+ for (dwDestLineID = 0; (c = *p); p++)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ dwDestLineID *= 10;
+ dwDestLineID += ((DWORD)(c - '0'));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (c != '\0' && c != '#')
+ {
+ goto ISESPAddress_freeAddr;
+ }
+
+ if (dwDestLineID < gESPGlobals.dwLineDeviceIDBase ||
+ dwDestLineID >= (gESPGlobals.dwNumLines +
+ gESPGlobals.dwLineDeviceIDBase))
+ {
+ goto ISESPAddress_freeAddr;
+ }
+
+ if (c == '\0')
+ {
+ *pdwAddressID = 0;
+ goto ISESPAddress_success;
+ }
+
+ p++;
+
+ if (*p < '0' || *p > '9')
+ {
+ goto ISESPAddress_freeAddr;
+ }
+
+ for (dwAddressID = 0; (c = *p); p++)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ dwAddressID *= 10;
+ dwAddressID += ((DWORD)(c - '0'));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (c != '\0' || dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
+ {
+ goto ISESPAddress_freeAddr;
+ }
+
+ *pdwAddressID = dwAddressID;
+
+ISESPAddress_success:
+
+ *ppLine = GetLineFromID (dwDestLineID);
+ bResult = TRUE;
+
+ISESPAddress_freeAddr:
+
+ DrvFree (pszDestAddress);
+ return bResult;
+}
+
+
+LONG
+PASCAL
+CreateIncomingCall(
+ LPCWSTR lpszDestAddress,
+ LPLINECALLPARAMS lpCallParams,
+ PDRVCALL pOutgoingCall,
+ BOOL *pbValidESPAddress,
+ PDRVLINE *ppIncomingLine,
+ PDRVCALL *ppIncomingCall
+ )
+{
+ LONG lResult;
+ DWORD dwIncomingAddressID;
+ PDRVCALL pIncomingCall;
+ PDRVLINE pIncomingLine;
+ LINECALLPARAMS callParams;
+
+
+ *pbValidESPAddress = FALSE;
+ *ppIncomingLine = NULL;
+ *ppIncomingCall = NULL;
+
+ if (!IsValidESPAddress(
+ lpszDestAddress,
+ &pIncomingLine,
+ &dwIncomingAddressID
+ ))
+ {
+ return LINEERR_INVALADDRESS;
+ }
+
+ *pbValidESPAddress = TRUE;
+
+ if (pIncomingLine->htLine == NULL ||
+ (pOutgoingCall &&
+ !(pIncomingLine->dwMediaModes & pOutgoingCall->dwMediaMode)))
+ {
+ return LINEERR_INVALMEDIAMODE;
+ }
+
+ if (!lpCallParams)
+ {
+ lpCallParams = &callParams;
+
+ ZeroMemory (&callParams, sizeof (LINECALLPARAMS));
+
+ callParams.dwTotalSize = sizeof (LINECALLPARAMS);
+ callParams.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
+ callParams.dwBearerMode = LINEBEARERMODE_VOICE;
+ }
+
+ lpCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
+ lpCallParams->dwAddressID = dwIncomingAddressID;
+
+ if ((lResult = AllocCall(
+ pIncomingLine,
+ 0,
+ lpCallParams,
+ &pIncomingCall
+
+ )) == 0)
+ {
+ if (pOutgoingCall)
+ {
+ pOutgoingCall->pDestCall = pIncomingCall;
+ pIncomingCall->pDestCall = pOutgoingCall;
+ }
+
+ *ppIncomingLine = pIncomingLine;
+ *ppIncomingCall = pIncomingCall;
+ }
+ else
+ {
+ ShowStr(
+ TRUE,
+ "lineMakeCall couldn't create incoming call on" \
+ "line/addr id %d/%d, exceeded max calls per line/addr",
+ pIncomingLine->dwDeviceID,
+ dwIncomingAddressID
+ );
+ }
+
+ return lResult;
+}
+
+
+void
+FAR
+PASCAL
+TransferCall_postProcess(
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bAsync
+ )
+{
+ DWORD dwCallInstThen = pAsyncReqInfo->dwParam2,
+ dwValidCurrentCallStates = pAsyncReqInfo->dwParam5,
+ dwNewCallState = pAsyncReqInfo->dwParam6,
+ dwCallInstNow;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1,
+ pDestCall = (PDRVCALL) pAsyncReqInfo->dwParam4;
+ PDRVLINE pDestLine = (PDRVLINE) pAsyncReqInfo->dwParam3;
+
+
+ DoCompletion (pAsyncReqInfo, bAsync);
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = SetCallState(
+ pCall,
+ dwCallInstThen,
+ dwValidCurrentCallStates,
+ LINECALLSTATE_IDLE,
+ 0,
+ TRUE
+
+ )) != 0)
+ {
+ goto TSPI_lineBlindTransfer_postProcess_freeDestCall;
+ }
+
+ if (pDestCall)
+ {
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, &dwCallInstNow) &&
+ dwCallInstNow == dwCallInstThen)
+ {
+ SendLineEvent(
+ pDestLine,
+ NULL,
+ LINE_NEWCALL,
+ (DWORD) pDestCall,
+ (DWORD) &pDestCall->htCall,
+ 0
+ );
+
+ if (pDestCall->htCall)
+ {
+ SetCallState(
+ pDestCall,
+ pDestCall->dwCallInstance,
+ 0xffffffff,
+ dwNewCallState,
+ 0,
+ TRUE
+ );
+ }
+ else
+ {
+ FreeCall (pDestCall, pDestCall->dwCallInstance);
+ }
+ }
+ else
+ {
+ FreeCall (pDestCall, pDestCall->dwCallInstance);
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+ }
+
+ }
+ else
+ {
+
+TSPI_lineBlindTransfer_postProcess_freeDestCall:
+
+ if (pDestCall)
+ {
+ FreeCall (pDestCall, pDestCall->dwCallInstance);
+ }
+ }
+}
+
+
+
+
+LONG
+PASCAL
+TransferCall(
+ PFUNC_INFO pInfo,
+ PDRVCALL pCall,
+ DWORD dwValidCurrentCallStates,
+ DWORD dwNewCallState, // initial call state of new incoming call
+ LPCWSTR lpszDestAddress
+ )
+{
+ BOOL bValidESPAddress;
+ LONG lResult = 0;
+ PDRVLINE pDestLine;
+ PDRVCALL pDestCall;
+
+
+ EnterCriticalSection (&gESPGlobals.CallListCritSec);
+
+ if (IsValidDrvCall (pCall, NULL) == FALSE)
+ {
+ lResult = LINEERR_INVALCALLHANDLE;
+ }
+ else if ((pCall->dwCallState & dwValidCurrentCallStates) == 0)
+ {
+ lResult = LINEERR_INVALCALLSTATE;
+ }
+ else
+ {
+ PDRVCALL pDestCallOrig = pCall->pDestCall;
+ LINECALLPARAMS callParams;
+
+
+ if (IsValidDrvCall (pDestCallOrig, NULL) == FALSE)
+ {
+ pDestCallOrig = NULL;
+ }
+
+ ZeroMemory (&callParams, sizeof (LINECALLPARAMS));
+
+ callParams.dwTotalSize = sizeof (LINECALLPARAMS);
+ callParams.dwMediaMode = pCall->dwMediaMode;
+ callParams.dwBearerMode = pCall->dwBearerMode;
+ callParams.dwMinRate = pCall->dwMinRate;
+ callParams.dwMaxRate = pCall->dwMaxRate;
+
+ if (CreateIncomingCall(
+ lpszDestAddress,
+ &callParams,
+ pDestCallOrig,
+ &bValidESPAddress,
+ &pDestLine,
+ &pDestCall
+
+ ) == 0)
+ {
+ pCall->pDestCall = NULL;
+ pDestCall->dwCallID = pCall->dwCallID;
+
+ if (pCall->dwCallDataSize &&
+ (pDestCall->pCallData = DrvAlloc (pCall->dwCallDataSize)))
+ {
+ CopyMemory(
+ pDestCall->pCallData,
+ pCall->pCallData,
+ (pDestCall->dwCallDataSize = pCall->dwCallDataSize)
+ );
+ }
+ }
+
+ pInfo->pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
+ TransferCall_postProcess;
+
+ pInfo->pAsyncReqInfo->dwParam1 = (DWORD) pCall;
+ pInfo->pAsyncReqInfo->dwParam2 = (DWORD) pCall->dwCallInstance;
+ pInfo->pAsyncReqInfo->dwParam3 = (DWORD) pDestLine;
+ pInfo->pAsyncReqInfo->dwParam4 = (DWORD) pDestCall;
+ pInfo->pAsyncReqInfo->dwParam5 = (DWORD) dwValidCurrentCallStates;
+ pInfo->pAsyncReqInfo->dwParam6 = (DWORD) dwNewCallState;
+ }
+
+ LeaveCriticalSection (&gESPGlobals.CallListCritSec);
+
+ return lResult;
+}
diff --git a/private/tapi/dev/sp/esp.new/tsp/esp.h b/private/tapi/dev/sp/esp.new/tsp/esp.h
new file mode 100644
index 000000000..54ca0494d
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/esp.h
@@ -0,0 +1,653 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ esp.h
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 18-Sep-1995
+
+Revision History:
+
+
+Notes:
+
+
+--*/
+
+
+#include "windows.h"
+#include "intrface.h"
+#include "tapi.h"
+#include "tspi.h"
+#include "espidl.h"
+
+
+#define DRVCALL_KEY ((DWORD) 'LLAC')
+#define INVAL_KEY ((DWORD) 'XXXX')
+
+#define SYNC 0
+#define ASYNC 1
+
+#define LINE_ICON 1
+#define PHONE_ICON 2
+#define IDD_DIALOG1 3
+
+#define IDC_LIST1 1001
+#define IDC_COMBO1 1002
+#define IDC_LIST2 1003
+
+#define MAX_STRING_PARAM_SIZE 32
+
+#define PT_DWORD 1
+#define PT_FLAGS 2
+#define PT_STRING 3
+#define PT_ORDINAL 4
+
+#define DEF_NUM_ASYNC_REQUESTS_IN_QUEUE 256
+#define DEF_NUM_EXTRA_LOOKUP_ENTRIES 16
+
+#define MAX_VAR_DATA_SIZE 1024
+
+#define MAX_NUM_COMPLETION_MESSAGES 100
+
+#define PHONE_DISPLAY_SIZE_IN_CHARS 32
+#define PHONE_DISPLAY_SIZE_IN_BYTES (PHONE_DISPLAY_SIZE_IN_CHARS * sizeof (WCHAR))
+
+#define AllAddrCaps1_0 \
+ (LINEADDRCAPFLAGS_FWDNUMRINGS | \
+ LINEADDRCAPFLAGS_PICKUPGROUPID | \
+ LINEADDRCAPFLAGS_SECURE | \
+ LINEADDRCAPFLAGS_BLOCKIDDEFAULT | \
+ LINEADDRCAPFLAGS_BLOCKIDOVERRIDE | \
+ LINEADDRCAPFLAGS_DIALED | \
+ LINEADDRCAPFLAGS_ORIGOFFHOOK | \
+ LINEADDRCAPFLAGS_DESTOFFHOOK | \
+ LINEADDRCAPFLAGS_FWDCONSULT | \
+ LINEADDRCAPFLAGS_SETUPCONFNULL | \
+ LINEADDRCAPFLAGS_AUTORECONNECT | \
+ LINEADDRCAPFLAGS_COMPLETIONID | \
+ LINEADDRCAPFLAGS_TRANSFERHELD | \
+ LINEADDRCAPFLAGS_TRANSFERMAKE | \
+ LINEADDRCAPFLAGS_CONFERENCEHELD | \
+ LINEADDRCAPFLAGS_CONFERENCEMAKE | \
+ LINEADDRCAPFLAGS_PARTIALDIAL | \
+ LINEADDRCAPFLAGS_FWDSTATUSVALID | \
+ LINEADDRCAPFLAGS_FWDINTEXTADDR | \
+ LINEADDRCAPFLAGS_FWDBUSYNAADDR | \
+ LINEADDRCAPFLAGS_ACCEPTTOALERT | \
+ LINEADDRCAPFLAGS_CONFDROP | \
+ LINEADDRCAPFLAGS_PICKUPCALLWAIT)
+
+#define AllAddrCaps2_0 \
+ (AllAddrCaps1_0 | \
+ LINEADDRCAPFLAGS_PREDICTIVEDIALER | \
+ LINEADDRCAPFLAGS_QUEUE | \
+ LINEADDRCAPFLAGS_ROUTEPOINT | \
+ LINEADDRCAPFLAGS_HOLDMAKESNEW | \
+ LINEADDRCAPFLAGS_NOINTERNALCALLS | \
+ LINEADDRCAPFLAGS_NOEXTERNALCALLS | \
+ LINEADDRCAPFLAGS_SETCALLINGID)
+
+#define AllAddrFeatures1_0 \
+ (LINEADDRFEATURE_FORWARD | \
+ LINEADDRFEATURE_MAKECALL | \
+ LINEADDRFEATURE_PICKUP | \
+ LINEADDRFEATURE_SETMEDIACONTROL | \
+ LINEADDRFEATURE_SETTERMINAL | \
+ LINEADDRFEATURE_SETUPCONF | \
+ LINEADDRFEATURE_UNCOMPLETECALL | \
+ LINEADDRFEATURE_UNPARK)
+
+#define AllAddrFeatures2_0 \
+ (AllAddrFeatures1_0 | \
+ LINEADDRFEATURE_PICKUPHELD | \
+ LINEADDRFEATURE_PICKUPGROUP | \
+ LINEADDRFEATURE_PICKUPDIRECT | \
+ LINEADDRFEATURE_PICKUPWAITING | \
+ LINEADDRFEATURE_FORWARDFWD | \
+ LINEADDRFEATURE_FORWARDDND)
+
+#define AllBearerModes1_0 \
+ (LINEBEARERMODE_VOICE | \
+ LINEBEARERMODE_SPEECH | \
+ LINEBEARERMODE_MULTIUSE | \
+ LINEBEARERMODE_DATA | \
+ LINEBEARERMODE_ALTSPEECHDATA | \
+ LINEBEARERMODE_NONCALLSIGNALING)
+
+#define AllBearerModes1_4 \
+ (AllBearerModes1_0 | \
+ LINEBEARERMODE_PASSTHROUGH)
+
+#define AllBearerModes2_0 \
+ (AllBearerModes1_4 | \
+ LINEBEARERMODE_RESTRICTEDDATA)
+
+#define AllCallFeatures1_0 \
+ (LINECALLFEATURE_ACCEPT | \
+ LINECALLFEATURE_ADDTOCONF | \
+ LINECALLFEATURE_ANSWER | \
+ LINECALLFEATURE_BLINDTRANSFER | \
+ LINECALLFEATURE_COMPLETECALL | \
+ LINECALLFEATURE_COMPLETETRANSF | \
+ LINECALLFEATURE_DIAL | \
+ LINECALLFEATURE_DROP | \
+ LINECALLFEATURE_GATHERDIGITS | \
+ LINECALLFEATURE_GENERATEDIGITS | \
+ LINECALLFEATURE_GENERATETONE | \
+ LINECALLFEATURE_HOLD | \
+ LINECALLFEATURE_MONITORDIGITS | \
+ LINECALLFEATURE_MONITORMEDIA | \
+ LINECALLFEATURE_MONITORTONES | \
+ LINECALLFEATURE_PARK | \
+ LINECALLFEATURE_PREPAREADDCONF | \
+ LINECALLFEATURE_REDIRECT | \
+ LINECALLFEATURE_REMOVEFROMCONF | \
+ LINECALLFEATURE_SECURECALL | \
+ LINECALLFEATURE_SENDUSERUSER | \
+ LINECALLFEATURE_SETCALLPARAMS | \
+ LINECALLFEATURE_SETMEDIACONTROL | \
+ LINECALLFEATURE_SETTERMINAL | \
+ LINECALLFEATURE_SETUPCONF | \
+ LINECALLFEATURE_SETUPTRANSFER | \
+ LINECALLFEATURE_SWAPHOLD | \
+ LINECALLFEATURE_UNHOLD)
+
+#define AllCallFeatures1_4 \
+ (AllCallFeatures1_0 | \
+ LINECALLFEATURE_RELEASEUSERUSERINFO)
+
+#define AllCallFeatures2_0 \
+ (AllCallFeatures1_4 | \
+ LINECALLFEATURE_SETTREATMENT | \
+ LINECALLFEATURE_SETQOS | \
+ LINECALLFEATURE_SETCALLDATA)
+
+#define AllCallFeaturesTwo \
+ (LINECALLFEATURE2_NOHOLDCONFERENCE | \
+ LINECALLFEATURE2_ONESTEPTRANSFER | \
+ LINECALLFEATURE2_COMPLCAMPON | \
+ LINECALLFEATURE2_COMPLCALLBACK | \
+ LINECALLFEATURE2_COMPLINTRUDE | \
+ LINECALLFEATURE2_COMPLMESSAGE | \
+ LINECALLFEATURE2_TRANSFERNORM | \
+ LINECALLFEATURE2_TRANSFERCONF | \
+ LINECALLFEATURE2_PARKDIRECT | \
+ LINECALLFEATURE2_PARKNONDIRECT)
+
+#define AllLineFeatures1_0 \
+ (LINEFEATURE_DEVSPECIFIC | \
+ LINEFEATURE_DEVSPECIFICFEAT | \
+ LINEFEATURE_FORWARD | \
+ LINEFEATURE_MAKECALL | \
+ LINEFEATURE_SETMEDIACONTROL | \
+ LINEFEATURE_SETTERMINAL)
+
+#define AllLineFeatures2_0 \
+ (AllLineFeatures1_0 | \
+ LINEFEATURE_SETDEVSTATUS | \
+ LINEFEATURE_FORWARDFWD | \
+ LINEFEATURE_FORWARDDND)
+
+#define AllMediaModes1_0 \
+ (LINEMEDIAMODE_UNKNOWN | \
+ LINEMEDIAMODE_INTERACTIVEVOICE | \
+ LINEMEDIAMODE_AUTOMATEDVOICE | \
+ LINEMEDIAMODE_DATAMODEM | \
+ LINEMEDIAMODE_G3FAX | \
+ LINEMEDIAMODE_TDD | \
+ LINEMEDIAMODE_G4FAX | \
+ LINEMEDIAMODE_DIGITALDATA | \
+ LINEMEDIAMODE_TELETEX | \
+ LINEMEDIAMODE_VIDEOTEX | \
+ LINEMEDIAMODE_TELEX | \
+ LINEMEDIAMODE_MIXED | \
+ LINEMEDIAMODE_ADSI)
+
+#define AllMediaModes1_4 \
+ (AllMediaModes1_0 | \
+ LINEMEDIAMODE_VOICEVIEW)
+
+#define AllHookSwitchDevs \
+ (PHONEHOOKSWITCHDEV_HANDSET | \
+ PHONEHOOKSWITCHDEV_SPEAKER | \
+ PHONEHOOKSWITCHDEV_HEADSET)
+
+#define AllHookSwitchModes \
+ (PHONEHOOKSWITCHMODE_ONHOOK | \
+ PHONEHOOKSWITCHMODE_MIC | \
+ PHONEHOOKSWITCHMODE_SPEAKER | \
+ PHONEHOOKSWITCHMODE_MICSPEAKER | \
+ PHONEHOOKSWITCHMODE_UNKNOWN)
+
+#define AllPhoneFeatures \
+ (PHONEFEATURE_GETBUTTONINFO | \
+ PHONEFEATURE_GETDATA | \
+ PHONEFEATURE_GETDISPLAY | \
+ PHONEFEATURE_GETGAINHANDSET | \
+ PHONEFEATURE_GETGAINSPEAKER | \
+ PHONEFEATURE_GETGAINHEADSET | \
+ PHONEFEATURE_GETHOOKSWITCHHANDSET | \
+ PHONEFEATURE_GETHOOKSWITCHSPEAKER | \
+ PHONEFEATURE_GETHOOKSWITCHHEADSET | \
+ PHONEFEATURE_GETLAMP | \
+ PHONEFEATURE_GETRING | \
+ PHONEFEATURE_GETVOLUMEHANDSET | \
+ PHONEFEATURE_GETVOLUMESPEAKER | \
+ PHONEFEATURE_GETVOLUMEHEADSET | \
+ PHONEFEATURE_SETBUTTONINFO | \
+ PHONEFEATURE_SETDATA | \
+ PHONEFEATURE_SETDISPLAY | \
+ PHONEFEATURE_SETGAINHANDSET | \
+ PHONEFEATURE_SETGAINSPEAKER | \
+ PHONEFEATURE_SETGAINHEADSET | \
+ PHONEFEATURE_SETHOOKSWITCHHANDSET | \
+ PHONEFEATURE_SETHOOKSWITCHSPEAKER | \
+ PHONEFEATURE_SETHOOKSWITCHHEADSET | \
+ PHONEFEATURE_SETLAMP | \
+ PHONEFEATURE_SETRING | \
+ PHONEFEATURE_SETVOLUMEHANDSET | \
+ PHONEFEATURE_SETVOLUMESPEAKER | \
+ PHONEFEATURE_SETVOLUMEHEADSET)
+
+typedef struct _DRVCALL
+{
+ DWORD dwKey;
+ LPVOID pLine;
+ HTAPICALL htCall;
+ DWORD dwAddressID;
+
+ DWORD dwMediaMode;
+ DWORD dwBearerMode;
+ DWORD dwMinRate;
+ DWORD dwMaxRate;
+
+ LINEDIALPARAMS DialParams;
+
+ DWORD dwTreatment;
+ DWORD dwCallState;
+ DWORD dwCallStateMode;
+ DWORD dwAppSpecific;
+
+ DWORD dwSendingFlowspecSize;
+ LPVOID pSendingFlowspec;
+ DWORD dwReceivingFlowspecSize;
+ LPVOID pReceivingFlowspec;
+
+ DWORD dwCallDataSize;
+ LPVOID pCallData;
+ struct _DRVCALL *pPrev;
+ struct _DRVCALL *pNext;
+
+ struct _DRVCALL *pConfParent;
+ struct _DRVCALL *pNextConfChild;
+ struct _DRVCALL *pDestCall;
+ DWORD bConnectedToDestCall;
+
+ DWORD dwCallInstance;
+ DWORD dwGatherDigitsEndToEndID;
+ DWORD dwGenerateDigitsEndToEndID;
+ DWORD dwGenerateToneEndToEndID;
+
+ DWORD dwMonitorToneListID;
+ DWORD dwCallID;
+
+} DRVCALL, *PDRVCALL;
+
+
+typedef struct _DRVADDRESS
+{
+ DWORD dwNumCalls;
+ PDRVCALL pCalls;
+
+} DRVADDRESS, *PDRVADDRESS;
+
+
+typedef struct _DRVLINE
+{
+ DWORD dwDeviceID;
+ HTAPILINE htLine;
+ DWORD dwMediaModes;
+ PDRVADDRESS aAddrs;
+
+} DRVLINE, *PDRVLINE;
+
+
+typedef struct _DRVLINETABLE
+{
+ DWORD dwNumTotalEntries;
+ DWORD dwNumUsedEntries;
+ struct _DRVLINETABLE *pNext;
+ DRVLINE aLines[1];
+
+} DRVLINETABLE, *PDRVLINETABLE;
+
+
+typedef struct _DRVPHONE
+{
+ DWORD dwDeviceID;
+ HTAPIPHONE htPhone;
+ DWORD dwHandsetGain;
+ DWORD dwSpeakerGain;
+
+ DWORD dwHeadsetGain;
+ DWORD dwHandsetHookSwitchMode;
+ DWORD dwSpeakerHookSwitchMode;
+ DWORD dwHeadsetHookSwitchMode;
+
+ DWORD dwHandsetVolume;
+ DWORD dwSpeakerVolume;
+ DWORD dwHeadsetVolume;
+ DWORD dwRingMode;
+
+ DWORD dwRingVolume;
+ DWORD dwLampMode;
+ DWORD dwDataSize;
+ LPVOID pData;
+
+ LPPHONEBUTTONINFO pButtonInfo;
+ WCHAR *pDisplay;
+
+} DRVPHONE, *PDRVPHONE;
+
+
+typedef struct _DRVPHONETABLE
+{
+ DWORD dwNumTotalEntries;
+ DWORD dwNumUsedEntries;
+ struct _DRVPHONETABLE *pNext;
+ DRVPHONE aPhones[1];
+
+} DRVPHONETABLE, *PDRVPHONETABLE;
+
+
+typedef struct _ESPGLOBALS
+{
+ DWORD dwDebugOptions;
+ DWORD dwCompletionMode;
+ DWORD dwNumLines;
+ DWORD dwNumAddressesPerLine;
+
+ DWORD dwNumCallsPerAddress;
+ DWORD dwNumPhones;
+ DWORD dwSPIVersion;
+ CRITICAL_SECTION CallListCritSec;
+
+ CRITICAL_SECTION PhoneCritSec;
+ HICON hIconLine;
+ HICON hIconPhone;
+ LINEEVENT pfnLineEvent;
+
+ PHONEEVENT pfnPhoneEvent;
+ ASYNC_COMPLETION pfnCompletion;
+ HPROVIDER hProvider;
+ DWORD dwPermanentProviderID;
+
+ DWORD dwLineDeviceIDBase;
+ DWORD dwPhoneDeviceIDBase;
+ DWORD dwInitialNumLines;
+ DWORD dwInitialNumPhones;
+
+ PDRVLINETABLE pLines;
+ PDRVPHONETABLE pPhones;
+ BOOL bProviderShutdown;
+ HANDLE hAsyncEventQueueServiceThread;
+
+ HANDLE hAsyncEventsPendingEvent;
+ CRITICAL_SECTION AsyncEventQueueCritSec;
+ DWORD dwNumTotalQueueEntries;
+ DWORD dwNumUsedQueueEntries;
+
+ DWORD *pAsyncRequestQueue;
+ DWORD *pAsyncRequestQueueIn;
+ DWORD *pAsyncRequestQueueOut;
+ CRITICAL_SECTION DebugBufferCritSec;
+
+ DWORD dwDebugBufferTotalSize;
+ DWORD dwDebugBufferUsedSize;
+ char *pDebugBuffer;
+ char *pDebugBufferIn;
+
+ char *pDebugBufferOut;
+ CRITICAL_SECTION EventBufferCritSec;
+ DWORD dwEventBufferTotalSize;
+ DWORD dwEventBufferUsedSize;
+
+ char *pEventBuffer;
+ char *pEventBufferIn;
+ char *pEventBufferOut;
+
+} ESPGLOBALS, *PESPGLOBALS;
+
+
+typedef struct _LOOKUP
+{
+ DWORD dwVal;
+ char *lpszVal;
+
+} LOOKUP, *PLOOKUP;
+
+
+typedef struct _ASYNC_REQUEST_INFO
+{
+ FARPROC pfnPostProcessProc;
+ DWORD dwRequestID;
+ LONG lResult;
+ DWORD dwParam1;
+
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+ DWORD dwParam5;
+
+ DWORD dwParam6;
+ DWORD dwParam7;
+ DWORD dwParam8;
+ char *pszFuncName;
+
+} ASYNC_REQUEST_INFO, far *PASYNC_REQUEST_INFO;
+
+
+typedef void (FAR PASCAL *POSTPROCESSPROC)(PASYNC_REQUEST_INFO, BOOL);
+
+
+typedef struct _FUNC_PARAM
+{
+ char *lpszVal;
+ DWORD dwVal;
+ PLOOKUP pLookup;
+
+} FUNC_PARAM, *PFUNC_PARAM;
+
+
+typedef struct _FUNC_INFO
+{
+ char *pszFuncName;
+ DWORD bAsync;
+ DWORD dwNumParams;
+ PFUNC_PARAM aParams;
+
+ POSTPROCESSPROC pfnPostProcessProc;
+ PASYNC_REQUEST_INFO pAsyncReqInfo;
+ LONG lResult;
+
+} FUNC_INFO, *PFUNC_INFO;
+
+typedef struct _EVENT_PARAM
+{
+ char far *szName;
+
+ DWORD dwType;
+
+ DWORD dwValue;
+
+ union
+ {
+ PLOOKUP pLookup;
+
+ char far *buf;
+
+ LPVOID ptr;
+
+ DWORD dwDefValue;
+
+ };
+
+} EVENT_PARAM, far *PEVENT_PARAM;
+
+
+typedef struct _EVENT_PARAM_HEADER
+{
+ DWORD dwNumParams;
+
+ LPSTR pszDlgTitle;
+
+ DWORD dwEventType;
+
+ PEVENT_PARAM aParams;
+
+} EVENT_PARAM_HEADER, far *PEVENT_PARAM_HEADER;
+
+
+
+
+#if DBG
+
+#define DBGOUT(arg) DbgPrt arg
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+DWORD gdwDebugLevel;
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
+
+BOOL
+Prolog(
+ PFUNC_INFO pInfo
+ );
+
+LONG
+Epilog(
+ PFUNC_INFO pInfo
+ );
+
+void
+PASCAL
+DoCompletion(
+ PASYNC_REQUEST_INFO pAsyncRequestInfo,
+ BOOL bAsync
+ );
+
+LONG
+PASCAL
+SetCallState(
+ PDRVCALL pCall,
+ DWORD dwExpectedCallInstance,
+ DWORD dwValidCurrentStates,
+ DWORD dwNewCallState,
+ DWORD dwNewCallStateMode,
+ BOOL bSendStateMsgToExe
+ );
+
+void
+PASCAL
+WriteEventBuffer(
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6
+ );
+
+LPVOID
+DrvAlloc(
+ size_t numBytes
+ );
+
+void
+DrvFree(
+ LPVOID p
+ );
+
+LONG
+PASCAL
+AllocCall(
+ PDRVLINE pLine,
+ HTAPICALL htCall,
+ LPLINECALLPARAMS pCallParams,
+ PDRVCALL *ppCall
+ );
+
+void
+PASCAL
+FreeCall(
+ PDRVCALL pCall,
+ DWORD dwExpectedCallInstance
+ );
+
+PDRVLINE
+PASCAL
+GetLineFromID(
+ DWORD dwDeviceID
+ );
+
+PDRVPHONE
+PASCAL
+GetPhoneFromID(
+ DWORD dwDeviceID
+ );
+
+BOOL
+WINAPI
+_CRT_INIT(
+ HINSTANCE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ );
+
+VOID
+ShowStr(
+ BOOL bAlertApp,
+ char *format,
+ ...
+ );
+
+void
+PASCAL
+SendLineEvent(
+ PDRVLINE pLine,
+ PDRVCALL pCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ );
+
+void
+PASCAL
+SendPhoneEvent(
+ PDRVPHONE pPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ );
diff --git a/private/tapi/dev/sp/esp.new/tsp/esp.rc b/private/tapi/dev/sp/esp.new/tsp/esp.rc
new file mode 100644
index 000000000..4c0a4be90
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/esp.rc
@@ -0,0 +1,38 @@
+#include "windows.h"
+#include "esp.h"
+
+LINE_ICON ICON DISCARDABLE "PHONE.ICO"
+PHONE_ICON ICON DISCARDABLE "LINE.ICO"
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 205, 192
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Parameters:",55,4,6,42,7
+ LISTBOX IDC_LIST1,4,16,100,148,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Value:",56,116,6,30,7
+ COMBOBOX IDC_COMBO1,116,16,80,47,CBS_SIMPLE | CBS_AUTOHSCROLL |
+ CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Options:",57,116,66,40,9
+ LISTBOX IDC_LIST2,116,75,80,89,LBS_MULTIPLESEL |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",IDOK,116,171,36,14
+ PUSHBUTTON "Cancel",IDCANCEL,160,171,37,14
+END
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Economical Service Provider"
+#define VER_INTERNALNAME_STR "esp"
+#define VER_ORIGINALFILENAME_STR "ESP32.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/esp.new/tsp/esp32.def b/private/tapi/dev/sp/esp.new/tsp/esp32.def
new file mode 100644
index 000000000..e99da9648
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/esp32.def
@@ -0,0 +1,113 @@
+LIBRARY ESP32
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept
+ TSPI_lineAddToConference
+ TSPI_lineAnswer
+ TSPI_lineBlindTransfer
+ TSPI_lineClose
+ TSPI_lineCloseCall
+ TSPI_lineCompleteCall
+ TSPI_lineCompleteTransfer
+ TSPI_lineConditionalMediaDetection
+ TSPI_lineDevSpecific
+ TSPI_lineDevSpecificFeature
+ TSPI_lineDial
+ TSPI_lineDrop
+ TSPI_lineForward
+ TSPI_lineGatherDigits
+ TSPI_lineGenerateDigits
+ TSPI_lineGenerateTone
+ TSPI_lineGetAddressCaps
+ TSPI_lineGetAddressID
+ TSPI_lineGetAddressStatus
+ TSPI_lineGetCallAddressID
+ TSPI_lineGetCallInfo
+ TSPI_lineGetCallStatus
+ TSPI_lineGetDevCaps
+ TSPI_lineGetDevConfig
+ TSPI_lineGetExtensionID
+ TSPI_lineGetIcon
+ TSPI_lineGetID
+ TSPI_lineGetLineDevStatus
+ TSPI_lineGetNumAddressIDs
+ TSPI_lineHold
+ TSPI_lineMakeCall
+ TSPI_lineMonitorDigits
+ TSPI_lineMonitorMedia
+ TSPI_lineMonitorTones
+ TSPI_lineNegotiateExtVersion
+ TSPI_lineNegotiateTSPIVersion
+ TSPI_lineOpen
+ TSPI_linePark
+ TSPI_linePickup
+ TSPI_linePrepareAddToConference
+ TSPI_lineRedirect
+ TSPI_lineReleaseUserUserInfo
+ TSPI_lineRemoveFromConference
+ TSPI_lineSecureCall
+ TSPI_lineSelectExtVersion
+ TSPI_lineSendUserUserInfo
+ TSPI_lineSetAppSpecific
+ TSPI_lineSetCallData
+ TSPI_lineSetCallParams
+ TSPI_lineSetCallQualityOfService
+ TSPI_lineSetCallTreatment
+ TSPI_lineSetCurrentLocation
+ TSPI_lineSetDefaultMediaDetection
+ TSPI_lineSetDevConfig
+ TSPI_lineSetLineDevStatus
+ TSPI_lineSetMediaControl
+ TSPI_lineSetMediaMode
+ TSPI_lineSetStatusMessages
+ TSPI_lineSetTerminal
+ TSPI_lineSetupConference
+ TSPI_lineSetupTransfer
+ TSPI_lineSwapHold
+ TSPI_lineUncompleteCall
+ TSPI_lineUnhold
+ TSPI_lineUnpark
+ TSPI_phoneClose
+ TSPI_phoneDevSpecific
+ TSPI_phoneGetButtonInfo
+ TSPI_phoneGetData
+ TSPI_phoneGetDevCaps
+ TSPI_phoneGetDisplay
+ TSPI_phoneGetExtensionID
+ TSPI_phoneGetGain
+ TSPI_phoneGetHookSwitch
+ TSPI_phoneGetIcon
+ TSPI_phoneGetID
+ TSPI_phoneGetLamp
+ TSPI_phoneGetRing
+ TSPI_phoneGetStatus
+ TSPI_phoneGetVolume
+ TSPI_phoneNegotiateExtVersion
+ TSPI_phoneNegotiateTSPIVersion
+ TSPI_phoneOpen
+ TSPI_phoneSelectExtVersion
+ TSPI_phoneSetButtonInfo
+ TSPI_phoneSetData
+ TSPI_phoneSetDisplay
+ TSPI_phoneSetGain
+ TSPI_phoneSetHookSwitch
+ TSPI_phoneSetLamp
+ TSPI_phoneSetRing
+ TSPI_phoneSetStatusMessages
+ TSPI_phoneSetVolume
+ TSPI_providerConfig
+ TSPI_providerCreateLineDevice
+ TSPI_providerCreatePhoneDevice
+ TSPI_providerEnumDevices
+ TSPI_providerFreeDialogInstance
+ TSPI_providerGenericDialogData
+ TSPI_providerInit
+ TSPI_providerInstall
+ TSPI_providerRemove
+ TSPI_providerShutdown
+ TSPI_providerUIIdentify
+
+ ValuesDlgProc
diff --git a/private/tapi/dev/sp/esp.new/tsp/intrface.h b/private/tapi/dev/sp/esp.new/tsp/intrface.h
new file mode 100644
index 000000000..041131a33
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/intrface.h
@@ -0,0 +1,67 @@
+#define SHOW_FUNC_ENTRY 0x00000001
+#define SHOW_PARAMETERS 0x00000002
+#define SHOW_FUNC_EXIT 0x00000004
+#define SHOW_EVENT_NOTIFICATIONS 0x00000008
+#define SHOW_COMPLETION_NOTIFICATIONS 0x00000010
+#define MANUAL_RESULTS 0x00000020
+
+#define DEF_DEBUG_OPTIONS SHOW_FUNC_ENTRY
+
+#define COMPLETE_ASYNC_EVENTS_SYNCHRONOUSLY 0L
+#define COMPLETE_ASYNC_EVENTS_ASYNCHRONOUSLY 1L
+#define COMPLETE_ASYNC_EVENTS_SYNC_AND_ASYNC 2L
+#define COMPLETE_ASYNC_EVENTS_MANUALLY 3L
+
+#define DEF_COMPLETION_MODE 2L
+
+#define DEF_NUM_LINES 3
+#define DEF_NUM_ADDRS_PER_LINE 2
+#define DEF_NUM_CALLS_PER_ADDR 1
+#define DEF_NUM_PHONES 2
+#define DEF_SPI_VERSION 0x20000
+
+#define WIDGETTYPE_LINE 0L
+#define WIDGETTYPE_CALL 1L
+#define WIDGETTYPE_PHONE 2L
+#define WIDGETTYPE_ASYNCREQUEST 3L
+#define WIDGETTYPE_STARTUP 4L
+
+typedef struct _WIDGETEVENT
+{
+ DWORD dwWidgetID;
+
+ DWORD dwWidgetType; // WIDGETYPE_*
+
+ union
+ {
+ DWORD hdXxx; // hdXxx (NULL for AsyncReq)
+
+ DWORD dwNumLines;
+
+ DWORD pAsyncReqInfo;
+ };
+
+ union
+ {
+ DWORD htXxx; // htXxx (NULL for AsyncReq)
+
+ DWORD dwNumPhones;
+ };
+
+ union
+ {
+ DWORD dwCallState;
+
+ DWORD dwRequestType; // func ord for lookup
+
+ DWORD dwLineDeviceIDBase;
+ };
+
+ union
+ {
+ DWORD dwCallAddressID;
+
+ DWORD dwPhoneDeviceIDBase;
+ };
+
+} WIDGETEVENT, *PWIDGETEVENT;
diff --git a/private/tapi/dev/sp/esp.new/tsp/line.ico b/private/tapi/dev/sp/esp.new/tsp/line.ico
new file mode 100644
index 000000000..6c2186e09
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/line.ico
Binary files differ
diff --git a/private/tapi/dev/sp/esp.new/tsp/makefile b/private/tapi/dev/sp/esp.new/tsp/makefile
new file mode 100644
index 000000000..23524cb99
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/makefile
@@ -0,0 +1,11 @@
+!ifndef NTMAKEENV
+NTMAKEENV=.
+!endif
+
+
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/tapi/dev/sp/esp.new/tsp/phone.ico b/private/tapi/dev/sp/esp.new/tsp/phone.ico
new file mode 100644
index 000000000..ee34203e3
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/phone.ico
Binary files differ
diff --git a/private/tapi/dev/sp/esp.new/tsp/sources b/private/tapi/dev/sp/esp.new/tsp/sources
new file mode 100644
index 000000000..409908852
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/sources
@@ -0,0 +1,60 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=esp32
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=tsp
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib
+
+C_DEFINES=-DTAPI_NT=1
+
+DLLBASE=0x60000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+USE_CRTDLL=1
+
+SOURCES=esp.c \
+ espidl_s.c \
+ vars.c \
+ esp.rc
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/esp.new/tsp/vars.c b/private/tapi/dev/sp/esp.new/tsp/vars.c
new file mode 100644
index 000000000..337a1dd7d
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/vars.c
@@ -0,0 +1,445 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ vars.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 18-Sep-1995
+
+Revision History:
+
+
+Notes:
+
+--*/
+
+
+#include "esp.h"
+
+
+char szTab[] = " ";
+char szhdLine[] = "hdLine";
+char szhdCall[] = "hdCall";
+char szdwSize[] = "dwSize";
+char szCallUp[] = "^^^^";
+char szEspTsp[] = "esp.tsp";
+char szhdPhone[] = "hdPhone";
+char szProvider[] = "Provider";
+WCHAR szESPUIDLL[] = L"espui.dll";
+char szhwndOwner[] = "hwndOwner";
+char szMySection[] = "ESP32";
+char szProviders[] = "Providers";
+char szProviderID[] = "ProviderID";
+char szdwDeviceID[] = "dwDeviceID";
+char szdwRequestID[] = "dwRequestID";
+char szTelephonIni[] = "telephon.ini";
+char szlpCallParams[] = "lpCallParams";
+char szNumProviders[] = "NumProviders";
+char szNextProviderID[] = "NextProviderID";
+char szProviderFilename[] = "ProviderFileName";
+char szdwPermanentProviderID[] = "dwPermanentProviderID";
+
+#if DBG
+DWORD gdwDebugLevel;
+#endif
+
+HANDLE ghInstance;
+HANDLE ghDebugOutputEvent;
+HANDLE ghShutdownEvent;
+HANDLE ghWidgetEventsEvent;
+
+ESPGLOBALS gESPGlobals;
+
+LOOKUP aAddressStates[] =
+{
+ { LINEADDRESSSTATE_OTHER ,"OTHER" },
+ { LINEADDRESSSTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINEADDRESSSTATE_INUSEZERO ,"INUSEZERO" },
+ { LINEADDRESSSTATE_INUSEONE ,"INUSEONE" },
+ { LINEADDRESSSTATE_INUSEMANY ,"INUSEMANY" },
+ { LINEADDRESSSTATE_NUMCALLS ,"NUMCALLS" },
+ { LINEADDRESSSTATE_FORWARD ,"FORWARD" },
+ { LINEADDRESSSTATE_TERMINALS ,"TERMINALS" },
+ { LINEADDRESSSTATE_CAPSCHANGE ,"CAPSCHANGE" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aBearerModes[] =
+{
+ { LINEBEARERMODE_VOICE ,"VOICE" },
+ { LINEBEARERMODE_SPEECH ,"SPEECH" },
+ { LINEBEARERMODE_MULTIUSE ,"MULTIUSE" },
+ { LINEBEARERMODE_DATA ,"DATA" },
+ { LINEBEARERMODE_ALTSPEECHDATA ,"ALTSPEECHDATA" },
+ { LINEBEARERMODE_NONCALLSIGNALING ,"NONCALLSIGNALING" },
+ { LINEBEARERMODE_PASSTHROUGH ,"PASSTHROUGH" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aButtonModes[] =
+{
+ { PHONEBUTTONMODE_DUMMY ,"DUMMY" },
+ { PHONEBUTTONMODE_CALL ,"CALL" },
+ { PHONEBUTTONMODE_FEATURE ,"FEATURE" },
+ { PHONEBUTTONMODE_KEYPAD ,"KEYPAD" },
+ { PHONEBUTTONMODE_LOCAL ,"LOCAL" },
+ { PHONEBUTTONMODE_DISPLAY ,"DISPLAY" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aButtonStates[] =
+{
+ { PHONEBUTTONSTATE_UP ,"UP" },
+ { PHONEBUTTONSTATE_DOWN ,"DOWN" },
+ { PHONEBUTTONSTATE_UNKNOWN ,"UNKNOWN" },
+ { PHONEBUTTONSTATE_UNAVAIL ,"UNAVAIL" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aCallInfoStates[] =
+{
+ { LINECALLINFOSTATE_OTHER ,"OTHER" },
+ { LINECALLINFOSTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINECALLINFOSTATE_BEARERMODE ,"BEARERMODE" },
+ { LINECALLINFOSTATE_RATE ,"RATE" },
+ { LINECALLINFOSTATE_MEDIAMODE ,"MEDIAMODE" },
+ { LINECALLINFOSTATE_APPSPECIFIC ,"APPSPECIFIC" },
+ { LINECALLINFOSTATE_CALLID ,"CALLID" },
+ { LINECALLINFOSTATE_RELATEDCALLID ,"RELATEDCALLID" },
+ { LINECALLINFOSTATE_ORIGIN ,"ORIGIN" },
+ { LINECALLINFOSTATE_REASON ,"REASON" },
+ { LINECALLINFOSTATE_COMPLETIONID ,"COMPLETIONID" },
+ { LINECALLINFOSTATE_NUMOWNERINCR ,"NUMOWNERINCR" },
+ { LINECALLINFOSTATE_NUMOWNERDECR ,"NUMOWNERDECR" },
+ { LINECALLINFOSTATE_NUMMONITORS ,"NUMMONITORS" },
+ { LINECALLINFOSTATE_TRUNK ,"TRUNK" },
+ { LINECALLINFOSTATE_CALLERID ,"CALLERID" },
+ { LINECALLINFOSTATE_CALLEDID ,"CALLEDID" },
+ { LINECALLINFOSTATE_CONNECTEDID ,"CONNECTEDID" },
+ { LINECALLINFOSTATE_REDIRECTIONID ,"REDIRECTIONID" },
+ { LINECALLINFOSTATE_REDIRECTINGID ,"REDIRECTINGID" },
+ { LINECALLINFOSTATE_DISPLAY ,"DISPLAY" },
+ { LINECALLINFOSTATE_USERUSERINFO ,"USERUSERINFO" },
+ { LINECALLINFOSTATE_HIGHLEVELCOMP ,"HIGHLEVELCOMP" },
+ { LINECALLINFOSTATE_LOWLEVELCOMP ,"LOWLEVELCOMP" },
+ { LINECALLINFOSTATE_CHARGINGINFO ,"CHARGINGINFO" },
+ { LINECALLINFOSTATE_TERMINAL ,"TERMINAL" },
+ { LINECALLINFOSTATE_DIALPARAMS ,"DIALPARAMS" },
+ { LINECALLINFOSTATE_MONITORMODES ,"MONITORMODES" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aCallSelects[] =
+{
+ { LINECALLSELECT_LINE ,"LINE" },
+ { LINECALLSELECT_ADDRESS ,"ADDRESS" },
+ { LINECALLSELECT_CALL ,"CALL" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aCallStates[] =
+{
+ { LINECALLSTATE_IDLE ,"IDLE" },
+ { LINECALLSTATE_OFFERING ,"OFFERING" },
+ { LINECALLSTATE_ACCEPTED ,"ACCEPTED" },
+ { LINECALLSTATE_DIALTONE ,"DIALTONE" },
+ { LINECALLSTATE_DIALING ,"DIALING" },
+ { LINECALLSTATE_RINGBACK ,"RINGBACK" },
+ { LINECALLSTATE_BUSY ,"BUSY" },
+ { LINECALLSTATE_SPECIALINFO ,"SPECIALINFO" },
+ { LINECALLSTATE_CONNECTED ,"CONNECTED" },
+ { LINECALLSTATE_PROCEEDING ,"PROCEEDING" },
+ { LINECALLSTATE_ONHOLD ,"ONHOLD" },
+ { LINECALLSTATE_CONFERENCED ,"CONFERENCED" },
+ { LINECALLSTATE_ONHOLDPENDCONF ,"ONHOLDPENDCONF" },
+ { LINECALLSTATE_ONHOLDPENDTRANSFER ,"ONHOLDPENDTRANSFER" },
+ { LINECALLSTATE_DISCONNECTED ,"DISCONNECTED" },
+ { LINECALLSTATE_UNKNOWN ,"UNKNOWN" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aDigitModes[] =
+{
+ { LINEDIGITMODE_PULSE ,"PULSE" },
+ { LINEDIGITMODE_DTMF ,"DTMF" },
+ { LINEDIGITMODE_DTMFEND ,"DTMFEND" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aHookSwitchDevs[] =
+{
+ { PHONEHOOKSWITCHDEV_HANDSET ,"HANDSET" },
+ { PHONEHOOKSWITCHDEV_SPEAKER ,"SPEAKER" },
+ { PHONEHOOKSWITCHDEV_HEADSET ,"HEADSET" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aHookSwitchModes[] =
+{
+ { PHONEHOOKSWITCHMODE_ONHOOK ,"ONHOOK" },
+ { PHONEHOOKSWITCHMODE_MIC ,"MIC" },
+ { PHONEHOOKSWITCHMODE_SPEAKER ,"SPEAKER" },
+ { PHONEHOOKSWITCHMODE_MICSPEAKER ,"MICSPEAKER" },
+ { PHONEHOOKSWITCHMODE_UNKNOWN ,"UNKNOWN" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aLampModes[] =
+{
+ { PHONELAMPMODE_DUMMY ,"DUMMY" },
+ { PHONELAMPMODE_OFF ,"OFF" },
+ { PHONELAMPMODE_STEADY ,"STEADY" },
+ { PHONELAMPMODE_WINK ,"WINK" },
+ { PHONELAMPMODE_FLASH ,"FLASH" },
+ { PHONELAMPMODE_FLUTTER ,"FLUTTER" },
+ { PHONELAMPMODE_BROKENFLUTTER ,"BROKENFLUTTER" },
+ { PHONELAMPMODE_UNKNOWN ,"UNKNOWN" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aLineStates[] =
+{
+ { LINEDEVSTATE_OTHER ,"OTHER" },
+ { LINEDEVSTATE_RINGING ,"RINGING" },
+ { LINEDEVSTATE_CONNECTED ,"CONNECTED" },
+ { LINEDEVSTATE_DISCONNECTED ,"DISCONNECTED" },
+ { LINEDEVSTATE_MSGWAITON ,"MSGWAITON" },
+ { LINEDEVSTATE_MSGWAITOFF ,"MSGWAITOFF" },
+ { LINEDEVSTATE_INSERVICE ,"INSERVICE" },
+ { LINEDEVSTATE_OUTOFSERVICE ,"OUTOFSERVICE" },
+ { LINEDEVSTATE_MAINTENANCE ,"MAINTENANCE" },
+ { LINEDEVSTATE_OPEN ,"OPEN" },
+ { LINEDEVSTATE_CLOSE ,"CLOSE" },
+ { LINEDEVSTATE_NUMCALLS ,"NUMCALLS" },
+ { LINEDEVSTATE_NUMCOMPLETIONS ,"NUMCOMPLETIONS" },
+ { LINEDEVSTATE_TERMINALS ,"TERMINALS" },
+ { LINEDEVSTATE_ROAMMODE ,"ROAMMODE" },
+ { LINEDEVSTATE_BATTERY ,"BATTERY" },
+ { LINEDEVSTATE_SIGNAL ,"SIGNAL" },
+ { LINEDEVSTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINEDEVSTATE_REINIT ,"REINIT" },
+ { LINEDEVSTATE_LOCK ,"LOCK" },
+ { LINEDEVSTATE_CAPSCHANGE ,"CAPSCHANGE" },
+ { LINEDEVSTATE_CONFIGCHANGE ,"CONFIGCHANGE" },
+ { LINEDEVSTATE_TRANSLATECHANGE ,"TRANSLATECHANGE" },
+ { LINEDEVSTATE_COMPLCANCEL ,"COMPLCANCEL" },
+ { LINEDEVSTATE_REMOVED ,"REMOVED" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aMediaModes[] =
+{
+ { LINEMEDIAMODE_UNKNOWN ,"UNKNOWN" },
+ { LINEMEDIAMODE_INTERACTIVEVOICE ,"INTERACTIVEVOICE" },
+ { LINEMEDIAMODE_AUTOMATEDVOICE ,"AUTOMATEDVOICE" },
+ { LINEMEDIAMODE_DATAMODEM ,"DATAMODEM" },
+ { LINEMEDIAMODE_G3FAX ,"G3FAX" },
+ { LINEMEDIAMODE_TDD ,"TDD" },
+ { LINEMEDIAMODE_G4FAX ,"G4FAX" },
+ { LINEMEDIAMODE_DIGITALDATA ,"DIGITALDATA" },
+ { LINEMEDIAMODE_TELETEX ,"TELETEX" },
+ { LINEMEDIAMODE_VIDEOTEX ,"VIDEOTEX" },
+ { LINEMEDIAMODE_TELEX ,"TELEX" },
+ { LINEMEDIAMODE_MIXED ,"MIXED" },
+ { LINEMEDIAMODE_ADSI ,"ADSI" },
+ { LINEMEDIAMODE_VOICEVIEW ,"VOICEVIEW" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aPhoneStates[] =
+{
+ { PHONESTATE_OTHER ,"OTHER" },
+ { PHONESTATE_CONNECTED ,"CONNECTED" },
+ { PHONESTATE_DISCONNECTED ,"DISCONNECTED" },
+ { PHONESTATE_OWNER ,"OWNER" },
+ { PHONESTATE_MONITORS ,"MONITORS" },
+ { PHONESTATE_DISPLAY ,"DISPLAY" },
+ { PHONESTATE_LAMP ,"LAMP" },
+ { PHONESTATE_RINGMODE ,"RINGMODE" },
+ { PHONESTATE_RINGVOLUME ,"RINGVOLUME" },
+ { PHONESTATE_HANDSETHOOKSWITCH ,"HANDSETHOOKSWITCH" },
+ { PHONESTATE_HANDSETVOLUME ,"HANDSETVOLUME" },
+ { PHONESTATE_HANDSETGAIN ,"HANDSETGAIN" },
+ { PHONESTATE_SPEAKERHOOKSWITCH ,"SPEAKERHOOKSWITCH" },
+ { PHONESTATE_SPEAKERVOLUME ,"SPEAKERVOLUME" },
+ { PHONESTATE_SPEAKERGAIN ,"SPEAKERGAIN" },
+ { PHONESTATE_HEADSETHOOKSWITCH ,"HEADSETHOOKSWITCH" },
+ { PHONESTATE_HEADSETVOLUME ,"HEADSETVOLUME" },
+ { PHONESTATE_HEADSETGAIN ,"HEADSETGAIN" },
+ { PHONESTATE_SUSPEND ,"SUSPEND" },
+ { PHONESTATE_RESUME ,"RESUME" },
+ { PHONESTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { PHONESTATE_REINIT ,"REINIT" },
+ { PHONESTATE_CAPSCHANGE ,"CAPSCHANGE" },
+ { PHONESTATE_REMOVED ,"REMOVED" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aTerminalModes[] =
+{
+ { LINETERMMODE_BUTTONS ,"BUTTONS" },
+ { LINETERMMODE_LAMPS ,"LAMPS" },
+ { LINETERMMODE_DISPLAY ,"DISPLAY" },
+ { LINETERMMODE_RINGER ,"RINGER" },
+ { LINETERMMODE_HOOKSWITCH ,"HOOKSWITCH" },
+ { LINETERMMODE_MEDIATOLINE ,"MEDIATOLINE" },
+ { LINETERMMODE_MEDIAFROMLINE ,"MEDIAFROMLINE" },
+ { LINETERMMODE_MEDIABIDIRECT ,"MEDIABIDIRECT" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aToneModes[] =
+{
+ { LINETONEMODE_CUSTOM ,"CUSTOM" },
+ { LINETONEMODE_RINGBACK ,"RINGBACK" },
+ { LINETONEMODE_BUSY ,"BUSY" },
+ { LINETONEMODE_BEEP ,"BEEP" },
+ { LINETONEMODE_BILLING ,"BILLING" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aTransferModes[] =
+{
+ { LINETRANSFERMODE_TRANSFER ,"TRANSFER" },
+ { LINETRANSFERMODE_CONFERENCE ,"CONFERENCE" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP aLineErrs[] =
+{
+ { 0 ,"<SUCCESS>" },
+ { LINEERR_ALLOCATED ,"ALLOCATED" },
+ { LINEERR_BADDEVICEID ,"BADDEVICEID" },
+ { LINEERR_BEARERMODEUNAVAIL ,"BEARERMODEUNAVAIL" },
+ { LINEERR_CALLUNAVAIL ,"CALLUNAVAIL" },
+ { LINEERR_COMPLETIONOVERRUN ,"COMPLETIONOVERRUN" },
+ { LINEERR_CONFERENCEFULL ,"CONFERENCEFULL" },
+ { LINEERR_DIALBILLING ,"DIALBILLING" },
+ { LINEERR_DIALDIALTONE ,"DIALDIALTONE" },
+ { LINEERR_DIALPROMPT ,"DIALPROMPT" },
+ { LINEERR_DIALQUIET ,"DIALQUIET" },
+ { LINEERR_INCOMPATIBLEAPIVERSION ,"INCOMPATIBLEAPIVERSION" },
+ { LINEERR_INCOMPATIBLEEXTVERSION ,"INCOMPATIBLEEXTVERSION" },
+ { LINEERR_INIFILECORRUPT ,"INIFILECORRUPT" },
+ { LINEERR_INUSE ,"INUSE" },
+ { LINEERR_INVALADDRESS ,"INVALADDRESS" },
+ { LINEERR_INVALADDRESSID ,"INVALADDRESSID" },
+ { LINEERR_INVALADDRESSMODE ,"INVALADDRESSMODE" },
+ { LINEERR_INVALADDRESSSTATE ,"INVALADDRESSSTATE" },
+ { LINEERR_INVALAPPHANDLE ,"INVALAPPHANDLE" },
+ { LINEERR_INVALAPPNAME ,"INVALAPPNAME" },
+ { LINEERR_INVALBEARERMODE ,"INVALBEARERMODE" },
+ { LINEERR_INVALCALLCOMPLMODE ,"INVALCALLCOMPLMODE" },
+ { LINEERR_INVALCALLHANDLE ,"INVALCALLHANDLE" },
+ { LINEERR_INVALCALLPARAMS ,"INVALCALLPARAMS" },
+ { LINEERR_INVALCALLPRIVILEGE ,"INVALCALLPRIVILEGE" },
+ { LINEERR_INVALCALLSELECT ,"INVALCALLSELECT" },
+ { LINEERR_INVALCALLSTATE ,"INVALCALLSTATE" },
+ { LINEERR_INVALCALLSTATELIST ,"INVALCALLSTATELIST" },
+ { LINEERR_INVALCARD ,"INVALCARD" },
+ { LINEERR_INVALCOMPLETIONID ,"INVALCOMPLETIONID" },
+ { LINEERR_INVALCONFCALLHANDLE ,"INVALCONFCALLHANDLE" },
+ { LINEERR_INVALCONSULTCALLHANDLE ,"INVALCONSULTCALLHANDLE" },
+ { LINEERR_INVALCOUNTRYCODE ,"INVALCOUNTRYCODE" },
+ { LINEERR_INVALDEVICECLASS ,"INVALDEVICECLASS" },
+ { LINEERR_INVALDEVICEHANDLE ,"INVALDEVICEHANDLE" },
+ { LINEERR_INVALDIALPARAMS ,"INVALDIALPARAMS" },
+ { LINEERR_INVALDIGITLIST ,"INVALDIGITLIST" },
+ { LINEERR_INVALDIGITMODE ,"INVALDIGITMODE" },
+ { LINEERR_INVALDIGITS ,"INVALDIGITS" },
+ { LINEERR_INVALEXTVERSION ,"INVALEXTVERSION" },
+ { LINEERR_INVALGROUPID ,"INVALGROUPID" },
+ { LINEERR_INVALLINEHANDLE ,"INVALLINEHANDLE" },
+ { LINEERR_INVALLINESTATE ,"INVALLINESTATE" },
+ { LINEERR_INVALLOCATION ,"INVALLOCATION" },
+ { LINEERR_INVALMEDIALIST ,"INVALMEDIALIST" },
+ { LINEERR_INVALMEDIAMODE ,"INVALMEDIAMODE" },
+ { LINEERR_INVALMESSAGEID ,"INVALMESSAGEID" },
+ { LINEERR_INVALPARAM ,"INVALPARAM" },
+ { LINEERR_INVALPARKID ,"INVALPARKID" },
+ { LINEERR_INVALPARKMODE ,"INVALPARKMODE" },
+ { LINEERR_INVALPOINTER ,"INVALPOINTER" },
+ { LINEERR_INVALPRIVSELECT ,"INVALPRIVSELECT" },
+ { LINEERR_INVALRATE ,"INVALRATE" },
+ { LINEERR_INVALREQUESTMODE ,"INVALREQUESTMODE" },
+ { LINEERR_INVALTERMINALID ,"INVALTERMINALID" },
+ { LINEERR_INVALTERMINALMODE ,"INVALTERMINALMODE" },
+ { LINEERR_INVALTIMEOUT ,"INVALTIMEOUT" },
+ { LINEERR_INVALTONE ,"INVALTONE" },
+ { LINEERR_INVALTONELIST ,"INVALTONELIST" },
+ { LINEERR_INVALTONEMODE ,"INVALTONEMODE" },
+ { LINEERR_INVALTRANSFERMODE ,"INVALTRANSFERMODE" },
+ { LINEERR_LINEMAPPERFAILED ,"LINEMAPPERFAILED" },
+ { LINEERR_NOCONFERENCE ,"NOCONFERENCE" },
+ { LINEERR_NODEVICE ,"NODEVICE" },
+ { LINEERR_NODRIVER ,"NODRIVER" },
+ { LINEERR_NOMEM ,"NOMEM" },
+ { LINEERR_NOREQUEST ,"NOREQUEST" },
+ { LINEERR_NOTOWNER ,"NOTOWNER" },
+ { LINEERR_NOTREGISTERED ,"NOTREGISTERED" },
+ { LINEERR_OPERATIONFAILED ,"OPERATIONFAILED" },
+ { LINEERR_OPERATIONUNAVAIL ,"OPERATIONUNAVAIL" },
+ { LINEERR_RATEUNAVAIL ,"RATEUNAVAIL" },
+ { LINEERR_RESOURCEUNAVAIL ,"RESOURCEUNAVAIL" },
+ { LINEERR_REQUESTOVERRUN ,"REQUESTOVERRUN" },
+ { LINEERR_STRUCTURETOOSMALL ,"STRUCTURETOOSMALL" },
+ { LINEERR_TARGETNOTFOUND ,"TARGETNOTFOUND" },
+ { LINEERR_TARGETSELF ,"TARGETSELF" },
+ { LINEERR_UNINITIALIZED ,"UNINITIALIZED" },
+ { LINEERR_USERUSERINFOTOOBIG ,"USERUSERINFOTOOBIG" },
+ { LINEERR_REINIT ,"REINIT" },
+ { LINEERR_ADDRESSBLOCKED ,"ADDRESSBLOCKED" },
+ { LINEERR_BILLINGREJECTED ,"BILLINGREJECTED" },
+ { LINEERR_INVALFEATURE ,"INVALFEATURE" },
+ { LINEERR_NOMULTIPLEINSTANCE ,"NOMULTIPLEINSTANCE" },
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP aPhoneErrs[] =
+{
+ { 0 ,"<SUCCESS>" },
+ { PHONEERR_ALLOCATED ,"ALLOCATED" },
+ { PHONEERR_BADDEVICEID ,"BADDEVICEID" },
+ { PHONEERR_INCOMPATIBLEAPIVERSION ,"INCOMPATIBLEAPIVERSION" },
+ { PHONEERR_INCOMPATIBLEEXTVERSION ,"INCOMPATIBLEEXTVERSION" },
+ { PHONEERR_INIFILECORRUPT ,"INIFILECORRUPT" },
+ { PHONEERR_INUSE ,"INUSE" },
+ { PHONEERR_INVALAPPHANDLE ,"INVALAPPHANDLE" },
+ { PHONEERR_INVALAPPNAME ,"INVALAPPNAME" },
+ { PHONEERR_INVALBUTTONLAMPID ,"INVALBUTTONLAMPID" },
+ { PHONEERR_INVALBUTTONMODE ,"INVALBUTTONMODE" },
+ { PHONEERR_INVALBUTTONSTATE ,"INVALBUTTONSTATE" },
+ { PHONEERR_INVALDATAID ,"INVALDATAID" },
+ { PHONEERR_INVALDEVICECLASS ,"INVALDEVICECLASS" },
+ { PHONEERR_INVALEXTVERSION ,"INVALEXTVERSION" },
+ { PHONEERR_INVALHOOKSWITCHDEV ,"INVALHOOKSWITCHDEV" },
+ { PHONEERR_INVALHOOKSWITCHMODE ,"INVALHOOKSWITCHMODE" },
+ { PHONEERR_INVALLAMPMODE ,"INVALLAMPMODE" },
+ { PHONEERR_INVALPARAM ,"INVALPARAM" },
+ { PHONEERR_INVALPHONEHANDLE ,"INVALPHONEHANDLE" },
+ { PHONEERR_INVALPHONESTATE ,"INVALPHONESTATE" },
+ { PHONEERR_INVALPOINTER ,"INVALPOINTER" },
+ { PHONEERR_INVALPRIVILEGE ,"INVALPRIVILEGE" },
+ { PHONEERR_INVALRINGMODE ,"INVALRINGMODE" },
+ { PHONEERR_NODEVICE ,"NODEVICE" },
+ { PHONEERR_NODRIVER ,"NODRIVER" },
+ { PHONEERR_NOMEM ,"NOMEM" },
+ { PHONEERR_NOTOWNER ,"NOTOWNER" },
+ { PHONEERR_OPERATIONFAILED ,"OPERATIONFAILED" },
+ { PHONEERR_OPERATIONUNAVAIL ,"OPERATIONUNAVAIL" },
+ { PHONEERR_RESOURCEUNAVAIL ,"RESOURCEUNAVAIL" },
+ { PHONEERR_REQUESTOVERRUN ,"REQUESTOVERRUN" },
+ { PHONEERR_STRUCTURETOOSMALL ,"STRUCTURETOOSMALL" },
+ { PHONEERR_UNINITIALIZED ,"UNINITIALIZED" },
+ { PHONEERR_REINIT ,"REINIT" },
+ { 0xffffffff ,"" }
+};
diff --git a/private/tapi/dev/sp/esp.new/tsp/vars.h b/private/tapi/dev/sp/esp.new/tsp/vars.h
new file mode 100644
index 000000000..712d66c65
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/tsp/vars.h
@@ -0,0 +1,76 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ vars.h
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 18-Sep-1995
+
+Revision History:
+
+
+Notes:
+
+--*/
+
+
+extern char szTab[];
+extern char szdwSize[];
+extern char szhdLine[];
+extern char szCallUp[];
+extern char szEspTsp[];
+extern char szhdCall[];
+extern char szhdPhone[];
+extern char szProvider[];
+extern WCHAR szESPUIDLL[];
+extern char szhwndOwner[];
+extern char szMySection[];
+extern char szProviders[];
+extern char szdwDeviceID[];
+extern char szProviderID[];
+extern char szdwRequestID[];
+extern char szTelephonIni[];
+extern char szlpCallParams[];
+extern char szNumProviders[];
+extern char szNextProviderID[];
+extern char szProviderFilename[];
+extern char szdwPermanentProviderID[];
+
+#if DBG
+extern DWORD gdwDebugLevel;
+#endif
+
+extern HANDLE ghInstance;
+extern HANDLE ghDebugOutputEvent;
+extern HANDLE ghShutdownEvent;
+extern HANDLE ghWidgetEventsEvent;
+
+extern LOOKUP aAddressStates[];
+extern LOOKUP aBearerModes[];
+extern LOOKUP aButtonModes[];
+extern LOOKUP aButtonStates[];
+extern LOOKUP aCallInfoStates[];
+extern LOOKUP aCallSelects[];
+extern LOOKUP aCallStates[];
+extern LOOKUP aDigitModes[];
+extern LOOKUP aHookSwitchDevs[];
+extern LOOKUP aHookSwitchModes[];
+extern LOOKUP aLampModes[];
+extern LOOKUP aLineStates[];
+extern LOOKUP aMediaModes[];
+extern LOOKUP aPhoneStates[];
+extern LOOKUP aTerminalModes[];
+extern LOOKUP aToneModes[];
+extern LOOKUP aTransferModes[];
+extern LOOKUP aLineErrs[];
+extern LOOKUP aPhoneErrs[];
+
+extern ESPGLOBALS gESPGlobals;
diff --git a/private/tapi/dev/sp/esp.new/ui/espui.c b/private/tapi/dev/sp/esp.new/ui/espui.c
new file mode 100644
index 000000000..d223ef1bb
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/ui/espui.c
@@ -0,0 +1,788 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ espui.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 30-Sep-1995
+
+Revision History:
+
+
+Notes:
+
+
+--*/
+
+
+#include "windows.h"
+#include "tapi.h"
+#include "tspi.h"
+#include "stdarg.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "malloc.h"
+#include "string.h"
+
+
+typedef struct _MYDIALOGPARAMS
+{
+ char *pszTitle;
+
+ char *pszDataIn;
+
+ TUISPIDLLCALLBACK lpfnUIDLLCallback;
+
+ DWORD dwObjectID;
+
+ DWORD dwObjectType;
+
+ LONG lResult;
+
+} MYDIALOGPARAMS, *PMYDIALOGPARAMS;
+
+
+HINSTANCE ghInstance;
+char szMySection[] = "ESP32";
+char szShowProviderXxxDlgs[] = "ShowProviderXxxDlgs";
+
+#if DBG
+
+#define DBGOUT(arg) DbgPrt arg
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+DWORD gdwDebugLevel;
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
+
+BOOL
+CALLBACK
+GenericDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+BOOL
+WINAPI
+_CRT_INIT(
+ HINSTANCE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ );
+
+LONG
+PASCAL
+ProviderInstall(
+ char *pszProviderName,
+ BOOL bNoMultipleInstance
+ );
+
+
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ static HANDLE hInitEvent;
+
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ OutputDebugString ("ESPUI: DllMain: _CRT_INIT() failed\n\r");
+ }
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+#if DBG
+
+ {
+ HKEY hKey;
+ DWORD dwDataSize, dwDataType;
+ TCHAR szTelephonyKey[] =
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony",
+ szEsp32DebugLevel[] = "Esp32DebugLevel";
+
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ szTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof (DWORD);
+ gdwDebugLevel=0;
+
+ RegQueryValueEx(
+ hKey,
+ szEsp32DebugLevel,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwDebugLevel,
+ &dwDataSize
+ );
+
+ RegCloseKey (hKey);
+ }
+
+#endif
+ ghInstance = hDLL;
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ break;
+ }
+
+ return TRUE;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_lineConfigDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ char buf[64];
+ MYDIALOGPARAMS params =
+ {
+ "TUISPI_lineConfigDialog",
+ buf,
+ lpfnUIDLLCallback,
+ dwDeviceID,
+ TUISPIDLL_OBJECT_LINEID,
+ 0
+ };
+
+
+ wsprintf(
+ buf,
+ "devID=%d, devClass='%ws'",
+ dwDeviceID,
+ (lpszDeviceClass ? lpszDeviceClass : L"")
+ );
+
+ DialogBoxParam(
+ ghInstance,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) GenericDlgProc,
+ (LPARAM) &params
+ );
+
+ return params.lResult;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_lineConfigDialogEdit(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass,
+ LPVOID const lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ )
+{
+ char buf[64];
+ MYDIALOGPARAMS params =
+ {
+ "TUISPI_lineConfigDialogEdit",
+ buf,
+ lpfnUIDLLCallback,
+ dwDeviceID,
+ TUISPIDLL_OBJECT_LINEID,
+ 0
+ };
+
+
+ wsprintf(
+ buf,
+ "devID=%d, devClass='%ws'",
+ dwDeviceID,
+ (lpszDeviceClass ? lpszDeviceClass : L"")
+ );
+
+ DialogBoxParam(
+ ghInstance,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) GenericDlgProc,
+ (LPARAM) &params
+ );
+
+ return params.lResult;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_phoneConfigDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ char buf[64];
+ MYDIALOGPARAMS params =
+ {
+ "TUISPI_phoneConfigDialog",
+ buf,
+ lpfnUIDLLCallback,
+ dwDeviceID,
+ TUISPIDLL_OBJECT_PHONEID,
+ 0
+ };
+
+
+ wsprintf(
+ buf,
+ "devID=%d, devClass='%ws'",
+ dwDeviceID,
+ (lpszDeviceClass ? lpszDeviceClass : L"")
+ );
+
+ DialogBoxParam(
+ ghInstance,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) GenericDlgProc,
+ (LPARAM) &params
+ );
+
+ if (params.lResult)
+ {
+ params.lResult = PHONEERR_OPERATIONFAILED;
+ }
+
+ return params.lResult;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerConfig(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ char buf[64];
+ MYDIALOGPARAMS params =
+ {
+ "TUISPI_providerConfig",
+ buf,
+ lpfnUIDLLCallback,
+ dwPermanentProviderID,
+ TUISPIDLL_OBJECT_PROVIDERID,
+ 0
+ };
+
+
+ wsprintf (buf, "providerID=%d", dwPermanentProviderID);
+
+ DialogBoxParam(
+ ghInstance,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) GenericDlgProc,
+ (LPARAM) &params
+ );
+
+ return params.lResult;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerGenericDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HTAPIDIALOGINSTANCE htDlgInst,
+ LPVOID lpParams,
+ DWORD dwSize,
+ HANDLE hEvent
+ )
+{
+ char buf[80];
+ MYDIALOGPARAMS params =
+ {
+ "TUISPI_providerGenericDialog",
+ buf,
+ lpfnUIDLLCallback,
+ (DWORD) htDlgInst,
+ TUISPIDLL_OBJECT_DIALOGINSTANCE
+ };
+
+
+ SetEvent (hEvent);
+
+ wsprintf(
+ buf,
+ "htDlgInst=x%x, lpParams='%s', dwSize=x%x",
+ htDlgInst,
+ lpParams,
+ dwSize
+ );
+
+ DialogBoxParam(
+ ghInstance,
+ MAKEINTRESOURCE(100),
+ NULL,
+ (DLGPROC) GenericDlgProc,
+ (LPARAM) &params
+ );
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerGenericDialogData(
+ HTAPIDIALOGINSTANCE htDlgInst,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ DBGOUT((3, "TUISPI_providerGenericDialogData: enter"));
+ DBGOUT((
+ 3,
+ "\thtDlgInst=x%x, lpParams='%s', dwSize=x%x",
+ htDlgInst,
+ lpParams,
+ dwSize
+ ));
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerInstall(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ char buf[64];
+ LONG lResult;
+ MYDIALOGPARAMS params =
+ {
+ "TUISPI_providerInstall",
+ buf,
+ lpfnUIDLLCallback,
+ dwPermanentProviderID,
+ TUISPIDLL_OBJECT_PROVIDERID,
+ 0
+ };
+ BOOL bShowDlgs = (BOOL) GetProfileInt(
+ szMySection,
+ szShowProviderXxxDlgs,
+ 0
+ );
+
+
+ if ((lResult = ProviderInstall ("esp32.tsp", TRUE)) == 0)
+ {
+ if (bShowDlgs)
+ {
+ wsprintf (buf, "providerID=%d", dwPermanentProviderID);
+
+ DialogBoxParam(
+ ghInstance,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) GenericDlgProc,
+ (LPARAM) &params
+ );
+
+ lResult = params.lResult;
+ }
+ }
+ else
+ {
+ if (bShowDlgs)
+ {
+ MessageBox(
+ hwndOwner,
+ "ESP32 already installed",
+ "ESP32.TSP",
+ MB_OK
+ );
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerRemove(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ LONG lResult = 0;
+
+
+ if (GetProfileInt (szMySection, szShowProviderXxxDlgs, 0) != 0)
+ {
+ char buf[64];
+ MYDIALOGPARAMS params =
+ {
+ "TUISPI_providerRemove",
+ buf,
+ lpfnUIDLLCallback,
+ dwPermanentProviderID,
+ TUISPIDLL_OBJECT_PROVIDERID,
+ 0
+ };
+
+
+ wsprintf (buf, "providerID=%d", dwPermanentProviderID);
+
+ DialogBoxParam(
+ ghInstance,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) GenericDlgProc,
+ (LPARAM) &params
+ );
+
+ lResult = params.lResult;
+ }
+
+ return lResult;
+}
+
+
+BOOL
+CALLBACK
+GenericDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ PMYDIALOGPARAMS pParams = (PMYDIALOGPARAMS) lParam;
+
+
+ SetWindowText (hwnd, pParams->pszTitle);
+ SetDlgItemText (hwnd, 104, pParams->pszDataIn);
+ SetWindowLong (hwnd, GWL_USERDATA, (LONG) pParams);
+
+ break;
+ }
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ case IDCANCEL:
+ {
+ PMYDIALOGPARAMS pParams;
+
+
+ pParams = (PMYDIALOGPARAMS) GetWindowLong (hwnd, GWL_USERDATA);
+
+ pParams->lResult = (LOWORD(wParam) == IDOK ?
+ 0 : LINEERR_OPERATIONFAILED);
+
+ EndDialog (hwnd, 0);
+ break;
+ }
+ case 102: // send data
+ {
+ #define BUFSIZE 32
+
+ char buf[BUFSIZE] = "espui data";
+ PMYDIALOGPARAMS pParams;
+
+
+ pParams = (PMYDIALOGPARAMS) GetWindowLong (hwnd, GWL_USERDATA);
+
+ (*pParams->lpfnUIDLLCallback)(
+ pParams->dwObjectID,
+ pParams->dwObjectType,
+ (LPVOID) buf,
+ BUFSIZE
+ );
+
+ DBGOUT((3, buf));
+
+ break;
+ }
+ }
+ break;
+
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+LONG
+PASCAL
+ProviderInstall(
+ char *pszProviderName,
+ BOOL bNoMultipleInstance
+ )
+{
+ LONG lResult;
+
+
+ //
+ // If only one installation instance of this provider is
+ // allowed then we want to check the provider list to see
+ // if the provider is already installed
+ //
+
+ if (bNoMultipleInstance)
+ {
+ LONG (WINAPI *pfnGetProviderList)();
+ DWORD dwTotalSize, i;
+ HINSTANCE hTapi32;
+ LPLINEPROVIDERLIST pProviderList;
+ LPLINEPROVIDERENTRY pProviderEntry;
+
+
+ //
+ // Load Tapi32.dll & get a pointer to the lineGetProviderList
+ // func. We could just statically link with Tapi32.lib and
+ // avoid the hassle (and this wouldn't have any adverse
+ // performance effects because of the fact that this
+ // implementation has a separate ui dll that runs only on the
+ // client context), but a provider who implemented these funcs
+ // in it's TSP module would want to do an explicit load like
+ // we do here to prevent the performance hit of Tapi32.dll
+ // always getting loaded in Tapisrv.exe's context.
+ //
+
+ if (!(hTapi32 = LoadLibrary ("tapi32.dll")))
+ {
+ DBGOUT((
+ 1,
+ "LoadLibrary(tapi32.dll) failed, err=%d",
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+ goto ProviderInstall_return;
+ }
+
+ if (!((FARPROC) pfnGetProviderList = GetProcAddress(
+ hTapi32,
+ (LPCSTR) "lineGetProviderList"
+ )))
+ {
+ DBGOUT((
+ 1,
+ "GetProcAddr(lineGetProviderList) failed, err=%d",
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+ goto ProviderInstall_unloadTapi32;
+ }
+
+
+ //
+ // Loop until we get the full provider list
+ //
+
+ dwTotalSize = sizeof (LINEPROVIDERLIST);
+
+ goto ProviderInstall_allocProviderList;
+
+ProviderInstall_getProviderList:
+
+ if ((lResult = (*pfnGetProviderList)(0x00020000, pProviderList)) != 0)
+ {
+ goto ProviderInstall_freeProviderList;
+ }
+
+ if (pProviderList->dwNeededSize > pProviderList->dwTotalSize)
+ {
+ dwTotalSize = pProviderList->dwNeededSize;
+
+ LocalFree (pProviderList);
+
+ProviderInstall_allocProviderList:
+
+ if (!(pProviderList = LocalAlloc (LPTR, dwTotalSize)))
+ {
+ lResult = LINEERR_NOMEM;
+ goto ProviderInstall_unloadTapi32;
+ }
+
+ pProviderList->dwTotalSize = dwTotalSize;
+
+ goto ProviderInstall_getProviderList;
+ }
+
+
+ //
+ // Inspect the provider list entries to see if this provider
+ // is already installed
+ //
+
+ pProviderEntry = (LPLINEPROVIDERENTRY) (((LPBYTE) pProviderList) +
+ pProviderList->dwProviderListOffset);
+
+ for (i = 0; i < pProviderList->dwNumProviders; i++)
+ {
+ char *pszInstalledProviderName = ((char *) pProviderList) +
+ pProviderEntry->dwProviderFilenameOffset,
+ *psz;
+
+
+ if ((psz = strrchr (pszInstalledProviderName, '\\')))
+ {
+ pszInstalledProviderName = psz + 1;
+ }
+
+ if (lstrcmpi (pszInstalledProviderName, pszProviderName) == 0)
+ {
+ lResult = LINEERR_NOMULTIPLEINSTANCE;
+ goto ProviderInstall_freeProviderList;
+ }
+
+ pProviderEntry++;
+ }
+
+
+ //
+ // If here then the provider isn't currently installed,
+ // so do whatever configuration stuff is necessary and
+ // indicate SUCCESS
+ //
+
+ lResult = 0;
+
+
+ProviderInstall_freeProviderList:
+
+ LocalFree (pProviderList);
+
+ProviderInstall_unloadTapi32:
+
+ FreeLibrary (hTapi32);
+ }
+ else
+ {
+ //
+ // Do whatever configuration stuff is necessary and return SUCCESS
+ //
+
+ lResult = 0;
+ }
+
+ProviderInstall_return:
+
+ return lResult;
+}
+
+
+#if DBG
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+{
+ if (dwDbgLevel <= gdwDebugLevel)
+ {
+ char buf[128] = "ESPUI: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ vsprintf (&buf[7],
+ lpszFormat,
+ ap
+ );
+
+ strcat (buf, "\n");
+
+ OutputDebugStringA (buf);
+
+ va_end(ap);
+ }
+}
+#endif
diff --git a/private/tapi/dev/sp/esp.new/ui/espui.def b/private/tapi/dev/sp/esp.new/ui/espui.def
new file mode 100644
index 000000000..a87af28a6
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/ui/espui.def
@@ -0,0 +1,16 @@
+LIBRARY ESPUI
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TUISPI_lineConfigDialog
+ TUISPI_lineConfigDialogEdit
+ TUISPI_phoneConfigDialog
+ TUISPI_providerConfig
+ TUISPI_providerGenericDialog
+ TUISPI_providerGenericDialogData
+ TUISPI_providerInstall
+ TUISPI_providerRemove
+
+ GenericDlgProc
diff --git a/private/tapi/dev/sp/esp.new/ui/espui.rc b/private/tapi/dev/sp/esp.new/ui/espui.rc
new file mode 100644
index 000000000..6aa4516c3
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/ui/espui.rc
@@ -0,0 +1,32 @@
+#include "windows.h"
+
+
+100 DIALOG 6, 18, 205, 67
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "TUISPI_providerGenericDialog"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "Success", IDOK, 20, 46, 40, 14
+ PUSHBUTTON "Error", IDCANCEL, 80, 46, 40, 14
+ PUSHBUTTON "Send data", 102, 140, 46, 40, 14
+ LTEXT "Data in:", 103, 6, 10, 34, 8
+ EDITTEXT 104, 42, 9, 159, 12, ES_AUTOHSCROLL | ES_READONLY
+END
+
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Economical Service Provider Configuration"
+#define VER_INTERNALNAME_STR "espui"
+#define VER_ORIGINALFILENAME_STR "ESPUI.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/esp.new/ui/makefile b/private/tapi/dev/sp/esp.new/ui/makefile
new file mode 100644
index 000000000..23524cb99
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/ui/makefile
@@ -0,0 +1,11 @@
+!ifndef NTMAKEENV
+NTMAKEENV=.
+!endif
+
+
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/tapi/dev/sp/esp.new/ui/sources b/private/tapi/dev/sp/esp.new/ui/sources
new file mode 100644
index 000000000..1d6fc2b10
--- /dev/null
+++ b/private/tapi/dev/sp/esp.new/ui/sources
@@ -0,0 +1,56 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=espui
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=dll
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib
+
+C_DEFINES=-DTAPI_NT=1
+
+DLLBASE=0x60000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+USE_CRTDLL=1
+
+SOURCES=espui.c \
+ espui.rc
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/esp/esp.c b/private/tapi/dev/sp/esp/esp.c
new file mode 100644
index 000000000..30cf48b5d
--- /dev/null
+++ b/private/tapi/dev/sp/esp/esp.c
@@ -0,0 +1,9641 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ esp.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) dd-Mmm-1995
+
+Revision History:
+
+
+Notes:
+
+ 1. Regarding the SP filling in structures with variable length fields
+ (dwXxxSize/dwXxxOffset) : "The SP's variable size fields start
+ immediately after the fixed part of the data structure. The order
+ of filling of the variable size fields owned by the SP is not
+ specified. The SP can fill them in any order it desires. Filling
+ should be contiguous, starting at the beginning of the variable
+ part." (Taken from Chapter 2 of the SPI Programmer's Guide.)
+
+ 2. The cheesey hack in the MsgLoopInTAPIClientContext() function of
+ having an in-line (within the calling app context) msg loop should
+ NOT be implemented by any real service provider. The only place a
+ real provider should have a msg loop (explicit or implicit [i.e. as
+ a result of calling DialogBox()]) is in one of the
+ TSPI_xxxConfigDialog[Edit] functions. If you need a msg processing
+ context (for handling comm events or whatever) then start up a
+ companion exe- it's cheap & easy.
+
+ // BUGBUG no SendMessage's in calling app context either
+
+ Examples of problems with having a msg loop in a service provider
+ in the calling app context:
+
+ * A call to the 16-bit GetMessage() will return a msg that
+ has a 16-bit WPARAM. If this msg is destined for a 32-bit
+ window, the high word of the WPARAM, which is 32-bit for
+ Win32 apps, will have been discarded. However, there is code
+ in the 16-bit system functions DialogBox(), MessageBox(), etc.
+ to deal with this and insure 32-bit WPARAM integrity.
+
+ * Applications can get re-entered when they don't expect it.
+ Consider an app that makes what it thinks will be an atomic
+ function call into TAPI; it waits to get the result back
+ before doing any manipulation of it's various data structures.
+ But in the meantime a service provider enters a Get\Dispatch
+ loop, which in turn causes the app's TapiCallback to be called
+ because there are some completion and/or async event
+ notification msgs available.
+
+
+--*/
+
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include "esp.h"
+#include "vars.h"
+
+
+HANDLE hInst;
+LONG cxList1, cxWnd;
+
+
+#ifdef WIN32
+HANDLE ghMsgLoopThread = NULL;
+#endif
+
+char szdwRequestID[] = "dwRequestID";
+char szdwDeviceID[] = "dwDeviceID";
+char szhdLine[] = "hdLine";
+char szhdCall[] = "hdCall";
+char szhdPhone[] = "hdPhone";
+char szdwSize[] = "dwSize";
+char szlpCallParams[] = "lpCallParams";
+char szTab[] = " ";
+char szTelephonIni[] = "telephon.ini";
+char szhwndOwner[] = "hwndOwner";
+char szMySection[] = "ESPExe";
+char szCallUp[] = "^^^^";
+char szEspTsp[] = "esp.tsp";
+char szProvider[] = "Provider";
+char szProviders[] = "Providers";
+char szProviderID[] = "ProviderID";
+char szNumProviders[] = "NumProviders";
+char szNextProviderID[] = "NextProviderID";
+char szProviderFilename[] = "ProviderFileName";
+char szdwPermanentProviderID[] = "dwPermanentProviderID";
+
+static char far *aszDeviceClasses[] =
+{
+ "tapi/line",
+ "tapi/phone",
+ "wave",
+ "wave/in",
+ "wave/out",
+ "comm",
+ "comm/datamodem",
+ (char far *) NULL
+};
+
+void
+PASCAL
+SendLineEvent(
+ PDRVLINE pLine,
+ PDRVCALL pCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ );
+
+void
+PASCAL
+SendPhoneEvent(
+ PDRVPHONE pPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ );
+
+void
+PASCAL
+DoCompletion(
+ char far *lpszFuncName,
+ DWORD dwRequestID,
+ LONG lResult,
+ BOOL bSync
+ );
+
+void
+PASCAL
+SetCallState(
+ PDRVCALL pCall,
+ DWORD dwCallState,
+ DWORD dwCallStateMode
+ );
+
+void
+UpdateTelephonIni(
+ DWORD dwPermanentProviderID
+ );
+
+void
+MsgLoopInTAPIClientContext(
+ HWND hwnd
+ );
+
+void
+SaveIniSettings(
+ void
+ );
+
+
+BOOL
+__loadds
+CALLBACK
+CallDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+#ifdef WIN32
+
+HANDLE ghShowStrBufMutex;
+
+
+BOOL
+WINAPI
+_CRT_INIT(
+ HINSTANCE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ );
+
+BOOL
+IsESPInstalled(
+ HWND hwnd
+ );
+
+
+void
+MsgLoopThread(
+ void
+ )
+{
+ DllMsgLoop();
+
+ ExitThread (0);
+}
+
+
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ if (!_CRT_INIT (hInst, dwReason, lpReserved))
+ {
+ OutputDebugString ("ESP: DllMain: _CRT_INIT() failed\n\r");
+ }
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+ hInst = hDLL;
+
+ ghShowStrBufMutex = CreateMutex(
+ NULL, // no security attrs
+ FALSE, // unowned
+ NULL // unnamed
+ );
+
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ CloseHandle (ghShowStrBufMutex);
+ break;
+
+ } // switch
+
+ return TRUE;
+}
+
+#else
+
+int
+FAR
+PASCAL
+LibMain(
+ HANDLE hInstance,
+ WORD wDataSegment,
+ WORD wHeapSize,
+ LPSTR lpszCmdLine
+ )
+{
+ hInst = hInstance;
+
+ return TRUE;
+}
+
+#endif
+
+
+//
+// We get a slough of C4047 (different levels of indrection) warnings down
+// below in the initialization of FUNC_PARAM structs as a result of the
+// real func prototypes having params that are types other than DWORDs,
+// so since these are known non-interesting warnings just turn them off
+//
+
+#pragma warning (disable:4047)
+
+
+//
+// --------------------------- TAPI_lineXxx funcs -----------------------------
+//
+
+void
+FAR
+PASCAL
+TSPI_lineAccept_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ SetCallState(
+ (PDRVCALL) pAsyncReqInfo->dwParam1,
+ LINECALLSTATE_ACCEPTED,
+ 0
+ );
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAccept(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "lineAccept", ASYNC, 4, params, TSPI_lineAccept_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineAddToConference_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ PDRVCALL pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+ PDRVCALL pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
+
+
+ pConsultCall->pConfParent = pConfCall;
+ pConsultCall->pNextConfChild = pConfCall->pNextConfChild;
+
+ pConfCall->pNextConfChild = pConsultCall;
+
+ SetCallState (pConsultCall, LINECALLSTATE_CONFERENCED, 0);
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HDRVCALL hdConsultCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { "hdConfCall", hdConfCall },
+ { "hdConsultCall", hdConsultCall }
+ };
+ FUNC_INFO info = { "lineAddToConference", ASYNC, 3, params, TSPI_lineAddToConference_postProcess };
+ PDRVCALL pConfCall = (PDRVCALL) hdConfCall;
+ PDRVCALL pConsultCall = (PDRVCALL) hdConsultCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdConfCall;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdConsultCall;
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineAnswer_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ SetCallState(
+ (PDRVCALL) pAsyncReqInfo->dwParam1,
+ LINECALLSTATE_CONNECTED,
+ 0
+ );
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAnswer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "lineAnswer", ASYNC, 4, params, TSPI_lineAnswer_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineBlindTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode }
+ };
+ FUNC_INFO info = { "lineBlindTransfer", ASYNC, 4, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine }
+ };
+ FUNC_INFO info = { "lineClose", SYNC, 1, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ //
+ // This is more of a "command" than a request, in that TAPI.DLL is
+ // going to consider the line closed whether we like it or not.
+ // Therefore we want to free up the line even if the user chooses
+ // to return an error.
+ //
+
+ if (!Prolog (&info))
+ {
+ // return (Epilog (&info));
+ }
+
+ pLine->htLine = (HTAPILINE) NULL;
+
+ //UpdateWidgetList();
+ PostUpdateWidgetListMsg();
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { "lineCloseCall", SYNC, 1, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ //
+ // This is more of a "command" than a request, in that TAPI.DLL is
+ // going to consider the call closed whether we like it or not.
+ // Therefore we want to free up the call even if the user chooses
+ // to return an error.
+ //
+
+ if (!Prolog (&info))
+ {
+ // return (Epilog (&info));
+ }
+
+ FreeCall (pCall);
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPDWORD lpdwCompletionID,
+ DWORD dwCompletionMode,
+ DWORD dwMessageID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpdwCompletionID", lpdwCompletionID },
+ { "dwCompletionMode", dwCompletionMode },
+ { "dwMessageID", dwMessageID }
+ };
+ FUNC_INFO info = { "lineCompleteCall", ASYNC, 5, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineCompleteTransfer_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pConfCall = (PDRVCALL) NULL;
+ PDRVCALL pCall = pAsyncReqInfo->dwParam1;
+ PDRVCALL pConsultCall = pAsyncReqInfo->dwParam2;
+ HTAPICALL htConfCall = pAsyncReqInfo->dwParam3;
+ LPHDRVCALL lphdConfCall = pAsyncReqInfo->dwParam4;
+
+
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ if (htConfCall)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall (
+ pCall->pLine,
+ htConfCall,
+ NULL,
+ &pConfCall
+ )) == 0)
+ {
+ *lphdConfCall = (HDRVCALL) pCall;
+ }
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ if (pConfCall)
+ {
+ SetCallState (pConfCall, LINECALLSTATE_CONNECTED, 0);
+ SetCallState (pCall, LINECALLSTATE_CONFERENCED, 0);
+ SetCallState (pConsultCall, LINECALLSTATE_CONFERENCED, 0);
+ }
+ else
+ {
+ SetCallState(
+ pCall,
+ LINECALLSTATE_DISCONNECTED,
+ LINEDISCONNECTMODE_NORMAL
+ );
+
+ SetCallState (pCall, LINECALLSTATE_IDLE, 0);
+
+ SetCallState(
+ pConsultCall,
+ LINECALLSTATE_DISCONNECTED,
+ LINEDISCONNECTMODE_NORMAL
+ );
+
+ SetCallState (pConsultCall, LINECALLSTATE_IDLE, 0);
+ }
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCompleteTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVCALL hdConsultCall,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ DWORD dwTransferMode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "hdConsultCall", hdConsultCall },
+ { "htConfCall", htConfCall },
+ { "lphdConfCall", lphdConfCall },
+ { "dwTransferMode", dwTransferMode, aTransferModes }
+ };
+ FUNC_INFO info = { "lineCompleteTransfer", ASYNC, 6, params, TSPI_lineCompleteTransfer_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdConsultCall;
+
+ if (dwTransferMode == LINETRANSFERMODE_CONFERENCE)
+ {
+ info.pAsyncReqInfo->dwParam3 = (DWORD) htConfCall;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) lphdConfCall;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwMediaModes", dwMediaModes, aMediaModes },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info = { "lineConditionalMediaDetection", SYNC, 3, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { szhwndOwner, hwndOwner },
+ { "lpszDeviceClass", lpszDeviceClass }
+ };
+ FUNC_INFO info = { "lineConfigDialog", SYNC, 3, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+#ifdef WIN32
+
+ //
+ // In Win32...
+ //
+
+ MessageBox(
+ hwndOwner,
+ "Config dlg for ESP line device",
+ "TSPI_lineConfigDialog",
+ MB_OK // | MB_SERVICE_NOTIFICATION
+ );
+
+#else
+
+ //
+ // Note: MessageBox() implements a get/dispatch msg loop which allows
+ // other apps (or other windows within the calling app) to gain
+ // focus. Once these other windows/apps have focus, it's
+ // possible that they will call into TAPI, and this service
+ // provider could be re-entered.
+ //
+
+ MessageBox(
+ hwndOwner,
+ "Config dlg for ESP line device",
+ "TSPI_lineConfigDialog",
+ MB_OK
+ );
+#endif
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineConfigDialogEdit(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass,
+ LPVOID lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { szhwndOwner, hwndOwner },
+ { "lpszDeviceClass", lpszDeviceClass },
+ { "lpDeviceConfigIn", lpDeviceConfigIn },
+ { szdwSize, dwSize },
+ { "lpDeviceConfigOut", lpDeviceConfigOut }
+ };
+ FUNC_INFO info = { "lineConfigDialogEdit", SYNC, 6, params };
+ static char szData[] = "device config out data";
+ DWORD len;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+#ifdef WIN32
+
+ //
+ // In Win32...
+ //
+
+ MessageBox(
+ (HWND) NULL, // NOTE: if hwndOwner specified dlg never appears
+ "Config dlg for ESP line device",
+ "TSPI_lineConfigDialogEdit",
+ MB_OK | MB_SERVICE_NOTIFICATION
+ );
+
+#else
+
+ //
+ // Note: MessageBox() implements a get/dispatch msg loop which allows
+ // other apps (or other windows within the calling app) to gain
+ // focus. Once these other windows/apps have focus, it's
+ // possible that they will call into TAPI, and this service
+ // provider could be re-entered.
+ //
+
+ MessageBox(
+ hwndOwner,
+ "Config dlg for ESP line device",
+ "TSPI_lineConfigDialogEdit",
+ MB_OK
+ );
+
+#endif
+
+ len = strlen (szData) + 1;
+
+ lpDeviceConfigOut->dwNeededSize = sizeof (VARSTRING) + len;
+
+ if (lpDeviceConfigOut->dwTotalSize >= lpDeviceConfigOut->dwNeededSize)
+ {
+ lpDeviceConfigOut->dwUsedSize = lpDeviceConfigOut->dwNeededSize;
+
+ lpDeviceConfigOut->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceConfigOut->dwStringSize = len;
+ lpDeviceConfigOut->dwStringOffset = sizeof (VARSTRING);
+
+ strcpy ((char *)(lpDeviceConfigOut + 1), szData);
+ }
+ else
+ {
+ lpDeviceConfigOut->dwUsedSize = 3 * sizeof(DWORD);
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineDevSpecific_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ LPVOID lpParams = pAsyncReqInfo->dwParam1;
+ DWORD dwSize = pAsyncReqInfo->dwParam2;
+
+
+ if (pAsyncReqInfo->lResult == 0 && dwSize >= 22)
+ {
+ strcpy (lpParams, "ESP dev specific info");
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "lpParams", lpParams },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ "lineDevSpecific",
+ ASYNC,
+ 6,
+ params,
+ TSPI_lineDevSpecific_postProcess
+ };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = lpParams;
+ info.pAsyncReqInfo->dwParam2 = dwSize;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDevSpecificFeature(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwFeature,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwFeature", dwFeature },
+ { "lpParams", lpParams },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ "lineDevSpecificFeature",
+ ASYNC,
+ 5,
+ params,
+ TSPI_lineDevSpecific_postProcess
+ };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = lpParams;
+ info.pAsyncReqInfo->dwParam2 = dwSize;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDial(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode }
+ };
+ FUNC_INFO info = { "lineDial", ASYNC, 4, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineDrop_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ SetCallState(
+ (PDRVCALL) pAsyncReqInfo->dwParam1,
+ LINECALLSTATE_IDLE,
+ 0
+ );
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "lineDrop", ASYNC, 4, params, TSPI_lineDrop_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+
+ return (Epilog (&info));
+}
+
+LONG
+TSPIAPI
+TSPI_lineDropOnClose(
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { "lineDropOnClose", SYNC, 1, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+ //
+ // Don't bother indicating call state, TAPI will follow up with
+ // a CloseCall request regardless
+ //
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDropNoOwner(
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { "lineDropNoOwner", SYNC, 1, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ SetCallState ((PDRVCALL) hdCall, LINECALLSTATE_IDLE, 0);
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineForward_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pConsultCall;
+ PDRVLINE pLine = (PDRVLINE) pAsyncReqInfo->dwParam1;
+ BOOL bAllAddresses = (BOOL) pAsyncReqInfo->dwParam2;
+ DWORD dwAddressID = pAsyncReqInfo->dwParam3;
+ LPLINEFORWARDLIST lpForwardList = (LPLINEFORWARDLIST) pAsyncReqInfo->dwParam4;
+ DWORD dwNumRingsNoAnswer = pAsyncReqInfo->dwParam5;
+ HTAPICALL htConsultCall = (HTAPICALL) pAsyncReqInfo->dwParam6;
+ LPHDRVCALL lphdConsultCall = (LPHDRVCALL) pAsyncReqInfo->dwParam7;
+ LPLINECALLPARAMS lpCallParams = (LPLINECALLPARAMS) pAsyncReqInfo->dwParam8;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall (
+ pLine,
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+ )) == 0)
+ {
+ // BUGBUG deal w/ addr id
+
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState (pConsultCall, LINECALLSTATE_CONNECTED, 0);
+ }
+
+ if (lpForwardList)
+ {
+ DrvFree (lpForwardList);
+ }
+
+ if (lpCallParams)
+ {
+ DrvFree (lpCallParams);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineForward(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD bAllAddresses,
+ DWORD dwAddressID,
+ LPLINEFORWARDLIST const lpForwardList,
+ DWORD dwNumRingsNoAnswer,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "bAllAddresses", bAllAddresses },
+ { "dwAddressID", dwAddressID },
+ { "lpForwardList", lpForwardList },
+ { "dwNumRingsNoAnswer", dwNumRingsNoAnswer },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info = { "lineForward", ASYNC, 9, params, TSPI_lineForward_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdLine;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) bAllAddresses;
+ info.pAsyncReqInfo->dwParam3 = dwAddressID;
+
+ if (lpForwardList)
+ {
+ info.pAsyncReqInfo->dwParam4 = (DWORD) DrvAlloc(
+ (size_t) lpForwardList->dwTotalSize
+ );
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam4,
+ (void far *) lpForwardList,
+ (size_t) lpForwardList->dwTotalSize
+ );
+ }
+
+ info.pAsyncReqInfo->dwParam5 = dwNumRingsNoAnswer;
+ info.pAsyncReqInfo->dwParam6 = (DWORD) htConsultCall;
+ info.pAsyncReqInfo->dwParam7 = (DWORD) lphdConsultCall;
+
+ if (lpCallParams)
+ {
+ info.pAsyncReqInfo->dwParam8 = (DWORD) DrvAlloc(
+ (size_t) lpCallParams->dwTotalSize
+ );
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam8,
+ (void far *) lpCallParams,
+ (size_t) lpCallParams->dwTotalSize
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGatherDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitModes,
+ LPSTR lpsDigits,
+ DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwEndToEndID", dwEndToEndID },
+ { "dwDigitModes", dwDigitModes, aDigitModes },
+ { "lpsDigits", lpsDigits },
+ { "dwNumDigits", dwNumDigits },
+ { "lpszTerminationDigits", lpszTerminationDigits },
+ { "dwFirstDigitTimeout", dwFirstDigitTimeout },
+ { "dwInterDigitTimeout", dwInterDigitTimeout }
+ };
+ FUNC_INFO info = { "lineGatherDigits", SYNC, 8, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGenerateDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitMode,
+ LPCSTR lpszDigits,
+ DWORD dwDuration
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwEndToEndID", dwEndToEndID },
+ { "dwDigitMode", dwDigitMode, aDigitModes },
+ { "lpszDigits", lpszDigits },
+ { "dwDuration", dwDuration }
+ };
+ FUNC_INFO info = { "lineGenerateDigits", SYNC, 5, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGenerateTone(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwToneMode,
+ DWORD dwDuration,
+ DWORD dwNumTones,
+ LPLINEGENERATETONE const lpTones
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwEndToEndID", dwEndToEndID },
+ { "dwToneMode", dwToneMode, aToneModes },
+ { "dwDuration", dwDuration },
+ { "dwNumTones", dwNumTones },
+ { "lpTones", lpTones }
+ };
+ FUNC_INFO info = { "lineGenerateTone", SYNC, 6, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwAddressID", dwAddressID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpAddressCaps", lpAddressCaps }
+ };
+ FUNC_INFO info = { "lineGetAddressCaps", SYNC, 5, params };
+ DWORD dwUsedSize;
+ PDRVLINE pLine = GetLine (dwDeviceID);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+ if (dwAddressID >= pLine->LineDevCaps.dwNumAddresses)
+ {
+ info.lResult = LINEERR_INVALADDRESSID;
+ return (Epilog (&info));
+ }
+
+
+ //
+ // Figure out how much caps data to copy (don't bother with var length
+ // fields if there's not room enough for all of them)
+ //
+
+ if (lpAddressCaps->dwTotalSize >= pLine->LineAddrCaps.dwNeededSize)
+ {
+ dwUsedSize = pLine->LineAddrCaps.dwNeededSize;
+ }
+ else if (lpAddressCaps->dwTotalSize >= sizeof(LINEADDRESSCAPS))
+ {
+ dwUsedSize = sizeof(LINEADDRESSCAPS);
+ }
+ else // it's a 1.3 app looking for just fixed 1.3 data struct size
+ {
+ dwUsedSize = sizeof(LINEADDRESSCAPS) - sizeof(DWORD);
+ }
+
+ memcpy(
+ &lpAddressCaps->dwNeededSize,
+ &pLine->LineAddrCaps.dwNeededSize,
+ (size_t) dwUsedSize - 4 // - 4 since not overwriting dwTotalSize
+ );
+
+ lpAddressCaps->dwUsedSize = dwUsedSize;
+
+
+ //
+ // If there's no room for the var length fields then we need to zero
+ // out all the dwXxxSize fields; otherwise, fill in the address field
+ //
+
+ if (lpAddressCaps->dwTotalSize < pLine->LineAddrCaps.dwNeededSize)
+ {
+ //lpAddessCaps->dwAddressSize =
+ //lpAddessCaps->dwDevSpecificSize =
+ //lpAddessCaps->dwCompletionMsgTextSize = 0;
+ }
+ else
+ {
+ char far *p = ((char far *) lpAddressCaps) +
+ lpAddressCaps->dwAddressOffset;
+
+ wsprintf (p, "%ld.%ld", dwDeviceID, dwAddressID);
+
+ lpAddressCaps->dwAddressSize = strlen (p) + 1;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCSTR lpsAddress,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "lpdwAddressID", lpdwAddressID },
+ { "dwAddressMode", dwAddressMode },
+ { "lpsAddress", lpsAddress },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "lineGetAddressID", SYNC, 5, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { "lpAddressStatus", lpAddressStatus }
+ };
+ FUNC_INFO info = { "lineGetAddressStatus", SYNC, 3, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ if (lpAddressStatus->dwTotalSize >= pLine->LineAddrStatus.dwNeededSize)
+ {
+ memcpy(
+ &lpAddressStatus->dwNeededSize,
+ &pLine->LineAddrStatus.dwNeededSize,
+ pLine->LineAddrStatus.dwNeededSize - sizeof (DWORD)
+ );
+ }
+ else
+ {
+ lpAddressStatus->dwNeededSize = pLine->LineAddrStatus.dwNeededSize;
+ lpAddressStatus->dwUsedSize = 3 * sizeof (DWORD);
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "lpdwAddressID", lpdwAddressID }
+ };
+ FUNC_INFO info = { "lineGetCallAddressID", SYNC, 2, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ *lpdwAddressID = ((PDRVCALL) hdCall)->LineCallInfo.dwAddressID;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "lpCallInfo", lpCallInfo }
+ };
+ FUNC_INFO info = { "lineGetCallInfo", SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ DWORD dwUsedSize;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+ //
+ // Figure out how much data to copy (don't bother with var length fields
+ // if there's not room enough for all of them)
+ //
+
+ if (lpCallInfo->dwTotalSize >= pCall->LineCallInfo.dwNeededSize)
+ {
+ dwUsedSize = pCall->LineCallInfo.dwNeededSize;
+ }
+ else
+ {
+ dwUsedSize = sizeof(LINECALLINFO);
+ }
+
+
+ memcpy(
+ &lpCallInfo->dwNeededSize,
+ &pCall->LineCallInfo.dwNeededSize,
+ (size_t) dwUsedSize - 4 // - 4 since not overwriting dwTotalSize
+ );
+
+ lpCallInfo->dwUsedSize = dwUsedSize;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "lpCallStatus", lpCallStatus }
+ };
+ FUNC_INFO info = { "lineGetCallStatus", SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ DWORD dwDevSpecificSize = pCall->LineCallInfo.dwDevSpecificSize;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ lpCallStatus->dwUsedSize = sizeof (LINECALLSTATUS);
+ lpCallStatus->dwNeededSize = sizeof (LINECALLSTATUS) + dwDevSpecificSize;
+
+ lpCallStatus->dwCallState = pCall->dwCallState;
+ lpCallStatus->dwCallStateMode = pCall->dwCallStateMode;
+ lpCallStatus->dwCallFeatures = pCall->dwCallFeatures;
+
+
+ //
+ // We're getting the DevSpecific field from the CalInfo
+ //
+
+ if (dwDevSpecificSize &&
+ (lpCallStatus->dwTotalSize >= lpCallStatus->dwNeededSize))
+ {
+ lpCallStatus->dwDevSpecificSize = dwDevSpecificSize;
+ lpCallStatus->dwDevSpecificOffset = sizeof(LINECALLSTATUS);
+
+ strcpy(
+ ((char far *) lpCallStatus) + sizeof(LINECALLSTATUS),
+ ((char far *) &pCall->LineCallInfo) +
+ pCall->LineCallInfo.dwDevSpecificOffset
+ );
+
+ lpCallStatus->dwUsedSize = lpCallStatus->dwNeededSize;
+ }
+ else
+ {
+ lpCallStatus->dwDevSpecificSize =
+ lpCallStatus->dwDevSpecificOffset = 0;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpLineDevCaps", lpLineDevCaps }
+ };
+ FUNC_INFO info = { "lineGetDevCaps", SYNC, 4, params };
+ DWORD dwUsedSize;
+ PDRVLINE pLine = GetLine (dwDeviceID);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+ //
+ // Figure out how much caps data to copy (don't bother with var length
+ // fields if there's not room enough for all of them)
+ //
+
+ if (lpLineDevCaps->dwTotalSize >= pLine->LineDevCaps.dwNeededSize)
+ {
+ dwUsedSize = pLine->LineDevCaps.dwNeededSize;
+ }
+ else if (lpLineDevCaps->dwTotalSize >= sizeof(LINEDEVCAPS))
+ {
+ dwUsedSize = sizeof(LINEDEVCAPS);
+ }
+ else // it's a 1.3 app looking for just fixed 1.3 data struct size
+ {
+ dwUsedSize = sizeof(LINEDEVCAPS) - sizeof(DWORD);
+ }
+
+
+ memcpy(
+ &lpLineDevCaps->dwNeededSize,
+ &pLine->LineDevCaps.dwNeededSize,
+ (size_t) dwUsedSize - 4 // - 4 since not overwriting dwTotalSize
+ );
+
+ lpLineDevCaps->dwUsedSize = dwUsedSize;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevConfig(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCSTR lpszDeviceClass
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpDeviceConfig", lpDeviceConfig },
+ { "lpszDeviceClass", lpszDeviceClass }
+ };
+ FUNC_INFO info = { "lineGetDevConfig", SYNC, 3, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPLINEEXTENSIONID lpExtensionID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpExtensionID", lpExtensionID }
+ };
+ FUNC_INFO info = { "lineGetExtensionID", SYNC, 3, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ memcpy (lpExtensionID, &gLineExtID, sizeof(LINEEXTENSIONID));
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetIcon(
+ DWORD dwDeviceID,
+ LPCSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass },
+ { "lphIcon", lphIcon }
+ };
+ FUNC_INFO info = { "lineGetIcon", SYNC, 3, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ *lphIcon = ghIconLine;
+
+ return (Epilog (&info));
+}
+
+
+#ifdef WIN32
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+#else
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+#endif
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "dwSelect", dwSelect, aCallSelects },
+ { "lpDeviceID", lpDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass }
+#ifdef WIN32
+ ,{ "hTargetProcess", hTargetProcess }
+#endif
+ };
+#ifdef WIN32
+ FUNC_INFO info = { "lineGetID", SYNC, 7, params };
+#else
+ FUNC_INFO info = { "lineGetID", SYNC, 6, params };
+#endif
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ DWORD i, dwDeviceID, dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ for (i = 0; aszDeviceClasses[i]; i++)
+ {
+ if (_stricmp (lpszDeviceClass, aszDeviceClasses[i]) == 0)
+ {
+ break;
+ }
+ }
+
+ if (!aszDeviceClasses[i])
+ {
+ info.lResult = LINEERR_NODEVICE;
+ return (Epilog (&info));
+ }
+
+ if (lpDeviceID->dwTotalSize < dwNeededSize)
+ {
+ lpDeviceID->dwNeededSize = dwNeededSize;
+ lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
+
+ return (Epilog (&info));
+ }
+
+ if (i == 0)
+ {
+ if (dwSelect == LINECALLSELECT_CALL)
+ {
+ dwDeviceID = pCall->pLine->dwDeviceID;
+ }
+ else
+ {
+ dwDeviceID = pLine->dwDeviceID;
+ }
+ }
+ else
+ {
+ if (gbShowLineGetIDDlg)
+ {
+ char szDlgTitle[64];
+ EVENT_PARAM params[] =
+ {
+ { "dwDeviceID", PT_DWORD, gdwDefLineGetIDID, 0 }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, szDlgTitle, XX_REQRESULTPOSTQUIT, params };
+ HWND hwnd;
+
+
+ if (strlen (lpszDeviceClass) > 20)
+ {
+ ((char far *)lpszDeviceClass)[19] = 0;
+ }
+
+ wsprintf(
+ szDlgTitle,
+ "TSPI_lineGetID: select ID for class '%s'",
+ lpszDeviceClass
+ );
+
+ hwnd = CreateDialogParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) NULL,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ );
+
+ MsgLoopInTAPIClientContext (hwnd);
+
+ dwDeviceID = params[0].dwValue;
+ }
+ else
+ {
+ dwDeviceID = gdwDefLineGetIDID;
+ }
+ }
+
+ lpDeviceID->dwNeededSize =
+ lpDeviceID->dwUsedSize = dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof(DWORD);
+ lpDeviceID->dwStringOffset = sizeof(VARSTRING);
+
+ *((LPDWORD)(lpDeviceID + 1)) = dwDeviceID;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "lpLineDevStatus", lpLineDevStatus }
+ };
+ FUNC_INFO info = { "lineGetLineDevStatus", SYNC, 2, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ DWORD dwTotalSize, dwNeededSize;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ dwNeededSize = pLine->LineDevStatus.dwNeededSize;
+
+ if ((dwTotalSize = lpLineDevStatus->dwTotalSize) < dwNeededSize)
+ {
+ lpLineDevStatus->dwNeededSize = dwNeededSize;
+ lpLineDevStatus->dwUsedSize = 3 * sizeof (DWORD);
+ }
+ else
+ {
+ memcpy(
+ lpLineDevStatus,
+ &pLine->LineDevStatus,
+ dwNeededSize
+ );
+
+ lpLineDevStatus->dwTotalSize = dwTotalSize;
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "lpdwNumAddressIDs", lpdwNumAddressIDs }
+ };
+ FUNC_INFO info = { "lineGetNumAddressIDs", SYNC, 2, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ *lpdwNumAddressIDs = pLine->LineDevCaps.dwNumAddresses;
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineHold_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ SetCallState(
+ (PDRVCALL) pAsyncReqInfo->dwParam1,
+ LINECALLSTATE_ONHOLD,
+ 0
+ );
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { "lineHold", ASYNC, 2, params, TSPI_lineHold_postProcess };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineMakeCall_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pCall;
+ PDRVLINE pLine = (PDRVLINE) pAsyncReqInfo->dwParam1;
+ HTAPICALL htCall = (HTAPICALL) pAsyncReqInfo->dwParam2;
+ LPHDRVCALL lphdCall = (LPHDRVCALL) pAsyncReqInfo->dwParam3;
+ LPSTR lpszDestAddress = (LPSTR) pAsyncReqInfo->dwParam4;
+ LPLINECALLPARAMS lpCallParams = (LPLINECALLPARAMS) pAsyncReqInfo->dwParam5;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall (
+ pLine,
+ htCall,
+ lpCallParams,
+ &pCall
+ )) == 0)
+ {
+ *lphdCall = (HDRVCALL) pCall;
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ int i;
+
+
+ //
+ // Loop on user-defined call state progression array
+ //
+
+ for (i = 0; ((i < MAX_OUT_CALL_STATES) && aOutCallStates[i]); i++)
+ {
+ SetCallState (pCall, aOutCallStates[i], aOutCallStateModes[i]);
+ }
+ }
+
+ if (lpszDestAddress)
+ {
+ DrvFree (lpszDestAddress);
+ }
+
+ if (lpCallParams)
+ {
+ DrvFree (lpCallParams);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "htCall", htCall },
+ { "lphdCall", lphdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info = { "lineMakeCall", ASYNC, 7, params, TSPI_lineMakeCall_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdLine;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) htCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) lphdCall;
+
+ if (lpszDestAddress)
+ {
+ size_t len = strlen (lpszDestAddress) + 1;
+
+
+ info.pAsyncReqInfo->dwParam4 = (DWORD) DrvAlloc (len);
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam4,
+ lpszDestAddress,
+ len
+ );
+ }
+
+ if (lpCallParams)
+ {
+ info.pAsyncReqInfo->dwParam5 = (DWORD) DrvAlloc(
+ (size_t) lpCallParams->dwTotalSize
+ );
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam5,
+ (void far *) lpCallParams,
+ (size_t) lpCallParams->dwTotalSize
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorDigits(
+ HDRVCALL hdCall,
+ DWORD dwDigitModes
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwDigitModes", dwDigitModes, aDigitModes }
+ };
+ FUNC_INFO info = { "lineMonitorDigits", SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorMedia(
+ HDRVCALL hdCall,
+ DWORD dwMediaModes
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwMediaModes", dwMediaModes, aMediaModes }
+ };
+ FUNC_INFO info = { "lineMonitorMedia", SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorTones(
+ HDRVCALL hdCall,
+ DWORD dwToneListID,
+ LPLINEMONITORTONE const lpToneList,
+ DWORD dwNumEntries
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwToneListID", dwToneListID },
+ { "lpToneList", lpToneList },
+ { "dwNumEntries", dwNumEntries }
+ };
+ FUNC_INFO info = { "lineMonitorTones", SYNC, 4, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwExtVersion", lpdwExtVersion }
+ };
+ FUNC_INFO info = { "lineNegotiateExtVersion", SYNC, 5, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ ShowStr(
+ "TSPI_lineNegoExtVer: setting *lpdwExtVersion = x%lx",
+ dwHighVersion
+ );
+
+ *lpdwExtVersion = dwHighVersion;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+#ifdef WIN32
+
+ if (!ghMsgLoopThread)
+ {
+ DWORD dwTID;
+
+
+ if (!(ghMsgLoopThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE) MsgLoopThread,
+ NULL,
+ 0,
+ &dwTID
+ )))
+ {
+ OutputDebugString ("ESP32.TSP: DllMain: CreateThread failed\n\r");
+ return LINEERR_OPERATIONFAILED;
+ }
+ }
+
+#endif
+
+ {
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwTSPIVersion", lpdwTSPIVersion }
+ };
+ FUNC_INFO info = { "lineNegotiateTSPIVersion", SYNC, 4, params };
+
+
+ {
+ // BUGBUG hangs if gbManualResults set, so...
+
+ BOOL bManualResultsSav = gbManualResults;
+
+
+ gbManualResults = FALSE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ gbManualResults = bManualResultsSav;
+ }
+
+ *lpdwTSPIVersion = gdwTSPIVersion;
+
+ return (Epilog (&info));
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "htLine", htLine },
+ { "lphdLine", lphdLine },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpfnEventProc", lpfnEventProc }
+ };
+ FUNC_INFO info = { "lineOpen", SYNC, 5, params };
+ PDRVLINE pLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ pLine = GetLine (dwDeviceID);
+
+ pLine->htLine = htLine;
+ pLine->lpfnEventProc = lpfnEventProc;
+
+ *lphdLine = (HDRVLINE) pLine;
+
+ //UpdateWidgetList();
+ PostUpdateWidgetListMsg();
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePark(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwParkMode,
+ LPCSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "dwParkMode", dwParkMode },
+ { "lpszDirAddress", lpszDirAddress },
+ { "lpNonDirAddress", lpNonDirAddress }
+ };
+ FUNC_INFO info = { "linePark", ASYNC, 5, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_linePickup_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pCall;
+ PDRVLINE pLine = (PDRVLINE) pAsyncReqInfo->dwParam1;
+ DWORD dwAddresssID = pAsyncReqInfo->dwParam2;
+ HTAPICALL htCall = (HTAPICALL) pAsyncReqInfo->dwParam3;
+ LPHDRVCALL lphdCall = (LPHDRVCALL) pAsyncReqInfo->dwParam4;
+ LPSTR lpszDestAddress = (LPSTR) pAsyncReqInfo->dwParam5;
+ LPSTR lpszGroupID = (LPSTR) pAsyncReqInfo->dwParam6;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall (
+ pLine,
+ htCall,
+ NULL,
+ &pCall
+ )) == 0)
+ {
+ // BUGBUG deal w/ addr id
+
+ *lphdCall = (HDRVCALL) pCall;
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState (pCall, LINECALLSTATE_OFFERING, 0);
+ }
+
+ if (lpszDestAddress)
+ {
+ DrvFree (lpszDestAddress);
+ }
+
+ if (lpszGroupID)
+ {
+ DrvFree (lpszGroupID);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePickup(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ LPCSTR lpszGroupID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { "htCall", htCall },
+ { "lphdCall", lphdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "lpszGroupID", lpszGroupID }
+ };
+ FUNC_INFO info = { "linePickup", ASYNC, 7, params, TSPI_linePickup_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdLine;
+ info.pAsyncReqInfo->dwParam2 = dwAddressID;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) htCall;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) lphdCall;
+
+ if (lpszDestAddress)
+ {
+ size_t len = strlen (lpszDestAddress) + 1;
+
+
+ info.pAsyncReqInfo->dwParam5 = (DWORD) DrvAlloc (len);
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam5,
+ lpszDestAddress,
+ len
+ );
+ }
+
+ if (lpszGroupID)
+ {
+ size_t len = strlen (lpszGroupID) + 1;
+
+
+ info.pAsyncReqInfo->dwParam6 = (DWORD) DrvAlloc (len);
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam6,
+ lpszGroupID,
+ len
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_linePrepareAddToConference_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pConsultCall = (PDRVCALL) NULL;
+ PDRVCALL pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+ HTAPICALL htConsultCall = (HTAPICALL) pAsyncReqInfo->dwParam2;
+ LPHDRVCALL lphdConsultCall = (LPHDRVCALL) pAsyncReqInfo->dwParam3;
+ LPLINECALLPARAMS lpCallParams = (LPLINECALLPARAMS) pAsyncReqInfo->dwParam4;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall(
+ pConfCall->pLine,
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+ )) == 0
+ )
+ {
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState (pConfCall, LINECALLSTATE_ONHOLDPENDCONF, 0);
+ SetCallState (pConsultCall, LINECALLSTATE_DIALTONE, 0);
+ }
+
+ if (lpCallParams)
+ {
+ DrvFree (lpCallParams);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePrepareAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { "hdConfCall", hdConfCall },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info = { "linePrepareAddToConference", ASYNC, 5, params, TSPI_linePrepareAddToConference_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdConfCall;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) htConsultCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) lphdConsultCall;
+
+ if (lpCallParams)
+ {
+ info.pAsyncReqInfo->dwParam4 = (DWORD) DrvAlloc(
+ (size_t) lpCallParams->dwTotalSize
+ );
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam4,
+ (void far *) lpCallParams,
+ (size_t) lpCallParams->dwTotalSize
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineRedirect(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpszDestAddress", lpszDestAddress },
+ { "dwCountryCode", dwCountryCode }
+ };
+ FUNC_INFO info = { "lineRedirect", ASYNC, 4, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineReleaseUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { "lineReleaseUserUserInfo", ASYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineRemoveFromConference_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+ PDRVCALL pCall2 = (PDRVCALL) pCall->pConfParent;
+
+
+ while (pCall2->pNextConfChild != pCall)
+ {
+ pCall2 = pCall2->pNextConfChild;
+ }
+
+ pCall2->pNextConfChild = pCall->pNextConfChild;
+
+ SetCallState (pCall, LINECALLSTATE_CONNECTED, 0);
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineRemoveFromConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { "lineRemoveFromConference", ASYNC, 2, params, TSPI_lineRemoveFromConference_postProcess };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSecureCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall }
+ };
+ FUNC_INFO info = { "lineSecureCall", ASYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSelectExtVersion(
+ HDRVLINE hdLine,
+ DWORD dwExtVersion
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwExtVersion", dwExtVersion }
+ };
+ FUNC_INFO info = { "lineSelectExtVersion", SYNC, 2, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSendUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "lpsUserUserInfo", lpsUserUserInfo },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "lineSendUserUserInfo", ASYNC, 4, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, hdCall },
+ { "dwAppSpecific", dwAppSpecific }
+ };
+ FUNC_INFO info = { "lineSetAppSpecific", SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallParams(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwBearerMode,
+ DWORD dwMinRate,
+ DWORD dwMaxRate,
+ LPLINEDIALPARAMS const lpDialParams
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "dwBearerMode", dwBearerMode, aBearerModes },
+ { "dwMinRate", dwMinRate },
+ { "dwMaxRate", dwMaxRate },
+ { "lpDialParams", lpDialParams }
+ };
+ FUNC_INFO info = { "lineSetCallParams", ASYNC, 6, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCurrentLocation(
+ DWORD dwLocation
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { "dwLocation", dwLocation }
+ };
+ FUNC_INFO info = { "lineSetCurrentLocation", SYNC, 1, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwMediaModes", dwMediaModes, aMediaModes }
+ };
+ FUNC_INFO info = { "lineSetDefaultMediaDetection", SYNC, 2, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDevConfig(
+ DWORD dwDeviceID,
+ LPVOID const lpDeviceConfig,
+ DWORD dwSize,
+ LPCSTR lpszDeviceClass
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpDeviceConfig", lpDeviceConfig },
+ { szdwSize, dwSize },
+ { "lpszDeviceClass", lpszDeviceClass }
+ };
+ FUNC_INFO info = { "lineSetDevConfig", SYNC, 4, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaControl(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPLINEMEDIACONTROLDIGIT const lpDigitList,
+ DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA const lpMediaList,
+ DWORD dwMediaNumEntries,
+ LPLINEMEDIACONTROLTONE const lpToneList,
+ DWORD dwToneNumEntries,
+ LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
+ DWORD dwCallStateNumEntries
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "dwSelect", dwSelect, aCallSelects },
+ { "lpDigitList", lpDigitList },
+ { "dwDigitNumEntries", dwDigitNumEntries },
+ { "lpMediaList", lpMediaList },
+ { "dwMediaNumEntries", dwMediaNumEntries },
+ { "lpToneList", lpToneList },
+ { "dwToneNumEntries", dwToneNumEntries },
+ { "lpCallStateList", lpCallStateList },
+ { "dwCallStateNumEntries", dwCallStateNumEntries }
+ };
+ FUNC_INFO info = { "lineSetMediaControl", SYNC, 12, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdCall, szhdCall },
+ { "dwMediaMode", dwMediaMode, aMediaModes }
+ };
+ FUNC_INFO info = { "lineSetMediaMode", SYNC, 2, params };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetStatusMessages(
+ HDRVLINE hdLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdLine, hdLine },
+ { "dwLineStates", dwLineStates, aLineStates },
+ { "dwAddressStates", dwAddressStates, aAddressStates }
+ };
+ FUNC_INFO info = { "lineSetStatusMessages", SYNC, 3, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetTerminal(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ DWORD dwTerminalModes,
+ DWORD dwTerminalID,
+ DWORD bEnable
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { szhdCall, hdCall },
+ { "dwSelect", dwSelect, aCallSelects },
+ { "dwTerminalModes", dwTerminalModes, aTerminalModes },
+ { "dwTerminalID", dwTerminalID },
+ { "bEnable", bEnable }
+ };
+ FUNC_INFO info = { "lineSetTerminal", ASYNC, 8, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetupConference_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pConfCall = (PDRVCALL) NULL;
+ PDRVCALL pConsultCall = (PDRVCALL) NULL;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+ PDRVLINE pLine = (PDRVLINE) pAsyncReqInfo->dwParam2;
+ HTAPICALL htConfCall = (HTAPICALL) pAsyncReqInfo->dwParam3;
+ LPHDRVCALL lphdConfCall = (LPHDRVCALL) pAsyncReqInfo->dwParam4;
+ HTAPICALL htConsultCall = (HTAPICALL) pAsyncReqInfo->dwParam5;
+ LPHDRVCALL lphdConsultCall = (LPHDRVCALL) pAsyncReqInfo->dwParam6;
+ LPLINECALLPARAMS lpCallParams = (LPLINECALLPARAMS) pAsyncReqInfo->dwParam7;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall(
+ pLine,
+ htConfCall,
+ lpCallParams,
+ &pConfCall
+ )) == 0
+
+ &&
+
+ (pAsyncReqInfo->lResult = AllocCall(
+ pLine,
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+ )) == 0
+ )
+ {
+ *lphdConfCall = (HDRVCALL) pConfCall;
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+
+ pConfCall->pNextConfChild = (pCall ? pCall : pConsultCall);
+
+ if (pCall)
+ {
+ pCall->pNextConfChild = pConsultCall;
+ pCall->pConfParent = pConfCall;
+ }
+
+ pConsultCall->pConfParent = pConfCall;
+ }
+ else if (pConfCall)
+ {
+ FreeCall (pConfCall);
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if (pCall)
+ {
+ SetCallState (pCall, LINECALLSTATE_CONFERENCED, 0);
+ }
+
+ SetCallState (pConfCall, LINECALLSTATE_ONHOLDPENDCONF, 0);
+ SetCallState (pConsultCall, LINECALLSTATE_DIALTONE, 0);
+ }
+
+ if (lpCallParams)
+ {
+ DrvFree (lpCallParams);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetupConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVLINE hdLine,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { szhdLine, hdLine },
+ { "htConfCall", htConfCall },
+ { "lphdConfCall", lphdConfCall },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { "dwNumParties", dwNumParties },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info = { "lineSetupConference", ASYNC, 9, params, TSPI_lineSetupConference_postProcess };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdLine;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) htConfCall;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) lphdConfCall;
+ info.pAsyncReqInfo->dwParam5 = (DWORD) htConsultCall;
+ info.pAsyncReqInfo->dwParam6 = (DWORD) lphdConsultCall;
+
+ if (lpCallParams)
+ {
+ info.pAsyncReqInfo->dwParam7 = (DWORD) DrvAlloc(
+ (size_t) lpCallParams->dwTotalSize
+ );
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam7,
+ lpCallParams,
+ (size_t) lpCallParams->dwTotalSize
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSetupTransfer_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pConsultCall = (PDRVCALL) NULL;
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+ HTAPICALL htConsultCall = (HTAPICALL) pAsyncReqInfo->dwParam2;
+ LPHDRVCALL lphdConsultCall = (LPHDRVCALL) pAsyncReqInfo->dwParam3;
+ LPLINECALLPARAMS lpCallParams = (LPLINECALLPARAMS) pAsyncReqInfo->dwParam4;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall(
+ pCall->pLine,
+ htConsultCall,
+ lpCallParams,
+ &pConsultCall
+ )) == 0
+ )
+ {
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState (pCall, LINECALLSTATE_ONHOLD, 0);
+ SetCallState (pConsultCall, LINECALLSTATE_DIALTONE, 0);
+ }
+
+ if (lpCallParams)
+ {
+ DrvFree (lpCallParams);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetupTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ { "htConsultCall", htConsultCall },
+ { "lphdConsultCall", lphdConsultCall },
+ { szlpCallParams, lpCallParams }
+ };
+ FUNC_INFO info = { "lineSetupTransfer", ASYNC, 5, params, TSPI_lineSetupTransfer_postProcess };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) htConsultCall;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) lphdConsultCall;
+
+ if (lpCallParams)
+ {
+ info.pAsyncReqInfo->dwParam4 = (DWORD) DrvAlloc(
+ (size_t) lpCallParams->dwTotalSize
+ );
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam4,
+ (void far *) lpCallParams,
+ (size_t) lpCallParams->dwTotalSize
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineSwapHold_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ SetCallState(
+ (PDRVCALL) pAsyncReqInfo->dwParam1,
+ LINECALLSTATE_ONHOLD,
+ 0
+ );
+
+ SetCallState(
+ (PDRVCALL) pAsyncReqInfo->dwParam2,
+ LINECALLSTATE_CONNECTED,
+ 0
+ );
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSwapHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdActiveCall,
+ HDRVCALL hdHeldCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { "hdActiveCall", hdActiveCall },
+ { "hdHeldCall", hdHeldCall }
+ };
+ FUNC_INFO info = { "lineSwapHold", ASYNC, 3, params, TSPI_lineSwapHold_postProcess };
+ PDRVCALL pActiveCall = (PDRVCALL) hdActiveCall;
+ PDRVCALL pHeldCall = (PDRVCALL) hdHeldCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdActiveCall;
+ info.pAsyncReqInfo->dwParam2 = (DWORD) hdHeldCall;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUncompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwCompletionID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwCompletionID", dwCompletionID }
+ };
+ FUNC_INFO info = { "lineUncompleteCall", ASYNC, 3, params };
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineUnhold_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ if ((pAsyncReqInfo->lResult == 0))
+ {
+ PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
+
+
+ if (pCall->dwCallState == LINECALLSTATE_ONHOLD)
+ {
+ SetCallState (pCall, LINECALLSTATE_CONNECTED, 0);
+ }
+ else
+ {
+ pAsyncReqInfo->lResult = LINEERR_INVALCALLSTATE;
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUnhold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdCall, hdCall },
+ };
+ FUNC_INFO info = { "lineUnhold", ASYNC, 2, params, TSPI_lineUnhold_postProcess };
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdCall;
+
+ return (Epilog (&info));
+}
+
+
+void
+FAR
+PASCAL
+TSPI_lineUnpark_postProcess(
+ char far *lpszFuncName,
+ PASYNC_REQUEST_INFO pAsyncReqInfo,
+ BOOL bSync
+ )
+{
+ PDRVCALL pCall;
+ PDRVLINE pLine = (PDRVLINE) pAsyncReqInfo->dwParam1;
+ DWORD dwAddressID = pAsyncReqInfo->dwParam2;
+ HTAPICALL htCall = (HTAPICALL) pAsyncReqInfo->dwParam3;
+ LPHDRVCALL lphdCall = (LPHDRVCALL) pAsyncReqInfo->dwParam4;
+ LPSTR lpszDestAddress = (LPSTR) pAsyncReqInfo->dwParam5;
+
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ if ((pAsyncReqInfo->lResult = AllocCall (
+ pLine,
+ htCall,
+ NULL,
+ &pCall
+ )) == 0)
+ {
+ // BUGBUG deal w/ addr id
+
+ *lphdCall = (HDRVCALL) pCall;
+ }
+ }
+
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ bSync
+ );
+
+ if (pAsyncReqInfo->lResult == 0)
+ {
+ SetCallState (pCall, LINECALLSTATE_ONHOLD, 0);
+ }
+
+ if (lpszDestAddress)
+ {
+ DrvFree (lpszDestAddress);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUnpark(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdLine, hdLine },
+ { "dwAddressID", dwAddressID },
+ { "htCall", htCall },
+ { "lphdCall", lphdCall },
+ { "lpszDestAddress", lpszDestAddress }
+ };
+ FUNC_INFO info = { "lineUnpark", ASYNC, 6, params, TSPI_lineUnpark_postProcess };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = (DWORD) hdLine;
+ info.pAsyncReqInfo->dwParam2 = dwAddressID;
+ info.pAsyncReqInfo->dwParam3 = (DWORD) htCall;
+ info.pAsyncReqInfo->dwParam4 = (DWORD) lphdCall;
+
+ if (lpszDestAddress)
+ {
+ size_t len = strlen (lpszDestAddress) + 1;
+
+
+ info.pAsyncReqInfo->dwParam5 = (DWORD) DrvAlloc (len);
+
+ memcpy(
+ (void far *) info.pAsyncReqInfo->dwParam5,
+ lpszDestAddress,
+ len
+ );
+ }
+
+ return (Epilog (&info));
+}
+
+
+
+//
+// -------------------------- TSPI_phoneXxx funcs -----------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_phoneClose(
+ HDRVPHONE hdPhone
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone }
+ };
+ FUNC_INFO info = { "phoneClose", SYNC, 1, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ //
+ // This is more of a "command" than a request, in that TAPI.DLL is
+ // going to consider the phone closed whether we like it or not.
+ // Therefore we want to free up the phone even if the user chooses
+ // to return an error.
+ //
+
+ if (!Prolog (&info))
+ {
+ // return (Epilog (&info));
+ }
+
+ pPhone->htPhone = (HTAPIPHONE) NULL;
+
+ //UpdateWidgetList();
+ PostUpdateWidgetListMsg();
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { szhwndOwner, hwndOwner },
+ { "lpszDeviceClass", lpszDeviceClass }
+ };
+ FUNC_INFO info = { "phoneConfigDialog", SYNC, 3, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+ //
+ // Note: MessageBox() implements a get/dispatch msg loop which allows
+ // other apps (or other windows within the calling app) to gain
+ // focus. Once these other windows/apps have focus, it's
+ // possible that they will call into TAPI, and this service
+ // provider could be re-entered.
+ //
+
+ MessageBox(
+ hwndOwner,
+ "Config dlg for ESP phone device",
+ "TSPI_phoneConfigDialog",
+ MB_OK
+ );
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "lpParams", lpParams },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info =
+ {
+ "phoneDevSpecific",
+ ASYNC,
+ 4,
+ params,
+ TSPI_lineDevSpecific_postProcess
+ };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ info.pAsyncReqInfo->dwParam1 = lpParams;
+ info.pAsyncReqInfo->dwParam2 = dwSize;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetButtonInfo(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO lpButtonInfo
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "lpButtonInfo", lpButtonInfo }
+ };
+ FUNC_INFO info = { "phoneGetButtonInfo", SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetData(
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID lpData,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwDataID", dwDataID },
+ { "lpData", lpData },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "phoneGetData", SYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPPHONECAPS lpPhoneCaps
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwExtVersion", dwExtVersion },
+ { "lpPhoneCaps", lpPhoneCaps }
+ };
+ FUNC_INFO info = { "phoneGetDevCaps", SYNC, 4, params };
+ DWORD dwUsedSize;
+ PDRVPHONE pPhone = GetPhone (dwDeviceID);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+
+ //
+ // Figure out how much caps data to copy
+ //
+
+ if (lpPhoneCaps->dwTotalSize >= pPhone->PhoneCaps.dwNeededSize)
+ {
+ dwUsedSize = pPhone->PhoneCaps.dwNeededSize;
+ }
+ else
+ {
+ dwUsedSize = sizeof(PHONECAPS);
+ }
+
+ memcpy(
+ &lpPhoneCaps->dwNeededSize,
+ &pPhone->PhoneCaps.dwNeededSize,
+ (size_t) dwUsedSize - 4 // - 4 since not overwriting dwTotalSize
+ );
+
+ lpPhoneCaps->dwUsedSize = dwUsedSize;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDisplay(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDisplay
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpDisplay", lpDisplay }
+ };
+ FUNC_INFO info = { "phoneGetDisplay", SYNC, 2, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPPHONEEXTENSIONID lpExtensionID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpExtensionID", lpExtensionID }
+ };
+ FUNC_INFO info = { "phoneGetExtensionID", SYNC, 3, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ memcpy (lpExtensionID, &gPhoneExtID, sizeof(PHONEEXTENSIONID));
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetGain(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwGain
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev },
+ { "lpdwGain", lpdwGain }
+ };
+ FUNC_INFO info = { "phoneGetGain", SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetHookSwitch(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwHookSwitchDevs
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpdwHookSwitchDevs", lpdwHookSwitchDevs }
+ };
+ FUNC_INFO info = { "phoneGetHookSwitch", SYNC, 2, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetIcon(
+ DWORD dwDeviceID,
+ LPCSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass },
+ { "lphIcon", lphIcon }
+ };
+ FUNC_INFO info = { "phoneGetIcon", SYNC, 3, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ *lphIcon = ghIconPhone;
+
+ return (Epilog (&info));
+}
+
+
+#ifdef WIN32
+LONG
+TSPIAPI
+TSPI_phoneGetID(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+#else
+LONG
+TSPIAPI
+TSPI_phoneGetID(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+#endif
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpDeviceID", lpDeviceID },
+ { "lpszDeviceClass", lpszDeviceClass }
+#ifdef WIN32
+ ,{ "hTargetProcess", hTargetProcess }
+#endif
+ };
+#ifdef WIN32
+ FUNC_INFO info = { "phoneGetID", SYNC, 4, params };
+#else
+ FUNC_INFO info = { "phoneGetID", SYNC, 3, params };
+#endif
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+ DWORD i, dwDeviceID, dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ for (i = 0; aszDeviceClasses[i]; i++)
+ {
+ if (_stricmp (lpszDeviceClass, aszDeviceClasses[i]) == 0)
+ {
+ break;
+ }
+ }
+
+ if (!aszDeviceClasses[i])
+ {
+ info.lResult = PHONEERR_NODEVICE;
+ return (Epilog (&info));
+ }
+
+ if (lpDeviceID->dwTotalSize < dwNeededSize)
+ {
+ lpDeviceID->dwNeededSize = dwNeededSize;
+ lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
+
+ return (Epilog (&info));
+ }
+
+ if (i == 1)
+ {
+ dwDeviceID = pPhone->dwDeviceID;
+ }
+ else
+ {
+ if (gbShowLineGetIDDlg)
+ {
+ char szDlgTitle[64];
+ EVENT_PARAM params[] =
+ {
+ { "dwDeviceID", PT_DWORD, gdwDefLineGetIDID, 0 }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, szDlgTitle, XX_REQRESULTPOSTQUIT, params };
+ HWND hwnd;
+
+
+ if (strlen (lpszDeviceClass) > 20)
+ {
+ ((char far *)lpszDeviceClass)[19] = 0;
+ }
+
+ wsprintf(
+ szDlgTitle,
+ "TSPI_phoneGetID: select ID for class '%s'",
+ lpszDeviceClass
+ );
+
+ hwnd = CreateDialogParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) NULL,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ );
+
+ MsgLoopInTAPIClientContext (hwnd);
+
+ dwDeviceID = params[0].dwValue;
+ }
+ else
+ {
+ dwDeviceID = gdwDefLineGetIDID;
+ }
+ }
+
+ lpDeviceID->dwNeededSize =
+ lpDeviceID->dwUsedSize = dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof(DWORD);
+ lpDeviceID->dwStringOffset = sizeof(VARSTRING);
+
+ *((LPDWORD)(lpDeviceID + 1)) = dwDeviceID;
+
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetLamp(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPDWORD lpdwLampMode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "lpdwLampMode", lpdwLampMode }
+ };
+ FUNC_INFO info = { "phoneGetLamp", SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetRing(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwRingMode,
+ LPDWORD lpdwVolume
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpdwRingMode", lpdwRingMode },
+ { "lpdwVolume", lpdwVolume }
+ };
+ FUNC_INFO info = { "phoneGetRing", SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetStatus(
+ HDRVPHONE hdPhone,
+ LPPHONESTATUS lpPhoneStatus
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "lpPhoneStatus", lpPhoneStatus }
+ };
+ FUNC_INFO info = { "phoneGetStatus", SYNC, 2, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ memcpy(
+ &lpPhoneStatus->dwNeededSize,
+ &pPhone->PhoneStatus.dwNeededSize,
+ sizeof(PHONESTATUS) - 4 // - 4 since not overwriting dwTotalSize
+ );
+
+ if (pPhone->PhoneStatus.dwDisplaySize)
+ {
+ lpPhoneStatus->dwNeededSize += pPhone->PhoneStatus.dwDisplaySize;
+
+ if (lpPhoneStatus->dwTotalSize >= lpPhoneStatus->dwNeededSize)
+ {
+ lpPhoneStatus->dwDisplaySize = pPhone->PhoneStatus.dwDisplaySize;
+ lpPhoneStatus->dwDisplayOffset = (DWORD) sizeof(PHONESTATUS);
+
+ strcpy(
+ ((char far *) lpPhoneStatus) + sizeof(PHONESTATUS),
+ ((char far *) &pPhone->PhoneStatus) +
+ pPhone->PhoneStatus.dwDisplayOffset
+ );
+
+ lpPhoneStatus->dwUsedSize = lpPhoneStatus->dwNeededSize;
+ }
+ }
+
+
+ //
+ // We're getting the LampModes field from the PhoneCaps
+ //
+
+ if (pPhone->PhoneCaps.dwLampModesSize)
+ {
+ lpPhoneStatus->dwNeededSize += pPhone->PhoneCaps.dwLampModesSize;
+
+ if (lpPhoneStatus->dwTotalSize >= lpPhoneStatus->dwNeededSize)
+ {
+ lpPhoneStatus->dwLampModesSize =
+ pPhone->PhoneCaps.dwLampModesSize;
+ lpPhoneStatus->dwLampModesOffset = lpPhoneStatus->dwUsedSize;
+
+ strcpy(
+ ((char far *) lpPhoneStatus) +
+ lpPhoneStatus->dwLampModesOffset,
+ ((char far *) &pPhone->PhoneCaps) +
+ pPhone->PhoneCaps.dwLampModesOffset
+ );
+
+ lpPhoneStatus->dwUsedSize = lpPhoneStatus->dwNeededSize;
+ }
+ }
+
+
+ //
+ // We're getting the DevSpecific field from the PhoneCaps
+ //
+
+ if (pPhone->PhoneCaps.dwDevSpecificSize)
+ {
+ lpPhoneStatus->dwNeededSize += pPhone->PhoneCaps.dwDevSpecificSize;
+
+ if (lpPhoneStatus->dwTotalSize >= lpPhoneStatus->dwNeededSize)
+ {
+ lpPhoneStatus->dwDevSpecificSize =
+ pPhone->PhoneCaps.dwDevSpecificSize;
+ lpPhoneStatus->dwDevSpecificOffset = lpPhoneStatus->dwUsedSize;
+
+ strcpy(
+ ((char far *) lpPhoneStatus) +
+ lpPhoneStatus->dwDevSpecificOffset,
+ ((char far *) &pPhone->PhoneCaps) +
+ pPhone->PhoneCaps.dwDevSpecificOffset
+ );
+
+ lpPhoneStatus->dwUsedSize = lpPhoneStatus->dwNeededSize;
+ }
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetVolume(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwVolume
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev, aHookSwitchDevs },
+ { "lpdwVolume", lpdwVolume }
+ };
+ FUNC_INFO info = { "phoneGetVolume", SYNC, 3, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwExtVersion", lpdwExtVersion }
+ };
+ FUNC_INFO info = { "phoneNegotiateExtVersion", SYNC, 5, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ ShowStr(
+ "TSPI_phonNegoExtVer: setting *lpdwExtVersion = x%lx",
+ dwHighVersion
+ );
+
+ *lpdwExtVersion = dwHighVersion;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "dwLowVersion", dwLowVersion },
+ { "dwHighVersion", dwHighVersion },
+ { "lpdwTSPIVersion", lpdwTSPIVersion }
+ };
+ FUNC_INFO info = { "phoneNegotiateTSPIVersion", SYNC, 4, params };
+
+
+ {
+ // BUGBUG hangs if gbManualResults set, so...
+
+ BOOL bManualResultsSav = gbManualResults;
+
+
+ gbManualResults = FALSE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ gbManualResults = bManualResultsSav;
+ }
+
+ *lpdwTSPIVersion = gdwTSPIVersion;
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneOpen(
+ DWORD dwDeviceID,
+ HTAPIPHONE htPhone,
+ LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion,
+ PHONEEVENT lpfnEventProc
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwDeviceID, dwDeviceID },
+ { "htPhone", htPhone },
+ { "lphdPhone", lphdPhone },
+ { "dwTSPIVersion", dwTSPIVersion },
+ { "lpfnEventProc", lpfnEventProc }
+ };
+ FUNC_INFO info = { "phoneOpen", SYNC, 5, params };
+ PDRVPHONE pPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ if (!(pPhone = GetPhone (dwDeviceID)))
+ {
+ // BUGBUG
+ }
+
+ pPhone->htPhone = htPhone;
+ pPhone->lpfnEventProc = lpfnEventProc;
+
+ *lphdPhone = (HDRVPHONE) pPhone;
+
+ //UpdateWidgetList();
+ PostUpdateWidgetListMsg();
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSelectExtVersion(
+ HDRVPHONE hdPhone,
+ DWORD dwExtVersion
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwExtVersion", dwExtVersion }
+ };
+ FUNC_INFO info = { "phoneSelectExtVersion", SYNC, 2, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetButtonInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO const lpButtonInfo
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "lpButtonInfo", lpButtonInfo }
+ };
+ FUNC_INFO info = { "phoneSetButtonInfo", ASYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetData(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID const lpData,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwDataID", dwDataID },
+ { "lpData", lpData },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "phoneSetData", ASYNC, 5, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetDisplay(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRow,
+ DWORD dwColumn,
+ LPCSTR lpsDisplay,
+ DWORD dwSize
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwRow", dwRow },
+ { "dwColumn", dwColumn },
+ { "lpsDisplay", lpsDisplay },
+ { szdwSize, dwSize }
+ };
+ FUNC_INFO info = { "phoneSetDisplay", ASYNC, 6, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetGain(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwGain
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev, aHookSwitchDevs },
+ { "dwGain", dwGain }
+ };
+ FUNC_INFO info = { "phoneSetGain", ASYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetHookSwitch(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDevs,
+ DWORD dwHookSwitchMode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDevs", dwHookSwitchDevs, aHookSwitchDevs },
+ { "dwHookSwitchMode", dwHookSwitchMode, aHookSwitchModes }
+ };
+ FUNC_INFO info = { "phoneSetHookSwitch", ASYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetLamp(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ DWORD dwLampMode
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwButtonLampID", dwButtonLampID },
+ { "dwLampMode", dwLampMode, aLampModes }
+ };
+ FUNC_INFO info = { "phoneSetLamp", ASYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetRing(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRingMode,
+ DWORD dwVolume
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwRingMode", dwRingMode },
+ { "dwVolume", dwVolume }
+ };
+ FUNC_INFO info = { "phoneSetRing", ASYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetStatusMessages(
+ HDRVPHONE hdPhone,
+ DWORD dwPhoneStates,
+ DWORD dwButtonModes,
+ DWORD dwButtonStates
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhdPhone, hdPhone },
+ { "dwPhoneStates", dwPhoneStates, aPhoneStates },
+ { "dwButtonModes", dwButtonModes, aButtonModes },
+ { "dwButtonStates", dwButtonStates, aButtonStates }
+ };
+ FUNC_INFO info = { "phoneSetStatusMessages", SYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetVolume(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwVolume
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwRequestID, dwRequestID },
+ { szhdPhone, hdPhone },
+ { "dwHookSwitchDev", dwHookSwitchDev }, // BUGBUG lookup
+ { "dwVolume", dwVolume }
+ };
+ FUNC_INFO info = { "phoneSetVolume", ASYNC, 4, params };
+ PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ return (Epilog (&info));
+}
+
+
+
+//
+// ------------------------- TSPI_providerXxx funcs ---------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhwndOwner, hwndOwner },
+ { szdwPermanentProviderID, dwPermanentProviderID }
+ };
+ FUNC_INFO info = { "providerConfig", SYNC, 2, params };
+
+
+ //
+ // Set gbExeStarted to TRUE so we don't get caught in the wait
+ // loop in Prolog, then reset it as appropriate
+ //
+
+ gbExeStarted = TRUE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ ESPConfigDialog();
+
+ gbExeStarted = (ghwndMain ? TRUE : FALSE);
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreateLineDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { "dwTempID", dwTempID },
+ { szdwDeviceID, dwDeviceID }
+ };
+ FUNC_INFO info = { "providerCreateLineDevice", SYNC, 2, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ AllocLine (dwDeviceID);
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreatePhoneDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { "dwTempID", dwTempID },
+ { szdwDeviceID, dwDeviceID }
+ };
+ FUNC_INFO info = { "providerCreatePhoneDevice", SYNC, 2, params };
+
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ AllocPhone (dwDeviceID);
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szdwPermanentProviderID, dwPermanentProviderID },
+ { "lpdwNumLines", lpdwNumLines },
+ { "lpdwNumPhones", lpdwNumPhones },
+ { "hProvider", hProvider },
+ { "lpfnLineCreateProc", lpfnLineCreateProc },
+ { "lpfnPhoneCreateProc", lpfnPhoneCreateProc }
+ };
+ FUNC_INFO info = { "providerEnumDevices", SYNC, 6, params };
+
+
+ {
+ // BUGBUG hangs if gbManualResults set, so...
+
+ BOOL bManualResultsSav = gbManualResults;
+
+
+ gbManualResults = FALSE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ gbManualResults = bManualResultsSav;
+ }
+
+ *lpdwNumLines = gdwNumLines;
+ *lpdwNumPhones = gdwNumPhones;
+
+ gpfnLineCreateProc = lpfnLineCreateProc;
+ gpfnPhoneCreateProc = lpfnPhoneCreateProc;
+
+ ghProvider = hProvider;
+
+ return (Epilog (&info));
+}
+
+#ifdef WIN32
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc,
+ LPDWORD lpdwTSPIOptions
+ )
+#else
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc
+ )
+#endif
+{
+ FUNC_PARAM params[] =
+ {
+ { "dwTSPIVersion", dwTSPIVersion },
+ { szdwPermanentProviderID, dwPermanentProviderID },
+ { "dwLineDeviceIDBase", dwLineDeviceIDBase },
+ { "dwPhoneDeviceIDBase", dwPhoneDeviceIDBase },
+ { "dwNumLines", dwNumLines },
+ { "dwNumPhones", dwNumPhones },
+ { "lpfnCompletionProc", lpfnCompletionProc }
+ };
+ FUNC_INFO info = { "providerInit", SYNC, 7, params };
+ DWORD i;
+ LONG lResult;
+
+
+#ifdef WIN32
+
+ *lpdwTSPIOptions = LINETSPIOPTION_NONREENTRANT;
+
+#endif
+
+ {
+ // BUGBUG hangs if gbManualResults set, so...
+
+ BOOL bManualResultsSav = gbManualResults;
+
+
+ gbManualResults = FALSE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ gbManualResults = bManualResultsSav;
+ }
+
+ gdwLineDeviceIDBase = dwLineDeviceIDBase;
+ gdwPermanentProviderID = dwPermanentProviderID;
+ gpfnCompletionProc = lpfnCompletionProc;
+
+ if (info.lResult == 0)
+ {
+ gdwNumInits++;
+ }
+
+ for (i = dwLineDeviceIDBase; i < (dwLineDeviceIDBase + dwNumLines); i++)
+ {
+ AllocLine (i);
+ }
+
+ for (i = dwPhoneDeviceIDBase; i < (dwPhoneDeviceIDBase + dwNumPhones); i++)
+ {
+ AllocPhone (i);
+ }
+
+ ghIconLine = LoadIcon (hInst, (LPCSTR)MAKEINTRESOURCE(IDI_ICON3));
+ ghIconPhone = LoadIcon (hInst, (LPCSTR)MAKEINTRESOURCE(IDI_ICON2));
+
+ if ((lResult = Epilog (&info)) == 0)
+ {
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON1), TRUE);
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON2), TRUE);
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON3), TRUE);
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhwndOwner, hwndOwner },
+ { szdwPermanentProviderID, dwPermanentProviderID }
+ };
+ FUNC_INFO info = { "providerInstall", SYNC, 2, params };
+
+
+ //
+ // Set gbExeStarted to TRUE so we don't get caught in the wait
+ // loop in Prolog, then reset it as appropriate
+ //
+
+ gbExeStarted = TRUE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ gbExeStarted = (ghwndMain ? TRUE : FALSE);
+
+
+ //
+ // Check to see if we're already installed
+ //
+
+ if (IsESPInstalled (hwndOwner))
+ {
+ info.lResult = LINEERR_OPERATIONFAILED;
+ }
+ else
+ {
+ UpdateTelephonIni (dwPermanentProviderID);
+ }
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { szhwndOwner, hwndOwner },
+ { szdwPermanentProviderID, dwPermanentProviderID }
+ };
+ FUNC_INFO info = { "providerRemove", SYNC, 2, params };
+ char szProviderN[16];
+
+
+ //
+ // Set gbExeStarted to TRUE so we don't get caught in the wait
+ // loop in Prolog, then reset it as appropriate
+ //
+
+ gbExeStarted = TRUE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ gbExeStarted = (ghwndMain ? TRUE : FALSE);
+
+
+ //
+ // Clean up the [ProviderN] section in telephon.ini
+ //
+
+ wsprintf (szProviderN, "%s%ld", szProvider, dwPermanentProviderID);
+
+ WritePrivateProfileString(
+ szProviderN,
+ (LPCSTR) NULL,
+ (LPCSTR) NULL,
+ szTelephonIni
+ );
+
+ return (Epilog (&info));
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion
+ )
+{
+ FUNC_PARAM params[] =
+ {
+ { "dwTSPIVersion", dwTSPIVersion }
+ };
+ FUNC_INFO info = { "providerShutdown", SYNC, 1, params };
+ LONG lResult;
+
+
+ {
+ // BUGBUG hangs if gbManualResults set, so...
+
+ BOOL bManualResultsSav = gbManualResults;
+
+
+ gbManualResults = FALSE;
+
+ if (!Prolog (&info))
+ {
+ return (Epilog (&info));
+ }
+
+ gbManualResults = bManualResultsSav;
+ }
+
+ if (info.lResult == 0)
+ {
+ gdwNumInits--;
+ }
+
+
+ //
+ // Since we're shutting down just tear everything down by hand
+ // (& save having to do all the MostMessage's, etc)
+ //
+
+ while (gaWidgets)
+ {
+ PDRVWIDGET pNextWidget = gaWidgets->pNext;
+
+
+ DrvFree (gaWidgets);
+ gaWidgets = pNextWidget;
+ }
+
+ SendMessage (ghwndList1, LB_RESETCONTENT, 0, 0);
+
+ if (gbAutoClose)
+ {
+ PostMessage (ghwndMain, WM_CLOSE, 0, 0);
+ }
+
+ DestroyIcon (ghIconLine);
+ DestroyIcon (ghIconPhone);
+
+ ghProvider = NULL;
+
+#ifdef WIN32
+
+ SaveIniSettings();
+
+#endif
+
+ lResult = Epilog (&info);
+
+#ifdef WIN32
+
+ PostMessage (ghwndMain, WM_CLOSE, 0, 0);
+
+ WaitForSingleObject (ghMsgLoopThread, INFINITE);
+
+ CloseHandle (ghMsgLoopThread);
+
+ ghMsgLoopThread = NULL;
+
+#endif
+
+ //
+ // Disable the buttons so the user doesn't press one & cause a GPF
+ //
+
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON1), FALSE);
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON2), FALSE);
+ EnableWindow (GetDlgItem (ghwndMain, IDC_BUTTON3), FALSE);
+
+ return lResult;
+}
+
+
+#pragma warning (default:4047)
+
+//
+// ------------------------ Private support routines --------------------------
+//
+
+
+VOID
+ShowStr(
+ char *format,
+ ...
+ )
+{
+ static char buf[256], bigBuf[2048] = "";
+ static int iTextLen = 1;
+ int len;
+ va_list ap;
+
+
+ if (gbDisableUI)
+ {
+ return;
+ }
+
+ va_start(ap, format);
+
+ // BUGBUG what if !ghwndMain
+
+ wvsprintf (buf, format, ap);
+
+ strcat (buf, "\r\n");
+
+ len = (int) strlen (buf);
+
+ if ((iTextLen + len) <= 2048)
+ {
+ iTextLen += len;
+
+
+ //
+ // Cat the new buf to the global buf that contains all the text
+ // that'll get added to the edit control the next time a
+ // WM_ADDTEXT msg is processed
+ //
+
+#ifdef WIN32
+ WaitForSingleObject (ghShowStrBufMutex, INFINITE);
+#endif
+ if (bigBuf[0] == 0)
+ {
+ //
+ // The handler for WM_ADDTEXT zeroes out the first byte in the
+ // buffer when it has added the text to the edit control, so if
+ // here we know we need to post another msg to alert that more
+ // text needs to be added
+ //
+
+ PostMessage(
+ ghwndMain,
+ WM_ADDTEXT,
+ ESP_MSG_KEY,
+ (LPARAM) bigBuf
+ );
+
+ iTextLen = 1; // to acct for null terminator
+ }
+
+ strcat (bigBuf, buf);
+
+#ifdef WIN32
+ ReleaseMutex (ghShowStrBufMutex);
+#endif
+
+ }
+ else
+ {
+ OutputDebugString ("ESP.TSP: buf overflow:\t");
+ OutputDebugString (buf);
+ }
+
+ va_end(ap);
+}
+
+
+BOOL
+ScanForDWORD(
+ char far *pBuf,
+ LPDWORD lpdw
+ )
+{
+ char c;
+ BOOL bValid = FALSE;
+ DWORD d = 0;
+
+ while ((c = *pBuf))
+ {
+ if ((c >= '0') && (c <= '9'))
+ {
+ c -= '0';
+ }
+ else if ((c >= 'a') && (c <= 'f'))
+ {
+ c -= ('a' - 10);
+ }
+ else if ((c >= 'A') && (c <= 'F'))
+ {
+ c -= ('A' - 10);
+ }
+ else
+ {
+ break;
+ }
+
+ bValid = TRUE;
+
+ d *= 16;
+
+ d += (DWORD) c;
+
+ pBuf++;
+ }
+
+ if (bValid)
+ {
+ *lpdw = d;
+ }
+
+ return bValid;
+}
+
+
+void
+UpdateTelephonIni(
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // 1.3 Support: write out the num lines & phones we support to
+ // [ProviderN] section in telephon.ini
+ //
+
+ char buf[16], szProviderN[16];
+
+
+ wsprintf (szProviderN, "%s%ld", szProvider, dwPermanentProviderID);
+
+ wsprintf (buf, "%ld", gdwNumLines);
+
+ WritePrivateProfileString(
+ szProviderN,
+ "NumLines",
+ buf,
+ szTelephonIni
+ );
+
+ wsprintf (buf, "%ld", gdwNumPhones);
+
+ WritePrivateProfileString(
+ szProviderN,
+ "NumPhones",
+ buf,
+ szTelephonIni
+ );
+}
+
+
+char far *
+GetFlags(
+ DWORD dwFlags,
+ PLOOKUP pLookup
+ )
+{
+ int i;
+ static char buf[256];
+ char far *p = (char far *) NULL;
+
+
+ buf[0] = 0;
+
+ for (i = 0; (dwFlags && (pLookup[i].dwVal != 0xffffffff)); i++)
+ {
+ if (dwFlags & pLookup[i].dwVal)
+ {
+ strcat (buf, pLookup[i].lpszVal);
+ strcat (buf, " ");
+
+ dwFlags = dwFlags & (~pLookup[i].dwVal);
+ }
+ }
+
+ if (buf[0])
+ {
+ if ((p = (char far *) DrvAlloc (strlen (buf) + 1)))
+ {
+ strcpy (p, buf);
+ }
+ }
+
+ return p;
+}
+
+
+void
+ShowLineEvent(
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ if (gbShowEvents)
+ {
+ static DWORD adwLineMsgs[] =
+ {
+ LINE_ADDRESSSTATE,
+ LINE_CALLINFO,
+ LINE_CALLSTATE,
+ LINE_CLOSE,
+ LINE_DEVSPECIFIC,
+ LINE_DEVSPECIFICFEATURE,
+ LINE_GATHERDIGITS,
+ LINE_GENERATE,
+ LINE_LINEDEVSTATE,
+ LINE_MONITORDIGITS,
+ LINE_MONITORMEDIA,
+ LINE_MONITORTONE,
+
+ LINE_CREATE,
+
+ LINE_NEWCALL,
+ LINE_CALLDEVSPECIFIC,
+ LINE_CALLDEVSPECIFICFEATURE,
+
+ 0xffffffff
+ };
+
+ static char *aszLineMsgs[] =
+ {
+ "LINE_ADDRESSSTATE",
+ "LINE_CALLINFO",
+ "LINE_CALLSTATE",
+ "LINE_CLOSE",
+ "LINE_DEVSPECIFIC",
+ "LINE_DEVSPECIFICFEATURE",
+ "LINE_GATHERDIGITS",
+ "LINE_GENERATE",
+ "LINE_LINEDEVSTATE",
+ "LINE_MONITORDIGITS",
+ "LINE_MONITORMEDIA",
+ "LINE_MONITORTONE",
+
+ "LINE_CREATE",
+
+ "LINE_NEWCALL",
+ "LINE_CALLDEVSPECIFIC",
+ "LINE_CALLDEVSPECIFICFEATURE"
+ };
+
+ int i;
+ char far *lpszParam1 = (char far *) NULL;
+ char far *lpszParam2 = (char far *) NULL;
+ char far *lpszParam3 = (char far *) NULL;
+
+
+ for (i = 0; adwLineMsgs[i] != 0xffffffff; i++)
+ {
+ if (dwMsg == adwLineMsgs[i])
+ {
+ ShowStr(
+ "%ssent %s : htLine=x%lx, htCall=x%lx",
+ szCallUp,
+ aszLineMsgs[i],
+ htLine,
+ htCall
+ );
+
+ break;
+ }
+ }
+
+ if (adwLineMsgs[i] == 0xffffffff)
+ {
+ ShowStr(
+ "%ssent <unknown msg id, x%lx> : htLine=x%lx, htCall=x%lx",
+ szCallUp,
+ dwMsg,
+ htLine,
+ htCall
+ );
+ }
+
+ switch (dwMsg)
+ {
+ case LINE_ADDRESSSTATE:
+
+ lpszParam2 = GetFlags (dwParam2, aAddressStates);
+ break;
+
+ case LINE_CALLINFO:
+
+ lpszParam1 = GetFlags (dwParam1, aCallInfoStates);
+ break;
+
+ case LINE_CALLSTATE:
+
+ lpszParam1 = GetFlags (dwParam1, aCallStates);
+ break;
+
+ case LINE_LINEDEVSTATE:
+
+ lpszParam1 = GetFlags (dwParam1, aLineStates);
+ break;
+
+ } // switch
+
+ ShowStr(
+ "%s%sdwParam1=x%lx, %s",
+ szCallUp,
+ szTab,
+ dwParam1,
+ (lpszParam1 ? lpszParam1 : "")
+ );
+
+ ShowStr(
+ "%s%sdwParam2=x%lx, %s",
+ szCallUp,
+ szTab,
+ dwParam2,
+ (lpszParam2 ? lpszParam2 : "")
+ );
+
+ ShowStr(
+ "%s%sdwParam3=x%lx, %s",
+ szCallUp,
+ szTab,
+ dwParam3,
+ (lpszParam3 ? lpszParam3 : "")
+ );
+
+ if (lpszParam1)
+ {
+ DrvFree (lpszParam1);
+ }
+
+ if (lpszParam2)
+ {
+ DrvFree (lpszParam2);
+ }
+
+ if (lpszParam3)
+ {
+ DrvFree (lpszParam3);
+ }
+ }
+}
+
+
+void
+ShowPhoneEvent(
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ if (gbShowEvents)
+ {
+ static char *aszPhoneMsgs[] =
+ {
+ "PHONE_BUTTON",
+ "PHONE_CLOSE",
+ "PHONE_DEVSPECIFIC",
+ "PHONE_REPLY",
+ "PHONE_STATE",
+
+ "PHONE_CREATE"
+ };
+ char far *lpszParam1 = (char far *) NULL;
+ char far *lpszParam2 = (char far *) NULL;
+ char far *lpszParam3 = (char far *) NULL;
+
+
+ if ((dwMsg < PHONE_BUTTON) ||
+ ((dwMsg > PHONE_STATE) && (dwMsg != PHONE_CREATE)))
+ {
+ ShowStr(
+ "%ssent <unknown msg id, x%lx> : htPhone=x%lx",
+ szCallUp,
+ dwMsg,
+ htPhone
+ );
+ }
+ else
+ {
+ //
+ // Munge dwMsg so that we get the right index into aszLineMsgs
+ //
+
+ if (dwMsg == PHONE_CREATE)
+ {
+ dwMsg = 5;
+ }
+ else
+ {
+ dwMsg -= PHONE_BUTTON;
+ }
+
+ ShowStr(
+ "%ssent %s : htPhone=x%lx",
+ szCallUp,
+ aszPhoneMsgs[dwMsg],
+ htPhone
+ );
+ }
+
+ switch (dwMsg)
+ {
+ case PHONE_BUTTON:
+
+ lpszParam2 = GetFlags (dwParam2, aButtonModes);
+ lpszParam3 = GetFlags (dwParam3, aButtonStates);
+ break;
+
+ case PHONE_STATE:
+
+ lpszParam1 = GetFlags (dwParam1, aPhoneStates);
+ break;
+
+ } // switch
+
+ ShowStr(
+ "%s%sdwParam1=x%lx, %s",
+ szCallUp,
+ szTab,
+ dwParam1,
+ (lpszParam1 ? lpszParam1 : "")
+ );
+
+ ShowStr(
+ "%s%sdwParam2=x%lx, %s",
+ szCallUp,
+ szTab,
+ dwParam2,
+ (lpszParam2 ? lpszParam2 : "")
+ );
+
+ ShowStr(
+ "%s%sdwParam3=x%lx, %s",
+ szCallUp,
+ szTab,
+ dwParam3,
+ (lpszParam3 ? lpszParam3 : "")
+ );
+
+ if (lpszParam1)
+ {
+ DrvFree (lpszParam1);
+ }
+
+ if (lpszParam2)
+ {
+ DrvFree (lpszParam2);
+ }
+
+ if (lpszParam3)
+ {
+ DrvFree (lpszParam3);
+ }
+ }
+}
+
+
+BOOL
+CALLBACK
+AboutDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ EndDialog (hwnd, 0);
+ break;
+ }
+ break;
+
+#ifdef WIN32
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+#else
+ case WM_CTLCOLOR:
+ {
+ if (HIWORD(lParam) == CTLCOLOR_STATIC)
+ {
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+ }
+ break;
+ }
+#endif
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+__loadds
+CALLBACK
+CallDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ DWORD i;
+
+ typedef struct _DLG_INST_DATA
+ {
+ PEVENT_PARAM_HEADER pParamsHeader;
+
+ LONG lLastSel;
+
+ char szComboText[MAX_STRING_PARAM_SIZE];
+
+ HGLOBAL hComboDS;
+
+ LPVOID pComboSeg;
+
+ HWND hwndCombo;
+
+ } DLG_INST_DATA, *PDLG_INST_DATA;
+
+ PDLG_INST_DATA pDlgInstData = (PDLG_INST_DATA)
+ GetWindowLong (hwnd, DWL_USER);
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ //
+ // Alloc a dlg instance data struct, init it, & save a ptr to it
+ //
+
+ pDlgInstData = (PDLG_INST_DATA) DrvAlloc (sizeof(DLG_INST_DATA));
+
+ // BUGBUG if (!pDlgInstData)
+
+ pDlgInstData->pParamsHeader = (PEVENT_PARAM_HEADER) lParam;
+ pDlgInstData->lLastSel = -1;
+
+ SetWindowLong (hwnd, DWL_USER, (LONG) pDlgInstData);
+
+
+#ifndef WIN32
+ {
+ //
+ // Go thru the hassle of creating combobox on the fly because
+ // otherwise we'll blow up when the combo tries to use our DS
+ // for it's heap.
+ //
+
+ RECT rect = { 116, 16, 80, 47 };
+
+
+ pDlgInstData->hComboDS = GlobalAlloc(
+ GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
+ 2048
+ );
+
+ pDlgInstData->pComboSeg = GlobalLock (pDlgInstData->hComboDS);
+
+ LocalInit(
+ HIWORD(pDlgInstData->pComboSeg),
+ 0,
+ (UINT) (GlobalSize (pDlgInstData->hComboDS) - 16)
+ );
+
+ UnlockSegment ((UINT)HIWORD(pDlgInstData->pComboSeg));
+
+ MapDialogRect (hwnd, &rect);
+
+ pDlgInstData->hwndCombo = CreateWindow(
+ "combobox",
+ NULL,
+ WS_CHILD | WS_VISIBLE | CBS_SIMPLE | CBS_NOINTEGRALHEIGHT |
+ CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP,
+ rect.left,
+ rect.top,
+ rect.right,
+ rect.bottom,
+ hwnd,
+ (HMENU) IDC_COMBO1,
+ (HINSTANCE) HIWORD(pDlgInstData->pComboSeg),
+ NULL
+ );
+ }
+#endif
+
+ //
+ // Limit the max text length for the combobox's edit field
+ // (NOTE: A combobox ctrl actually has two child windows: a
+ // edit ctrl & a listbox. We need to get the hwnd of the
+ // child edit ctrl & send it the LIMITTEXT msg.)
+ //
+
+ {
+ HWND hwndChild = GetWindow (pDlgInstData->hwndCombo, GW_CHILD);
+
+
+ while (hwndChild)
+ {
+ char buf[8];
+
+
+ GetClassName (hwndChild, buf, 7);
+
+ if (_stricmp (buf, "edit") == 0)
+ {
+ break;
+ }
+
+ hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
+ }
+
+ SendMessage(
+ hwndChild,
+ EM_LIMITTEXT,
+ (WPARAM) MAX_STRING_PARAM_SIZE - 1,
+ 0
+ );
+ }
+
+
+ //
+ // Misc other init
+ //
+
+ pDlgInstData->pParamsHeader = (PEVENT_PARAM_HEADER) lParam;
+
+ SetWindowText (hwnd, pDlgInstData->pParamsHeader->pszDlgTitle);
+
+ for (i = 0; i < pDlgInstData->pParamsHeader->dwNumParams; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pDlgInstData->pParamsHeader->aParams[i].szName
+ );
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ LONG lLastSel = pDlgInstData->lLastSel;
+ char far *lpszComboText = pDlgInstData->szComboText;
+ PEVENT_PARAM_HEADER pParamsHeader = pDlgInstData->pParamsHeader;
+
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ if (lLastSel != -1)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ //
+ // Save val of currently selected param
+ //
+
+ i = GetDlgItemText (hwnd, IDC_COMBO1, buf, MAX_STRING_PARAM_SIZE-1);
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD) 0;
+ }
+ else // "Valid string"
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].u.buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].u.buf[MAX_STRING_PARAM_SIZE-1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].u.buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!ScanForDWORD(
+ buf,
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+ // Drop thru to IDCANCEL cleanup code
+
+ case IDCANCEL:
+
+#ifndef WIN32
+ DestroyWindow (pDlgInstData->hwndCombo);
+ GlobalFree (pDlgInstData->hComboDS);
+#endif
+ DrvFree (pDlgInstData);
+ EndDialog (hwnd, (int)LOWORD(wParam));
+
+ if (pParamsHeader->dwEventType == XX_REQRESULTPOSTQUIT)
+ {
+ PostQuitMessage(0);
+ }
+ break;
+
+ case IDC_LIST1:
+
+#ifdef WIN32
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+#else
+ if (HIWORD(lParam) == LBN_SELCHANGE)
+#endif
+ {
+ char buf[MAX_STRING_PARAM_SIZE] = "";
+ LPCSTR lpstr = buf;
+ LONG lSel =
+ SendDlgItemMessage (hwnd, IDC_LIST1, LB_GETCURSEL, 0, 0);
+
+
+ if (lLastSel != -1)
+ {
+ //
+ // Save the old param value
+ //
+
+ i = GetDlgItemText(
+ hwnd,
+ IDC_COMBO1,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)0;
+ }
+ else // "Valid string" or no sel
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].u.buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].u.buf[MAX_STRING_PARAM_SIZE - 1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].u.buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!ScanForDWORD(
+ buf,
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+
+ SendDlgItemMessage (hwnd, IDC_LIST2, LB_RESETCONTENT, 0, 0);
+ SendDlgItemMessage (hwnd, IDC_COMBO1, CB_RESETCONTENT, 0, 0);
+
+ switch (pParamsHeader->aParams[lSel].dwType)
+ {
+ case PT_STRING:
+ {
+ char * aszOptions[] =
+ {
+ "NUL (dwXxxSize=0)",
+ "Valid string"
+ };
+
+
+ for (i = 0; i < 2; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) aszOptions[i]
+ );
+ }
+
+ if (pParamsHeader->aParams[lSel].dwValue == 0)
+ {
+ i = 0;
+ buf[0] = 0;
+ }
+ else
+ {
+ i = 1;
+ lpstr = (LPCSTR) pParamsHeader->aParams[lSel].dwValue;
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_SETCURSEL,
+ (WPARAM) i,
+ 0
+ );
+
+ break;
+ }
+ case PT_DWORD:
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "0000000"
+ );
+
+ if (pParamsHeader->aParams[lSel].u.dwDefValue)
+ {
+ //
+ // Add the default val string to the combo
+ //
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].u.dwDefValue
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) buf
+ );
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "ffffffff"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_ORDINAL:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].u.pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].lpszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue ==
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_FLAGS:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].u.pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].lpszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue &
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select all"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ } //switch
+
+ SetDlgItemText (hwnd, IDC_COMBO1, lpstr);
+
+ pDlgInstData->lLastSel = lSel;
+ }
+ break;
+
+ case IDC_LIST2:
+
+#ifdef WIN32
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+#else
+ if (HIWORD(lParam) == LBN_SELCHANGE)
+#endif
+ {
+ //
+ // BUGBUG in the PT_ORDINAL case we should compare the
+ // currently selected item(s) against the previous DWORD
+ // val and figure out which item we need to deselect,
+ // if any, in order to maintain a mutex of values
+ //
+
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].u.pLookup;
+ char buf[16];
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendDlgItemMessage (hwnd, IDC_LIST2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) DrvAlloc ((size_t)lSelCount * sizeof(int));
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_FLAGS)
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+ }
+ else // if (.dwType == PT_ORDINAL)
+ {
+ if (lSelCount == 1)
+ {
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ else if (lSelCount == 2)
+ {
+ //
+ // Figure out which item we need to de-select, since
+ // we're doing ordinals & only want 1 item selected
+ // at a time
+ //
+
+ GetDlgItemText (hwnd, IDC_COMBO1, buf, 16);
+
+ if (ScanForDWORD (buf, &dwValue))
+ {
+ if (pLookup[ai[0]].dwVal == dwValue)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[0]
+ );
+
+ dwValue = pLookup[ai[1]].dwVal;
+ }
+ else
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[1]
+ );
+
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ else if (lSelCount > 2)
+ {
+ //
+ // Determine previous selection & de-select all the
+ // latest selections
+ //
+
+ GetDlgItemText (hwnd, IDC_COMBO1, buf, 16);
+
+ if (ScanForDWORD (buf, &dwValue))
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ if (pLookup[ai[i]].dwVal != dwValue)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[i]
+ );
+ }
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ }
+
+ DrvFree (ai);
+ wsprintf (buf, "%08lx", dwValue);
+ SetDlgItemText (hwnd, IDC_COMBO1, buf);
+ }
+ break;
+
+ case IDC_COMBO1:
+
+#ifdef WIN32
+ switch (HIWORD(wParam))
+#else
+ switch (HIWORD(lParam))
+#endif
+ {
+ case CBN_SELCHANGE:
+ {
+ LONG lSel =
+ SendDlgItemMessage (hwnd, IDC_COMBO1, CB_GETCURSEL, 0, 0);
+
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_ORDINAL:
+
+ //
+ // The only option here is "select none"
+ //
+
+ strcpy (lpszComboText, "00000000");
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+ break;
+
+ case PT_FLAGS:
+ {
+ BOOL bSelect = (lSel ? TRUE : FALSE);
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ (WPARAM) bSelect,
+ (LPARAM) -1
+ );
+
+ if (bSelect)
+ {
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].u.pLookup;
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendDlgItemMessage (hwnd, IDC_LIST2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) DrvAlloc(
+ (size_t)lSelCount * sizeof(int)
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+
+ DrvFree (ai);
+ wsprintf (lpszComboText, "%08lx", dwValue);
+
+ }
+ else
+ {
+ strcpy (lpszComboText, "00000000");
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+ }
+ case PT_STRING:
+
+ if (lSel == 1)
+ {
+ strncpy(
+ lpszComboText,
+ pParamsHeader->aParams[lLastSel].u.buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ lpszComboText[MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ else
+ {
+ lpszComboText[0] = 0;
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+
+ case PT_DWORD:
+
+ break;
+
+ } // switch
+ break;
+ }
+ case CBN_EDITCHANGE:
+ {
+ //
+ // If user entered text in the edit field then copy the
+ // text to our buffer
+ //
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_STRING)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ GetDlgItemText(
+ hwnd,
+ IDC_COMBO1,
+ buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ strncpy(
+ pParamsHeader->aParams[lLastSel].u.buf,
+ buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ pParamsHeader->aParams[lLastSel].u.buf
+ [MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ break;
+ }
+ } // switch
+
+ } // switch
+
+ break;
+ }
+ case WM_USER+55:
+
+ SetDlgItemText (hwnd, IDC_COMBO1, pDlgInstData->szComboText);
+ break;
+
+#ifdef WIN32
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+#else
+ case WM_CTLCOLOR:
+ {
+ if (HIWORD(lParam) == CTLCOLOR_STATIC)
+ {
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+ }
+ break;
+ }
+#endif
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+void
+MsgLoopInTAPIClientContext(
+ HWND hwnd
+ )
+{
+
+ //
+ // -> See NOTE #2 in header above for info on the following
+ //
+ // We're filtering msgs here, only letting thru those which are
+ // destined for the dlg or it's children- we don't want to run
+ // into a situation where we're re-entering an app that's not
+ // expecting to be re-entered.
+ //
+ // Also, there's a special case in the dlg proc in which a quit
+ // msg will get posted when the dlg is dismissed so we'll drop
+ // out of this msg loop
+ //
+
+ MSG msg;
+
+ while (1)
+ {
+ if (PeekMessage (&msg, hwnd, 0, 0, PM_NOYIELD | PM_REMOVE))
+ {
+ if (msg.message == WM_QUIT)
+ {
+ break;
+ }
+
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+
+ DestroyWindow (hwnd);
+}
+
+
+BOOL
+Prolog(
+ PFUNC_INFO pInfo
+ )
+{
+ BOOL bLineFunc = (pInfo->lpszFuncName[1] != 'h');
+ DWORD i, j;
+
+
+
+#ifdef WIN32
+
+ // BUGBUG move this to the first func called (TSPI nego?)
+
+ while (!gbExeStarted)
+ {
+ Sleep (0);
+ }
+
+#else
+
+ if (!gbExeStarted)
+ {
+ UINT uiResult = WinExec ("espexe.exe", SW_SHOW);
+
+
+ if (uiResult < 32)
+ {
+ char buf[64];
+
+ wsprintf (buf, "WinExec('espexe.exe') failed, err=x%x", uiResult);
+ MessageBox ((HWND) NULL, buf, "Error: esp.tsp", MB_SYSTEMMODAL);
+ pInfo->lResult = LINEERR_OPERATIONFAILED;
+ return FALSE;
+ }
+
+ while (!gbExeStarted)
+ {
+ Yield();
+ }
+ }
+
+#endif
+
+ if (gbShowFuncEntry)
+ {
+ ShowStr ("TSPI_%s: enter", pInfo->lpszFuncName);
+ }
+
+ if (gbShowFuncParams)
+ {
+ for (i = 0; i < pInfo->dwNumParams; i++)
+ {
+ if (pInfo->aParams[i].dwVal &&
+ (strncmp (pInfo->aParams[i].lpszVal, "lpsz", 4) == 0))
+ {
+ ShowStr(
+ "%s%s=x%lx, '%s'",
+ szTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal,
+ pInfo->aParams[i].dwVal
+ );
+ }
+ else if (pInfo->aParams[i].pLookup)
+ {
+ char buf[90];
+ PLOOKUP pLookup = pInfo->aParams[i].pLookup;
+
+
+ wsprintf(
+ buf,
+ "%s%s=x%lx, ",
+ szTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal
+ );
+
+ for (j = 0; pLookup[j].dwVal != 0xffffffff; j++)
+ {
+ if (pInfo->aParams[i].dwVal & pLookup[j].dwVal)
+ {
+ strcat (buf, pLookup[j].lpszVal);
+ strcat (buf, " ");
+
+ if (strlen (buf) > 60)
+ {
+ ShowStr (buf);
+ wsprintf (buf, "%s%s", szTab, szTab);
+ }
+ }
+ }
+
+ ShowStr (buf);
+ }
+ else
+ {
+ ShowStr(
+ "%s%s=x%lx",
+ szTab,
+ pInfo->aParams[i].lpszVal,
+ pInfo->aParams[i].dwVal
+ );
+ }
+ }
+ }
+
+ if (gbManualResults)
+ {
+ char szDlgTitle[64];
+ EVENT_PARAM params[] =
+ {
+ { "lResult", PT_ORDINAL, 0, (bLineFunc ? aLineErrs : aPhoneErrs) }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, szDlgTitle, XX_REQRESULTPOSTQUIT, params };
+ HWND hwnd;
+
+
+ wsprintf (szDlgTitle, "TSPI_%s request result", pInfo->lpszFuncName);
+
+ hwnd = CreateDialogParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) NULL,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ );
+
+ MsgLoopInTAPIClientContext (hwnd);
+
+
+ //
+ // If user selected to synchronously return an error we'll save
+ // the error & return FALSE to indicate to caller that it should
+ // return immediately.
+ //
+
+ if (params[0].dwValue)
+ {
+ pInfo->lResult = (LONG) params[0].dwValue;
+
+ return FALSE;
+ }
+ }
+
+ if (pInfo->bAsync)
+ {
+ //
+ // Alloc & init an async request info structure
+ //
+
+ PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO)
+ DrvAlloc (sizeof(ASYNC_REQUEST_INFO));
+
+
+ if (pAsyncReqInfo)
+ {
+ memset (pAsyncReqInfo, 0, sizeof(ASYNC_REQUEST_INFO));
+
+ pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
+ pInfo->pfnPostProcessProc;
+ pAsyncReqInfo->dwRequestID = pInfo->aParams[0].dwVal;
+
+ pInfo->pAsyncReqInfo = pAsyncReqInfo;
+
+ strcpy (pAsyncReqInfo->szFuncName, pInfo->lpszFuncName);
+ }
+ else
+ {
+ pInfo->lResult = (bLineFunc ?
+ LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
+
+ return FALSE;
+ }
+ }
+
+ if (gbBreakOnFuncEntry)
+ {
+ DebugBreak();
+ }
+
+ return TRUE;
+}
+
+
+LONG
+Epilog(
+ PFUNC_INFO pInfo
+ )
+{
+ if (pInfo->bAsync)
+ {
+ if (pInfo->lResult == 0)
+ {
+ if (gbManualCompl || gbAsyncCompl)
+ {
+ PostMessage(
+ ghwndMain,
+ (gbManualCompl ? WM_MANUALCOMPL : WM_ASYNCCOMPL),
+ ESP_MSG_KEY,
+ (LPARAM) pInfo->pAsyncReqInfo
+ );
+ }
+ else
+ {
+ //
+ // We're completing this async request synchronously, so call
+ // the post processing proc (if there is one) or call the
+ // completion routine directly
+ //
+
+ if (pInfo->pAsyncReqInfo->pfnPostProcessProc)
+ {
+ (*((POSTPROCESSPROC)pInfo->pAsyncReqInfo->pfnPostProcessProc))(
+ pInfo->lpszFuncName,
+ pInfo->pAsyncReqInfo,
+ TRUE
+ );
+ }
+ else
+ {
+ DoCompletion(
+ pInfo->lpszFuncName,
+ pInfo->aParams[0].dwVal,
+ pInfo->lResult,
+ TRUE
+ );
+ }
+
+ DrvFree (pInfo->pAsyncReqInfo);
+ }
+
+
+ //
+ // Finally, for success cases want to return the request ID per spec
+ //
+
+ pInfo->lResult = pInfo->aParams[0].dwVal;
+ }
+ else
+ {
+ if (pInfo->pAsyncReqInfo)
+ {
+ DrvFree (pInfo->pAsyncReqInfo);
+ }
+ }
+ }
+
+ if (gbShowFuncExit)
+ {
+ ShowStr(
+ "TSPI_%s: exit, returning x%lx",
+ pInfo->lpszFuncName,
+ pInfo->lResult
+ );
+ }
+
+ return (pInfo->lResult);
+}
+
+
+PDRVWIDGET
+GetSelectedWidget(
+ void
+ )
+{
+ PDRVWIDGET pWidget = NULL;
+ LONG lSel = SendMessage (ghwndList1, LB_GETCURSEL, 0, 0), i;
+
+
+ if (lSel != LB_ERR)
+ {
+ pWidget = gaWidgets;
+
+ for (i = 0; i < lSel; i++)
+ {
+ if (!pWidget)
+ {
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+ }
+
+ return pWidget;
+}
+
+
+void
+ESPConfigDialog(
+ void
+ )
+{
+ EVENT_PARAM params[] =
+ {
+ { "TSPI Version", PT_DWORD, gdwTSPIVersion, NULL },
+ { "Num Lines", PT_DWORD, gdwNumLines, NULL },
+ { "Num Addrs/Line", PT_DWORD, gdwNumAddrsPerLine, NULL },
+ { "Num Phones", PT_DWORD, gdwNumPhones, NULL },
+ { "ShowLineGetIDDlg", PT_DWORD, gbShowLineGetIDDlg, NULL },
+ { "DefLineGetIDID", PT_DWORD, gdwDefLineGetIDID, NULL },
+ { "LineExtID0", PT_DWORD, gLineExtID.dwExtensionID0, NULL },
+ { "LineExtID1", PT_DWORD, gLineExtID.dwExtensionID1, NULL },
+ { "LineExtID2", PT_DWORD, gLineExtID.dwExtensionID2, NULL },
+ { "LineExtID3", PT_DWORD, gLineExtID.dwExtensionID3, NULL },
+ { "PhoneExtID0", PT_DWORD, gPhoneExtID.dwExtensionID0, NULL },
+ { "PhoneExtID1", PT_DWORD, gPhoneExtID.dwExtensionID1, NULL },
+ { "PhoneExtID2", PT_DWORD, gPhoneExtID.dwExtensionID2, NULL },
+ { "PhoneExtID3", PT_DWORD, gPhoneExtID.dwExtensionID3, NULL }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 12, "Default Provider Values", XX_DEFAULTS, params };
+
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) ghwndMain,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ if (!gdwNumInits)
+ {
+ gdwTSPIVersion = params[0].dwValue;
+ gdwNumAddrsPerLine = params[2].dwValue;
+
+
+ //
+ // v1.0 support (since 1.0 doesn't call providerEnumDevices). Find
+ // [ProviderN] section for ESP & updates NumLines & NumPhones.
+ //
+
+ if ((gdwNumLines != params[1].dwValue) ||
+ (gdwNumPhones != params[3].dwValue))
+ {
+ int iNumProviders, i;
+ char szProviderN[32];
+
+
+ gdwNumLines = params[1].dwValue;
+ gdwNumPhones = params[3].dwValue;
+
+ iNumProviders = GetPrivateProfileInt(
+ szProviders,
+ szNumProviders,
+ 0,
+ szTelephonIni
+ );
+
+ for (i = 0; i < iNumProviders; i++)
+ {
+ char szProviderName[16];
+
+
+ wsprintf (szProviderN, "%s%d", szProviderFilename, i);
+
+ GetPrivateProfileString(
+ szProviders,
+ szProviderN,
+ "",
+ szProviderName,
+ 16,
+ szTelephonIni
+ );
+
+ if (_stricmp (szProviderName, szEspTsp) == 0)
+ {
+ wsprintf (szProviderN, "%s%d", szProviderID, i);
+
+ i = GetPrivateProfileInt(
+ szProviders,
+ szProviderN,
+ 30000,
+ szTelephonIni
+ );
+
+ // BUGBUG chk if err
+
+ break;
+ }
+ }
+
+ UpdateTelephonIni ((DWORD) i);
+ }
+ }
+ else if ((gdwTSPIVersion != params[0].dwValue) ||
+ (gdwNumLines != params[1].dwValue) ||
+ (gdwNumAddrsPerLine != params[2].dwValue) ||
+ (gdwNumPhones != params[3].dwValue))
+ {
+ MessageBox(
+ ghwndMain,
+ "You must shut down all active TAPI applications in order " \
+ "for changes to TSPI Version, Num Lines, NumAddrs/Line," \
+ " or Num Phones to take effect",
+ "Note",
+ MB_OK
+ );
+ }
+
+ gdwTSPIVersion = params[0].dwValue;
+ gdwNumLines = params[1].dwValue;
+ gdwNumAddrsPerLine = params[2].dwValue;
+ gdwNumPhones = params[3].dwValue;
+
+ gbShowLineGetIDDlg = (BOOL) params[4].dwValue;
+ gdwDefLineGetIDID = params[5].dwValue;
+
+ gLineExtID.dwExtensionID0 = params[4].dwValue;
+ gLineExtID.dwExtensionID1 = params[5].dwValue;
+ gLineExtID.dwExtensionID2 = params[6].dwValue;
+ gLineExtID.dwExtensionID3 = params[7].dwValue;
+
+ gPhoneExtID.dwExtensionID0 = params[8].dwValue;
+ gPhoneExtID.dwExtensionID1 = params[9].dwValue;
+ gPhoneExtID.dwExtensionID2 = params[10].dwValue;
+ gPhoneExtID.dwExtensionID3 = params[11].dwValue;
+ }
+}
+
+
+void
+WidgetPropertiesDialog(
+ PDRVWIDGET pWidget,
+ BOOL bIncomingCall
+ )
+{
+ static char aszVarFields[17][MAX_STRING_PARAM_SIZE];
+ DWORD i;
+
+
+ switch (pWidget->dwType)
+ {
+ case WT_DRVCALL:
+ {
+ //
+ // We use the bIncomingCall flag here automatically cause a chg in
+ // the call state (from IDLE to OFFERING) on incoming calls, otherwise
+ // if the user forgets to chg it (from IDLE) any chgs they make will
+ // just be ignored by TAPI.DLL
+ //
+
+ PDRVCALL pCall = (PDRVCALL) pWidget;
+ LPLINECALLINFO lpCallInfo = &pCall->LineCallInfo;
+ char far *lpVarFields = (char far *) lpCallInfo + sizeof(LINECALLINFO);
+ EVENT_PARAM params[] =
+ {
+ { "Status.dwCallState", PT_FLAGS, (bIncomingCall ? LINECALLSTATE_OFFERING : pCall->dwCallState), aCallStates },
+ { "Status.dwCallStateMode", PT_DWORD, pCall->dwCallStateMode, NULL },
+ { "Status.dwCallFeatures", PT_FLAGS, pCall->dwCallFeatures, aCallFeatures },
+
+ { "Info.dwBearerMode", PT_FLAGS, lpCallInfo->dwBearerMode, aBearerModes },
+ { "Info.dwRate", PT_DWORD, lpCallInfo->dwRate, NULL },
+ { "Info.dwMediaMode", PT_FLAGS, lpCallInfo->dwMediaMode, aMediaModes },
+ { "Info.dwAppSpecific", PT_DWORD, lpCallInfo->dwAppSpecific, 0 },
+ { "Info.dwCallID", PT_DWORD, lpCallInfo->dwCallID, 0 },
+ { "Info.dwRelatedCallID", PT_DWORD, lpCallInfo->dwRelatedCallID, 0 },
+ { "Info.dwCallParamFlags", PT_FLAGS, lpCallInfo->dwCallParamFlags, aCallParamFlags },
+ { "Info.dwCallStates", PT_FLAGS, lpCallInfo->dwCallStates, aCallStates },
+ { "Info.DialParams.dwDialPause", PT_DWORD, lpCallInfo->DialParams.dwDialPause, 0 },
+ { "Info.DialParams.dwDialSpeed", PT_DWORD, lpCallInfo->DialParams.dwDialSpeed, 0 },
+ { "Info.DialParams.dwDigitDuration", PT_DWORD, lpCallInfo->DialParams.dwDigitDuration, 0 },
+ { "Info.DialParams.dwWaitForDialtone", PT_DWORD, lpCallInfo->DialParams.dwWaitForDialtone, 0 },
+ { "Info.dwOrigin", PT_FLAGS, lpCallInfo->dwOrigin, aCallOrigins },
+ { "Info.dwReason", PT_FLAGS, lpCallInfo->dwReason, aCallReasons },
+ { "Info.dwCompletionID", PT_DWORD, lpCallInfo->dwCompletionID, 0 },
+ { "Info.dwCountryCode", PT_DWORD, lpCallInfo->dwCountryCode, 0 },
+ { "Info.dwTrunk", PT_DWORD, lpCallInfo->dwTrunk, 0 },
+ { "Info.dwCallerIDFlags", PT_FLAGS, lpCallInfo->dwCallerIDFlags, aCallerIDFlags },
+ { "Info.szCallerID", PT_STRING, (DWORD) (lpCallInfo->dwCallerIDSize ? aszVarFields[0] : 0), (LPVOID) aszVarFields[0] },
+ { "Info.szCallerIDName", PT_STRING, (DWORD) (lpCallInfo->dwCallerIDNameSize ? aszVarFields[1] : 0), (LPVOID) aszVarFields[1] },
+ { "Info.dwCalledIDFlags", PT_FLAGS, lpCallInfo->dwCalledIDFlags, aCallerIDFlags },
+ { "Info.szCalledID", PT_STRING, (DWORD) (lpCallInfo->dwCalledIDSize ? aszVarFields[2] : 0), (LPVOID) aszVarFields[2] },
+ { "Info.szCalledIDName", PT_STRING, (DWORD) (lpCallInfo->dwCalledIDNameSize ? aszVarFields[3] : 0), (LPVOID) aszVarFields[3] },
+ { "Info.dwConnectedIDFlags", PT_FLAGS, lpCallInfo->dwConnectedIDFlags, aCallerIDFlags },
+ { "Info.szConnectedID", PT_STRING, (DWORD) (lpCallInfo->dwConnectedIDSize ? aszVarFields[4] : 0), (LPVOID) aszVarFields[4] },
+ { "Info.szConnectedIDName", PT_STRING, (DWORD) (lpCallInfo->dwConnectedIDNameSize ? aszVarFields[5] : 0), (LPVOID) aszVarFields[5] },
+ { "Info.dwRedirectionIDFlags", PT_FLAGS, lpCallInfo->dwRedirectionIDFlags, aCallerIDFlags },
+ { "Info.szRedirectionID", PT_STRING, (DWORD) (lpCallInfo->dwRedirectionIDSize ? aszVarFields[6] : 0), (LPVOID) aszVarFields[6] },
+ { "Info.szRedirectionIDName", PT_STRING, (DWORD) (lpCallInfo->dwRedirectionIDNameSize ? aszVarFields[7] : 0), (LPVOID) aszVarFields[7] },
+ { "Info.dwRedirectingIDFlags", PT_FLAGS, lpCallInfo->dwRedirectingIDFlags, aCallerIDFlags },
+ { "Info.szRedirectingID", PT_STRING, (DWORD) (lpCallInfo->dwRedirectingIDSize ? aszVarFields[8] : 0), (LPVOID) aszVarFields[8] },
+ { "Info.szRedirectingIDName", PT_STRING, (DWORD) (lpCallInfo->dwRedirectingIDNameSize ? aszVarFields[9] : 0), (LPVOID) aszVarFields[9] },
+ { "Info.szDisplay", PT_STRING, (DWORD) (lpCallInfo->dwDisplaySize ? aszVarFields[10] : 0), (LPVOID) aszVarFields[10] },
+ { "Info.szUserUserInfo", PT_STRING, (DWORD) (lpCallInfo->dwUserUserInfoSize ? aszVarFields[11] : 0), (LPVOID) aszVarFields[11] },
+ { "Info.szHighLevelComp", PT_STRING, (DWORD) (lpCallInfo->dwHighLevelCompSize ? aszVarFields[12] : 0), (LPVOID) aszVarFields[12] },
+ { "Info.szLowLevelComp", PT_STRING, (DWORD) (lpCallInfo->dwLowLevelCompSize ? aszVarFields[13] : 0), (LPVOID) aszVarFields[13] },
+ { "Info.szChargingInfo", PT_STRING, (DWORD) (lpCallInfo->dwChargingInfoSize ? aszVarFields[14] : 0), (LPVOID) aszVarFields[14] },
+ { "Info.szTerminalModes", PT_STRING, (DWORD) (lpCallInfo->dwTerminalModesSize ? aszVarFields[15] : 0), (LPVOID) aszVarFields[15] },
+ { "Info.szDevSpecific", PT_STRING, (DWORD) (lpCallInfo->dwDevSpecificSize ? aszVarFields[16] : 0), (LPVOID) aszVarFields[16] }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 42, "Call status/info", XX_CALL, params };
+
+
+ for (i = 0; i < 17; i++)
+ {
+ strcpy (aszVarFields[i], lpVarFields + i*MAX_STRING_PARAM_SIZE);
+ }
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) ghwndMain,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ LPDWORD alpdwXxxSize[17] =
+ {
+ &lpCallInfo->dwCallerIDSize,
+ &lpCallInfo->dwCallerIDNameSize,
+ &lpCallInfo->dwCalledIDSize,
+ &lpCallInfo->dwCalledIDNameSize,
+ &lpCallInfo->dwConnectedIDSize,
+ &lpCallInfo->dwConnectedIDNameSize,
+ &lpCallInfo->dwRedirectionIDSize,
+ &lpCallInfo->dwRedirectionIDNameSize,
+ &lpCallInfo->dwRedirectingIDSize,
+ &lpCallInfo->dwRedirectingIDNameSize,
+ &lpCallInfo->dwDisplaySize,
+ &lpCallInfo->dwUserUserInfoSize,
+ &lpCallInfo->dwHighLevelCompSize,
+ &lpCallInfo->dwLowLevelCompSize,
+ &lpCallInfo->dwChargingInfoSize,
+ &lpCallInfo->dwTerminalModesSize,
+ &lpCallInfo->dwDevSpecificSize
+ };
+ LPDWORD alpdwXxx[22] =
+ {
+ &lpCallInfo->dwBearerMode,
+ &lpCallInfo->dwRate,
+ &lpCallInfo->dwMediaMode,
+ &lpCallInfo->dwAppSpecific,
+ &lpCallInfo->dwCallID,
+ &lpCallInfo->dwRelatedCallID,
+ &lpCallInfo->dwCallParamFlags,
+ &lpCallInfo->dwCallStates,
+ &lpCallInfo->DialParams.dwDialPause,
+ &lpCallInfo->DialParams.dwDialSpeed,
+ &lpCallInfo->DialParams.dwDigitDuration,
+ &lpCallInfo->DialParams.dwWaitForDialtone,
+ &lpCallInfo->dwOrigin,
+ &lpCallInfo->dwReason,
+ &lpCallInfo->dwCompletionID,
+ &lpCallInfo->dwCountryCode,
+ &lpCallInfo->dwTrunk,
+ &lpCallInfo->dwCallerIDFlags,
+ &lpCallInfo->dwCalledIDFlags,
+ &lpCallInfo->dwConnectedIDFlags,
+ &lpCallInfo->dwRedirectionIDFlags,
+ &lpCallInfo->dwRedirectingIDFlags
+ };
+ DWORD dwCallInfoChangedFlags, i;
+ static DWORD adwVarFieldFlags[17] =
+ {
+ LINECALLINFOSTATE_CALLERID,
+ LINECALLINFOSTATE_CALLERID,
+ LINECALLINFOSTATE_CALLEDID,
+ LINECALLINFOSTATE_CALLEDID,
+ LINECALLINFOSTATE_CONNECTEDID,
+ LINECALLINFOSTATE_CONNECTEDID,
+ LINECALLINFOSTATE_REDIRECTIONID,
+ LINECALLINFOSTATE_REDIRECTIONID,
+ LINECALLINFOSTATE_REDIRECTINGID,
+ LINECALLINFOSTATE_REDIRECTINGID,
+ LINECALLINFOSTATE_DISPLAY,
+ LINECALLINFOSTATE_USERUSERINFO,
+ LINECALLINFOSTATE_HIGHLEVELCOMP,
+ LINECALLINFOSTATE_LOWLEVELCOMP,
+ LINECALLINFOSTATE_CHARGINGINFO,
+ LINECALLINFOSTATE_TERMINAL,
+ LINECALLINFOSTATE_DEVSPECIFIC
+ };
+ static DWORD adwDWORDFieldFlags[22] =
+ {
+ LINECALLINFOSTATE_BEARERMODE,
+ LINECALLINFOSTATE_RATE,
+ LINECALLINFOSTATE_MEDIAMODE,
+ LINECALLINFOSTATE_APPSPECIFIC,
+ LINECALLINFOSTATE_CALLID,
+ LINECALLINFOSTATE_RELATEDCALLID,
+ LINECALLINFOSTATE_OTHER,
+ LINECALLINFOSTATE_OTHER,
+ LINECALLINFOSTATE_DIALPARAMS,
+ LINECALLINFOSTATE_DIALPARAMS,
+ LINECALLINFOSTATE_DIALPARAMS,
+ LINECALLINFOSTATE_DIALPARAMS,
+ LINECALLINFOSTATE_ORIGIN,
+ LINECALLINFOSTATE_REASON,
+ LINECALLINFOSTATE_COMPLETIONID,
+ LINECALLINFOSTATE_OTHER,
+ LINECALLINFOSTATE_TRUNK,
+ LINECALLINFOSTATE_CALLERID,
+ LINECALLINFOSTATE_CALLEDID,
+ LINECALLINFOSTATE_CONNECTEDID,
+ LINECALLINFOSTATE_REDIRECTIONID,
+ LINECALLINFOSTATE_REDIRECTINGID
+ };
+ static int aiVarFieldIndices[17] =
+ {
+ 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41
+ };
+ static int aiDWORDFieldIndices[22] =
+ {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 23, 26, 29, 32
+ };
+
+
+ //
+ // If the state info chgd then save it & send a call state msg
+ //
+
+ if ((params[0].dwValue != pCall->dwCallState) ||
+ (params[1].dwValue != pCall->dwCallStateMode) ||
+ (params[2].dwValue != pCall->dwCallFeatures))
+ {
+ //
+ // We want to make sure that the media mode is up to date
+ // when we send the CALLSTATE msg
+ //
+
+ DWORD dwMediaModeOrig = lpCallInfo->dwMediaMode;
+
+
+ lpCallInfo->dwMediaMode = params[5].dwValue;
+
+
+ //
+ // We need to zero the state in order to force a msg (even
+ // if state didn't chg)
+ //
+
+ pCall->dwCallState = 0xdeadbeef;
+
+ SetCallState (pCall, params[0].dwValue, params[1].dwValue);
+
+ pCall->dwCallFeatures = params[2].dwValue;
+
+
+ //
+ // Restore the media mode so we can catch the chg down below
+ //
+
+ lpCallInfo->dwMediaMode = dwMediaModeOrig;
+ }
+
+
+ //
+ // If the info chgd then save it & send a call info msg
+ //
+
+ dwCallInfoChangedFlags = 0;
+
+ for (i = 0; i < 22; i++)
+ {
+ if (params[aiDWORDFieldIndices[i]].dwValue != *(alpdwXxx[i]))
+ {
+ *(alpdwXxx[i]) = params[aiDWORDFieldIndices[i]].dwValue;
+ dwCallInfoChangedFlags |= adwDWORDFieldFlags[i];
+ }
+ }
+
+ for (i = 0; i < 17; i++)
+ {
+ if (params[aiVarFieldIndices[i]].dwValue == 0)
+ {
+ if (*(alpdwXxxSize[i]) != 0)
+ {
+ *(alpdwXxxSize[i]) = *(alpdwXxxSize[i] + 1) = 0;
+ lpVarFields[i*MAX_STRING_PARAM_SIZE] = 0;
+ dwCallInfoChangedFlags |= adwVarFieldFlags[i];
+ }
+ }
+ else if (strcmp(
+ aszVarFields[i],
+ lpVarFields + i*MAX_STRING_PARAM_SIZE
+ ) ||
+ (*(alpdwXxxSize[i]) == 0))
+ {
+ strcpy(
+ lpVarFields + i*MAX_STRING_PARAM_SIZE,
+ aszVarFields[i]
+ );
+
+ *(alpdwXxxSize[i]) = strlen (aszVarFields[i]) + 1;
+ *(alpdwXxxSize[i] + 1) = sizeof(LINECALLINFO) +
+ i*MAX_STRING_PARAM_SIZE;
+ dwCallInfoChangedFlags |= adwVarFieldFlags[i];
+ }
+ }
+
+ if (dwCallInfoChangedFlags)
+ {
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLINFO,
+ dwCallInfoChangedFlags,
+ 0,
+ 0
+ );
+ }
+ }
+
+ break;
+ }
+ case WT_DRVLINE:
+ {
+ PDRVLINE pLine = (PDRVLINE) pWidget;
+ EVENT_PARAM params[] =
+ {
+ { "<under contruction>", PT_DWORD, 0, NULL }
+// { "Caps.dwBearerModes", PT_FLAGS, pLine->LineDevCaps.dwBearerModes, aBearerModes },
+// { "Caps.dwMediaModes", PT_FLAGS, pLine->LineDevCaps.dwMediaModes, aMediaModes }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, "Line caps/status", XX_LINE, params };
+
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) ghwndMain,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ }
+
+ break;
+ }
+ case WT_DRVPHONE:
+ {
+ PDRVPHONE pPhone = (PDRVPHONE) pWidget;
+ LPPHONECAPS lpPhoneCaps = &pPhone->PhoneCaps;
+ char far *lpCapsVarFields = (char far *) lpPhoneCaps + sizeof(PHONECAPS);
+ LPPHONESTATUS lpPhoneStatus = &pPhone->PhoneStatus;
+ char far *lpStatusVarFields = (char far *) lpPhoneStatus + sizeof(PHONESTATUS);
+ EVENT_PARAM params[] =
+ {
+ { "Caps.szProviderInfo", PT_STRING, (DWORD) (lpPhoneCaps->dwProviderInfoSize ? aszVarFields[0] : 0) , (LPVOID) aszVarFields[0] },
+ { "Caps.szPhoneInfo", PT_STRING, (DWORD) (lpPhoneCaps->dwPhoneInfoSize ? aszVarFields[1] : 0) , (LPVOID) aszVarFields[1] },
+ { "Caps.szPhoneName", PT_STRING, (DWORD) (lpPhoneCaps->dwPhoneNameSize ? aszVarFields[2] : 0) , (LPVOID) aszVarFields[2] },
+ { "Caps.dwPhoneStates", PT_FLAGS, lpPhoneCaps->dwPhoneStates, aPhoneStates },
+ { "Caps.dwHookSwitchDevs", PT_FLAGS, lpPhoneCaps->dwHookSwitchDevs, aHookSwitchDevs },
+ { "Caps.dwHandsetHookSwitchModes", PT_FLAGS, lpPhoneCaps->dwHandsetHookSwitchModes, aHookSwitchModes },
+ { "Caps.dwSpeakerHookSwitchModes", PT_FLAGS, lpPhoneCaps->dwSpeakerHookSwitchModes, aHookSwitchModes },
+ { "Caps.dwHeadsetHookSwitchModes", PT_FLAGS, lpPhoneCaps->dwHeadsetHookSwitchModes, aHookSwitchModes },
+ { "Caps.dwVolumeFlags", PT_FLAGS, lpPhoneCaps->dwVolumeFlags, aHookSwitchDevs },
+ { "Caps.dwGainFlags", PT_FLAGS, lpPhoneCaps->dwGainFlags, aHookSwitchDevs },
+ { "Caps.dwDisplayNumRows", PT_DWORD, lpPhoneCaps->dwDisplayNumRows, 0 },
+ { "Caps.dwDisplayNumColumns", PT_DWORD, lpPhoneCaps->dwDisplayNumColumns, 0 },
+ { "Caps.dwNumRingModes", PT_DWORD, lpPhoneCaps->dwNumRingModes, 0 },
+ { "Caps.dwNumButtonLamps", PT_DWORD, lpPhoneCaps->dwNumButtonLamps, 0 },
+ { "Caps.szButtonModes", PT_STRING, (DWORD) (lpPhoneCaps->dwButtonModesSize ? aszVarFields[3] : 0) , (LPVOID) aszVarFields[3] },
+ { "Caps.szButtonFunctions", PT_STRING, (DWORD) (lpPhoneCaps->dwButtonFunctionsSize ? aszVarFields[4] : 0) , (LPVOID) aszVarFields[4] },
+ { "Caps.szLampModes", PT_STRING, (DWORD) (lpPhoneCaps->dwLampModesSize ? aszVarFields[5] : 0) , (LPVOID) aszVarFields[5] },
+ { "Caps.dwNumSetData", PT_DWORD, lpPhoneCaps->dwNumSetData, 0 },
+ { "Caps.szSetData", PT_STRING, (DWORD) (lpPhoneCaps->dwSetDataSize ? aszVarFields[6] : 0) , (LPVOID) aszVarFields[6] },
+ { "Caps.dwNumGetData", PT_DWORD, lpPhoneCaps->dwNumGetData, 0 },
+ { "Caps.szGetData", PT_STRING, (DWORD) (lpPhoneCaps->dwGetDataSize ? aszVarFields[7] : 0) , (LPVOID) aszVarFields[7] },
+ { "Caps.szDevSpecific", PT_STRING, (DWORD) (lpPhoneCaps->dwDevSpecificSize ? aszVarFields[8] : 0) , (LPVOID) aszVarFields[8] },
+
+ { "Status.dwStatusFlags", PT_FLAGS, lpPhoneStatus->dwStatusFlags, aPhoneStatusFlags },
+ { "Status.dwRingMode", PT_DWORD, lpPhoneStatus->dwRingMode, 0 },
+ { "Status.dwRingVolume", PT_DWORD, lpPhoneStatus->dwRingVolume, 0 },
+ { "Status.dwHandsetHookSwitchMode", PT_FLAGS, lpPhoneStatus->dwHandsetHookSwitchMode, aHookSwitchModes },
+ { "Status.dwHandsetVolume", PT_DWORD, lpPhoneStatus->dwHandsetVolume, 0 },
+ { "Status.dwHandsetGain", PT_DWORD, lpPhoneStatus->dwHandsetGain, 0 },
+ { "Status.dwSpeakerHookSwitchMode", PT_FLAGS, lpPhoneStatus->dwSpeakerHookSwitchMode, aHookSwitchModes },
+ { "Status.dwSpeakerVolume", PT_DWORD, lpPhoneStatus->dwSpeakerVolume, 0 },
+ { "Status.dwSpeakerGain", PT_DWORD, lpPhoneStatus->dwSpeakerGain, 0 },
+ { "Status.dwHeadsetHookSwitchMode", PT_FLAGS, lpPhoneStatus->dwHeadsetHookSwitchMode, aHookSwitchModes },
+ { "Status.dwHeadsetVolume", PT_DWORD, lpPhoneStatus->dwHeadsetVolume, 0 },
+ { "Status.dwHeadsetGain", PT_DWORD, lpPhoneStatus->dwHeadsetGain, 0 },
+ { "Status.szDisplay", PT_STRING, (DWORD) (lpPhoneStatus->dwDisplaySize ? aszVarFields[10] : 0) , (LPVOID) aszVarFields[10] }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 35, "Phone caps/status", XX_PHONE, params };
+
+
+ for (i = 0; i < 9; i++)
+ {
+ strcpy (aszVarFields[i], lpCapsVarFields + i*MAX_STRING_PARAM_SIZE);
+ }
+
+ strcpy (aszVarFields[9], lpStatusVarFields);
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) ghwndMain,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ LPDWORD alpdwXxxSize[10] =
+ {
+ &lpPhoneCaps->dwProviderInfoSize,
+ &lpPhoneCaps->dwPhoneInfoSize,
+ &lpPhoneCaps->dwPhoneNameSize,
+ &lpPhoneCaps->dwButtonModesSize,
+ &lpPhoneCaps->dwButtonFunctionsSize,
+ &lpPhoneCaps->dwLampModesSize,
+ &lpPhoneCaps->dwSetDataSize,
+ &lpPhoneCaps->dwGetDataSize,
+ &lpPhoneCaps->dwDevSpecificSize,
+
+ &lpPhoneStatus->dwDisplaySize
+ };
+ LPDWORD alpdwXxx[25] =
+ {
+ &lpPhoneCaps->dwPhoneStates,
+ &lpPhoneCaps->dwHookSwitchDevs,
+ &lpPhoneCaps->dwHandsetHookSwitchModes,
+ &lpPhoneCaps->dwSpeakerHookSwitchModes,
+ &lpPhoneCaps->dwHeadsetHookSwitchModes,
+ &lpPhoneCaps->dwVolumeFlags,
+ &lpPhoneCaps->dwGainFlags,
+ &lpPhoneCaps->dwDisplayNumRows,
+ &lpPhoneCaps->dwDisplayNumColumns,
+ &lpPhoneCaps->dwNumRingModes,
+ &lpPhoneCaps->dwNumButtonLamps,
+ &lpPhoneCaps->dwNumSetData,
+ &lpPhoneCaps->dwNumGetData,
+
+ &lpPhoneStatus->dwStatusFlags,
+ &lpPhoneStatus->dwRingMode,
+ &lpPhoneStatus->dwRingVolume,
+ &lpPhoneStatus->dwHandsetHookSwitchMode,
+ &lpPhoneStatus->dwHandsetVolume,
+ &lpPhoneStatus->dwHandsetGain,
+ &lpPhoneStatus->dwSpeakerHookSwitchMode,
+ &lpPhoneStatus->dwSpeakerVolume,
+ &lpPhoneStatus->dwSpeakerGain,
+ &lpPhoneStatus->dwHeadsetHookSwitchMode,
+ &lpPhoneStatus->dwHeadsetVolume,
+ &lpPhoneStatus->dwHeadsetGain
+ };
+ DWORD dwStatusChangedFlags, i;
+ static DWORD adwVarFieldFlags[10] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ PHONESTATE_LAMP,
+ 0,
+ 0,
+ PHONESTATE_DEVSPECIFIC,
+ PHONESTATE_DISPLAY,
+ };
+ static DWORD adwDWORDFieldFlags[12] =
+ {
+ PHONESTATE_OTHER,
+ PHONESTATE_RINGMODE,
+ PHONESTATE_RINGVOLUME,
+ PHONESTATE_HANDSETHOOKSWITCH,
+ PHONESTATE_HANDSETVOLUME,
+ PHONESTATE_HANDSETGAIN,
+ PHONESTATE_SPEAKERHOOKSWITCH,
+ PHONESTATE_SPEAKERVOLUME,
+ PHONESTATE_SPEAKERGAIN,
+ PHONESTATE_HEADSETHOOKSWITCH,
+ PHONESTATE_HEADSETVOLUME,
+ PHONESTATE_HEADSETGAIN
+ };
+ static int aiVarFieldIndices[10] =
+ {
+ 0, 1, 2, 14, 15, 16, 18, 20, 21, 34
+ };
+ static int aiDWORDFieldIndices[25] =
+ {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 17, 19, 22, 23,
+ 24, 25, 25, 27, 28, 29, 30, 31, 32, 33
+ };
+
+
+ //
+ // If the caps/status chgd then save it & send a state msg
+ //
+
+ dwStatusChangedFlags = 0;
+
+ for (i = 0; i < 25; i++)
+ {
+ if (params[aiDWORDFieldIndices[i]].dwValue != *(alpdwXxx[i]))
+ {
+ *(alpdwXxx[i]) = params[aiDWORDFieldIndices[i]].dwValue;
+
+ if (i >= 13)
+ {
+ dwStatusChangedFlags |= adwDWORDFieldFlags[i-13];
+ }
+ }
+ }
+
+ for (i = 0; i < 10; i++)
+ {
+ if (params[aiVarFieldIndices[i]].dwValue == 0)
+ {
+ if (*(alpdwXxxSize[i]) != 0)
+ {
+ *(alpdwXxxSize[i]) = *(alpdwXxxSize[i] + 1) = 0;
+ if (i < 9)
+ {
+ lpCapsVarFields[i*MAX_STRING_PARAM_SIZE] = 0;
+ }
+ else
+ {
+ lpStatusVarFields[0] = 0;
+ }
+ dwStatusChangedFlags |= adwVarFieldFlags[i];
+ }
+ }
+ else if (strcmp(
+ aszVarFields[i],
+ (i < 9 ?
+ lpCapsVarFields + i*MAX_STRING_PARAM_SIZE :
+ lpStatusVarFields)
+ ) ||
+ (*(alpdwXxxSize[i]) == 0))
+ {
+ if (i < 9)
+ {
+ strcpy(
+ lpCapsVarFields + i*MAX_STRING_PARAM_SIZE,
+ aszVarFields[i]
+ );
+
+ *(alpdwXxxSize[i] + 1) = sizeof(PHONECAPS) +
+ i*MAX_STRING_PARAM_SIZE;
+ }
+ else
+ {
+ strcpy (lpStatusVarFields, aszVarFields[i]);
+
+ *(alpdwXxxSize[i] + 1) = sizeof(PHONESTATUS);
+ }
+
+ *(alpdwXxxSize[i]) = strlen (aszVarFields[i]) + 1;
+ dwStatusChangedFlags |= adwVarFieldFlags[i];
+ }
+ }
+
+ if (dwStatusChangedFlags)
+ {
+ SendPhoneEvent(
+ pPhone,
+ PHONE_STATE,
+ dwStatusChangedFlags,
+ 0,
+ 0
+ );
+ }
+ }
+
+ break;
+ }
+ } // switch
+}
+
+
+BOOL
+__loadds
+CALLBACK
+MainWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ static HICON hIcon;
+ static int icyButton, icyBorder;
+
+ static BOOL bCaptured = FALSE;
+ static LONG xCapture, cxVScroll;
+ static int cyWnd;
+ static HFONT hFont;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ char buf[64];
+ RECT rect;
+
+
+ //
+ // Init some globals
+ //
+
+ hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1));
+
+ ghwndMain = hwnd;
+ ghwndList1 = GetDlgItem (hwnd, IDC_LIST1);
+ ghwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ ghwndEdit = GetDlgItem (hwnd, IDC_EDIT1);
+ ghMenu = GetMenu (hwnd);
+
+ icyBorder = GetSystemMetrics (SM_CYFRAME);
+ GetWindowRect (GetDlgItem (hwnd, IDC_BUTTON1), &rect);
+ icyButton = (rect.bottom - rect.top) + icyBorder + 3;
+ cxVScroll = 2*GetSystemMetrics (SM_CXVSCROLL);
+
+
+ //
+ //
+ //
+
+ {
+ #define MYBOOL 1
+ #define MYDWORD 2
+
+ typedef struct _INIT_VALUE
+ {
+ char *lpszValue;
+
+ LPVOID lpValue;
+
+ int iType;
+
+ union
+ {
+ DWORD dwMenuItem;
+
+ char *lpszDefValueAscii;
+
+ } u;
+
+ } INIT_VALUE, *PINIT_VALUE;
+
+ int i;
+ INIT_VALUE aValues[] =
+ {
+ { "TSPIVersion", &gdwTSPIVersion, MYDWORD, (DWORD) ((char far *)"10003") },
+ { "NumLines", &gdwNumLines, MYDWORD, (DWORD) ((char far *)"3") },
+ { "NumAddrsPerLine", &gdwNumAddrsPerLine, MYDWORD, (DWORD) ((char far *)"2") },
+ { "NumPhones", &gdwNumPhones, MYDWORD, (DWORD) ((char far *)"2") },
+ { "ShowFuncEntry", &gbShowFuncEntry, MYBOOL, (DWORD) IDM_SHOWFUNCENTRY },
+ { "ShowFuncExit", &gbShowFuncExit, MYBOOL, (DWORD) IDM_SHOWFUNCEXIT },
+ { "ShowFuncParams", &gbShowFuncParams, MYBOOL, (DWORD) IDM_SHOWFUNCPARAMS },
+ { "ShowEvents", &gbShowEvents, MYBOOL, (DWORD) IDM_SHOWEVENTS },
+ { "ShowCompletions", &gbShowCompletions, MYBOOL, (DWORD) IDM_SHOWCOMPLETIONS },
+ { "BreakOnFuncEntry", &gbBreakOnFuncEntry, MYBOOL, (DWORD) IDM_DEBUGBREAK },
+ { "AutoClose", &gbAutoClose, MYBOOL, (DWORD) IDM_AUTOCLOSE },
+ { "SyncCompl", &gbSyncCompl, MYBOOL, (DWORD) IDM_SYNCCOMPL },
+ { "AsyncCompl", &gbAsyncCompl, MYBOOL, (DWORD) IDM_ASYNCCOMPL },
+ { "ManualCompl", &gbManualCompl, MYBOOL, (DWORD) IDM_MANUALCOMPL },
+ { "ManualResults", &gbManualResults, MYBOOL, (DWORD) IDM_MANUALRESULTS },
+ { "DisableUI", &gbDisableUI, MYBOOL, (DWORD) IDM_DISABLEUI },
+ { "ShowLineGetIDDlg", &gbShowLineGetIDDlg, MYBOOL, (DWORD) 0 },
+ { "DefLineGetIDID", &gdwDefLineGetIDID, MYDWORD, (DWORD) ((char far *)"ffffffff") },
+ { "LineExtID0", &gLineExtID.dwExtensionID0, MYDWORD, (DWORD) ((char far *)"6f79f180") },
+ { "LineExtID1", &gLineExtID.dwExtensionID1, MYDWORD, (DWORD) ((char far *)"101b0bb0") },
+ { "LineExtID2", &gLineExtID.dwExtensionID2, MYDWORD, (DWORD) ((char far *)"00089e96") },
+ { "LineExtID3", &gLineExtID.dwExtensionID3, MYDWORD, (DWORD) ((char far *)"8a2e312b") },
+ { "PhoneExtID0", &gPhoneExtID.dwExtensionID0, MYDWORD, (DWORD) ((char far *)"0") },
+ { "PhoneExtID1", &gPhoneExtID.dwExtensionID1, MYDWORD, (DWORD) ((char far *)"0") },
+ { "PhoneExtID2", &gPhoneExtID.dwExtensionID2, MYDWORD, (DWORD) ((char far *)"0") },
+ { "PhoneExtID3", &gPhoneExtID.dwExtensionID3, MYDWORD, (DWORD) ((char far *)"0") },
+ { "OutCallState1", &aOutCallStates[0], MYDWORD, (DWORD) ((char far *)"10") }, // DIALING
+ { "OutCallStateMode1", &aOutCallStateModes[0], MYDWORD, (DWORD) ((char far *)"0") },
+ { "OutCallState2", &aOutCallStates[1], MYDWORD, (DWORD) ((char far *)"200") }, // PROCEEDING
+ { "OutCallStateMode2", &aOutCallStateModes[1], MYDWORD, (DWORD) ((char far *)"0") },
+ { "OutCallState3", &aOutCallStates[2], MYDWORD, (DWORD) ((char far *)"0") },
+ { "OutCallStateMode3", &aOutCallStateModes[2], MYDWORD, (DWORD) ((char far *)"0") },
+ { "OutCallState4", &aOutCallStates[3], MYDWORD, (DWORD) ((char far *)"0") },
+ { "OutCallStateMode4", &aOutCallStateModes[3], MYDWORD, (DWORD) ((char far *)"0") },
+ { NULL, NULL, 0, 0 }
+ };
+
+
+ for (i = 0; aValues[i].lpszValue; i++)
+ {
+ switch (aValues[i].iType)
+ {
+ case MYBOOL:
+
+ *((BOOL *) aValues[i].lpValue) = (BOOL)
+ GetProfileInt(
+ szMySection,
+ aValues[i].lpszValue,
+ ((i == 4) || (i == 12) ? 1 : 0)
+ );
+
+ if (*((BOOL *)aValues[i].lpValue) &&
+ aValues[i].u.dwMenuItem)
+ {
+ CheckMenuItem(
+ ghMenu,
+ (UINT) aValues[i].u.dwMenuItem,
+ MF_BYCOMMAND | MF_CHECKED
+ );
+ }
+
+ break;
+
+ case MYDWORD:
+ {
+ char buf[16];
+
+
+ GetProfileString(
+ szMySection,
+ aValues[i].lpszValue,
+ aValues[i].u.lpszDefValueAscii,
+ buf,
+ 15
+ );
+
+ ScanForDWORD (buf, (LPDWORD) aValues[i].lpValue);
+
+ break;
+ }
+ } // switch
+ }
+ }
+
+
+ //
+ // Set control fonts
+ //
+
+ {
+ HWND hwndCtrl = GetDlgItem (hwnd, IDC_BUTTON1);
+ hFont = CreateFont(
+ 13, 5, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 34, "MS Sans Serif"
+ );
+
+ do
+ {
+ SendMessage(
+ hwndCtrl,
+ WM_SETFONT,
+ (WPARAM) hFont,
+ 0
+ );
+
+ } while ((hwndCtrl = GetNextWindow (hwndCtrl, GW_HWNDNEXT)));
+ }
+
+
+ //
+ // Read in control size ratios
+ //
+
+ cxWnd = GetProfileInt (szMySection, "cxWnd", 100);
+ cxList1 = GetProfileInt (szMySection, "cxList1", 25);
+
+
+ //
+ // Send self WM_SIZE to position child controls correctly
+ //
+
+ GetProfileString(
+ szMySection,
+ "Left",
+ "0",
+ buf,
+ 63
+ );
+
+ if (strcmp (buf, "max") == 0)
+ {
+ ShowWindow (hwnd, SW_SHOWMAXIMIZED);
+ }
+ else if (strcmp (buf, "min") == 0)
+ {
+ ShowWindow (hwnd, SW_SHOWMINIMIZED);
+ }
+ else
+ {
+ int left, top, right, bottom;
+ int cxScreen = GetSystemMetrics (SM_CXSCREEN);
+ int cyScreen = GetSystemMetrics (SM_CYSCREEN);
+
+
+ left = GetProfileInt (szMySection, "Left", 0);
+ top = GetProfileInt (szMySection, "Top", 3*cyScreen/4);
+ right = GetProfileInt (szMySection, "Right", cxScreen);
+ bottom = GetProfileInt (szMySection, "Bottom", cyScreen);
+
+ SetWindowPos(
+ hwnd,
+ HWND_TOP,
+ left,
+ top,
+ right - left,
+ bottom - top,
+ SWP_SHOWWINDOW
+ );
+
+ GetClientRect (hwnd, &rect);
+
+ SendMessage(
+ hwnd,
+ WM_SIZE,
+ 0,
+ MAKELONG((rect.right-rect.left),(rect.bottom-rect.top))
+ );
+
+ ShowWindow (hwnd, SW_SHOW);
+ }
+
+ gbExeStarted = TRUE;
+
+ break;
+ }
+ case WM_ADDTEXT:
+ {
+ if (wParam == ESP_MSG_KEY)
+ {
+#ifdef WIN32
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)0xfffffffd,
+ (LPARAM)0xfffffffe
+ );
+
+ WaitForSingleObject (ghShowStrBufMutex, INFINITE);
+#else
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)0,
+ (LPARAM) MAKELONG(0xfffd,0xfffe)
+ );
+#endif
+
+ SendMessage (ghwndEdit, EM_REPLACESEL, 0, lParam);
+
+#ifdef WIN32
+ SendMessage (ghwndEdit, EM_SCROLLCARET, 0, 0);
+#endif
+ memset ((char *) lParam, 0, 16);
+#ifdef WIN32
+ ReleaseMutex (ghShowStrBufMutex);
+#endif
+ }
+
+ break;
+ }
+ case WM_UPDATEWIDGETLIST:
+
+ if (wParam == ESP_MSG_KEY)
+ {
+ UpdateWidgetList();
+ }
+
+ break;
+
+ case WM_ASYNCCOMPL:
+ {
+ PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO) lParam;
+ char buf[64];
+
+
+ if (gbManualResults)
+ {
+ EVENT_PARAM params[] =
+ {
+ { "lResult", PT_ORDINAL, 0, aLineErrs }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, buf, XX_REQRESULT, params };
+
+
+ if (strstr (pAsyncReqInfo->szFuncName, "pho"))
+ {
+ params[0].u.pLookup = aPhoneErrs;
+ }
+
+ wsprintf(
+ buf,
+ "Completing ReqID=x%lx, TSPI_%s",
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->szFuncName
+ );
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) hwnd,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ pAsyncReqInfo->lResult = (LONG) params[0].dwValue;
+ }
+ else
+ {
+ // BUGBUG? for now just return opfailed err if user cancels
+
+ if (params[0].u.pLookup == aLineErrs)
+ {
+ pAsyncReqInfo->lResult = LINEERR_OPERATIONFAILED;
+ }
+ else
+ {
+ pAsyncReqInfo->lResult = PHONEERR_OPERATIONFAILED;
+ }
+ }
+ }
+
+ wsprintf (buf, "TSPI_%s", pAsyncReqInfo->szFuncName);
+
+ if (pAsyncReqInfo->pfnPostProcessProc)
+ {
+ (*((POSTPROCESSPROC)pAsyncReqInfo->pfnPostProcessProc))(
+ buf,
+ pAsyncReqInfo,
+ FALSE
+ );
+ }
+ else
+ {
+ DoCompletion(
+ buf,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ FALSE
+ );
+ }
+
+ DrvFree (pAsyncReqInfo);
+
+ break;
+ }
+ case WM_MANUALCOMPL:
+ {
+ PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO) lParam;
+ char buf[64];
+ int iIndex;
+
+
+ wsprintf(
+ buf,
+ "ReqID=x%lx, TSPI_%s",
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->szFuncName
+ );
+
+ SendMessage(
+ ghwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) buf
+ );
+
+ iIndex = (int) (SendMessage (ghwndList2, LB_GETCOUNT, 0, 0) - 1);
+
+ SendMessage(
+ ghwndList2,
+ LB_SETITEMDATA,
+ (WPARAM) iIndex,
+ (LPARAM) pAsyncReqInfo
+ );
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD((DWORD)wParam))
+ {
+ case IDC_EDIT1:
+
+#ifdef WIN32
+ if (HIWORD(wParam) == EN_CHANGE)
+#else
+ if (HIWORD(lParam) == EN_CHANGE)
+#endif
+ {
+ //
+ // Watch to see if the edit control is full, & if so
+ // purge the top half of the text to make room for more
+ //
+
+ int length = GetWindowTextLength (ghwndEdit);
+
+
+ if (length > 20000)
+ {
+#ifdef WIN32
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)0 ,
+ (LPARAM) 10000
+ );
+#else
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)1,
+ (LPARAM) MAKELONG (0, 10000)
+ );
+#endif
+
+ SendMessage(
+ ghwndEdit,
+ EM_REPLACESEL,
+ 0,
+ (LPARAM) (char far *) ""
+ );
+
+#ifdef WIN32
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)0xfffffffd,
+ (LPARAM)0xfffffffe
+ );
+#else
+ SendMessage(
+ ghwndEdit,
+ EM_SETSEL,
+ (WPARAM)1,
+ (LPARAM) MAKELONG (0xfffd, 0xfffe)
+ );
+#endif
+ }
+ }
+ break;
+
+ case IDM_INSTALL:
+ {
+ int iNumProviders, iNextProviderID;
+ char szProviderXxxN[32];
+ char buf[32];
+
+
+ //
+ // First, see if ESP is already installed
+ //
+
+ if (IsESPInstalled (hwnd))
+ {
+ return FALSE;
+ }
+
+ //
+ // If here need to add the provider entries to telephon.ini
+ //
+ // BUGBUG ought to call lineAddProvider instead
+ //
+
+ MessageBox(
+ hwnd,
+ "Please close all active TAPI applications, then press OK.",
+ "Installing ESP",
+ MB_OK
+ );
+
+ iNumProviders = GetPrivateProfileInt(
+ szProviders,
+ szNumProviders,
+ 0,
+ szTelephonIni
+ );
+
+ wsprintf (buf, "%d", 1 + iNumProviders);
+
+ WritePrivateProfileString(
+ szProviders,
+ szNumProviders,
+ buf,
+ szTelephonIni
+ );
+
+ iNextProviderID = GetPrivateProfileInt(
+ szProviders,
+ szNextProviderID,
+ 0,
+ szTelephonIni
+ );
+
+ wsprintf (buf, "%d", 1 + iNextProviderID);
+
+ WritePrivateProfileString(
+ szProviders,
+ szNextProviderID,
+ buf,
+ szTelephonIni
+ );
+
+ wsprintf (buf, "%d", iNextProviderID);
+ wsprintf (szProviderXxxN, "ProviderID%d", iNumProviders);
+
+ WritePrivateProfileString(
+ szProviders,
+ szProviderXxxN,
+ buf,
+ szTelephonIni
+ );
+
+ wsprintf(
+ szProviderXxxN,
+ "%s%d",
+ szProviderFilename,
+ iNumProviders
+ );
+
+ WritePrivateProfileString(
+ szProviders,
+ szProviderXxxN,
+ szEspTsp,
+ szTelephonIni
+ );
+
+ UpdateTelephonIni ((DWORD) iNextProviderID);
+
+ MessageBox(
+ hwnd,
+ "ESP has been successfully installed. " \
+ "You can now restart your TAPI applications. " \
+ "(If TAPI fails to successfully initialize ESP " \
+ "then try manually copying the files ESP.TSP " \
+ "and ESPEXE.EXE to your <windows>/system directory.)",
+ "Installing ESP",
+ MB_OK
+ );
+
+ break;
+ }
+ case IDM_UNINSTALL:
+ {
+ int iNumProviders, i;
+ char szProviderN[32], buf[128];
+
+
+ //
+ // First, see if ESP is already installed
+ //
+
+ iNumProviders = GetPrivateProfileInt(
+ szProviders,
+ szNumProviders,
+ 0,
+ szTelephonIni
+ );
+
+ for (i = 0; i < iNumProviders; i++)
+ {
+ char szProviderName[8];
+
+
+ wsprintf (szProviderN, "%s%d", szProviderFilename, i);
+
+ GetPrivateProfileString(
+ szProviders,
+ szProviderN,
+ "",
+ szProviderName,
+ 8,
+ szTelephonIni
+ );
+
+ if (_stricmp (szProviderName, szEspTsp) == 0)
+ {
+ break;
+ }
+ }
+
+ if (i == iNumProviders)
+ {
+ MessageBox(
+ hwnd,
+ "ESP is not installed.",
+ "Uninstalling ESP",
+ MB_OK
+ );
+
+ break;
+ }
+
+
+ //
+ // If here need to remove the provider entries to telephon.ini
+ //
+
+ wsprintf (buf, "%d", iNumProviders - 1);
+
+ WritePrivateProfileString(
+ szProviders,
+ szNumProviders,
+ buf,
+ szTelephonIni
+ );
+
+
+ //
+ // Nuke the [ProviderN] section
+ //
+
+ {
+ int iProviderID;
+
+
+ wsprintf (szProviderN, "%s%d", szProviderID, i);
+
+ iProviderID = GetPrivateProfileInt(
+ szProviders,
+ szProviderN,
+ 0,
+ szTelephonIni
+ );
+
+ wsprintf (szProviderN, "%s%d", szProvider, iProviderID);
+
+ WritePrivateProfileString(
+ szProviderN,
+ (LPCSTR) NULL,
+ (LPCSTR) NULL,
+ szTelephonIni
+ );
+ }
+
+
+ //
+ // Shuffle the ProviderID[i+1] & ProviderFilename[i+1] down
+ // to ProviderID[i] & ProviderFilename[i]
+ //
+
+ for (; i < (iNumProviders - 1); i++)
+ {
+ wsprintf (szProviderN, "%s%d", szProviderID, i + 1);
+
+ GetPrivateProfileString(
+ szProviders,
+ szProviderN,
+ "",
+ buf,
+ 128,
+ szTelephonIni
+ );
+
+ wsprintf (szProviderN, "%s%d", szProviderID, i);
+
+ WritePrivateProfileString(
+ szProviders,
+ szProviderN,
+ buf,
+ szTelephonIni
+ );
+
+
+ wsprintf (szProviderN, "%s%d", szProviderFilename, i + 1);
+
+ GetPrivateProfileString(
+ szProviders,
+ szProviderN,
+ "",
+ buf,
+ 128,
+ szTelephonIni
+ );
+
+ wsprintf (szProviderN, "%s%d", szProviderFilename, i);
+
+ WritePrivateProfileString(
+ szProviders,
+ szProviderN,
+ buf,
+ szTelephonIni
+ );
+ }
+
+
+ //
+ // Nuke the last ProviderIDN & ProviderFilenameN entries
+ //
+
+ wsprintf (szProviderN, "%s%d", szProviderID, i);
+
+ WritePrivateProfileString(
+ szProviders,
+ szProviderN,
+ (LPCSTR) NULL,
+ szTelephonIni
+ );
+
+ wsprintf (szProviderN, "%s%d", szProviderFilename, i);
+
+ WritePrivateProfileString(
+ szProviders,
+ szProviderN,
+ (LPCSTR) NULL,
+ szTelephonIni
+ );
+
+
+ //
+ // Alert user of success
+ //
+
+ MessageBox(
+ hwnd,
+ "ESP has been successfully uninstalled.",
+ "Uninstalling ESP",
+ MB_OK
+ );
+
+ break;
+ }
+ case IDM_DUMPGLOBALS:
+ {
+ typedef struct _MYGLOBAL
+ {
+ char far *lpszGlobal;
+
+ LPDWORD lpdwGlobal;
+
+ } MYGLOBAL, far *PMYGLOBAL;
+
+ static MYGLOBAL aGlobals[] =
+ {
+ //
+ // When making chgs here make sure to chg init of iNumGlobals
+ // down below
+ //
+
+ { "PermanentProviderID", (LPDWORD) &gdwPermanentProviderID },
+
+
+ //
+ // Globals past here are 1.4 only
+ //
+
+ { "hProvider", (LPDWORD) &ghProvider }
+ };
+
+
+ ShowStr ("ESP globals:");
+
+ if (gdwNumInits)
+ {
+ int i, iNumGlobals = (gdwTSPIVersion == 0x10003 ? 1 : 2);
+
+ for (i = 0; i < iNumGlobals; i++)
+ {
+ ShowStr(
+ "%s%s=x%lx",
+ szTab,
+ aGlobals[i].lpszGlobal,
+ *(aGlobals[i].lpdwGlobal)
+ );
+ }
+ }
+ else
+ {
+ ShowStr(
+ "%s<Provider not initialized>",
+ szTab
+ );
+ }
+
+ break;
+ }
+ case IDM_EXIT:
+
+ PostMessage (hwnd, WM_CLOSE, 0, 0);
+ break;
+
+ case IDM_OUTCALLSTATEPROG:
+ {
+ EVENT_PARAM params[] =
+ {
+ { "State 1", PT_ORDINAL, aOutCallStates[0], aCallStates },
+ { "State 1 mode", PT_DWORD, aOutCallStateModes[0], NULL },
+ { "State 2", PT_ORDINAL, aOutCallStates[1], aCallStates },
+ { "State 2 mode", PT_DWORD, aOutCallStateModes[1], NULL },
+ { "State 3", PT_ORDINAL, aOutCallStates[2], aCallStates },
+ { "State 3 mode", PT_DWORD, aOutCallStateModes[2], NULL },
+ { "State 4", PT_ORDINAL, aOutCallStates[3], aCallStates },
+ { "State 4 mode", PT_DWORD, aOutCallStateModes[3], NULL }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 2*MAX_OUT_CALL_STATES, "Outgoing call state progress", XX_OUTCALLSTATEPROG, params };
+ int i;
+
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) hwnd,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ memset(
+ aOutCallStates,
+ 0,
+ sizeof(DWORD) * MAX_OUT_CALL_STATES
+ );
+
+ memset(
+ aOutCallStateModes,
+ 0,
+ sizeof(DWORD) * MAX_OUT_CALL_STATES
+ );
+
+ for (i = 0; i < MAX_OUT_CALL_STATES; i++)
+ {
+ if (params[2*i].dwValue == 0)
+ {
+ break;
+ }
+
+ aOutCallStates[i] = params[2*i].dwValue;
+ aOutCallStateModes[i] = params[(2*i)+1].dwValue;
+ }
+ }
+
+ break;
+ }
+ case IDM_ABOUT:
+
+ DialogBox(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG2),
+ (HWND) hwnd,
+ (DLGPROC) AboutDlgProc
+ );
+
+ break;
+
+ case IDM_USAGE:
+ {
+ static char szDlgText[] =
+
+ "ABSTRACT:\n\r" \
+ " ESP is a TAPI Service Provider that supports " \
+ "multiple virtual line and phone devices. It is " \
+ "configurable, requires no special hardware, " \
+ "and implements the entire Telephony Service Provider " \
+ "Interface (including Win95 TAPI extensions). ESP " \
+ "will work in both Windows 3.1/TAPI 1.0 and " \
+ "Windows95/TAPI 1.1 systems.\n\r" \
+
+ "\n\rGETTING STARTED:\n\r" \
+ " 1. Choose 'File/Install' to install ESP.\n\r" \
+ " 2. Start a TAPI application and try to make a call " \
+ "on one of ESP's line devices (watch for messages appearing " \
+ "in the ESP window).\n\r" \
+ " *. Choose 'File/Uninstall' to uninstall ESP.\n\r" \
+
+ "\n\rMORE INFO:\n\r" \
+ " * Double-click on a line, call, or phone widget (in " \
+ "upper-left listbox) to view/modify properties. The 'hd' " \
+ "widget field is the driver handle; the 'ht' field is the " \
+ "TAPI handle.\n\r" \
+ " * Press the 'LEvt' or 'PEvt' button to indicate a " \
+ "line or phone event to TAPI.DLL. Press the 'Call+' button " \
+ "to indicate an incoming call.\n\r" \
+ " * Choose 'Options/Default values...' to modify " \
+ "provider paramters (SPI version, # lines, etc).\n\r" \
+ " * All parameter values displayed in hexadecimal " \
+ "unless specified otherwise (strings displayed by contents)." \
+ "\n\r" \
+ " * Choose 'Options/Complete async requests/Xxx' to " \
+ "specify async requests completion behavior. Manually-" \
+ "completed requests appear in lower-left listbox.";
+
+ MessageBox (hwnd, szDlgText, "Using ESP", MB_OK);
+
+ break;
+ }
+ case IDM_SHOWFUNCENTRY:
+
+ gbShowFuncEntry = (gbShowFuncEntry ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SHOWFUNCENTRY,
+ MF_BYCOMMAND | (gbShowFuncEntry ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_SHOWFUNCEXIT:
+
+ gbShowFuncExit = (gbShowFuncExit ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SHOWFUNCEXIT,
+ MF_BYCOMMAND | (gbShowFuncExit ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_SHOWFUNCPARAMS:
+
+ gbShowFuncParams = (gbShowFuncParams ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SHOWFUNCPARAMS,
+ MF_BYCOMMAND | (gbShowFuncParams ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_SHOWEVENTS:
+
+ gbShowEvents = (gbShowEvents ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SHOWEVENTS,
+ MF_BYCOMMAND | (gbShowEvents ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_SHOWCOMPLETIONS:
+
+ gbShowCompletions = (gbShowCompletions ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SHOWCOMPLETIONS,
+ MF_BYCOMMAND | (gbShowCompletions ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_DEBUGBREAK:
+
+ gbBreakOnFuncEntry = (gbBreakOnFuncEntry ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_DEBUGBREAK,
+ MF_BYCOMMAND | (gbBreakOnFuncEntry ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_SYNCCOMPL:
+
+ gbSyncCompl = TRUE;
+ gbAsyncCompl = gbManualCompl = FALSE;
+ goto Do_compl_menuitems;
+
+ case IDM_ASYNCCOMPL:
+
+ gbAsyncCompl = TRUE;
+ gbSyncCompl = gbManualCompl = FALSE;
+ goto Do_compl_menuitems;
+
+ case IDM_MANUALCOMPL:
+
+ gbManualCompl = TRUE;
+ gbSyncCompl = gbAsyncCompl = FALSE;
+ goto Do_compl_menuitems;
+
+Do_compl_menuitems:
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SYNCCOMPL,
+ MF_BYCOMMAND | (gbSyncCompl ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_ASYNCCOMPL,
+ MF_BYCOMMAND | (gbAsyncCompl ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_MANUALCOMPL,
+ MF_BYCOMMAND | (gbManualCompl ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_MANUALRESULTS:
+
+ gbManualResults = (gbManualResults ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_MANUALRESULTS,
+ MF_BYCOMMAND | (gbManualResults ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_DISABLEUI:
+
+ if ((gbDisableUI = (gbDisableUI ? FALSE : TRUE)) == FALSE)
+ {
+ PostUpdateWidgetListMsg();
+ }
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_DISABLEUI,
+ MF_BYCOMMAND | (gbDisableUI ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_AUTOCLOSE:
+
+ gbAutoClose = (gbAutoClose ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_AUTOCLOSE,
+ MF_BYCOMMAND | (gbAutoClose ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_SHOWALL:
+ {
+ static UINT ai[5] =
+ { IDM_SHOWFUNCENTRY, IDM_SHOWFUNCEXIT, IDM_SHOWFUNCPARAMS,
+ IDM_SHOWEVENTS, IDM_SHOWCOMPLETIONS };
+ int i;
+
+
+ gbShowFuncEntry =
+ gbShowFuncExit =
+ gbShowFuncParams =
+ gbShowEvents =
+ gbShowCompletions = TRUE;
+
+ for (i = 0; i < 5; i++)
+ {
+ CheckMenuItem (ghMenu, ai[i], MF_BYCOMMAND | MF_CHECKED);
+ }
+
+ break;
+ }
+ case IDM_SHOWNONE:
+ {
+ static UINT ai[5] =
+ { IDM_SHOWFUNCENTRY, IDM_SHOWFUNCEXIT, IDM_SHOWFUNCPARAMS,
+ IDM_SHOWEVENTS, IDM_SHOWCOMPLETIONS };
+ int i;
+
+
+ gbShowFuncEntry =
+ gbShowFuncExit =
+ gbShowFuncParams =
+ gbShowEvents =
+ gbShowCompletions = FALSE;
+
+ for (i = 0; i < 5; i++)
+ {
+ CheckMenuItem (ghMenu, ai[i], MF_BYCOMMAND | MF_UNCHECKED);
+ }
+
+ break;
+ }
+ case IDM_DEFAULTS:
+
+ ESPConfigDialog();
+
+ break;
+
+ case IDC_PREVCTRL:
+ {
+ HWND hwndPrev = GetNextWindow (GetFocus (), GW_HWNDPREV);
+
+ if (!hwndPrev)
+ {
+ hwndPrev = GetDlgItem (hwnd, IDC_LIST2);
+ }
+
+ SetFocus (hwndPrev);
+ break;
+ }
+ case IDC_NEXTCTRL:
+ {
+ HWND hwndNext = GetNextWindow (GetFocus (), GW_HWNDNEXT);
+
+ if (!hwndNext)
+ {
+ hwndNext = GetDlgItem (hwnd, IDC_BUTTON1);
+ }
+
+ SetFocus (hwndNext);
+ break;
+ }
+ case IDC_ENTER:
+ {
+ HWND hwndFocus = GetFocus();
+
+ if (hwndFocus == ghwndList1)
+ {
+ PDRVWIDGET pWidget = GetSelectedWidget();
+
+
+ if (!pWidget)
+ {
+ break;
+ }
+
+ WidgetPropertiesDialog (pWidget, FALSE);
+ }
+ else if ((hwndFocus == ghwndList2) &&
+ (SendMessage (ghwndList2, LB_GETCURSEL, 0, 0) != LB_ERR))
+ {
+#ifdef WIN32
+ wParam = MAKEWPARAM (0, LBN_DBLCLK);
+#else
+ lParam = MAKELPARAM (0, LBN_DBLCLK);
+#endif
+ goto CompleteAsyncRequest;
+ }
+
+ break;
+ }
+ case IDC_BUTTON1:
+ {
+ EVENT_PARAM params[] =
+ {
+ { "htLine", PT_DWORD, 0, NULL },
+ { "htCall", PT_DWORD, 0, NULL },
+ { "dwMsg", PT_ORDINAL, 0, aLineMsgs },
+ { "dwParam1", PT_DWORD, 0, NULL },
+ { "dwParam2", PT_DWORD, 0, NULL },
+ { "dwParam3", PT_DWORD, 0, NULL }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 6, "Line event", XX_LINEEVENT, params };
+ PDRVWIDGET pWidget = GetSelectedWidget();
+
+
+ //
+ // If the selected widget is a line
+ // or call then reset the defaults
+ //
+
+ if (pWidget)
+ {
+ if (pWidget->dwType == WT_DRVCALL)
+ {
+ params[0].dwValue = (DWORD)
+ (((PDRVCALL)pWidget)->pLine->htLine);
+ params[1].dwValue = (DWORD)
+ (((PDRVCALL)pWidget)->htCall);
+ }
+ else if (pWidget->dwType == WT_DRVLINE)
+ {
+ params[0].dwValue = (DWORD)
+ (((PDRVLINE)pWidget)->htLine);
+ }
+ }
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) hwnd,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ //
+ // BUGBUG Currently the pfnLineCreateProc == pfnLineEventProc
+ //
+
+ (*gpfnLineCreateProc)(
+ (HTAPILINE) params[0].dwValue,
+ (HTAPICALL) params[1].dwValue,
+ params[2].dwValue,
+ params[3].dwValue,
+ params[4].dwValue,
+ params[5].dwValue
+ );
+
+ ShowLineEvent(
+ (HTAPILINE) params[0].dwValue,
+ (HTAPICALL) params[1].dwValue,
+ params[2].dwValue,
+ params[3].dwValue,
+ params[4].dwValue,
+ params[5].dwValue
+ );
+
+
+ //
+ // BUGBUG
+ //
+ // Currently (12/28/94) TAPI.DLL is calling back into the
+ // SP to clean up calls & lines even after the CLOSE msg
+ // is sent.
+ //
+
+ if (params[2].dwValue == LINE_CLOSE)
+ {
+ //
+ // See if we can match the htLine specified by the user
+ // against those in the widgets list, and if so nuke
+ // the line & all calls on that line
+ //
+
+ pWidget = gaWidgets;
+
+ while (pWidget)
+ {
+ if ((pWidget->dwType == WT_DRVLINE) &&
+ ( (DWORD) (((PDRVLINE)pWidget)->htLine) ==
+ params[0].dwValue))
+ {
+ // BUGBUG must clean up all pending reqs
+
+ ShowStr ("Forcibly closing line, any pending reqs NOT completed");
+
+ ((PDRVLINE)pWidget)->htLine = (HTAPILINE) NULL;
+
+ pWidget = pWidget->pNext;
+
+ while (pWidget->dwType == WT_DRVCALL)
+ {
+ PDRVWIDGET pWidgetNext = pWidget->pNext;
+
+ FreeCall ((PDRVCALL) pWidget);
+
+ pWidget = pWidgetNext;
+ }
+
+ UpdateWidgetList();
+
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+ }
+ }
+
+ break;
+ }
+ case IDC_BUTTON2:
+ {
+ EVENT_PARAM params[] =
+ {
+ { "htPhone", PT_DWORD, 0, NULL },
+ { "dwMsg", PT_ORDINAL, 0, aPhoneMsgs },
+ { "dwParam1", PT_DWORD, 0, NULL },
+ { "dwParam2", PT_DWORD, 0, NULL },
+ { "dwParam3", PT_DWORD, 0, NULL }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 5, "Phone event", XX_PHONEEVENT, params };
+ PDRVWIDGET pWidget = GetSelectedWidget();
+
+
+ //
+ // If the selected widget is a phone then reset the default
+ //
+
+ if (pWidget)
+ {
+ if (pWidget->dwType == WT_DRVPHONE)
+ {
+ params[0].dwValue = (DWORD)
+ (((PDRVPHONE)pWidget)->htPhone);
+ }
+ }
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) hwnd,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ //
+ // BUGBUG Currently the pfnPhoneCreateProc == pfnPhoneEventProc
+ //
+
+ (*gpfnPhoneCreateProc)(
+ (HTAPIPHONE) params[0].dwValue,
+ params[1].dwValue,
+ params[2].dwValue,
+ params[3].dwValue,
+ params[4].dwValue
+ );
+
+ ShowPhoneEvent(
+ (HTAPIPHONE) params[0].dwValue,
+ params[1].dwValue,
+ params[2].dwValue,
+ params[3].dwValue,
+ params[4].dwValue
+ );
+
+ if (params[1].dwValue == PHONE_CLOSE)
+ {
+ //
+ // See if we can match the htPhone specified by the
+ // user against those in the widgets list, and if so
+ // nuke the phone
+ //
+
+ pWidget = gaWidgets;
+
+ while (pWidget)
+ {
+ if ((pWidget->dwType == WT_DRVPHONE) &&
+ ( (DWORD) (((PDRVPHONE)pWidget)->htPhone) ==
+ params[0].dwValue))
+ {
+ // BUGBUG must clean up all pending reqs
+
+ ShowStr ("Forcibly closing phone, any pending reqs NOT completed");
+
+ ((PDRVPHONE)pWidget)->htPhone = (HTAPIPHONE) NULL;
+
+ UpdateWidgetList();
+
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+ }
+ }
+
+ break;
+ }
+ case IDC_BUTTON3:
+ {
+ PDRVWIDGET pWidget = GetSelectedWidget();
+ PDRVCALL pCall;
+
+
+ if (!pWidget ||
+ (pWidget->dwType != WT_DRVLINE) ||
+ !((PDRVLINE)pWidget)->htLine)
+ {
+ MessageBox(
+ hwnd,
+ "You must select an open provider line",
+ "Creating an incoming call",
+ MB_OK
+ );
+
+ break;
+ }
+
+ AllocCall(
+ (PDRVLINE) pWidget,
+ (HTAPICALL) NULL,
+ (LPLINECALLPARAMS) NULL,
+ &pCall
+ );
+
+ SendLineEvent(
+ (PDRVLINE) pWidget,
+ NULL, //pCall,
+ LINE_NEWCALL,
+ (DWORD) pCall,
+ (DWORD) &pCall->htCall,
+ 0
+ );
+
+ if (!pCall->htCall)
+ {
+ // BUGBUG try again
+
+ break;
+ }
+ else
+ {
+ //
+ // Make sure htCall gets shown
+ //
+
+ UpdateWidgetList();
+ }
+
+ SendMessage(
+ ghwndList1,
+ LB_SETCURSEL,
+ (WPARAM) (GetWidgetIndex ((PDRVWIDGET) pCall)),
+ 0
+ );
+
+
+ //
+ // Bring up the props dlg for the call automatically so user
+ // can select call state
+ //
+
+ WidgetPropertiesDialog ((PDRVWIDGET) pCall, TRUE);
+
+ break;
+ }
+ case IDC_BUTTON4:
+
+ SetDlgItemText (hwnd, IDC_EDIT1, "");
+
+ break;
+
+ case IDC_LIST1:
+
+#ifdef WIN32
+ if (HIWORD(wParam) == LBN_DBLCLK)
+#else
+ if (HIWORD(lParam) == LBN_DBLCLK)
+#endif
+ {
+ PDRVWIDGET pWidget = GetSelectedWidget();
+
+
+ if (!pWidget)
+ {
+ return FALSE;
+ }
+
+ WidgetPropertiesDialog (pWidget, FALSE);
+ }
+
+ break;
+
+ case IDC_LIST2:
+
+CompleteAsyncRequest:
+
+#ifdef WIN32
+ if (HIWORD(wParam) == LBN_DBLCLK)
+#else
+ if (HIWORD(lParam) == LBN_DBLCLK)
+#endif
+ {
+ int iSelIndex = (int) SendMessage(ghwndList2,LB_GETCURSEL,0,0);
+ char buf[64] = "Completing ";
+ char far *lpszFuncName;
+ PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO)
+ SendMessage(
+ ghwndList2,
+ LB_GETITEMDATA,
+ (WPARAM) iSelIndex,
+ 0
+ );
+
+
+ SendMessage(
+ ghwndList2,
+ LB_GETTEXT,
+ (WPARAM) iSelIndex,
+ (LPARAM) &buf[11]
+ );
+
+ lpszFuncName = strstr (buf, "TSP") + 5;
+
+ if (gbManualResults)
+ {
+ EVENT_PARAM params[] =
+ {
+ { "lResult", PT_ORDINAL, 0, aLineErrs }
+ };
+ EVENT_PARAM_HEADER paramsHeader =
+ { 1, buf, XX_REQRESULT, params };
+
+
+ if (strstr (buf, "pho"))
+ {
+ params[0].u.pLookup = aPhoneErrs;
+ }
+
+ if (DialogBoxParam(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) hwnd,
+ (DLGPROC) CallDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDCANCEL)
+ {
+ break;
+ }
+
+ pAsyncReqInfo->lResult = (LONG) params[0].dwValue;
+ }
+
+
+ if (pAsyncReqInfo->pfnPostProcessProc)
+ {
+
+ (*((POSTPROCESSPROC)pAsyncReqInfo->pfnPostProcessProc))(
+ lpszFuncName,
+ pAsyncReqInfo,
+ FALSE
+ );
+ }
+ else
+ {
+ DoCompletion(
+ lpszFuncName,
+ pAsyncReqInfo->dwRequestID,
+ pAsyncReqInfo->lResult,
+ FALSE
+ );
+ }
+
+ DrvFree (pAsyncReqInfo);
+
+ SendMessage(
+ ghwndList2,
+ LB_DELETESTRING,
+ (WPARAM) iSelIndex,
+ 0
+ );
+ }
+
+ break;
+
+ } //switch
+
+ break;
+ }
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+
+ BeginPaint (hwnd, &ps);
+
+ if (IsIconic (hwnd))
+ {
+ DrawIcon (ps.hdc, 0, 0, hIcon);
+ }
+ else
+ {
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+#ifdef WIN32
+ MoveToEx (ps.hdc, 0, 0, NULL);
+#else
+ MoveTo (ps.hdc, 0, 0);
+#endif
+ LineTo (ps.hdc, 5000, 0);
+
+#ifdef WIN32
+ MoveToEx (ps.hdc, 0, icyButton - 4, NULL);
+#else
+ MoveTo (ps.hdc, 0, icyButton - 4);
+#endif
+ LineTo (ps.hdc, 5000, icyButton - 4);
+ }
+
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ case WM_SIZE:
+ {
+ LONG width = (LONG)LOWORD(lParam);
+
+
+ //
+ // Adjust globals based on new size
+ //
+
+ cxList1 = (cxList1 * width) / cxWnd;
+ cxWnd = width;
+ cyWnd = ((int)HIWORD(lParam)) - icyButton;
+
+
+ //
+ // Now reposition the child windows
+ //
+
+ SetWindowPos(
+ ghwndList1,
+ GetNextWindow (ghwndList1, GW_HWNDPREV),
+ 0,
+ icyButton,
+ (int) cxList1,
+ 2*cyWnd/3,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndList2,
+ GetNextWindow (ghwndList2, GW_HWNDPREV),
+ 0,
+ icyButton + 2*cyWnd/3 + icyBorder,
+ (int) cxList1,
+ cyWnd/3 - icyBorder,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndEdit,
+ GetNextWindow (ghwndEdit, GW_HWNDPREV),
+ (int) cxList1 + icyBorder,
+ icyButton,
+ (int)width - ((int)cxList1 + icyBorder),
+ cyWnd,
+ SWP_SHOWWINDOW
+ );
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ break;
+ }
+ case WM_MOUSEMOVE:
+ {
+ LONG x = (LONG)((short)LOWORD(lParam));
+ int y = (int)((short)HIWORD(lParam));
+ int cxList1New;
+
+
+ if (((y > icyButton) && (x > cxList1)) || bCaptured)
+ {
+ SetCursor(
+ LoadCursor ((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_SIZEWE))
+ );
+ }
+
+ if (bCaptured)
+ {
+ x = (x < cxVScroll ? cxVScroll : x);
+ x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x);
+
+ cxList1New = (int) (cxList1 + x - xCapture);
+
+ SetWindowPos(
+ ghwndList1,
+ GetNextWindow (ghwndList1, GW_HWNDPREV),
+ 0,
+ icyButton,
+ cxList1New,
+ 2*cyWnd/3,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndList2,
+ GetNextWindow (ghwndList2, GW_HWNDPREV),
+ 0,
+ icyButton + 2*cyWnd/3 + icyBorder,
+ cxList1New,
+ cyWnd/3 - icyBorder,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndEdit,
+ GetNextWindow (ghwndEdit, GW_HWNDPREV),
+ (int) cxList1New + icyBorder,
+ icyButton,
+ (int)cxWnd - (cxList1New + icyBorder),
+ cyWnd,
+ SWP_SHOWWINDOW
+ );
+ }
+
+ break;
+ }
+ case WM_LBUTTONDOWN:
+ {
+ if (((int)((short)HIWORD(lParam)) > icyButton) &&
+ ((int)((short)LOWORD(lParam)) > cxList1))
+ {
+ xCapture = (LONG)LOWORD(lParam);
+
+ SetCapture (hwnd);
+
+ bCaptured = TRUE;
+ }
+
+ break;
+ }
+ case WM_LBUTTONUP:
+ {
+ if (bCaptured)
+ {
+ POINT p;
+ LONG x;
+
+ GetCursorPos (&p);
+ MapWindowPoints (HWND_DESKTOP, hwnd, &p, 1);
+ x = (LONG) p.x;
+
+ ReleaseCapture();
+
+ x = (x < cxVScroll ? cxVScroll : x);
+ x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x);
+
+ cxList1 = cxList1 + (x - xCapture);
+
+ bCaptured = FALSE;
+
+ InvalidateRect (hwnd, NULL, TRUE);
+ }
+
+ break;
+ }
+ case WM_CLOSE:
+
+ SaveIniSettings();
+ ghwndEdit = ghwndList1 = (HWND) NULL;
+ DestroyIcon (hIcon);
+ DeleteObject (hFont);
+ gbExeStarted = FALSE;
+ PostQuitMessage (0);
+ break;
+
+ } // switch
+
+ return FALSE;
+}
+
+
+void
+TSPIAPI
+DllMsgLoop(
+ void
+ )
+{
+ MSG msg;
+ HACCEL hAccel;
+
+
+ OutputDebugString ("ESP: DllMsgLoop: enter\n\r");
+
+ ghwndMain = CreateDialog(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG1),
+ (HWND)NULL,
+ (DLGPROC) MainWndProc
+ );
+
+ if (!ghwndMain)
+ {
+ OutputDebugString ("ESP.TSP: DllMsgLoop: CreateDlg failed\n\r");
+ }
+
+ hAccel = LoadAccelerators(
+ hInst,
+ (LPCSTR)MAKEINTRESOURCE(IDR_ACCELERATOR1)
+ );
+
+ while (GetMessage (&msg, (HWND) NULL, 0, 0))
+ {
+ if (!TranslateAccelerator (ghwndMain, hAccel, &msg))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+
+#ifdef WIN32
+
+ DestroyWindow (ghwndMain);
+
+ DestroyAcceleratorTable (hAccel);
+
+#endif
+
+ ghwndMain = (HWND) NULL;
+}
+
+
+void
+PASCAL
+SendLineEvent(
+ PDRVLINE pLine,
+ PDRVCALL pCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ //
+ //
+ //
+
+ (*(pLine->lpfnEventProc))(
+ pLine->htLine,
+ (pCall ? pCall->htCall : (HTAPICALL) NULL),
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ if (dwMsg == LINE_CALLSTATE)
+ {
+ PostUpdateWidgetListMsg();
+ }
+
+ ShowLineEvent(
+ pLine->htLine,
+ (pCall ? pCall->htCall : (HTAPICALL) NULL),
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+}
+
+
+void
+PASCAL
+SendPhoneEvent(
+ PDRVPHONE pPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ //
+ //
+ //
+
+ (*(pPhone->lpfnEventProc))(
+ pPhone->htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+
+ ShowPhoneEvent(
+ pPhone->htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+}
+
+
+void
+PASCAL
+DoCompletion(
+ char far *lpszFuncName,
+ DWORD dwRequestID,
+ LONG lResult,
+ BOOL bSync
+ )
+{
+ (*gpfnCompletionProc)(dwRequestID, lResult);
+
+ if (gbShowCompletions)
+ {
+ ShowStr(
+ "%sTSPI_%s: calling compl proc (%ssync), dwReqID=x%lx, lResult = x%lx",
+ szCallUp,
+ lpszFuncName,
+ (bSync ? "" : "a"),
+ dwRequestID,
+ lResult
+ );
+ }
+}
+
+
+void
+PASCAL
+SetCallState(
+ PDRVCALL pCall,
+ DWORD dwCallState,
+ DWORD dwCallStateMode
+ )
+{
+ //
+ // First, check the current call state. Never send another call state
+ // msg on a call once you've sent a LINECALLSTATE_IDLE msg (because
+ // it'll hose apps, and calls instances aren't supposed to be reused).
+ //
+
+ if (pCall->dwCallState == LINECALLSTATE_IDLE)
+ {
+ ShowStr(
+ "SetCallState: call x%lx is IDLE, not changing call state",
+ pCall
+ );
+
+ return;
+ }
+
+
+ //
+ // Next, check to see if the new state matches the current state, and
+ // if so just return.
+ //
+
+ if (dwCallState == pCall->dwCallState)
+ {
+ ShowStr(
+ "SetCallState: not sending call x%lx state msg " \
+ "(new state = current state)",
+ pCall
+ );
+
+ return;
+ }
+
+
+ //
+ // Change the call state & notify TAPI
+ //
+
+ pCall->dwCallState = dwCallState;
+ pCall->dwCallStateMode = dwCallStateMode;
+
+ SendLineEvent(
+ pCall->pLine,
+ pCall,
+ LINE_CALLSTATE,
+ dwCallState,
+ dwCallStateMode,
+ pCall->LineCallInfo.dwMediaMode
+ );
+}
+
+
+LPVOID
+DrvAlloc(
+ size_t numBytes
+ )
+{
+ LPVOID p = (LPVOID) malloc (numBytes);
+
+
+ if (!p)
+ {
+ ShowStr ("Error: DrvAlloc (x%lx) failed", (DWORD) numBytes);
+ }
+
+ return p;
+}
+
+
+void
+DrvFree(
+ LPVOID lp
+ )
+{
+ free (lp);
+}
+
+
+void
+SaveIniSettings(
+ void
+ )
+{
+ char buf[32];
+ RECT rect;
+
+
+ GetWindowRect (ghwndMain, &rect);
+
+ {
+ typedef struct _SAVE_VALUE
+ {
+ char *lpszVal;
+
+ DWORD dwValue;
+
+ } SAVE_VALUE, *PSAVE_VALUE;
+
+ SAVE_VALUE aValues[] =
+ {
+ { "Left", (DWORD) rect.left },
+ { "Top", (DWORD) rect.top },
+ { "Right", (DWORD) rect.right },
+ { "Bottom", (DWORD) rect.bottom },
+ { "cxWnd", (DWORD) cxWnd },
+ { "cxList1", (DWORD) cxList1 },
+ { "ShowFuncEntry", (DWORD) gbShowFuncEntry },
+ { "ShowFuncExit", (DWORD) gbShowFuncExit },
+ { "ShowFuncParams", (DWORD) gbShowFuncParams },
+ { "ShowEvents", (DWORD) gbShowEvents },
+ { "ShowCompletions", (DWORD) gbShowCompletions },
+ { "AutoClose", (DWORD) gbAutoClose },
+ { "SyncCompl", (DWORD) gbSyncCompl },
+ { "AsyncCompl", (DWORD) gbAsyncCompl },
+ { "ManualCompl", (DWORD) gbManualCompl },
+ { "ManualResults", (DWORD) gbManualResults },
+ { "ShowLineGetIDDlg", (DWORD) gbShowLineGetIDDlg },
+ { "DisableUI", (DWORD) gbDisableUI },
+ { NULL, 0 },
+ { "TSPIVersion", gdwTSPIVersion },
+ { "NumLines", gdwNumLines },
+ { "NumAddrsPerLine", gdwNumAddrsPerLine },
+ { "NumPhones", gdwNumPhones },
+ { "LineExtID0", gLineExtID.dwExtensionID0 },
+ { "LineExtID1", gLineExtID.dwExtensionID1 },
+ { "LineExtID2", gLineExtID.dwExtensionID2 },
+ { "LineExtID3", gLineExtID.dwExtensionID3 },
+ { "PhoneExtID0", gPhoneExtID.dwExtensionID0 },
+ { "PhoneExtID1", gPhoneExtID.dwExtensionID1 },
+ { "PhoneExtID2", gPhoneExtID.dwExtensionID2 },
+ { "PhoneExtID3", gPhoneExtID.dwExtensionID3 },
+ { "OutCallState1", aOutCallStates[0] },
+ { "OutCallStateMode1", aOutCallStateModes[0] },
+ { "OutCallState2", aOutCallStates[1] },
+ { "OutCallStateMode2", aOutCallStateModes[1] },
+ { "OutCallState3", aOutCallStates[2] },
+ { "OutCallStateMode3", aOutCallStateModes[2] },
+ { "OutCallState4", aOutCallStates[3] },
+ { "OutCallStateMode4", aOutCallStateModes[3] },
+ { "DefLineGetIDID", gdwDefLineGetIDID },
+ { NULL, 0 }
+ };
+ int i;
+
+
+ for (i = 0; aValues[i].lpszVal; i++)
+ {
+ wsprintf (buf, "%ld", aValues[i].dwValue); // decimal
+
+ WriteProfileString(
+ szMySection,
+ aValues[i].lpszVal,
+ (LPCSTR) buf
+ );
+ }
+
+ for (++i; aValues[i].lpszVal; i++)
+ {
+ wsprintf (buf, "%lx", aValues[i].dwValue); // hex for DWORDs
+
+ WriteProfileString(
+ szMySection,
+ aValues[i].lpszVal,
+ (LPCSTR) buf
+ );
+ }
+
+ if (IsIconic (ghwndMain))
+ {
+ WriteProfileString(
+ szMySection,
+ "Left",
+ "min"
+ );
+ }
+ else if (IsZoomed (ghwndMain))
+ {
+ WriteProfileString(
+ szMySection,
+ "Left",
+ "max"
+ );
+ }
+ }
+}
+
+
+BOOL
+IsESPInstalled(
+ HWND hwnd
+ )
+{
+ int i, iNumProviders;
+ BOOL bResult = FALSE;
+
+
+ iNumProviders = GetPrivateProfileInt(
+ szProviders,
+ szNumProviders,
+ 0,
+ szTelephonIni
+ );
+
+ for (i = 0; i < iNumProviders; i++)
+ {
+ char szProviderFilenameN[32], szProviderName[32];
+
+
+ wsprintf (szProviderFilenameN, "%s%d", szProviderFilename, i);
+
+ GetPrivateProfileString(
+ szProviders,
+ szProviderFilenameN,
+ "",
+ szProviderName,
+ 31,
+ szTelephonIni
+ );
+
+ if (_stricmp (szProviderName, szEspTsp) == 0)
+ {
+ MessageBox(
+ hwnd,
+ "ESP is already installed.",
+ "Installing ESP",
+ MB_OK
+ );
+
+ bResult = TRUE;
+ break;
+ }
+ }
+
+ return bResult;
+}
diff --git a/private/tapi/dev/sp/esp/esp.def b/private/tapi/dev/sp/esp/esp.def
new file mode 100644
index 000000000..3c53f1b75
--- /dev/null
+++ b/private/tapi/dev/sp/esp/esp.def
@@ -0,0 +1,117 @@
+LIBRARY ESP
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept @500
+ TSPI_lineAddToConference @501
+ TSPI_lineAnswer @502
+ TSPI_lineBlindTransfer @503
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineCompleteCall @506
+ TSPI_lineCompleteTransfer @507
+ TSPI_lineConditionalMediaDetection @508
+ TSPI_lineConfigDialog @509
+ TSPI_lineDevSpecific @510
+ TSPI_lineDevSpecificFeature @511
+ TSPI_lineDial @512
+ TSPI_lineDrop @513
+ TSPI_lineForward @514
+ TSPI_lineGatherDigits @515
+ TSPI_lineGenerateDigits @516
+ TSPI_lineGenerateTone @517
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetDevConfig @525
+ TSPI_lineGetExtensionID @526
+ TSPI_lineGetIcon @527
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineHold @531
+ TSPI_lineMakeCall @532
+ TSPI_lineMonitorDigits @533
+ TSPI_lineMonitorMedia @534
+ TSPI_lineMonitorTones @535
+ TSPI_lineNegotiateExtVersion @536
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_lineOpen @538
+ TSPI_linePark @539
+ TSPI_linePickup @540
+ TSPI_linePrepareAddToConference @541
+ TSPI_lineRedirect @542
+ TSPI_lineRemoveFromConference @543
+ TSPI_lineSecureCall @544
+ TSPI_lineSelectExtVersion @545
+ TSPI_lineSendUserUserInfo @546
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetCallParams @548
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetDevConfig @550
+ TSPI_lineSetMediaControl @551
+ TSPI_lineSetMediaMode @552
+ TSPI_lineSetStatusMessages @553
+ TSPI_lineSetTerminal @554
+ TSPI_lineSetupConference @555
+ TSPI_lineSetupTransfer @556
+ TSPI_lineSwapHold @557
+ TSPI_lineUncompleteCall @558
+ TSPI_lineUnhold @559
+ TSPI_lineUnpark @560
+
+ TSPI_phoneClose @561
+ TSPI_phoneConfigDialog @562
+ TSPI_phoneDevSpecific @563
+ TSPI_phoneGetButtonInfo @564
+ TSPI_phoneGetData @565
+ TSPI_phoneGetDevCaps @566
+ TSPI_phoneGetDisplay @567
+ TSPI_phoneGetExtensionID @568
+ TSPI_phoneGetGain @569
+ TSPI_phoneGetHookSwitch @570
+ TSPI_phoneGetIcon @571
+ TSPI_phoneGetID @572
+ TSPI_phoneGetLamp @573
+ TSPI_phoneGetRing @574
+ TSPI_phoneGetStatus @575
+ TSPI_phoneGetVolume @576
+ TSPI_phoneNegotiateExtVersion @577
+ TSPI_phoneNegotiateTSPIVersion @578
+ TSPI_phoneOpen @579
+ TSPI_phoneSelectExtVersion @580
+ TSPI_phoneSetButtonInfo @581
+ TSPI_phoneSetData @582
+ TSPI_phoneSetDisplay @583
+ TSPI_phoneSetGain @584
+ TSPI_phoneSetHookSwitch @585
+ TSPI_phoneSetLamp @586
+ TSPI_phoneSetRing @587
+ TSPI_phoneSetStatusMessages @588
+ TSPI_phoneSetVolume @589
+
+ TSPI_providerConfig @590
+ TSPI_providerInit @591
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerShutdown @594
+
+ TSPI_providerEnumDevices @595
+ TSPI_lineDropOnClose @596
+ TSPI_lineDropNoOwner @597
+ TSPI_providerCreateLineDevice @598
+ TSPI_providerCreatePhoneDevice @599
+ TSPI_lineSetCurrentLocation @600
+ TSPI_lineConfigDialogEdit @601
+ TSPI_lineReleaseUserUserInfo @602
+
+ DllMsgLoop
+ MainWndProc
+ AboutDlgProc
+ CallDlgProc
diff --git a/private/tapi/dev/sp/esp/esp.h b/private/tapi/dev/sp/esp/esp.h
new file mode 100644
index 000000000..71d07ed1a
--- /dev/null
+++ b/private/tapi/dev/sp/esp/esp.h
@@ -0,0 +1,631 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ esp.h
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) dd-Mmm-1995
+
+Revision History:
+
+--*/
+
+#include <windows.h>
+#include <stddef.h>
+
+#ifdef WIN32
+#define __loadds
+#endif
+
+#include <tapi.h>
+#include <tspi.h>
+
+#include "resource.h"
+
+
+#define TEXT_BUF_SIZE 4096
+
+#define WM_ADDTEXT (WM_USER+0x55)
+#define WM_UPDATEWIDGETLIST (WM_USER+0x56)
+#define WM_ASYNCCOMPL (WM_USER+0x57)
+#define WM_MANUALCOMPL (WM_USER+0x58)
+#define ESP_MSG_KEY 0x1234
+
+#define XX_LINEEVENT 1
+#define XX_PHONEEVENT 2
+#define XX_DEFAULTS 3
+#define XX_CALL 4
+#define XX_OUTCALLSTATEPROG 5
+#define XX_REQRESULTPOSTQUIT 6
+#define XX_REQRESULT 7
+#define XX_LINE 8
+#define XX_PHONE 9
+
+#define SYNC 0
+#define ASYNC 1
+
+#define WT_DRVLINE 1
+#define WT_DRVCALL 2
+#define WT_DRVPHONE 3
+
+#define PT_DWORD 1
+#define PT_FLAGS 2
+//#define PT_POINTER 3
+#define PT_STRING 4
+#define PT_ORDINAL 5
+
+#define MAX_STRING_PARAM_SIZE 32
+
+#define MAX_OUT_CALL_STATES 4
+
+#define ALL_ADDRESS_FEATURES (LINEADDRFEATURE_FORWARD | \
+ LINEADDRFEATURE_MAKECALL | \
+ LINEADDRFEATURE_PICKUP | \
+ LINEADDRFEATURE_SETMEDIACONTROL | \
+ LINEADDRFEATURE_SETTERMINAL | \
+ LINEADDRFEATURE_SETUPCONF | \
+ LINEADDRFEATURE_UNCOMPLETECALL | \
+ LINEADDRFEATURE_UNPARK)
+#define ALL_ADDRESS_MODES (LINEADDRESSMODE_ADDRESSID | \
+ LINEADDRESSMODE_DIALABLEADDR)
+#define ALL_ADDRESS_STATES (LINEADDRESSSTATE_OTHER | \
+ LINEADDRESSSTATE_DEVSPECIFIC | \
+ LINEADDRESSSTATE_INUSEZERO | \
+ LINEADDRESSSTATE_INUSEONE | \
+ LINEADDRESSSTATE_INUSEMANY | \
+ LINEADDRESSSTATE_NUMCALLS | \
+ LINEADDRESSSTATE_FORWARD | \
+ LINEADDRESSSTATE_TERMINALS | \
+ LINEADDRESSSTATE_CAPSCHANGE)
+#define ALL_BEARER_MODES (LINEBEARERMODE_VOICE | \
+ LINEBEARERMODE_SPEECH | \
+ LINEBEARERMODE_MULTIUSE | \
+ LINEBEARERMODE_DATA | \
+ LINEBEARERMODE_ALTSPEECHDATA | \
+ LINEBEARERMODE_NONCALLSIGNALING | \
+ LINEBEARERMODE_PASSTHROUGH)
+#define ALL_BUSY_MODES (LINEBUSYMODE_STATION | \
+ LINEBUSYMODE_TRUNK | \
+ LINEBUSYMODE_UNKNOWN | \
+ LINEBUSYMODE_UNAVAIL)
+#define ALL_CALL_FEATURES (LINECALLFEATURE_ACCEPT | \
+ LINECALLFEATURE_ADDTOCONF | \
+ LINECALLFEATURE_ANSWER | \
+ LINECALLFEATURE_BLINDTRANSFER | \
+ LINECALLFEATURE_COMPLETECALL | \
+ LINECALLFEATURE_COMPLETETRANSF | \
+ LINECALLFEATURE_DIAL | \
+ LINECALLFEATURE_DROP | \
+ LINECALLFEATURE_GATHERDIGITS | \
+ LINECALLFEATURE_GENERATEDIGITS | \
+ LINECALLFEATURE_GENERATETONE | \
+ LINECALLFEATURE_HOLD | \
+ LINECALLFEATURE_MONITORDIGITS | \
+ LINECALLFEATURE_MONITORMEDIA | \
+ LINECALLFEATURE_MONITORTONES | \
+ LINECALLFEATURE_PARK | \
+ LINECALLFEATURE_PREPAREADDCONF | \
+ LINECALLFEATURE_REDIRECT | \
+ LINECALLFEATURE_REMOVEFROMCONF | \
+ LINECALLFEATURE_SECURECALL | \
+ LINECALLFEATURE_SENDUSERUSER | \
+ LINECALLFEATURE_SETCALLPARAMS | \
+ LINECALLFEATURE_SETMEDIACONTROL | \
+ LINECALLFEATURE_SETTERMINAL | \
+ LINECALLFEATURE_SETUPCONF | \
+ LINECALLFEATURE_SETUPTRANSFER | \
+ LINECALLFEATURE_SWAPHOLD | \
+ LINECALLFEATURE_UNHOLD | \
+ LINECALLFEATURE_RELEASEUSERUSERINFO)
+#define ALL_CALL_INFO_STATES (LINECALLINFOSTATE_OTHER | \
+ LINECALLINFOSTATE_DEVSPECIFIC | \
+ LINECALLINFOSTATE_BEARERMODE | \
+ LINECALLINFOSTATE_RATE | \
+ LINECALLINFOSTATE_MEDIAMODE | \
+ LINECALLINFOSTATE_APPSPECIFIC | \
+ LINECALLINFOSTATE_CALLID | \
+ LINECALLINFOSTATE_RELATEDCALLID | \
+ LINECALLINFOSTATE_ORIGIN | \
+ LINECALLINFOSTATE_REASON | \
+ LINECALLINFOSTATE_COMPLETIONID | \
+ LINECALLINFOSTATE_TRUNK | \
+ LINECALLINFOSTATE_CALLERID | \
+ LINECALLINFOSTATE_CALLEDID | \
+ LINECALLINFOSTATE_CONNECTEDID | \
+ LINECALLINFOSTATE_REDIRECTIONID | \
+ LINECALLINFOSTATE_REDIRECTINGID | \
+ LINECALLINFOSTATE_DISPLAY | \
+ LINECALLINFOSTATE_USERUSERINFO | \
+ LINECALLINFOSTATE_HIGHLEVELCOMP | \
+ LINECALLINFOSTATE_LOWLEVELCOMP | \
+ LINECALLINFOSTATE_CHARGINGINFO | \
+ LINECALLINFOSTATE_TERMINAL | \
+ LINECALLINFOSTATE_DIALPARAMS | \
+ LINECALLINFOSTATE_MONITORMODES)
+ //LINECALLINFOSTATE_NUMMONITORS not SP flag
+ //LINECALLINFOSTATE_NUMOWNERINCR not SP flag
+ //LINECALLINFOSTATE_NUMOWNERDECR not SP flag
+#define ALL_CALL_PARTY_ID_FLAGS (LINECALLPARTYID_BLOCKED | \
+ LINECALLPARTYID_OUTOFAREA | \
+ LINECALLPARTYID_NAME | \
+ LINECALLPARTYID_ADDRESS | \
+ LINECALLPARTYID_PARTIAL | \
+ LINECALLPARTYID_UNKNOWN | \
+ LINECALLPARTYID_UNAVAIL)
+#define ALL_CALL_STATES (LINECALLSTATE_IDLE | \
+ LINECALLSTATE_OFFERING | \
+ LINECALLSTATE_ACCEPTED | \
+ LINECALLSTATE_DIALTONE | \
+ LINECALLSTATE_DIALING | \
+ LINECALLSTATE_RINGBACK | \
+ LINECALLSTATE_BUSY | \
+ LINECALLSTATE_SPECIALINFO | \
+ LINECALLSTATE_CONNECTED | \
+ LINECALLSTATE_PROCEEDING | \
+ LINECALLSTATE_ONHOLD | \
+ LINECALLSTATE_CONFERENCED | \
+ LINECALLSTATE_ONHOLDPENDCONF | \
+ LINECALLSTATE_ONHOLDPENDTRANSFER | \
+ LINECALLSTATE_DISCONNECTED | \
+ LINECALLSTATE_UNKNOWN)
+#define ALL_DIAL_TONE_MODES (LINEDIALTONEMODE_NORMAL | \
+ LINEDIALTONEMODE_SPECIAL | \
+ LINEDIALTONEMODE_INTERNAL | \
+ LINEDIALTONEMODE_EXTERNAL | \
+ LINEDIALTONEMODE_UNKNOWN | \
+ LINEDIALTONEMODE_UNAVAIL)
+#define ALL_DISCONNECT_MODES (LINEDISCONNECTMODE_NORMAL | \
+ LINEDISCONNECTMODE_UNKNOWN | \
+ LINEDISCONNECTMODE_REJECT | \
+ LINEDISCONNECTMODE_PICKUP | \
+ LINEDISCONNECTMODE_FORWARDED | \
+ LINEDISCONNECTMODE_BUSY | \
+ LINEDISCONNECTMODE_NOANSWER | \
+ LINEDISCONNECTMODE_BADADDRESS | \
+ LINEDISCONNECTMODE_UNREACHABLE | \
+ LINEDISCONNECTMODE_CONGESTION | \
+ LINEDISCONNECTMODE_INCOMPATIBLE | \
+ LINEDISCONNECTMODE_UNAVAIL | \
+ LINEDISCONNECTMODE_NODIALTONE)
+#define ALL_MEDIA_MODES (LINEMEDIAMODE_UNKNOWN | \
+ LINEMEDIAMODE_INTERACTIVEVOICE | \
+ LINEMEDIAMODE_AUTOMATEDVOICE | \
+ LINEMEDIAMODE_DATAMODEM | \
+ LINEMEDIAMODE_G3FAX | \
+ LINEMEDIAMODE_TDD | \
+ LINEMEDIAMODE_G4FAX | \
+ LINEMEDIAMODE_DIGITALDATA | \
+ LINEMEDIAMODE_TELETEX | \
+ LINEMEDIAMODE_VIDEOTEX | \
+ LINEMEDIAMODE_TELEX | \
+ LINEMEDIAMODE_MIXED | \
+ LINEMEDIAMODE_ADSI | \
+ LINEMEDIAMODE_VOICEVIEW)
+#define ALL_LINE_DEV_CAP_FLAGS (LINEDEVCAPFLAGS_CROSSADDRCONF | \
+ LINEDEVCAPFLAGS_HIGHLEVCOMP | \
+ LINEDEVCAPFLAGS_LOWLEVCOMP | \
+ LINEDEVCAPFLAGS_MEDIACONTROL | \
+ LINEDEVCAPFLAGS_MULTIPLEADDR | \
+ LINEDEVCAPFLAGS_CLOSEDROP | \
+ LINEDEVCAPFLAGS_DIALBILLING | \
+ LINEDEVCAPFLAGS_DIALQUIET | \
+ LINEDEVCAPFLAGS_DIALDIALTONE)
+#define ALL_LINE_STATES (LINEDEVSTATE_OTHER | \
+ LINEDEVSTATE_RINGING | \
+ LINEDEVSTATE_CONNECTED | \
+ LINEDEVSTATE_DISCONNECTED | \
+ LINEDEVSTATE_MSGWAITON | \
+ LINEDEVSTATE_MSGWAITOFF | \
+ LINEDEVSTATE_INSERVICE | \
+ LINEDEVSTATE_OUTOFSERVICE | \
+ LINEDEVSTATE_MAINTENANCE | \
+ LINEDEVSTATE_OPEN | \
+ LINEDEVSTATE_CLOSE | \
+ LINEDEVSTATE_NUMCALLS | \
+ LINEDEVSTATE_NUMCOMPLETIONS | \
+ LINEDEVSTATE_TERMINALS | \
+ LINEDEVSTATE_ROAMMODE | \
+ LINEDEVSTATE_BATTERY | \
+ LINEDEVSTATE_SIGNAL | \
+ LINEDEVSTATE_DEVSPECIFIC | \
+ LINEDEVSTATE_REINIT | \
+ LINEDEVSTATE_LOCK | \
+ LINEDEVSTATE_CAPSCHANGE | \
+ LINEDEVSTATE_CONFIGCHANGE | \
+ LINEDEVSTATE_TRANSLATECHANGE | \
+ LINEDEVSTATE_COMPLCANCEL | \
+ LINEDEVSTATE_REMOVED)
+#define ALL_LINE_FEATURES (LINEFEATURE_DEVSPECIFIC | \
+ LINEFEATURE_DEVSPECIFICFEAT | \
+ LINEFEATURE_FORWARD | \
+ LINEFEATURE_MAKECALL | \
+ LINEFEATURE_SETMEDIACONTROL | \
+ LINEFEATURE_SETTERMINAL)
+#define ALL_SPECIAL_INFO (LINESPECIALINFO_NOCIRCUIT | \
+ LINESPECIALINFO_CUSTIRREG | \
+ LINESPECIALINFO_REORDER | \
+ LINESPECIALINFO_UNKNOWN | \
+ LINESPECIALINFO_UNAVAIL)
+#define ALL_ADDRESS_CAP_FLAGS (LINEADDRCAPFLAGS_FWDNUMRINGS | \
+ LINEADDRCAPFLAGS_PICKUPGROUPID | \
+ LINEADDRCAPFLAGS_SECURE | \
+ LINEADDRCAPFLAGS_BLOCKIDDEFAULT | \
+ LINEADDRCAPFLAGS_BLOCKIDOVERRIDE | \
+ LINEADDRCAPFLAGS_DIALED | \
+ LINEADDRCAPFLAGS_ORIGOFFHOOK | \
+ LINEADDRCAPFLAGS_DESTOFFHOOK | \
+ LINEADDRCAPFLAGS_FWDCONSULT | \
+ LINEADDRCAPFLAGS_SETUPCONFNULL | \
+ LINEADDRCAPFLAGS_AUTORECONNECT | \
+ LINEADDRCAPFLAGS_COMPLETIONID | \
+ LINEADDRCAPFLAGS_TRANSFERHELD | \
+ LINEADDRCAPFLAGS_TRANSFERMAKE | \
+ LINEADDRCAPFLAGS_CONFERENCEHELD | \
+ LINEADDRCAPFLAGS_CONFERENCEMAKE | \
+ LINEADDRCAPFLAGS_PARTIALDIAL | \
+ LINEADDRCAPFLAGS_FWDSTATUSVALID | \
+ LINEADDRCAPFLAGS_FWDINTEXTADDR | \
+ LINEADDRCAPFLAGS_FWDBUSYNAADDR | \
+ LINEADDRCAPFLAGS_ACCEPTTOALERT | \
+ LINEADDRCAPFLAGS_CONFDROP | \
+ LINEADDRCAPFLAGS_PICKUPCALLWAIT)
+
+//
+// Note: Some fields in the following structures are dups, & so we just
+// ignore them & copy them on the fly when necessary
+//
+// PHONESTATUS: LampModes(Size\Offset) & DevSpecific(Size\Offset)
+// copied from PHONECAPS. OwnerName(Size\Offset) filled
+// in by TAPI.DLL
+//
+
+#define LINE_DEV_CAPS_VAR_DATA_SIZE (6*MAX_STRING_PARAM_SIZE)
+#define LINE_DEV_STATUS_VAR_DATA_SIZE (2*MAX_STRING_PARAM_SIZE)
+#define LINE_ADDR_CAPS_VAR_DATA_SIZE (3*MAX_STRING_PARAM_SIZE)
+#define LINE_ADDR_STATUS_VAR_DATA_SIZE (2*MAX_STRING_PARAM_SIZE)
+#define LINE_CALL_INFO_VAR_DATA_SIZE (17*MAX_STRING_PARAM_SIZE)
+#define PHONE_CAPS_VAR_DATA_SIZE (9*MAX_STRING_PARAM_SIZE)
+#define PHONE_STATUS_VAR_DATA_SIZE (1*MAX_STRING_PARAM_SIZE)
+
+
+typedef struct _ASYNC_REQUEST_INFO
+{
+ FARPROC pfnPostProcessProc;
+
+ DWORD dwRequestID;
+
+ LONG lResult;
+
+ DWORD dwParam1;
+
+ DWORD dwParam2;
+
+ DWORD dwParam3;
+
+ DWORD dwParam4;
+
+ DWORD dwParam5;
+
+ DWORD dwParam6;
+
+ DWORD dwParam7;
+
+ DWORD dwParam8;
+
+ char szFuncName[32];
+
+} ASYNC_REQUEST_INFO, far *PASYNC_REQUEST_INFO;
+
+
+typedef void (FAR PASCAL *POSTPROCESSPROC)(char far *, PASYNC_REQUEST_INFO, BOOL);
+
+
+typedef struct _LOOKUP
+{
+ DWORD dwVal;
+
+ char far *lpszVal;
+
+} LOOKUP, *PLOOKUP;
+
+
+typedef struct _EVENT_PARAM
+{
+ char far *szName;
+
+ DWORD dwType;
+
+ DWORD dwValue;
+
+ union
+ {
+ PLOOKUP pLookup;
+
+ char far *buf;
+
+ LPVOID ptr;
+
+ DWORD dwDefValue;
+
+ } u;
+
+} EVENT_PARAM, far *PEVENT_PARAM;
+
+
+typedef struct _EVENT_PARAM_HEADER
+{
+ DWORD dwNumParams;
+
+ LPSTR pszDlgTitle;
+
+ DWORD dwEventType;
+
+ PEVENT_PARAM aParams;
+
+} EVENT_PARAM_HEADER, far *PEVENT_PARAM_HEADER;
+
+
+typedef struct _FUNC_PARAM
+{
+ char *lpszVal;
+
+ DWORD dwVal;
+
+ PLOOKUP pLookup;
+
+} FUNC_PARAM, *PFUNC_PARAM;
+
+
+typedef struct _FUNC_INFO
+{
+ char *lpszFuncName;
+
+ DWORD bAsync;
+
+ DWORD dwNumParams;
+
+ PFUNC_PARAM aParams;
+
+ POSTPROCESSPROC pfnPostProcessProc;
+
+ PASYNC_REQUEST_INFO pAsyncReqInfo;
+
+ LONG lResult;
+
+} FUNC_INFO, *PFUNC_INFO;
+
+
+typedef struct _ASYNC_REQUEST
+{
+ DWORD dwRequestID;
+
+ LONG lResult;
+
+} ASYNC_REQUEST, *PASYNC_REQUEST;
+
+
+typedef struct _DRVWIDGET
+{
+ DWORD dwType;
+
+ struct _DRVWIDGET *pNext;
+
+} DRVWIDGET, *PDRVWIDGET;
+
+
+typedef struct _DRVLINE
+{
+ DRVWIDGET Widget;
+
+ HTAPILINE htLine;
+
+ LINEEVENT lpfnEventProc;
+
+ DWORD dwDeviceID;
+
+ DWORD dwDetectedMediaModes;
+
+ LINEDEVCAPS LineDevCaps;
+
+ char LineDevCapsVarData[LINE_DEV_CAPS_VAR_DATA_SIZE];
+
+ LINEDEVSTATUS LineDevStatus;
+
+ char LineDevStatusVarData[LINE_DEV_STATUS_VAR_DATA_SIZE];
+
+ LINEADDRESSCAPS LineAddrCaps;
+
+ char LineAddrCapsVarData[LINE_ADDR_CAPS_VAR_DATA_SIZE];
+
+ LINEADDRESSSTATUS LineAddrStatus;
+
+ char LineAddrStatusVarData[LINE_ADDR_STATUS_VAR_DATA_SIZE];
+
+} DRVLINE, FAR *PDRVLINE;
+
+
+typedef struct _DRVCALL
+{
+ DRVWIDGET Widget;
+
+ PDRVLINE pLine;
+
+ HTAPICALL htCall;
+
+ DWORD dwCallState;
+
+ DWORD dwCallStateMode;
+
+ DWORD dwCallFeatures;
+
+ struct _DRVCALL far *pConfParent;
+
+ struct _DRVCALL far *pNextConfChild;
+
+ LINECALLINFO LineCallInfo;
+
+ char LineAddressStatusVarData[LINE_CALL_INFO_VAR_DATA_SIZE];
+
+} DRVCALL, FAR *PDRVCALL;
+
+
+typedef struct _DRVPHONE
+{
+ DRVWIDGET Widget;
+
+ HTAPIPHONE htPhone;
+
+ PHONEEVENT lpfnEventProc;
+
+ DWORD dwDeviceID;
+
+ PHONECAPS PhoneCaps;
+
+ char PhoneCapsVarData[PHONE_CAPS_VAR_DATA_SIZE];
+
+ PHONESTATUS PhoneStatus;
+
+ char PhoneStatusVarData[PHONE_STATUS_VAR_DATA_SIZE];
+
+} DRVPHONE, FAR *PDRVPHONE;
+
+
+typedef struct _LINE_EVENT_RECORD
+{
+ PDRVLINE pLine;
+
+ HTAPICALL htCall;
+
+ DWORD dwMsg;
+
+ DWORD dwParam1;
+
+ DWORD dwParam2;
+
+ DWORD dwParam3;
+
+} LINE_EVENT_RECORD, FAR *PLINE_EVENT_RECORD;
+
+
+BOOL
+InitGlobals(
+ );
+
+VOID
+ShowStr(
+ char *lpszFormat,
+ ...
+ );
+
+BOOL
+Prolog(
+ PFUNC_INFO pInfo
+ );
+
+LONG
+Epilog(
+ PFUNC_INFO pInfo
+ );
+
+void
+TSPIAPI
+ExeAttach(
+ void
+ );
+
+void
+TSPIAPI
+ExeDetach(
+ void
+ );
+
+LPVOID
+DrvAlloc(
+ size_t numBytes
+ );
+
+void
+DrvFree(
+ LPVOID lp
+ );
+
+void
+ESPConfigDialog(
+ void
+ );
+
+void
+TSPIAPI
+DllMsgLoop(
+ void
+ );
+
+//
+// Exports from WIDGET.C
+//
+
+PDRVLINE
+AllocLine(
+ DWORD dwDeviceID
+ );
+
+VOID
+FreeLine(
+ PDRVLINE pLine
+ );
+
+LONG
+AllocCall(
+ PDRVLINE pLine,
+ HTAPICALL htCall,
+ LPLINECALLPARAMS lpCallParams,
+ PDRVCALL *ppCall
+ );
+
+VOID
+FreeCall(
+ PDRVCALL pCall
+ );
+
+PDRVPHONE
+AllocPhone(
+ DWORD dwDeviceID
+ );
+
+VOID
+FreePhone(
+ PDRVPHONE pPhone
+ );
+
+int
+GetWidgetIndex(
+ PDRVWIDGET pWidget
+ );
+
+void
+UpdateWidgetList(
+ void
+ );
+
+PDRVLINE
+GetLine(
+ DWORD dwDeviceID
+ );
+
+PDRVPHONE
+GetPhone(
+ DWORD dwDeviceID
+ );
+
+void
+PostUpdateWidgetListMsg(
+ void
+ );
diff --git a/private/tapi/dev/sp/esp/esp.ico b/private/tapi/dev/sp/esp/esp.ico
new file mode 100644
index 000000000..516eb3f84
--- /dev/null
+++ b/private/tapi/dev/sp/esp/esp.ico
Binary files differ
diff --git a/private/tapi/dev/sp/esp/esp.rc b/private/tapi/dev/sp/esp/esp.rc
new file mode 100644
index 000000000..d8a6a58fd
--- /dev/null
+++ b/private/tapi/dev/sp/esp/esp.rc
@@ -0,0 +1,224 @@
+//Microsoft App Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifdef WIN32
+#include "windows.h"
+#else
+#include "afxres.h"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+//////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // APSTUDIO_INVOKED
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 292, 217
+STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU |
+ WS_THICKFRAME
+CAPTION "ESP: The Economical Service Provider"
+MENU IDR_MENU2
+FONT 6, "Courier"
+BEGIN
+ PUSHBUTTON "LEvt",IDC_BUTTON1,1,1,16,16,WS_DISABLED
+ PUSHBUTTON "PEvt",IDC_BUTTON2,19,1,16,16,WS_DISABLED
+ PUSHBUTTON "Call+",IDC_BUTTON3,37,1,16,16,WS_DISABLED
+ PUSHBUTTON "Clear",IDC_BUTTON4,55,1,16,16
+ EDITTEXT IDC_EDIT1,129,19,117,195,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL | 0x1000
+ LISTBOX IDC_LIST1,62,17,65,197,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+ LISTBOX IDC_LIST2,0,0,0,0,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+END
+
+IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 185, 69
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "About ESPExe"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,69,50,50,14
+ LTEXT "ESP v1.0",38,88,12,70,7
+ LTEXT "Copyright (c) 1995 Microsoft Corporation",70,24,30,160,
+ 12
+ ICON IDI_ICON1,IDC_STATIC1,60,5,18,20
+END
+
+IDD_DIALOG3 DIALOG DISCARDABLE 0, 0, 205, 192
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Parameters:",55,4,6,42,7
+ LISTBOX IDC_LIST1,4,16,100,148,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Value:",56,116,6,30,7
+#ifdef WIN32
+ COMBOBOX IDC_COMBO1,116,16,80,47,CBS_SIMPLE | CBS_AUTOHSCROLL |
+ CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+#endif
+ LTEXT "Bit flags:",57,116,66,40,9
+ LISTBOX IDC_LIST2,116,75,80,89,LBS_MULTIPLESEL |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",IDOK,116,171,36,14
+ PUSHBUTTON "Cancel",IDCANCEL,160,171,37,14
+END
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU2 MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Install", IDM_INSTALL
+ MENUITEM "&Uninstall", IDM_UNINSTALL
+ MENUITEM SEPARATOR
+ MENUITEM "&Dump globals", IDM_DUMPGLOBALS
+#ifndef WIN32
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_EXIT
+#endif
+ END
+ POPUP "&Options"
+ BEGIN
+ MENUITEM "&Default values...", IDM_DEFAULTS
+ MENUITEM SEPARATOR
+ MENUITEM "&Outgoing call state progress...", IDM_OUTCALLSTATEPROG
+ MENUITEM SEPARATOR
+ POPUP "D&ebug Output"
+ BEGIN
+ MENUITEM "Show function &entry", IDM_SHOWFUNCENTRY
+ MENUITEM "Show &parameters", IDM_SHOWFUNCPARAMS
+ MENUITEM "Show function e&xit", IDM_SHOWFUNCEXIT
+ MENUITEM "Show event &notifications", IDM_SHOWEVENTS
+ MENUITEM "Show &completion notifications", IDM_SHOWCOMPLETIONS
+ MENUITEM SEPARATOR
+ MENUITEM "Show &all", IDM_SHOWALL
+ MENUITEM "Show n&one", IDM_SHOWNONE
+ END
+ MENUITEM "Debug&Break() on function entry", IDM_DEBUGBREAK
+ MENUITEM SEPARATOR
+
+ POPUP "Complete async requests"
+ BEGIN
+ MENUITEM "Synchronously", IDM_SYNCCOMPL
+ MENUITEM "Asynchronously", IDM_ASYNCCOMPL
+ MENUITEM "Manually", IDM_MANUALCOMPL
+ END
+ MENUITEM "User-specified request results", IDM_MANUALRESULTS
+ MENUITEM SEPARATOR
+ MENUITEM "Disable UI (for faster auto-testing)",IDM_DISABLEUI
+#ifndef WIN32
+ MENUITEM SEPARATOR
+ MENUITEM "Close &window on shutdown", IDM_AUTOCLOSE
+#endif
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Using ESP...", IDM_USAGE
+ MENUITEM SEPARATOR
+ MENUITEM "&About...", IDM_ABOUT
+ END
+END
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+#if TAPI_NT
+IDI_ICON1 ICON DISCARDABLE "ESP.ICO"
+IDI_ICON2 ICON DISCARDABLE "PHONE.ICO"
+IDI_ICON3 ICON DISCARDABLE "LINE.ICO"
+#else
+IDI_ICON1 ICON DISCARDABLE "..\\ESP.ICO"
+IDI_ICON2 ICON DISCARDABLE "..\\PHONE.ICO"
+IDI_ICON3 ICON DISCARDABLE "..\\LINE.ICO"
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ VK_F1, IDC_F1HELP, VIRTKEY
+ VK_TAB, IDC_PREVCTRL, VIRTKEY, SHIFT
+ VK_TAB, IDC_NEXTCTRL, VIRTKEY
+ VK_RETURN, IDC_ENTER, VIRTKEY
+END
+
+
+#ifndef APSTUDIO_INVOKED
+////////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+// /////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Economical Service Provider"
+#define VER_INTERNALNAME_STR "esp"
+#define VER_ORIGINALFILENAME_STR "ESP.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
+
+// /////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/private/tapi/dev/sp/esp/esp32.def b/private/tapi/dev/sp/esp/esp32.def
new file mode 100644
index 000000000..1a3210653
--- /dev/null
+++ b/private/tapi/dev/sp/esp/esp32.def
@@ -0,0 +1,117 @@
+LIBRARY ESP
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept @500
+ TSPI_lineAddToConference @501
+ TSPI_lineAnswer @502
+ TSPI_lineBlindTransfer @503
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineCompleteCall @506
+ TSPI_lineCompleteTransfer @507
+ TSPI_lineConditionalMediaDetection @508
+ TSPI_lineConfigDialog @509
+ TSPI_lineDevSpecific @510
+ TSPI_lineDevSpecificFeature @511
+ TSPI_lineDial @512
+ TSPI_lineDrop @513
+ TSPI_lineForward @514
+ TSPI_lineGatherDigits @515
+ TSPI_lineGenerateDigits @516
+ TSPI_lineGenerateTone @517
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetDevConfig @525
+ TSPI_lineGetExtensionID @526
+ TSPI_lineGetIcon @527
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineHold @531
+ TSPI_lineMakeCall @532
+ TSPI_lineMonitorDigits @533
+ TSPI_lineMonitorMedia @534
+ TSPI_lineMonitorTones @535
+ TSPI_lineNegotiateExtVersion @536
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_lineOpen @538
+ TSPI_linePark @539
+ TSPI_linePickup @540
+ TSPI_linePrepareAddToConference @541
+ TSPI_lineRedirect @542
+ TSPI_lineRemoveFromConference @543
+ TSPI_lineSecureCall @544
+ TSPI_lineSelectExtVersion @545
+ TSPI_lineSendUserUserInfo @546
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetCallParams @548
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetDevConfig @550
+ TSPI_lineSetMediaControl @551
+ TSPI_lineSetMediaMode @552
+ TSPI_lineSetStatusMessages @553
+ TSPI_lineSetTerminal @554
+ TSPI_lineSetupConference @555
+ TSPI_lineSetupTransfer @556
+ TSPI_lineSwapHold @557
+ TSPI_lineUncompleteCall @558
+ TSPI_lineUnhold @559
+ TSPI_lineUnpark @560
+
+ TSPI_phoneClose @561
+ TSPI_phoneConfigDialog @562
+ TSPI_phoneDevSpecific @563
+ TSPI_phoneGetButtonInfo @564
+ TSPI_phoneGetData @565
+ TSPI_phoneGetDevCaps @566
+ TSPI_phoneGetDisplay @567
+ TSPI_phoneGetExtensionID @568
+ TSPI_phoneGetGain @569
+ TSPI_phoneGetHookSwitch @570
+ TSPI_phoneGetIcon @571
+ TSPI_phoneGetID @572
+ TSPI_phoneGetLamp @573
+ TSPI_phoneGetRing @574
+ TSPI_phoneGetStatus @575
+ TSPI_phoneGetVolume @576
+ TSPI_phoneNegotiateExtVersion @577
+ TSPI_phoneNegotiateTSPIVersion @578
+ TSPI_phoneOpen @579
+ TSPI_phoneSelectExtVersion @580
+ TSPI_phoneSetButtonInfo @581
+ TSPI_phoneSetData @582
+ TSPI_phoneSetDisplay @583
+ TSPI_phoneSetGain @584
+ TSPI_phoneSetHookSwitch @585
+ TSPI_phoneSetLamp @586
+ TSPI_phoneSetRing @587
+ TSPI_phoneSetStatusMessages @588
+ TSPI_phoneSetVolume @589
+
+ TSPI_providerConfig @590
+ TSPI_providerInit @591
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerShutdown @594
+
+ TSPI_providerEnumDevices @595
+ TSPI_lineDropOnClose @596
+ TSPI_lineDropNoOwner @597
+ TSPI_providerCreateLineDevice @598
+ TSPI_providerCreatePhoneDevice @599
+ TSPI_lineSetCurrentLocation @600
+ TSPI_lineConfigDialogEdit @601
+ TSPI_lineReleaseUserUserInfo @602
+
+ DllMsgLoop
+ MainWndProc
+ AboutDlgProc
+ CallDlgProc
diff --git a/private/tapi/dev/sp/esp/espexe.c b/private/tapi/dev/sp/esp/espexe.c
new file mode 100644
index 000000000..565c7672e
--- /dev/null
+++ b/private/tapi/dev/sp/esp/espexe.c
@@ -0,0 +1,67 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ espexe.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) dd-Mmm-1995
+
+Revision History:
+
+--*/
+
+
+#include "esp.h"
+
+
+
+typedef void (TSPIAPI *MYFUNC)(void);
+
+
+int
+WINAPI
+WinMain(
+ HANDLE hInstance,
+ HANDLE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow
+ )
+{
+ HINSTANCE hLib = LoadLibrary ("esp.tsp");
+ MYFUNC pfnDllMsgLoop;
+
+
+ if (hLib < HINSTANCE_ERROR)
+ {
+ char buf[32];
+
+
+ wsprintf (buf, "WinExec returned %d", hLib);
+
+ MessageBox(
+ (HWND) NULL,
+ buf,
+ "ESPEXE.EXE: Error loading ESP.TSP",
+ MB_OK
+ );
+
+ return 0;
+ }
+
+ if ((pfnDllMsgLoop = (MYFUNC) GetProcAddress (hLib, "DLLMSGLOOP")))
+ {
+ (*pfnDllMsgLoop)();
+ }
+
+ FreeLibrary (hLib);
+
+ return 0;
+}
diff --git a/private/tapi/dev/sp/esp/espexe.def b/private/tapi/dev/sp/esp/espexe.def
new file mode 100644
index 000000000..4a7235c37
--- /dev/null
+++ b/private/tapi/dev/sp/esp/espexe.def
@@ -0,0 +1,6 @@
+NAME ESPEXE
+STUB 'WINSTUB.EXE'
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE MULTIPLE
+HEAPSIZE 4096
+STACKSIZE 16384
diff --git a/private/tapi/dev/sp/esp/espexe.rc b/private/tapi/dev/sp/esp/espexe.rc
new file mode 100644
index 000000000..b5fa5dee7
--- /dev/null
+++ b/private/tapi/dev/sp/esp/espexe.rc
@@ -0,0 +1,57 @@
+//Microsoft App Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+//////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // APSTUDIO_INVOKED
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+IDI_ICON1 ICON DISCARDABLE "ESP.ICO"
+
+#ifndef APSTUDIO_INVOKED
+////////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/private/tapi/dev/sp/esp/line.ico b/private/tapi/dev/sp/esp/line.ico
new file mode 100644
index 000000000..6c2186e09
--- /dev/null
+++ b/private/tapi/dev/sp/esp/line.ico
Binary files differ
diff --git a/private/tapi/dev/sp/esp/makefile b/private/tapi/dev/sp/esp/makefile
new file mode 100644
index 000000000..b0bb9d98e
--- /dev/null
+++ b/private/tapi/dev/sp/esp/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# esp Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/esp/makefile.def b/private/tapi/dev/sp/esp/makefile.def
new file mode 100644
index 000000000..8524448df
--- /dev/null
+++ b/private/tapi/dev/sp/esp/makefile.def
@@ -0,0 +1,46 @@
+ROOT=..\..\..\..\..\..
+
+IS_OEM=1
+IS_32 = TRUE
+WIN32=1
+WANT_C932=1
+
+DLLENTRY=DllMain
+BUILDDLL=1
+
+CLEANLIST=*.tsp
+
+DEPENDNAME=..\depend.mk
+
+DRVNAME=esp
+TARGETS=esp32.tsp
+
+SRCDIR=..
+
+
+L32EXE=esp32.tsp # Name of exe.
+L32DEF=..\esp.def # Our def file.
+L32MAP=esp.map # Our map file.
+L32SYM=esp.sym # Our sym file.
+L32RES=esp.res # Resource file.
+L32OBJS = esp.obj vars.obj widget.obj
+L32LIBS= \
+ $(DEVROOT)\tools\c932\lib\crtdll.lib \
+ $(DEVROOT)\lib\user32.lib \
+ $(DEVROOT)\lib\gdi32.lib \
+ $(DEVROOT)\lib\kernel32.lib
+
+
+!include $(ROOT)\dev\master.mk
+
+
+INCLUDE=$(ROOT)\win\thunk;$(ROOT)\win\core\inc;$(INCLUDE)
+
+RCFLAGS=$(RCFLAGS) -DWIN32
+
+CFLAGS=$(CFLAGS) -DWIN32=100
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
+
diff --git a/private/tapi/dev/sp/esp/phone.ico b/private/tapi/dev/sp/esp/phone.ico
new file mode 100644
index 000000000..ee34203e3
--- /dev/null
+++ b/private/tapi/dev/sp/esp/phone.ico
Binary files differ
diff --git a/private/tapi/dev/sp/esp/resource.h b/private/tapi/dev/sp/esp/resource.h
new file mode 100644
index 000000000..83a7de59d
--- /dev/null
+++ b/private/tapi/dev/sp/esp/resource.h
@@ -0,0 +1,60 @@
+//{{NO_DEPENDENCIES}}
+// App Studio generated include file.
+// Used by ESP.RC
+//
+#define IDR_MENU1 101
+#define IDD_DIALOG1 102
+#define IDD_DIALOG2 103
+#define IDI_ICON1 104
+#define IDD_DIALOG3 105
+#define IDI_ICON2 105
+#define IDI_ICON3 106
+#define IDR_ACCELERATOR1 107
+#define IDC_LIST1 1000
+#define IDC_LIST2 1001
+#define IDC_LIST3 1002
+#define IDC_EDIT1 1003
+#define IDC_STATIC1 1004
+#define IDC_BUTTON1 1005
+#define IDC_BUTTON2 1006
+#define IDC_BUTTON3 1007
+#define IDC_BUTTON4 1009
+#define IDC_COMBO1 1010
+#define IDC_F1HELP 1011
+#define IDC_PREVCTRL 1012
+#define IDC_NEXTCTRL 1013
+#define IDC_ENTER 1014
+#define IDM_ABOUT 40000
+#define IDM_EXIT 40001
+#define IDM_SHOWFUNCENTRY 40002
+#define IDM_SHOWFUNCPARAMS 40003
+#define IDM_SHOWFUNCEXIT 40004
+#define IDM_SHOWEVENTS 40005
+#define IDM_SHOWCOMPLETIONS 40006
+#define IDM_DEBUGBREAK 40007
+#define IDM_SHOWALL 40008
+#define IDM_SHOWNONE 40009
+#define IDM_DEFAULTS 40010
+#define IDM_OUTCALLSTATEPROG 40011
+#define IDM_AUTOCLOSE 40012
+#define IDM_INSTALL 40013
+#define IDM_UNINSTALL 40014
+#define IDM_USAGE 40015
+#define IDM_DUMPGLOBALS 40016
+#define IDM_SYNCCOMPL 40017
+#define IDM_ASYNCCOMPL 40018
+#define IDM_MANUALCOMPL 40019
+#define IDM_MANUALRESULTS 40020
+#define IDM_DISABLEUI 40021
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE 108
+#define _APS_NEXT_COMMAND_VALUE 40021
+#define _APS_NEXT_CONTROL_VALUE 1015
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/private/tapi/dev/sp/esp/sources b/private/tapi/dev/sp/esp/sources
new file mode 100644
index 000000000..2cda20238
--- /dev/null
+++ b/private/tapi/dev/sp/esp/sources
@@ -0,0 +1,58 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=esp32
+TARGETPATH=.
+TARGETTYPE=DYNLINK
+TARGETEXT=tsp
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib
+
+C_DEFINES=-DTAPI_NT=1
+
+DLLBASE=0x60000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+USE_CRTDLL=1
+
+SOURCES=esp.c \
+ vars.c \
+ widget.c \
+ esp.rc
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/esp/vars.c b/private/tapi/dev/sp/esp/vars.c
new file mode 100644
index 000000000..4698da789
--- /dev/null
+++ b/private/tapi/dev/sp/esp/vars.c
@@ -0,0 +1,605 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ vars.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) dd-Mmm-1995
+
+Revision History:
+
+--*/
+
+
+#include "esp.h"
+
+#ifdef WIN32
+#define my_far
+#else
+#define my_far _far
+#endif
+
+
+HWND ghwndMain = (HWND) NULL;
+HWND ghwndEdit = (HWND) NULL;
+HWND ghwndList1 = (HWND) NULL;
+HWND ghwndList2 = (HWND) NULL;
+BOOL gbExeStarted = FALSE;
+BOOL gbAutoClose;
+BOOL gbShowFuncEntry;
+BOOL gbShowFuncExit;
+BOOL gbShowFuncParams;
+BOOL gbShowEvents;
+BOOL gbShowCompletions;
+BOOL gbBreakOnFuncEntry;
+BOOL gbDisableUI;
+BOOL gbSyncCompl;
+BOOL gbAsyncCompl;
+BOOL gbManualCompl;
+BOOL gbManualResults;
+BOOL gbShowLineGetIDDlg;
+HICON ghIconLine;
+HICON ghIconPhone;
+HMENU ghMenu = (HMENU) NULL;
+DWORD gdwTSPIVersion;
+DWORD gdwNumLines;
+DWORD gdwNumAddrsPerLine;
+DWORD gdwNumPhones;
+DWORD gdwNumInits = 0;
+DWORD gdwDefLineGetIDID;
+DWORD gdwLineDeviceIDBase;
+DWORD gdwPermanentProviderID;
+DWORD aOutCallStates[MAX_OUT_CALL_STATES];
+DWORD aOutCallStateModes[MAX_OUT_CALL_STATES];
+HPROVIDER ghProvider = (HPROVIDER) NULL;
+LINEEVENT gpfnLineCreateProc;
+PHONEEVENT gpfnPhoneCreateProc;
+PDRVWIDGET gaWidgets = (PDRVWIDGET) NULL;
+LINEEXTENSIONID gLineExtID;
+PHONEEXTENSIONID gPhoneExtID;
+ASYNC_COMPLETION gpfnCompletionProc;
+LPLINEADDRESSCAPS gpDefLineAddrCaps = (LPLINEADDRESSCAPS) NULL;
+
+
+LOOKUP my_far aPhoneStatusFlags[] =
+{
+ { PHONESTATUSFLAGS_CONNECTED ,"CONNECTED" },
+ { PHONESTATUSFLAGS_SUSPENDED ,"SUSPENDED" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aCallParamFlags[] =
+{
+ { LINECALLPARAMFLAGS_SECURE ,"SECURE" },
+ { LINECALLPARAMFLAGS_IDLE ,"IDLE" },
+ { LINECALLPARAMFLAGS_BLOCKID ,"BLOCKID" },
+ { LINECALLPARAMFLAGS_ORIGOFFHOOK ,"ORIGOFFHOOK" },
+ { LINECALLPARAMFLAGS_DESTOFFHOOK ,"DESTOFFHOOK" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aCallOrigins[] =
+{
+ { LINECALLORIGIN_OUTBOUND ,"OUTBOUND" },
+ { LINECALLORIGIN_INTERNAL ,"INTERNAL" },
+ { LINECALLORIGIN_EXTERNAL ,"EXTERNAL" },
+ { LINECALLORIGIN_UNKNOWN ,"UNKNOWN" },
+ { LINECALLORIGIN_UNAVAIL ,"UNAVAIL" },
+ { LINECALLORIGIN_CONFERENCE ,"CONFERENCE" },
+#ifdef TAPI_1_1
+ { LINECALLORIGIN_INBOUND ,"INBOUND" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aCallReasons[] =
+{
+ { LINECALLREASON_DIRECT ,"DIRECT" },
+ { LINECALLREASON_FWDBUSY ,"FWDBUSY" },
+ { LINECALLREASON_FWDNOANSWER ,"FWDNOANSWER" },
+ { LINECALLREASON_FWDUNCOND ,"FWDUNCOND" },
+ { LINECALLREASON_PICKUP ,"PICKUP" },
+ { LINECALLREASON_UNPARK ,"UNPARK" },
+ { LINECALLREASON_REDIRECT ,"REDIRECT" },
+ { LINECALLREASON_CALLCOMPLETION ,"CALLCOMPLETION" },
+ { LINECALLREASON_TRANSFER ,"TRANSFER" },
+ { LINECALLREASON_REMINDER ,"REMINDER" },
+ { LINECALLREASON_UNKNOWN ,"UNKNOWN" },
+ { LINECALLREASON_UNAVAIL ,"UNAVAIL" },
+#ifdef TAPI_1_
+ { LINECALLREASON_INTRUDE ,"INTRUDE" },
+ { LINECALLREASON_PARKED ,"PARKED" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aLineMsgs[] =
+{
+// { LINE_ADDRESSSTATE, "ADDRESSSTATE" },
+ { LINE_CALLDEVSPECIFIC, "CALLDEVSPECIFIC" },
+ { LINE_CALLDEVSPECIFICFEATURE, "CALLDEVSPECIFICFEATURE" },
+// { LINE_CALLINFO, "CALLINFO" },
+// { LINE_CALLSTATE, "CALLSTATE" },
+ { LINE_CLOSE, "CLOSE" },
+ { LINE_CREATE, "CREATE" },
+ { LINE_DEVSPECIFIC, "DEVSPECIFIC" },
+ { LINE_DEVSPECIFICFEATURE, "DEVSPECIFICFEATURE" },
+ { LINE_GATHERDIGITS, "GATHERDIGITS" },
+ { LINE_GENERATE, "GENERATE" },
+ { LINE_LINEDEVSTATE, "LINEDEVSTATE" },
+ { LINE_MONITORDIGITS, "MONITORDIGITS" },
+ { LINE_MONITORMEDIA, "MONITORMEDIA" },
+ { LINE_MONITORTONE, "MONITORTONE" },
+// { LINE_NEWCALL, "NEWCALL" },
+ { 0xffffffff, "" }
+};
+
+
+LOOKUP my_far aPhoneMsgs[] =
+{
+ { PHONE_BUTTON, "BUTTON" },
+ { PHONE_CLOSE, "CLOSE" },
+ { PHONE_CREATE, "CREATE" },
+ { PHONE_DEVSPECIFIC, "DEVSPECIFIC" },
+ { PHONE_STATE, "STATE" },
+ { 0xffffffff, "" }
+};
+
+
+LOOKUP my_far aCallerIDFlags[] =
+{
+ { LINECALLPARTYID_BLOCKED ,"BLOCKED" },
+ { LINECALLPARTYID_OUTOFAREA ,"OUTOFAREA" },
+ { LINECALLPARTYID_NAME ,"NAME" },
+ { LINECALLPARTYID_ADDRESS ,"ADDRESS" },
+ { LINECALLPARTYID_PARTIAL ,"PARTIAL" },
+ { LINECALLPARTYID_UNKNOWN ,"UNKNOWN" },
+ { LINECALLPARTYID_UNAVAIL ,"UNAVAIL" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aCallStates[] =
+{
+ { LINECALLSTATE_IDLE ,"IDLE" },
+ { LINECALLSTATE_OFFERING ,"OFFERING" },
+ { LINECALLSTATE_ACCEPTED ,"ACCEPTED" },
+ { LINECALLSTATE_DIALTONE ,"DIALTONE" },
+ { LINECALLSTATE_DIALING ,"DIALING" },
+ { LINECALLSTATE_RINGBACK ,"RINGBACK" },
+ { LINECALLSTATE_BUSY ,"BUSY" },
+ { LINECALLSTATE_SPECIALINFO ,"SPECIALINFO" },
+ { LINECALLSTATE_CONNECTED ,"CONNECTED" },
+ { LINECALLSTATE_PROCEEDING ,"PROCEEDING" },
+ { LINECALLSTATE_ONHOLD ,"ONHOLD" },
+ { LINECALLSTATE_CONFERENCED ,"CONFERENCED" },
+ { LINECALLSTATE_ONHOLDPENDCONF ,"ONHOLDPENDCONF" },
+ { LINECALLSTATE_ONHOLDPENDTRANSFER ,"ONHOLDPENDTRANSFER" },
+ { LINECALLSTATE_DISCONNECTED ,"DISCONNECTED" },
+ { LINECALLSTATE_UNKNOWN ,"UNKNOWN" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aCallInfoStates[] =
+{
+ { LINECALLINFOSTATE_OTHER ,"OTHER" },
+ { LINECALLINFOSTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINECALLINFOSTATE_BEARERMODE ,"BEARERMODE" },
+ { LINECALLINFOSTATE_RATE ,"RATE" },
+ { LINECALLINFOSTATE_MEDIAMODE ,"MEDIAMODE" },
+ { LINECALLINFOSTATE_APPSPECIFIC ,"APPSPECIFIC" },
+ { LINECALLINFOSTATE_CALLID ,"CALLID" },
+ { LINECALLINFOSTATE_RELATEDCALLID ,"RELATEDCALLID" },
+ { LINECALLINFOSTATE_ORIGIN ,"ORIGIN" },
+ { LINECALLINFOSTATE_REASON ,"REASON" },
+ { LINECALLINFOSTATE_COMPLETIONID ,"COMPLETIONID" },
+ { LINECALLINFOSTATE_NUMOWNERINCR ,"NUMOWNERINCR" },
+ { LINECALLINFOSTATE_NUMOWNERDECR ,"NUMOWNERDECR" },
+ { LINECALLINFOSTATE_NUMMONITORS ,"NUMMONITORS" },
+ { LINECALLINFOSTATE_TRUNK ,"TRUNK" },
+ { LINECALLINFOSTATE_CALLERID ,"CALLERID" },
+ { LINECALLINFOSTATE_CALLEDID ,"CALLEDID" },
+ { LINECALLINFOSTATE_CONNECTEDID ,"CONNECTEDID" },
+ { LINECALLINFOSTATE_REDIRECTIONID ,"REDIRECTIONID" },
+ { LINECALLINFOSTATE_REDIRECTINGID ,"REDIRECTINGID" },
+ { LINECALLINFOSTATE_DISPLAY ,"DISPLAY" },
+ { LINECALLINFOSTATE_USERUSERINFO ,"USERUSERINFO" },
+ { LINECALLINFOSTATE_HIGHLEVELCOMP ,"HIGHLEVELCOMP" },
+ { LINECALLINFOSTATE_LOWLEVELCOMP ,"LOWLEVELCOMP" },
+ { LINECALLINFOSTATE_CHARGINGINFO ,"CHARGINGINFO" },
+ { LINECALLINFOSTATE_TERMINAL ,"TERMINAL" },
+ { LINECALLINFOSTATE_DIALPARAMS ,"DIALPARAMS" },
+ { LINECALLINFOSTATE_MONITORMODES ,"MONITORMODES" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aCallFeatures[] =
+{
+ { LINECALLFEATURE_ACCEPT ,"ACCEPT" },
+ { LINECALLFEATURE_ADDTOCONF ,"ADDTOCONF" },
+ { LINECALLFEATURE_ANSWER ,"ANSWER" },
+ { LINECALLFEATURE_BLINDTRANSFER ,"BLINDTRANSFER" },
+ { LINECALLFEATURE_COMPLETECALL ,"COMPLETECALL" },
+ { LINECALLFEATURE_COMPLETETRANSF ,"COMPLETETRANSF" },
+ { LINECALLFEATURE_DIAL ,"DIAL" },
+ { LINECALLFEATURE_DROP ,"DROP" },
+ { LINECALLFEATURE_GATHERDIGITS ,"GATHERDIGITS" },
+ { LINECALLFEATURE_GENERATEDIGITS ,"GENERATEDIGITS" },
+ { LINECALLFEATURE_GENERATETONE ,"GENERATETONE" },
+ { LINECALLFEATURE_HOLD ,"HOLD" },
+ { LINECALLFEATURE_MONITORDIGITS ,"MONITORDIGITS" },
+ { LINECALLFEATURE_MONITORMEDIA ,"MONITORMEDIA" },
+ { LINECALLFEATURE_MONITORTONES ,"MONITORTONES" },
+ { LINECALLFEATURE_PARK ,"PARK" },
+ { LINECALLFEATURE_PREPAREADDCONF ,"PREPAREADDCONF" },
+ { LINECALLFEATURE_REDIRECT ,"REDIRECT" },
+ { LINECALLFEATURE_REMOVEFROMCONF ,"REMOVEFROMCONF" },
+ { LINECALLFEATURE_SECURECALL ,"SECURECALL" },
+ { LINECALLFEATURE_SENDUSERUSER ,"SENDUSERUSER" },
+ { LINECALLFEATURE_SETCALLPARAMS ,"SETCALLPARAMS" },
+ { LINECALLFEATURE_SETMEDIACONTROL ,"SETMEDIACONTROL" },
+ { LINECALLFEATURE_SETTERMINAL ,"SETTERMINAL" },
+ { LINECALLFEATURE_SETUPCONF ,"SETUPCONF" },
+ { LINECALLFEATURE_SETUPTRANSFER ,"SETUPTRANSFER" },
+ { LINECALLFEATURE_SWAPHOLD ,"SWAPHOLD" },
+ { LINECALLFEATURE_UNHOLD ,"UNHOLD" },
+#ifdef TAPI_1_1
+ { LINECALLFEATURE_RELEASEUSERUSERINFO ,"RELEASEUSERUSERINFO" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aMediaModes[] =
+{
+ { LINEMEDIAMODE_UNKNOWN ,"UNKNOWN" },
+ { LINEMEDIAMODE_INTERACTIVEVOICE ,"INTERACTIVEVOICE" },
+ { LINEMEDIAMODE_AUTOMATEDVOICE ,"AUTOMATEDVOICE" },
+ { LINEMEDIAMODE_DATAMODEM ,"DATAMODEM" },
+ { LINEMEDIAMODE_G3FAX ,"G3FAX" },
+ { LINEMEDIAMODE_TDD ,"TDD" },
+ { LINEMEDIAMODE_G4FAX ,"G4FAX" },
+ { LINEMEDIAMODE_DIGITALDATA ,"DIGITALDATA" },
+ { LINEMEDIAMODE_TELETEX ,"TELETEX" },
+ { LINEMEDIAMODE_VIDEOTEX ,"VIDEOTEX" },
+ { LINEMEDIAMODE_TELEX ,"TELEX" },
+ { LINEMEDIAMODE_MIXED ,"MIXED" },
+ { LINEMEDIAMODE_ADSI ,"ADSI" },
+#ifdef TAPI_1_1
+ { LINEMEDIAMODE_VOICEVIEW ,"VOICEVIEW" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP my_far aButtonModes[] =
+{
+ { PHONEBUTTONMODE_DUMMY ,"DUMMY" },
+ { PHONEBUTTONMODE_CALL ,"CALL" },
+ { PHONEBUTTONMODE_FEATURE ,"FEATURE" },
+ { PHONEBUTTONMODE_KEYPAD ,"KEYPAD" },
+ { PHONEBUTTONMODE_LOCAL ,"LOCAL" },
+ { PHONEBUTTONMODE_DISPLAY ,"DISPLAY" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aButtonStates[] =
+{
+ { PHONEBUTTONSTATE_UP ,"UP" },
+ { PHONEBUTTONSTATE_DOWN ,"DOWN" },
+#ifdef TAPI_1_1
+ { PHONEBUTTONSTATE_UNKNOWN ,"UNKNOWN" },
+ { PHONEBUTTONSTATE_UNAVAIL ,"UNAVAIL" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP my_far aHookSwitchDevs[] =
+{
+ { PHONEHOOKSWITCHDEV_HANDSET ,"HANDSET" },
+ { PHONEHOOKSWITCHDEV_SPEAKER ,"SPEAKER" },
+ { PHONEHOOKSWITCHDEV_HEADSET ,"HEADSET" },
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP my_far aCallSelects[] =
+{
+ { LINECALLSELECT_LINE ,"LINE" },
+ { LINECALLSELECT_ADDRESS ,"ADDRESS" },
+ { LINECALLSELECT_CALL ,"CALL" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aTransferModes[] =
+{
+ { LINETRANSFERMODE_TRANSFER ,"TRANSFER" },
+ { LINETRANSFERMODE_CONFERENCE ,"CONFERENCE" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aDigitModes[] =
+{
+ { LINEDIGITMODE_PULSE ,"PULSE" },
+ { LINEDIGITMODE_DTMF ,"DTMF" },
+ { LINEDIGITMODE_DTMFEND ,"DTMFEND" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aToneModes[] =
+{
+ { LINETONEMODE_CUSTOM ,"CUSTOM" },
+ { LINETONEMODE_RINGBACK ,"RINGBACK" },
+ { LINETONEMODE_BUSY ,"BUSY" },
+ { LINETONEMODE_BEEP ,"BEEP" },
+ { LINETONEMODE_BILLING ,"BILLING" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aBearerModes[] =
+{
+ { LINEBEARERMODE_VOICE ,"VOICE" },
+ { LINEBEARERMODE_SPEECH ,"SPEECH" },
+ { LINEBEARERMODE_MULTIUSE ,"MULTIUSE" },
+ { LINEBEARERMODE_DATA ,"DATA" },
+ { LINEBEARERMODE_ALTSPEECHDATA ,"ALTSPEECHDATA" },
+ { LINEBEARERMODE_NONCALLSIGNALING ,"NONCALLSIGNALING" },
+#ifdef TAPI_1_1
+ { LINEBEARERMODE_PASSTHROUGH ,"PASSTHROUGH" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aLineStates[] =
+{
+ { LINEDEVSTATE_OTHER ,"OTHER" },
+ { LINEDEVSTATE_RINGING ,"RINGING" },
+ { LINEDEVSTATE_CONNECTED ,"CONNECTED" },
+ { LINEDEVSTATE_DISCONNECTED ,"DISCONNECTED" },
+ { LINEDEVSTATE_MSGWAITON ,"MSGWAITON" },
+ { LINEDEVSTATE_MSGWAITOFF ,"MSGWAITOFF" },
+ { LINEDEVSTATE_INSERVICE ,"INSERVICE" },
+ { LINEDEVSTATE_OUTOFSERVICE ,"OUTOFSERVICE" },
+ { LINEDEVSTATE_MAINTENANCE ,"MAINTENANCE" },
+ { LINEDEVSTATE_OPEN ,"OPEN" },
+ { LINEDEVSTATE_CLOSE ,"CLOSE" },
+ { LINEDEVSTATE_NUMCALLS ,"NUMCALLS" },
+ { LINEDEVSTATE_NUMCOMPLETIONS ,"NUMCOMPLETIONS" },
+ { LINEDEVSTATE_TERMINALS ,"TERMINALS" },
+ { LINEDEVSTATE_ROAMMODE ,"ROAMMODE" },
+ { LINEDEVSTATE_BATTERY ,"BATTERY" },
+ { LINEDEVSTATE_SIGNAL ,"SIGNAL" },
+ { LINEDEVSTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINEDEVSTATE_REINIT ,"REINIT" },
+ { LINEDEVSTATE_LOCK ,"LOCK" },
+#ifdef TAPI_1_1
+ { LINEDEVSTATE_CAPSCHANGE ,"CAPSCHANGE" },
+ { LINEDEVSTATE_CONFIGCHANGE ,"CONFIGCHANGE" },
+ { LINEDEVSTATE_TRANSLATECHANGE ,"TRANSLATECHANGE" },
+ { LINEDEVSTATE_COMPLCANCEL ,"COMPLCANCEL" },
+ { LINEDEVSTATE_REMOVED ,"REMOVED" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aAddressStates[] =
+{
+ { LINEADDRESSSTATE_OTHER ,"OTHER" },
+ { LINEADDRESSSTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINEADDRESSSTATE_INUSEZERO ,"INUSEZERO" },
+ { LINEADDRESSSTATE_INUSEONE ,"INUSEONE" },
+ { LINEADDRESSSTATE_INUSEMANY ,"INUSEMANY" },
+ { LINEADDRESSSTATE_NUMCALLS ,"NUMCALLS" },
+ { LINEADDRESSSTATE_FORWARD ,"FORWARD" },
+ { LINEADDRESSSTATE_TERMINALS ,"TERMINALS" },
+#ifdef TAPI_1_1
+ { LINEADDRESSSTATE_CAPSCHANGE ,"CAPSCHANGE" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aTerminalModes[] =
+{
+ { LINETERMMODE_BUTTONS ,"BUTTONS" },
+ { LINETERMMODE_LAMPS ,"LAMPS" },
+ { LINETERMMODE_DISPLAY ,"DISPLAY" },
+ { LINETERMMODE_RINGER ,"RINGER" },
+ { LINETERMMODE_HOOKSWITCH ,"HOOKSWITCH" },
+ { LINETERMMODE_MEDIATOLINE ,"MEDIATOLINE" },
+ { LINETERMMODE_MEDIAFROMLINE ,"MEDIAFROMLINE" },
+ { LINETERMMODE_MEDIABIDIRECT ,"MEDIABIDIRECT" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aHookSwitchModes[] =
+{
+ { PHONEHOOKSWITCHMODE_ONHOOK ,"ONHOOK" },
+ { PHONEHOOKSWITCHMODE_MIC ,"MIC" },
+ { PHONEHOOKSWITCHMODE_SPEAKER ,"SPEAKER" },
+ { PHONEHOOKSWITCHMODE_MICSPEAKER ,"MICSPEAKER" },
+ { PHONEHOOKSWITCHMODE_UNKNOWN ,"UNKNOWN" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aLampModes[] =
+{
+ { PHONELAMPMODE_DUMMY ,"DUMMY" },
+ { PHONELAMPMODE_OFF ,"OFF" },
+ { PHONELAMPMODE_STEADY ,"STEADY" },
+ { PHONELAMPMODE_WINK ,"WINK" },
+ { PHONELAMPMODE_FLASH ,"FLASH" },
+ { PHONELAMPMODE_FLUTTER ,"FLUTTER" },
+ { PHONELAMPMODE_BROKENFLUTTER ,"BROKENFLUTTER" },
+ { PHONELAMPMODE_UNKNOWN ,"UNKNOWN" },
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP my_far aPhoneStates[] =
+{
+ { PHONESTATE_OTHER ,"OTHER" },
+ { PHONESTATE_CONNECTED ,"CONNECTED" },
+ { PHONESTATE_DISCONNECTED ,"DISCONNECTED" },
+ { PHONESTATE_OWNER ,"OWNER" },
+ { PHONESTATE_MONITORS ,"MONITORS" },
+ { PHONESTATE_DISPLAY ,"DISPLAY" },
+ { PHONESTATE_LAMP ,"LAMP" },
+ { PHONESTATE_RINGMODE ,"RINGMODE" },
+ { PHONESTATE_RINGVOLUME ,"RINGVOLUME" },
+ { PHONESTATE_HANDSETHOOKSWITCH ,"HANDSETHOOKSWITCH" },
+ { PHONESTATE_HANDSETVOLUME ,"HANDSETVOLUME" },
+ { PHONESTATE_HANDSETGAIN ,"HANDSETGAIN" },
+ { PHONESTATE_SPEAKERHOOKSWITCH ,"SPEAKERHOOKSWITCH" },
+ { PHONESTATE_SPEAKERVOLUME ,"SPEAKERVOLUME" },
+ { PHONESTATE_SPEAKERGAIN ,"SPEAKERGAIN" },
+ { PHONESTATE_HEADSETHOOKSWITCH ,"HEADSETHOOKSWITCH" },
+ { PHONESTATE_HEADSETVOLUME ,"HEADSETVOLUME" },
+ { PHONESTATE_HEADSETGAIN ,"HEADSETGAIN" },
+ { PHONESTATE_SUSPEND ,"SUSPEND" },
+ { PHONESTATE_RESUME ,"RESUME" },
+ { PHONESTATE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { PHONESTATE_REINIT ,"REINIT" },
+#ifdef TAPI_1_1
+ { PHONESTATE_CAPSCHANGE ,"CAPSCHANGE" },
+ { PHONESTATE_REMOVED ,"REMOVED" },
+#endif
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP my_far aLineErrs[] =
+{
+ { 0 ,"<SUCCESS>" },
+ { LINEERR_ALLOCATED ,"ALLOCATED" },
+ { LINEERR_BADDEVICEID ,"BADDEVICEID" },
+ { LINEERR_BEARERMODEUNAVAIL ,"BEARERMODEUNAVAIL" },
+ { LINEERR_CALLUNAVAIL ,"CALLUNAVAIL" },
+ { LINEERR_COMPLETIONOVERRUN ,"COMPLETIONOVERRUN" },
+ { LINEERR_CONFERENCEFULL ,"CONFERENCEFULL" },
+ { LINEERR_DIALBILLING ,"DIALBILLING" },
+ { LINEERR_DIALDIALTONE ,"DIALDIALTONE" },
+ { LINEERR_DIALPROMPT ,"DIALPROMPT" },
+ { LINEERR_DIALQUIET ,"DIALQUIET" },
+ { LINEERR_INCOMPATIBLEAPIVERSION ,"INCOMPATIBLEAPIVERSION" },
+ { LINEERR_INCOMPATIBLEEXTVERSION ,"INCOMPATIBLEEXTVERSION" },
+ { LINEERR_INIFILECORRUPT ,"INIFILECORRUPT" },
+ { LINEERR_INUSE ,"INUSE" },
+ { LINEERR_INVALADDRESS ,"INVALADDRESS" },
+ { LINEERR_INVALADDRESSID ,"INVALADDRESSID" },
+ { LINEERR_INVALADDRESSMODE ,"INVALADDRESSMODE" },
+ { LINEERR_INVALADDRESSSTATE ,"INVALADDRESSSTATE" },
+ { LINEERR_INVALAPPHANDLE ,"INVALAPPHANDLE" },
+ { LINEERR_INVALAPPNAME ,"INVALAPPNAME" },
+ { LINEERR_INVALBEARERMODE ,"INVALBEARERMODE" },
+ { LINEERR_INVALCALLCOMPLMODE ,"INVALCALLCOMPLMODE" },
+ { LINEERR_INVALCALLHANDLE ,"INVALCALLHANDLE" },
+ { LINEERR_INVALCALLPARAMS ,"INVALCALLPARAMS" },
+ { LINEERR_INVALCALLPRIVILEGE ,"INVALCALLPRIVILEGE" },
+ { LINEERR_INVALCALLSELECT ,"INVALCALLSELECT" },
+ { LINEERR_INVALCALLSTATE ,"INVALCALLSTATE" },
+ { LINEERR_INVALCALLSTATELIST ,"INVALCALLSTATELIST" },
+ { LINEERR_INVALCARD ,"INVALCARD" },
+ { LINEERR_INVALCOMPLETIONID ,"INVALCOMPLETIONID" },
+ { LINEERR_INVALCONFCALLHANDLE ,"INVALCONFCALLHANDLE" },
+ { LINEERR_INVALCONSULTCALLHANDLE ,"INVALCONSULTCALLHANDLE" },
+ { LINEERR_INVALCOUNTRYCODE ,"INVALCOUNTRYCODE" },
+ { LINEERR_INVALDEVICECLASS ,"INVALDEVICECLASS" },
+ { LINEERR_INVALDEVICEHANDLE ,"INVALDEVICEHANDLE" },
+ { LINEERR_INVALDIALPARAMS ,"INVALDIALPARAMS" },
+ { LINEERR_INVALDIGITLIST ,"INVALDIGITLIST" },
+ { LINEERR_INVALDIGITMODE ,"INVALDIGITMODE" },
+ { LINEERR_INVALDIGITS ,"INVALDIGITS" },
+ { LINEERR_INVALEXTVERSION ,"INVALEXTVERSION" },
+ { LINEERR_INVALGROUPID ,"INVALGROUPID" },
+ { LINEERR_INVALLINEHANDLE ,"INVALLINEHANDLE" },
+ { LINEERR_INVALLINESTATE ,"INVALLINESTATE" },
+ { LINEERR_INVALLOCATION ,"INVALLOCATION" },
+ { LINEERR_INVALMEDIALIST ,"INVALMEDIALIST" },
+ { LINEERR_INVALMEDIAMODE ,"INVALMEDIAMODE" },
+ { LINEERR_INVALMESSAGEID ,"INVALMESSAGEID" },
+ { LINEERR_INVALPARAM ,"INVALPARAM" },
+ { LINEERR_INVALPARKID ,"INVALPARKID" },
+ { LINEERR_INVALPARKMODE ,"INVALPARKMODE" },
+ { LINEERR_INVALPOINTER ,"INVALPOINTER" },
+ { LINEERR_INVALPRIVSELECT ,"INVALPRIVSELECT" },
+ { LINEERR_INVALRATE ,"INVALRATE" },
+ { LINEERR_INVALREQUESTMODE ,"INVALREQUESTMODE" },
+ { LINEERR_INVALTERMINALID ,"INVALTERMINALID" },
+ { LINEERR_INVALTERMINALMODE ,"INVALTERMINALMODE" },
+ { LINEERR_INVALTIMEOUT ,"INVALTIMEOUT" },
+ { LINEERR_INVALTONE ,"INVALTONE" },
+ { LINEERR_INVALTONELIST ,"INVALTONELIST" },
+ { LINEERR_INVALTONEMODE ,"INVALTONEMODE" },
+ { LINEERR_INVALTRANSFERMODE ,"INVALTRANSFERMODE" },
+ { LINEERR_LINEMAPPERFAILED ,"LINEMAPPERFAILED" },
+ { LINEERR_NOCONFERENCE ,"NOCONFERENCE" },
+ { LINEERR_NODEVICE ,"NODEVICE" },
+ { LINEERR_NODRIVER ,"NODRIVER" },
+ { LINEERR_NOMEM ,"NOMEM" },
+ { LINEERR_NOREQUEST ,"NOREQUEST" },
+ { LINEERR_NOTOWNER ,"NOTOWNER" },
+ { LINEERR_NOTREGISTERED ,"NOTREGISTERED" },
+ { LINEERR_OPERATIONFAILED ,"OPERATIONFAILED" },
+ { LINEERR_OPERATIONUNAVAIL ,"OPERATIONUNAVAIL" },
+ { LINEERR_RATEUNAVAIL ,"RATEUNAVAIL" },
+ { LINEERR_RESOURCEUNAVAIL ,"RESOURCEUNAVAIL" },
+ { LINEERR_REQUESTOVERRUN ,"REQUESTOVERRUN" },
+ { LINEERR_STRUCTURETOOSMALL ,"STRUCTURETOOSMALL" },
+ { LINEERR_TARGETNOTFOUND ,"TARGETNOTFOUND" },
+ { LINEERR_TARGETSELF ,"TARGETSELF" },
+ { LINEERR_UNINITIALIZED ,"UNINITIALIZED" },
+ { LINEERR_USERUSERINFOTOOBIG ,"USERUSERINFOTOOBIG" },
+ { LINEERR_REINIT ,"REINIT" },
+ { LINEERR_ADDRESSBLOCKED ,"ADDRESSBLOCKED" },
+ { LINEERR_BILLINGREJECTED ,"BILLINGREJECTED" },
+ { LINEERR_INVALFEATURE ,"INVALFEATURE" },
+ { LINEERR_NOMULTIPLEINSTANCE ,"NOMULTIPLEINSTANCE" },
+ { 0xffffffff ,"" }
+};
+
+LOOKUP my_far aPhoneErrs[] =
+{
+ { 0 ,"<SUCCESS>" },
+ { PHONEERR_ALLOCATED ,"ALLOCATED" },
+ { PHONEERR_BADDEVICEID ,"BADDEVICEID" },
+ { PHONEERR_INCOMPATIBLEAPIVERSION ,"INCOMPATIBLEAPIVERSION" },
+ { PHONEERR_INCOMPATIBLEEXTVERSION ,"INCOMPATIBLEEXTVERSION" },
+ { PHONEERR_INIFILECORRUPT ,"INIFILECORRUPT" },
+ { PHONEERR_INUSE ,"INUSE" },
+ { PHONEERR_INVALAPPHANDLE ,"INVALAPPHANDLE" },
+ { PHONEERR_INVALAPPNAME ,"INVALAPPNAME" },
+ { PHONEERR_INVALBUTTONLAMPID ,"INVALBUTTONLAMPID" },
+ { PHONEERR_INVALBUTTONMODE ,"INVALBUTTONMODE" },
+ { PHONEERR_INVALBUTTONSTATE ,"INVALBUTTONSTATE" },
+ { PHONEERR_INVALDATAID ,"INVALDATAID" },
+ { PHONEERR_INVALDEVICECLASS ,"INVALDEVICECLASS" },
+ { PHONEERR_INVALEXTVERSION ,"INVALEXTVERSION" },
+ { PHONEERR_INVALHOOKSWITCHDEV ,"INVALHOOKSWITCHDEV" },
+ { PHONEERR_INVALHOOKSWITCHMODE ,"INVALHOOKSWITCHMODE" },
+ { PHONEERR_INVALLAMPMODE ,"INVALLAMPMODE" },
+ { PHONEERR_INVALPARAM ,"INVALPARAM" },
+ { PHONEERR_INVALPHONEHANDLE ,"INVALPHONEHANDLE" },
+ { PHONEERR_INVALPHONESTATE ,"INVALPHONESTATE" },
+ { PHONEERR_INVALPOINTER ,"INVALPOINTER" },
+ { PHONEERR_INVALPRIVILEGE ,"INVALPRIVILEGE" },
+ { PHONEERR_INVALRINGMODE ,"INVALRINGMODE" },
+ { PHONEERR_NODEVICE ,"NODEVICE" },
+ { PHONEERR_NODRIVER ,"NODRIVER" },
+ { PHONEERR_NOMEM ,"NOMEM" },
+ { PHONEERR_NOTOWNER ,"NOTOWNER" },
+ { PHONEERR_OPERATIONFAILED ,"OPERATIONFAILED" },
+ { PHONEERR_OPERATIONUNAVAIL ,"OPERATIONUNAVAIL" },
+ { PHONEERR_RESOURCEUNAVAIL ,"RESOURCEUNAVAIL" },
+ { PHONEERR_REQUESTOVERRUN ,"REQUESTOVERRUN" },
+ { PHONEERR_STRUCTURETOOSMALL ,"STRUCTURETOOSMALL" },
+ { PHONEERR_UNINITIALIZED ,"UNINITIALIZED" },
+ { PHONEERR_REINIT ,"REINIT" },
+ { 0xffffffff ,"" }
+};
diff --git a/private/tapi/dev/sp/esp/vars.h b/private/tapi/dev/sp/esp/vars.h
new file mode 100644
index 000000000..dc87e6439
--- /dev/null
+++ b/private/tapi/dev/sp/esp/vars.h
@@ -0,0 +1,95 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ vars.h
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) dd-Mmm-1995
+
+Revision History:
+
+--*/
+
+
+#ifdef WIN32
+#define my_far
+#else
+#define my_far _far
+#endif
+
+
+extern HWND ghwndMain;
+extern HWND ghwndEdit;
+extern HWND ghwndList1;
+extern HWND ghwndList2;
+extern BOOL gbAutoClose;
+extern BOOL gbExeStarted;
+extern BOOL gbShowFuncEntry;
+extern BOOL gbShowFuncExit;
+extern BOOL gbShowFuncParams;
+extern BOOL gbShowEvents;
+extern BOOL gbShowCompletions;
+extern BOOL gbBreakOnFuncEntry;
+extern BOOL gbDisableUI;
+extern BOOL gbSyncCompl;
+extern BOOL gbAsyncCompl;
+extern BOOL gbManualCompl;
+extern BOOL gbManualResults;
+extern BOOL gbShowLineGetIDDlg;
+extern HICON ghIconLine;
+extern HICON ghIconPhone;
+extern HMENU ghMenu;
+extern DWORD gdwTSPIVersion;
+extern DWORD gdwNumLines;
+extern DWORD gdwNumAddrsPerLine;
+extern DWORD gdwNumPhones;
+extern DWORD gdwNumInits;
+extern DWORD gdwDefLineGetIDID;
+extern DWORD gdwLineDeviceIDBase;
+extern DWORD gdwPermanentProviderID;
+extern DWORD aOutCallStates[MAX_OUT_CALL_STATES];
+extern DWORD aOutCallStateModes[MAX_OUT_CALL_STATES];
+extern HPROVIDER ghProvider;
+extern LINEEVENT gpfnLineCreateProc;
+extern PHONEEVENT gpfnPhoneCreateProc;
+extern PDRVWIDGET gaWidgets;
+extern LINEEXTENSIONID gLineExtID;
+extern PHONEEXTENSIONID gPhoneExtID;
+extern ASYNC_COMPLETION gpfnCompletionProc;
+extern LPLINEADDRESSCAPS gpDefLineAddrCaps;
+
+extern LOOKUP my_far aPhoneStatusFlags[];
+extern LOOKUP my_far aCallParamFlags[];
+extern LOOKUP my_far aCallOrigins[];
+extern LOOKUP my_far aCallReasons[];
+extern LOOKUP my_far aLineMsgs[];
+extern LOOKUP my_far aPhoneMsgs[];
+extern LOOKUP my_far aCallerIDFlags[];
+extern LOOKUP my_far aCallStates[];
+extern LOOKUP my_far aCallInfoStates[];
+extern LOOKUP my_far aCallFeatures[];
+extern LOOKUP my_far aMediaModes[];
+extern LOOKUP my_far aButtonModes[];
+extern LOOKUP my_far aButtonStates[];
+extern LOOKUP my_far aHookSwitchDevs[];
+extern LOOKUP my_far aCallSelects[];
+extern LOOKUP my_far aTransferModes[];
+extern LOOKUP my_far aDigitModes[];
+extern LOOKUP my_far aToneModes[];
+extern LOOKUP my_far aBearerModes[];
+extern LOOKUP my_far aLineStates[];
+extern LOOKUP my_far aAddressStates[];
+extern LOOKUP my_far aTerminalModes[];
+extern LOOKUP my_far aHookSwitchModes[];
+extern LOOKUP my_far aLampModes[];
+extern LOOKUP my_far aPhoneStates[];
+extern LOOKUP my_far aLineErrs[];
+extern LOOKUP my_far aPhoneErrs[];
diff --git a/private/tapi/dev/sp/esp/widget.c b/private/tapi/dev/sp/esp/widget.c
new file mode 100644
index 000000000..7152a412a
--- /dev/null
+++ b/private/tapi/dev/sp/esp/widget.c
@@ -0,0 +1,885 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ widget.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) dd-Mmm-1995
+
+Revision History:
+
+--*/
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+#include "esp.h"
+#include "vars.h"
+
+
+char szProviderInfo[] = "ESP v1.0";
+
+void
+UpdateWidgetList(
+ void
+ )
+{
+ PDRVWIDGET pWidget = gaWidgets;
+
+
+ if (gbDisableUI)
+ {
+ return;
+ }
+
+ SendMessage (ghwndList1, LB_RESETCONTENT, 0, 0);
+
+#ifdef WIN32
+ try
+ {
+#endif
+ while (pWidget)
+ {
+ char buf[128];
+
+
+ switch (pWidget->dwType)
+ {
+ case WT_DRVLINE:
+
+ wsprintf(
+ buf,
+ "Line%ld, hd=x%lx (ht=x%lx, %s)",
+ ((PDRVLINE)pWidget)->dwDeviceID,
+ pWidget,
+ ((PDRVLINE)pWidget)->htLine,
+ (((PDRVLINE)pWidget)->htLine ? "open" : "closed")
+ );
+
+ break;
+
+ case WT_DRVCALL:
+ {
+ int i;
+ char far *lpszCallState = "";
+
+
+ for (i = 0; aCallStates[i].dwVal != 0xffffffff; i++)
+ {
+ if (((PDRVCALL)pWidget)->dwCallState == aCallStates[i].dwVal)
+ {
+ lpszCallState = aCallStates[i].lpszVal;
+ break;
+ }
+ }
+
+ wsprintf(
+ buf,
+ " Addr%ld, hdCall=x%lx %s (htCall=x%lx)",
+ ((PDRVCALL)pWidget)->LineCallInfo.dwAddressID,
+ pWidget,
+ lpszCallState,
+ ((PDRVCALL)pWidget)->htCall
+ );
+
+ break;
+ }
+ case WT_DRVPHONE:
+
+ wsprintf(
+ buf,
+ "Phone%ld, hd=x%lx (ht=x%lx, %s)",
+ ((PDRVPHONE)pWidget)->dwDeviceID,
+ pWidget,
+ ((PDRVPHONE)pWidget)->htPhone,
+ (((PDRVPHONE)pWidget)->htPhone ? "open" : "closed")
+ );
+
+ break;
+ }
+
+ SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)buf);
+
+ pWidget = pWidget->pNext;
+ }
+#ifdef WIN32
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ PostUpdateWidgetListMsg();
+ }
+#endif
+}
+
+
+void
+PostUpdateWidgetListMsg(
+ void
+ )
+{
+ PostMessage (ghwndMain, WM_UPDATEWIDGETLIST, ESP_MSG_KEY, 0);
+}
+
+
+void
+InsertWidgetInList(
+ PDRVWIDGET pNewWidget,
+ PDRVWIDGET pWidgetInsertBefore
+ )
+{
+ pNewWidget->pNext = pWidgetInsertBefore;
+
+ if ((gaWidgets == NULL) || (pWidgetInsertBefore == gaWidgets))
+ {
+ gaWidgets = pNewWidget;
+ }
+ else
+ {
+ PDRVWIDGET pPrevWidget = gaWidgets;
+
+
+ while (pPrevWidget->pNext &&
+ (pPrevWidget->pNext != pWidgetInsertBefore))
+ {
+ pPrevWidget = pPrevWidget->pNext;
+ }
+
+ pPrevWidget->pNext = pNewWidget;
+ }
+
+ //UpdateWidgetList();
+ PostUpdateWidgetListMsg();
+}
+
+
+BOOL
+RemoveWidgetFromList(
+ PDRVWIDGET pWidgetToRemove
+ )
+{
+ if (gaWidgets == NULL)
+ {
+ goto RemoveWidgetFromList_error;
+ }
+
+ if (pWidgetToRemove == gaWidgets)
+ {
+ gaWidgets = pWidgetToRemove->pNext;
+ }
+ else
+ {
+ PDRVWIDGET pPrevWidget = gaWidgets;
+
+
+ while (pPrevWidget->pNext && (pPrevWidget->pNext != pWidgetToRemove))
+ {
+ pPrevWidget = pPrevWidget->pNext;
+ }
+
+ if (pPrevWidget->pNext == NULL)
+ {
+ goto RemoveWidgetFromList_error;
+ }
+
+ pPrevWidget->pNext = pWidgetToRemove->pNext;
+ }
+
+ DrvFree (pWidgetToRemove);
+
+ //UpdateWidgetList();
+ PostUpdateWidgetListMsg();
+
+ return TRUE;
+
+RemoveWidgetFromList_error:
+
+ ShowStr(
+ "error: RemoveWidgetFromList: widget x%lx not in list",
+ pWidgetToRemove
+ );
+
+ return FALSE;
+}
+
+
+PDRVLINE
+AllocLine(
+ DWORD dwDeviceID
+ )
+{
+ PDRVLINE pNewLine = (PDRVLINE) DrvAlloc (sizeof(DRVLINE));
+
+
+ if (pNewLine)
+ {
+ char far *p;
+ PDRVWIDGET pWidget = gaWidgets;
+
+
+ //
+ // Init the data structure
+ //
+
+ memset (pNewLine, 0, sizeof(DRVLINE));
+ pNewLine->Widget.dwType = WT_DRVLINE;
+ pNewLine->dwDeviceID = dwDeviceID;
+
+
+ //
+ // Dev caps
+ //
+
+ pNewLine->LineDevCaps.dwNeededSize =
+ pNewLine->LineDevCaps.dwUsedSize = sizeof(LINEDEVCAPS) +
+ LINE_DEV_CAPS_VAR_DATA_SIZE;
+
+ pNewLine->LineDevCaps.dwProviderInfoSize = strlen (szProviderInfo) + 1;
+ pNewLine->LineDevCaps.dwProviderInfoOffset = sizeof(LINEDEVCAPS);
+
+ p = ((char far *) &pNewLine->LineDevCaps) +
+ pNewLine->LineDevCaps.dwProviderInfoOffset;
+
+ strcpy (p, szProviderInfo);
+
+ //pNewLine->LineDevCaps.dwSwitchInfoSize;
+ //pNewLine->LineDevCaps.dwSwitchInfoOffset =
+
+ pNewLine->LineDevCaps.dwPermanentLineID =
+ (0x0000ffff & dwDeviceID) |
+ ((0x0000ffff & gdwPermanentProviderID) << 16);
+
+ pNewLine->LineDevCaps.dwLineNameOffset =
+ sizeof(LINEDEVCAPS) + 2*MAX_STRING_PARAM_SIZE;
+
+ p = ((char far *) &pNewLine->LineDevCaps) +
+ pNewLine->LineDevCaps.dwLineNameOffset;
+
+ sprintf (p, "Line%ld (ESP)", dwDeviceID);
+
+ pNewLine->LineDevCaps.dwLineNameSize = (DWORD) strlen (p) + 1;
+ pNewLine->LineDevCaps.dwStringFormat = STRINGFORMAT_ASCII;
+
+ pNewLine->LineDevCaps.dwAddressModes = ALL_ADDRESS_MODES;
+ pNewLine->LineDevCaps.dwNumAddresses = gdwNumAddrsPerLine;
+ pNewLine->LineDevCaps.dwBearerModes = ALL_BEARER_MODES;
+ pNewLine->LineDevCaps.dwMaxRate = 0x100000; //BUGBUG
+ pNewLine->LineDevCaps.dwMediaModes = ALL_MEDIA_MODES;
+
+ //pNewLine->LineDevCaps.dwGenerateToneModes;
+ //pNewLine->LineDevCaps.dwGenerateToneMaxNumFreq;
+ //pNewLine->LineDevCaps.dwGenerateDigitModes;
+ //pNewLine->LineDevCaps.dwMonitorToneMaxNumFreq;
+ //pNewLine->LineDevCaps.dwMonitorToneMaxNumEntries;
+ //pNewLine->LineDevCaps.dwMonitorDigitModes;
+ //pNewLine->LineDevCaps.dwGatherDigitsMinTimeout;
+ //pNewLine->LineDevCaps.dwGatherDigitsMaxTimeout;
+
+ //pNewLine->LineDevCaps.dwMedCtlDigitMaxListSize;
+ //pNewLine->LineDevCaps.dwMedCtlMediaMaxListSize;
+ //pNewLine->LineDevCaps.dwMedCtlToneMaxListSize;
+ //pNewLine->LineDevCaps.dwMedCtlCallStateMaxListSize;
+
+ pNewLine->LineDevCaps.dwDevCapFlags = ALL_LINE_DEV_CAP_FLAGS;
+ pNewLine->LineDevCaps.dwMaxNumActiveCalls = 1024; // BUGBUG
+ pNewLine->LineDevCaps.dwAnswerMode = LINEANSWERMODE_NONE; // BUGBUG???
+ pNewLine->LineDevCaps.dwRingModes = 1;
+ pNewLine->LineDevCaps.dwLineStates = ALL_LINE_STATES;
+
+ //pNewLine->LineDevCaps.dwUUIAcceptSize;
+ //pNewLine->LineDevCaps.dwUUIAnswerSize;
+ //pNewLine->LineDevCaps.dwUUIMakeCallSize;
+ //pNewLine->LineDevCaps.dwUUIDropSize;
+ //pNewLine->LineDevCaps.dwUUISendUserUserInfoSize;
+ //pNewLine->LineDevCaps.dwUUICallInfoSize;
+
+ //pNewLine->LineDevCaps.MinDialParams;
+ //pNewLine->LineDevCaps.MaxDialParams;
+ //pNewLine->LineDevCaps.DefaultDialParams;
+
+ //pNewLine->LineDevCaps.dwNumTerminals;
+ //pNewLine->LineDevCaps.dwTerminalCapsSize;
+ //pNewLine->LineDevCaps.dwTerminalCapsOffset
+ //pNewLine->LineDevCaps.dwTerminalTextEntrySize;
+ //pNewLine->LineDevCaps.dwTerminalTextSize;
+ //pNewLine->LineDevCaps.dwTerminalTextOffset
+
+ //pNewLine->LineDevCaps.dwDevSpecificSize;
+ //pNewLine->LineDevCaps.dwDevSpecificOffset
+ pNewLine->LineDevCaps.dwLineFeatures = ALL_LINE_FEATURES;
+
+
+ //
+ // Dev status
+ //
+
+ pNewLine->LineDevStatus.dwNeededSize =
+ pNewLine->LineDevStatus.dwUsedSize = sizeof (LINEDEVSTATUS) +
+ LINE_DEV_STATUS_VAR_DATA_SIZE;
+
+ //pNewLine->LineDevStatus.dwNumOpens // TAPI.DLL fills in
+ //pNewLine->LineDevStatus.dwOpenMediaModes // TAPI.DLL fills in
+
+ //pNewLine->LineDevStatus.dwNumActiveCalls
+ //pNewLine->LineDevStatus.dwNumOnHoldCalls
+ //pNewLine->LineDevStatus.dwNumOnHoldPendCalls
+ pNewLine->LineDevStatus.dwLineFeatures = ALL_LINE_FEATURES;
+ //pNewLine->LineDevStatus.dwNumCallCompletions
+ //pNewLine->LineDevStatus.dwRingMode
+ //pNewLine->LineDevStatus.dwSignalLevel
+ //pNewLine->LineDevStatus.dwBatteryLevel
+ //pNewLine->LineDevStatus.dwRoamMode
+
+ pNewLine->LineDevStatus.dwDevStatusFlags =
+ LINEDEVSTATUSFLAGS_CONNECTED | LINEDEVSTATUSFLAGS_INSERVICE;
+
+ //pNewLine->LineDevStatus.dwTerminalModesSize;
+ //pNewLine->LineDevStatus.dwTerminalModesOffset
+
+ //pNewLine->LineDevStatus.dwDevSpecificSize
+ //pNewLine->LineDevStatus.dwDevSpecificOffset
+
+
+ //
+ // Addr caps
+ //
+
+ pNewLine->LineAddrCaps.dwNeededSize =
+ pNewLine->LineAddrCaps.dwUsedSize = sizeof(LINEADDRESSCAPS) +
+ LINE_ADDR_CAPS_VAR_DATA_SIZE;
+
+ pNewLine->LineAddrCaps.dwLineDeviceID = dwDeviceID;
+
+ //pNewLine->LineAddrCaps.dwAddressSize
+ pNewLine->LineAddrCaps.dwAddressOffset = sizeof(LINEADDRESSCAPS);
+
+ //pNewLine->LineAddrCaps.dwDevSpecificSize
+ //pNewLine->LineAddrCaps.dwDevSpecificOffset
+
+ pNewLine->LineAddrCaps.dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
+ pNewLine->LineAddrCaps.dwAddressStates = ALL_ADDRESS_STATES;
+ pNewLine->LineAddrCaps.dwCallInfoStates = ALL_CALL_INFO_STATES;
+ pNewLine->LineAddrCaps.dwCallerIDFlags =
+ pNewLine->LineAddrCaps.dwCalledIDFlags =
+ pNewLine->LineAddrCaps.dwConnectedIDFlags =
+ pNewLine->LineAddrCaps.dwRedirectionIDFlags =
+ pNewLine->LineAddrCaps.dwRedirectingIDFlags = ALL_CALL_PARTY_ID_FLAGS;
+ pNewLine->LineAddrCaps.dwCallStates = ALL_CALL_STATES;
+ pNewLine->LineAddrCaps.dwDialToneModes = ALL_DIAL_TONE_MODES;
+ pNewLine->LineAddrCaps.dwBusyModes = ALL_BUSY_MODES;
+ pNewLine->LineAddrCaps.dwSpecialInfo = ALL_SPECIAL_INFO;
+ pNewLine->LineAddrCaps.dwDisconnectModes = ALL_DISCONNECT_MODES;
+
+ pNewLine->LineAddrCaps.dwMaxNumActiveCalls =
+ pNewLine->LineAddrCaps.dwMaxNumOnHoldCalls =
+ pNewLine->LineAddrCaps.dwMaxNumOnHoldPendingCalls =
+ pNewLine->LineAddrCaps.dwMaxNumConference =
+ pNewLine->LineAddrCaps.dwMaxNumTransConf = 64; // BUGBUG
+
+ pNewLine->LineAddrCaps.dwAddrCapFlags = ALL_ADDRESS_CAP_FLAGS;
+ pNewLine->LineAddrCaps.dwCallFeatures = ALL_CALL_FEATURES;
+ //pNewLine->LineAddrCaps.dwRemoveFromConfCaps
+ //pNewLine->LineAddrCaps.dwRemoveFromConfState
+ //pNewLine->LineAddrCaps.dwTransferModes
+ //pNewLine->LineAddrCaps.dwParkModes
+
+ //pNewLine->LineAddrCaps.dwForwardModes
+ //pNewLine->LineAddrCaps.dwMaxForwardEntries
+ //pNewLine->LineAddrCaps.dwMaxSpecificEntries
+ //pNewLine->LineAddrCaps.dwMinFwdNumRings
+ //pNewLine->LineAddrCaps.dwMaxFwdNumRings
+
+ //pNewLine->LineAddrCaps.dwMaxCallCompletions
+ //pNewLine->LineAddrCaps.dwCallCompletionConds
+ //pNewLine->LineAddrCaps.dwCallCompletionModes
+ //pNewLine->LineAddrCaps.dwNumCompletionMessages
+ //pNewLine->LineAddrCaps.dwCompletionMsgTextEntrySize
+ //pNewLine->LineAddrCaps.dwCompletionMsgTextSize
+ //pNewLine->LineAddrCaps.dwCompletionMsgTextOffset
+ pNewLine->LineAddrCaps.dwAddressFeatures = ALL_ADDRESS_FEATURES;
+
+
+ //
+ // Addr status
+ //
+
+ pNewLine->LineAddrStatus.dwNeededSize =
+ pNewLine->LineAddrStatus.dwUsedSize =
+ sizeof (LINEADDRESSSTATUS) + LINE_ADDR_STATUS_VAR_DATA_SIZE;
+
+ //pNewLine->LineAddrStatus.dwNumInUse
+ //pNewLine->LineAddrStatus.dwNumActiveCalls
+ //pNewLine->LineAddrStatus.dwNumOnHoldCalls
+ //pNewLine->LineAddrStatus.dwNumOnHoldPendCalls
+ pNewLine->LineAddrStatus.dwAddressFeatures = ALL_ADDRESS_FEATURES;
+
+ //pNewLine->LineAddrStatus.dwNumRingsNoAnswer
+ //pNewLine->LineAddrStatus.dwForwardNumEntries
+ //pNewLine->LineAddrStatus.dwForwardSize
+ //pNewLine->LineAddrStatus.dwForwardOffset
+
+ //pNewLine->LineAddrStatus.dwTerminalModesSize
+ //pNewLine->LineAddrStatus.dwTerminalModesOffset
+
+ //pNewLine->LineAddrStatus.dwDevSpecificSize
+ //pNewLine->LineAddrStatus.dwDevSpecificOffset
+
+
+ //
+ // Insert new line...
+ //
+
+ while (pWidget && (pWidget->dwType != WT_DRVPHONE))
+ {
+ PDRVLINE pLine = (PDRVLINE) pWidget;
+
+
+ if ((pWidget->dwType == WT_DRVLINE) &&
+ (pLine->dwDeviceID > dwDeviceID))
+ {
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+
+ InsertWidgetInList ((PDRVWIDGET) pNewLine, pWidget);
+ }
+
+ return pNewLine;
+}
+
+
+PDRVLINE
+GetLine(
+ DWORD dwDeviceID
+ )
+{
+ PDRVWIDGET pWidget = gaWidgets;
+
+
+ while (pWidget)
+ {
+ if ((pWidget->dwType == WT_DRVLINE) &&
+ (((PDRVLINE) pWidget)->dwDeviceID == dwDeviceID))
+ {
+ return ((PDRVLINE) pWidget);
+ }
+
+ pWidget = pWidget->pNext;
+ }
+
+ return ((PDRVLINE) NULL);
+}
+
+
+VOID
+FreeLine(
+ PDRVLINE pLine
+ )
+{
+ PDRVWIDGET pWidget = pLine->Widget.pNext;
+
+
+ if (RemoveWidgetFromList ((PDRVWIDGET) pLine))
+ {
+ // BUGBUG need to complete all pending reqs
+
+ while (pWidget && (pWidget->dwType == WT_DRVCALL))
+ {
+ PDRVWIDGET pWidget2 = pWidget->pNext;
+
+
+ RemoveWidgetFromList (pWidget);
+ pWidget = pWidget2;
+ }
+ }
+}
+
+
+LONG
+AllocCall(
+ PDRVLINE pLine,
+ HTAPICALL htCall,
+ LPLINECALLPARAMS lpCallParams,
+ PDRVCALL *ppCall
+ )
+{
+ LONG lResult = 0;
+ DWORD dwAddressID = 0;
+ PDRVCALL pNewCall = (PDRVCALL) DrvAlloc (sizeof(DRVCALL));
+ PDRVWIDGET pWidget = (PDRVWIDGET) pLine->Widget.pNext;
+
+
+ //
+ // Validate call params
+ //
+
+ if (lpCallParams)
+ {
+ if (lpCallParams->dwAddressMode == LINEADDRESSMODE_ADDRESSID)
+ {
+ if (lpCallParams->dwAddressID >= gdwNumAddrsPerLine)
+ {
+ lResult = LINEERR_INVALCALLPARAMS;
+ goto AllocCall_exit;
+ }
+ else
+ {
+ dwAddressID = lpCallParams->dwAddressID;
+ }
+ }
+
+ // BUGBUG chk against currently supported bearer/media modes on line
+ }
+
+
+ //
+ // Alloc a new call struct
+ //
+
+ if (!pNewCall)
+ {
+ lResult = LINEERR_NOMEM;
+ goto AllocCall_exit;
+ }
+
+
+ //
+ // Initialize the new call fields
+ //
+
+ memset (pNewCall, 0, sizeof(DRVCALL));
+
+ pNewCall->Widget.dwType = WT_DRVCALL;
+ pNewCall->pLine = pLine;
+ pNewCall->htCall = htCall;
+ pNewCall->dwCallState = LINECALLSTATE_UNKNOWN;
+ pNewCall->dwCallFeatures = ALL_CALL_FEATURES;
+
+ pNewCall->LineCallInfo.dwNeededSize =
+ pNewCall->LineCallInfo.dwUsedSize = sizeof (LINECALLINFO) +
+ LINE_CALL_INFO_VAR_DATA_SIZE;
+
+ pNewCall->LineCallInfo.dwLineDeviceID = pLine->dwDeviceID;
+ pNewCall->LineCallInfo.dwAddressID = dwAddressID;
+
+ pNewCall->LineCallInfo.dwBearerMode =
+ (lpCallParams ? lpCallParams->dwBearerMode : LINEBEARERMODE_VOICE);
+ pNewCall->LineCallInfo.dwRate =
+ (lpCallParams ? lpCallParams->dwMaxRate : 65536);
+ pNewCall->LineCallInfo.dwMediaMode =
+ (lpCallParams ? lpCallParams->dwMediaMode :
+ LINEMEDIAMODE_INTERACTIVEVOICE);
+
+ //pNewCall->LineCallInfo.dwAppSpecific
+ //pNewCall->LineCallInfo.dwCallID
+ //pNewCall->LineCallInfo.dwRelatedCallID
+ //pNewCall->LineCallInfo.dwCallParamFlags
+ pNewCall->LineCallInfo.dwCallStates = ALL_CALL_STATES;
+
+ //pNewCall->LineCallInfo.dwMonitorDigitModes FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwMonitorMediaModes FILLED IN BY TAPI
+
+ if (lpCallParams)
+ {
+ memcpy(
+ &pNewCall->LineCallInfo.DialParams,
+ &lpCallParams->DialParams,
+ sizeof(LINEDIALPARAMS)
+ );
+ }
+
+ //pNewCall->LineCallInfo.dwOrigin
+ //pNewCall->LineCallInfo.dwReason
+ //pNewCall->LineCallInfo.dwCompletionID
+
+ //pNewCall->LineCallInfo.dwNumOwners FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwNumMonitors FILLED IN BY TAPI
+
+ //pNewCall->LineCallInfo.dwCountryCode
+ //pNewCall->LineCallInfo.dwTrunk
+
+ //pNewCall->LineCallInfo.dwCallerIDFlags
+ //pNewCall->LineCallInfo.dwCallerIDSize
+ //pNewCall->LineCallInfo.dwCallerIDOffset
+
+ //pNewCall->LineCallInfo.dwCallerIDNameSize
+ //pNewCall->LineCallInfo.dwCallerIDNameOffset
+
+ //pNewCall->LineCallInfo.dwCalledIDFlags
+ //pNewCall->LineCallInfo.dwCalledIDSize
+ //pNewCall->LineCallInfo.dwCalledIDOffset
+
+ //pNewCall->LineCallInfo.dwCalledIDNameSize
+ //pNewCall->LineCallInfo.dwCalledIDNameOffset
+
+ //pNewCall->LineCallInfo.dwConnectedIDFlags
+ //pNewCall->LineCallInfo.dwConnectedIDSize
+ //pNewCall->LineCallInfo.dwConnectedIDOffset
+
+ //pNewCall->LineCallInfo.dwConnectedIDNameSize
+ //pNewCall->LineCallInfo.dwConnectedIDNameOffset
+
+ //pNewCall->LineCallInfo.dwRedirectionIDFlags
+ //pNewCall->LineCallInfo.dwRedirectionIDSize
+ //pNewCall->LineCallInfo.dwRedirectionIDOffset
+
+ //pNewCall->LineCallInfo.dwRedirectionIDNameSize
+ //pNewCall->LineCallInfo.dwRedirectionIDNameOffset
+
+ //pNewCall->LineCallInfo.dwRedirectingIDFlags
+ //pNewCall->LineCallInfo.dwRedirectingIDSize
+ //pNewCall->LineCallInfo.dwRedirectingIDOffset
+
+ //pNewCall->LineCallInfo.dwRedirectingIDNameSize
+ //pNewCall->LineCallInfo.dwRedirectingIDNameOffset
+
+ //pNewCall->LineCallInfo.dwAppNameSize FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwAppNameOffset FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwDisplayableAddressSize FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwDisplayableAddressOffset FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwCalledPartySize FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwCalledPartyOffset FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwCommentSize FILLED IN BY TAPI
+ //pNewCall->LineCallInfo.dwCommentOffset FILLED IN BY TAPI
+
+ //pNewCall->LineCallInfo.dwDisplaySize
+ //pNewCall->LineCallInfo.dwDisplayOffset
+
+ //pNewCall->LineCallInfo.dwUserUserInfoSize
+ //pNewCall->LineCallInfo.dwUserUserInfoOffset
+
+ //pNewCall->LineCallInfo.dwHighLevelCompSize
+ //pNewCall->LineCallInfo.dwHighLevelCompOffset
+
+ //pNewCall->LineCallInfo.dwLowLevelCompSize
+ //pNewCall->LineCallInfo.dwLowLevelCompOffset
+
+ //pNewCall->LineCallInfo.dwChargingInfoSize
+ //pNewCall->LineCallInfo.dwChargingInfoOffset
+
+ //pNewCall->LineCallInfo.dwTerminalModesSize
+ //pNewCall->LineCallInfo.dwTerminalModesOffset
+
+ //pNewCall->LineCallInfo.dwDevSpecificSize
+ //pNewCall->LineCallInfo.dwDevSpecificOffset
+
+
+ //
+ // Insert new call...
+ //
+
+ while (pWidget &&
+ (pWidget->dwType == WT_DRVCALL) &&
+ (((PDRVCALL)pWidget)->LineCallInfo.dwAddressID <= dwAddressID))
+ {
+ pWidget = pWidget->pNext;
+ }
+
+ InsertWidgetInList ((PDRVWIDGET) pNewCall, pWidget);
+
+
+ //
+ // Fill in the blanks
+ //
+
+ *ppCall = pNewCall;
+
+AllocCall_exit:
+
+ return lResult;
+}
+
+
+VOID
+FreeCall(
+ PDRVCALL pCall
+ )
+{
+ // BUGBUG need to complete all pending reqs
+
+ RemoveWidgetFromList ((PDRVWIDGET) pCall);
+}
+
+
+PDRVPHONE
+AllocPhone(
+ DWORD dwDeviceID
+ )
+{
+ PDRVPHONE pNewPhone = (PDRVPHONE) DrvAlloc (sizeof(DRVPHONE));
+
+
+ if (pNewPhone)
+ {
+ PDRVWIDGET pWidget = gaWidgets;
+ char far *p;
+
+
+ memset (pNewPhone, 0, sizeof(DRVPHONE));
+
+ pNewPhone->Widget.dwType = WT_DRVPHONE;
+ pNewPhone->dwDeviceID = dwDeviceID;
+
+
+ //
+ // Caps
+ //
+
+ pNewPhone->PhoneCaps.dwNeededSize =
+ pNewPhone->PhoneCaps.dwUsedSize =
+ sizeof(PHONECAPS) + PHONE_CAPS_VAR_DATA_SIZE;
+
+ pNewPhone->PhoneCaps.dwProviderInfoSize = strlen (szProviderInfo) + 1;
+ pNewPhone->PhoneCaps.dwProviderInfoOffset = sizeof(PHONECAPS);
+
+ p = ((char far *) &pNewPhone->PhoneCaps) +
+ pNewPhone->PhoneCaps.dwProviderInfoOffset;
+
+ strcpy (p, szProviderInfo);
+
+ //pNewPhone->PhoneCaps.dwPhoneInfoSize
+ //pNewPhone->PhoneCaps.dwPhoneInfoOffset
+
+ pNewPhone->PhoneCaps.dwPermanentPhoneID;
+ (0x0000ffff & dwDeviceID) |
+ ((0x0000ffff & gdwPermanentProviderID) << 16);
+
+ pNewPhone->PhoneCaps.dwPhoneNameOffset =
+ sizeof(PHONECAPS) + 2*MAX_STRING_PARAM_SIZE;
+
+ p = ((char far *) &pNewPhone->PhoneCaps) +
+ pNewPhone->PhoneCaps.dwPhoneNameOffset;
+
+ sprintf (p, "Phone%ld (ESP)", dwDeviceID);
+
+ pNewPhone->PhoneCaps.dwPhoneNameSize = (DWORD) strlen (p) + 1;
+
+ pNewPhone->PhoneCaps.dwStringFormat = STRINGFORMAT_ASCII;
+
+ //pNewPhone->PhoneCaps.dwPhoneStates
+ //pNewPhone->PhoneCaps.dwHookSwitchDevs
+ //pNewPhone->PhoneCaps.dwHandsetHookSwitchModes
+ //pNewPhone->PhoneCaps.dwSpeakerHookSwitchModes
+ //pNewPhone->PhoneCaps.dwHeadsetHookSwitchModes
+
+ //pNewPhone->PhoneCaps.dwVolumeFlags
+ //pNewPhone->PhoneCaps.dwGainFlags
+ //pNewPhone->PhoneCaps.dwDisplayNumRows
+ //pNewPhone->PhoneCaps.dwDisplayNumColumns
+ //pNewPhone->PhoneCaps.dwNumRingModes
+ //pNewPhone->PhoneCaps.dwNumButtonLamps
+
+ //pNewPhone->PhoneCaps.dwButtonModesSize
+ //pNewPhone->PhoneCaps.dwButtonModesOffset
+
+ //pNewPhone->PhoneCaps.dwButtonFunctionsSize
+ //pNewPhone->PhoneCaps.dwButtonFunctionsOffset
+
+ //pNewPhone->PhoneCaps.dwLampModesSize
+ //pNewPhone->PhoneCaps.dwLampModesOffset
+
+ //pNewPhone->PhoneCaps.dwNumSetData
+ //pNewPhone->PhoneCaps.dwSetDataSize
+ //pNewPhone->PhoneCaps.dwSetDataOffset
+
+ //pNewPhone->PhoneCaps.dwNumGetData
+ //pNewPhone->PhoneCaps.dwGetDataSize
+ //pNewPhone->PhoneCaps.dwGetDataOffset
+
+ //pNewPhone->PhoneCaps.dwDevSpecificSize
+ //pNewPhone->PhoneCaps.dwDevSpecificOffset
+
+
+ //
+ // Status
+ //
+
+ pNewPhone->PhoneStatus.dwUsedSize =
+ pNewPhone->PhoneStatus.dwNeededSize = sizeof(PHONESTATUS);
+
+
+ //
+ // Insert new phone...
+ //
+
+ while (pWidget)
+ {
+ if ((pWidget->dwType == WT_DRVPHONE) &&
+ (((PDRVPHONE)pWidget)->dwDeviceID > dwDeviceID))
+ {
+ break;
+ }
+
+ pWidget = pWidget->pNext;
+ }
+
+ InsertWidgetInList ((PDRVWIDGET) pNewPhone, pWidget);
+ }
+
+ return pNewPhone;
+}
+
+
+PDRVPHONE
+GetPhone(
+ DWORD dwDeviceID
+ )
+{
+ PDRVWIDGET pWidget = gaWidgets;
+
+
+ while (pWidget)
+ {
+ if ((pWidget->dwType == WT_DRVPHONE) &&
+ (((PDRVPHONE) pWidget)->dwDeviceID == dwDeviceID))
+ {
+ return ((PDRVPHONE) pWidget);
+ }
+
+ pWidget = pWidget->pNext;
+ }
+
+ return ((PDRVPHONE) NULL);
+}
+
+
+VOID
+FreePhone(
+ PDRVPHONE pPhone
+ )
+{
+ // BUGBUG need to complete all pending reqs
+
+ RemoveWidgetFromList ((PDRVWIDGET) pPhone);
+}
+
+
+int
+GetWidgetIndex(
+ PDRVWIDGET pWidget
+ )
+{
+ int i;
+ PDRVWIDGET pWidget2 = gaWidgets;
+
+
+ for (i = 0; pWidget != pWidget2; i++)
+ {
+ pWidget2 = pWidget2->pNext;
+ }
+
+ return i;
+}
diff --git a/private/tapi/dev/sp/esp/win31.mak b/private/tapi/dev/sp/esp/win31.mak
new file mode 100644
index 000000000..05b19002e
--- /dev/null
+++ b/private/tapi/dev/sp/esp/win31.mak
@@ -0,0 +1,60 @@
+!include \telephon\tapi\tapi.mak
+
+!ifndef TAPI_1_1
+TAPI_1_1 = 1
+!endif
+
+!if $(TAPI_1_1)
+TAPI_VER_FLAGS = -DTAPI_1_1
+!else
+TAPI_VER_FLAGS =
+!endif
+
+
+DLLOBJ = esp.obj widget.obj vars.obj
+APPOBJ = espexe.obj
+
+release: esp.tsp espexe.exe
+
+esp.obj:
+ cl $(CFLAGS) $(TAPI_VER_FLAGS) /c esp.c
+
+widget.obj:
+ cl $(CFLAGS) $(TAPI_VER_FLAGS) /c widget.c
+
+vars.obj:
+ cl $(CFLAGS) $(TAPI_VER_FLAGS) /c vars.c
+
+esp.tsp:: $(DLLOBJ) $(@B).def $(@B).rc
+ echo >NUL @<<$(@B).CRF
+$(DLLOBJ)
+$@
+$(@B).map
+c:\msvc\lib\+
+$(LIBS)
+$(@B).def;
+<<
+ link $(LFLAGS) /NOPACKC @$(@B).CRF
+ $(RC) $(RESFLAGS) $(@B).rc $@
+ implib /nologo /nowep $(@B).LIB $@
+ mapsym $(@B)
+ copy esp.tsp ..\..\lib\i386
+
+
+
+espexe.obj:
+ cl $(APPCFLAGS) /c espexe.c
+
+espexe.exe:: $(APPOBJ) $(@B).def $(@B).rc
+ echo >NUL @<<$(@B).CRF
+$(APPOBJ)
+$@
+$(@B).MAP
+c:\msvc\lib\+
+libw llibcew esp
+$(@B).def;
+<<
+ link $(LFLAGS) @$(@B).CRF
+ $(RC) $(RESFLAGS) $(@B).rc $@
+ mapsym $(@B)
+ copy espexe.exe ..\..\lib\i386
diff --git a/private/tapi/dev/sp/hmtsp/depend.mk b/private/tapi/dev/sp/hmtsp/depend.mk
new file mode 100644
index 000000000..e7ec80539
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/depend.mk
@@ -0,0 +1,3 @@
+.\hmtsp.obj: ..\hmtsp.c ..\hmtsp.h
+
+.\hmtsp.res: ..\hmtsp.rc ..\hmtsprc.h
diff --git a/private/tapi/dev/sp/hmtsp/hmtsp.c b/private/tapi/dev/sp/hmtsp/hmtsp.c
new file mode 100644
index 000000000..5aafed5b5
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/hmtsp.c
@@ -0,0 +1,1160 @@
+// Happy Modem Testing Service Provider
+// derived from PDISP
+
+#ifndef TESTING
+#define TESTING
+#endif
+
+#define USECOMM /* for chicago windows.h */
+#include <windows.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "hmtsp.h"
+
+#ifdef TESTING
+void FAR PASCAL LogDestAddress(LPCSTR szDestAddress);
+#endif
+
+BOOL CALLBACK ConfigDlgProc(HWND, UINT, WPARAM, LPARAM);
+
+int SerialOpenComms (LPSTR, LPSTR);
+void LoadIniStrings (DWORD);
+long appCall (int, char *, long);
+
+
+#define msgMakeCall 1
+#define msgDrop 2
+
+
+// The number of entries in the devices and speed array.
+
+#define NUMPORTS 4
+
+char *lpszCommDevArray[NUMPORTS] =
+{ "COM1", "COM2", "COM3", "COM4" };
+
+
+// Various tags in the ini file.
+
+char s_telephon_ini[] = "telephon.ini";
+
+char s_one[] = "1";
+char s_zero[] = "0";
+char s_numlines[] = "NumLines";
+char s_numphones[] = "NumPhones";
+char s_providerx[] = "Provider%d";
+
+char s_port[] = "Port";
+char s_linename[] = "LineName";
+char s_lineaddr[] = "LineAddress";
+
+// The global module handle
+
+HANDLE hInst = NULL;
+
+// Line object.
+ATSPLineData line;
+
+// Provider description string
+char gszProviderInfo[255];
+
+
+///////////////////////////////////////////////////////////
+// The required DLL functions
+///////////////////////////////////////////////////////////
+
+int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSegment,
+ WORD wHeapSize, LPSTR lpszCmdLine)
+{
+ if (hInst != NULL)
+ return FALSE;
+
+ hInst = hInstance;
+
+ return TRUE;
+}
+
+VOID FAR PASCAL WEP (int bSystemExit)
+{
+ hInst = NULL;
+}
+
+
+///////////////////////////////////////////////////////////
+// The Service Provider Basic Configuration Routines
+///////////////////////////////////////////////////////////
+
+static BOOL initialised = FALSE;
+
+LONG TSPIAPI TSPI_lineNegotiateTSPIVersion (
+DWORD dwDeviceID,
+DWORD dwLowVersion,
+DWORD dwHighVersion,
+LPDWORD lpdwTSPIVersion)
+{
+ DebugMsg (("Entering TSPI_lineNegotiateTSPIVersion"));
+
+ // line.lineID will contain garbage before provider_init has
+ // been called (ie. first time through). However, we can guarantee
+ // that the first call will be with INITIALIZE_NEGOTIATION and that
+ // is followed immediately by provider_init. This would be a problem
+ // if the line data structure was dynamically allocated !
+
+ if (dwDeviceID == INITIALIZE_NEGOTIATION ||
+ dwDeviceID == line.lineID) // we support only one line
+ {
+ *lpdwTSPIVersion = ATSP_VERSION;
+
+ if (dwLowVersion > ATSP_VERSION || // the app is too new for us
+ dwHighVersion < ATSP_VERSION) // we are too new for the app
+ return LINEERR_INCOMPATIBLEAPIVERSION;
+ else
+ return 0;
+ }
+
+ return LINEERR_BADDEVICEID; // The requested device doesn't exist
+}
+
+
+LONG TSPIAPI TSPI_providerInit (
+DWORD dwTSPIVersion,
+DWORD dwPermanentProviderID,
+DWORD dwLineDeviceIDBase,
+DWORD dwPhoneDeviceIDBase,
+DWORD dwNumLines,
+DWORD dwNumPhones,
+ASYNC_COMPLETION lpfnCompletionProc,
+LPDWORD lpdwOptions
+)
+{
+ DebugMsg (("Entering TSPI_providerInit"));
+
+ assert (dwTSPIVersion == ATSP_VERSION);
+ assert (dwNumLines == 1);
+ assert (dwNumPhones == 0);
+
+ if (initialised)
+ return LINEERR_NOMULTIPLEINSTANCE;
+
+ // initialise our internal structures
+
+ ZeroMemory (&line, sizeof (ATSPLineData));
+
+ line.lpfnCompletion = lpfnCompletionProc;
+ line.lineID = dwLineDeviceIDBase;
+ line.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
+ line.hcd = -1;
+ LoadIniStrings (dwPermanentProviderID);
+
+ initialised = TRUE;
+
+ return 0;
+}
+
+
+LONG TSPIAPI TSPI_providerShutdown (DWORD dwTSPIVersion)
+{
+ DebugMsg (("Entering TSPI_providerShutdown"));
+
+ initialised = FALSE;
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////
+// The Line Specific Calls
+///////////////////////////////////////////////////////////
+
+LONG TSPIAPI TSPI_lineConfigDialog (
+DWORD dwDeviceID,
+HWND hwndOwner,
+LPCSTR lpszDeviceClass)
+{
+ DebugMsg (("Entering TSPI_lineConfigDialog"));
+
+ if (dwDeviceID != line.lineID)
+ return LINEERR_BADDEVICEID;
+
+#ifndef TESTING
+ DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG),
+ hwndOwner, ConfigDlgProc);
+#endif
+
+ return 0;
+}
+
+
+long lineDropCore (ATSPLineData *theLine, DWORD dwRequestID)
+{
+ // if the call is not idle, transition to idle and close the comms port
+
+ return appCall (msgDrop, 0, dwRequestID);
+}
+
+
+LONG TSPIAPI TSPI_lineClose (HDRVLINE hdLine)
+{
+ DebugMsg (("Entering TSPI_lineClose"));
+
+ if (hdLine != (HDRVLINE) &line)
+ return LINEERR_INVALLINEHANDLE;
+
+ // call drop in case there is still an active call on the line
+ lineDropCore (&line, 0);
+
+ return 0;
+}
+
+
+LONG TSPIAPI TSPI_lineCloseCall (HDRVCALL hdCall)
+{
+ DebugMsg (("Entering TSPI_lineCloseCall"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+ // call drop in case there is still an active call on the line
+ lineDropCore (&line, 0);
+
+ line.callState = 0;
+ return 0;
+}
+
+
+LONG TSPIAPI TSPI_lineDrop (
+DRV_REQUESTID dwRequestID,
+HDRVCALL hdCall,
+LPCSTR lpsUserUserInfo,
+DWORD dwSize)
+{
+ // Transition a call to the IDLE state.
+
+ DebugMsg (("Entering TSPI_lineDrop"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+ return lineDropCore (&line, dwRequestID); // it was our active call
+}
+
+LONG TSPIAPI TSPI_lineGetAddressCaps (
+DWORD dwDeviceID,
+DWORD dwAddressID,
+DWORD dwTSPIVersion,
+DWORD dwExtVersion,
+LPLINEADDRESSCAPS lpAddressCaps)
+
+{
+ int cbLineAddr;
+
+ DebugMsg (("Entering TSPI_lineGetAddressCaps"));
+
+ // We support only one line and one address.
+
+ if (dwDeviceID != line.lineID)
+ return LINEERR_BADDEVICEID;
+
+ if (dwAddressID != 0)
+ return LINEERR_INVALADDRESSID;
+
+ cbLineAddr = lstrlen (line.lineaddr) + 1;
+
+ lpAddressCaps->dwNeededSize = sizeof (LINEADDRESSCAPS) + cbLineAddr;
+
+ if (lpAddressCaps->dwTotalSize < lpAddressCaps->dwNeededSize)
+ lpAddressCaps->dwUsedSize = sizeof (LINEADDRESSCAPS);
+ else
+ {
+ MoveMemory((char *) lpAddressCaps + sizeof (LINEADDRESSCAPS),
+ line.lineaddr, cbLineAddr);
+
+ lpAddressCaps->dwAddressSize = cbLineAddr;
+ lpAddressCaps->dwAddressOffset = sizeof (LINEADDRESSCAPS);
+ lpAddressCaps->dwUsedSize = lpAddressCaps->dwNeededSize;
+ }
+
+ lpAddressCaps->dwLineDeviceID = line.lineID;
+
+ lpAddressCaps->dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
+ lpAddressCaps->dwAddressStates = LINEADDRESSSTATE_OTHER |
+ LINEADDRESSSTATE_INUSEZERO |
+ LINEADDRESSSTATE_INUSEONE |
+ LINEADDRESSSTATE_NUMCALLS;
+ lpAddressCaps->dwCallInfoStates = LINECALLINFOSTATE_OTHER |
+ LINECALLINFOSTATE_APPSPECIFIC |
+ LINECALLINFOSTATE_NUMOWNERINCR |
+ LINECALLINFOSTATE_NUMOWNERDECR |
+ LINECALLINFOSTATE_NUMMONITORS |
+ LINECALLINFOSTATE_DIALPARAMS;
+ lpAddressCaps->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwCallStates = LINECALLSTATE_IDLE |
+ LINECALLSTATE_DIALTONE |
+ LINECALLSTATE_DIALING |
+ LINECALLSTATE_BUSY |
+ LINECALLSTATE_CONNECTED |
+ LINECALLSTATE_PROCEEDING |
+ LINECALLSTATE_UNKNOWN;
+ lpAddressCaps->dwDialToneModes = LINEDIALTONEMODE_UNAVAIL;
+ lpAddressCaps->dwBusyModes = LINEBUSYMODE_UNAVAIL;
+ lpAddressCaps->dwSpecialInfo = LINESPECIALINFO_UNAVAIL;
+ lpAddressCaps->dwDisconnectModes = LINEDISCONNECTMODE_UNKNOWN;
+ lpAddressCaps->dwMaxNumActiveCalls = 1;
+ lpAddressCaps->dwAddrCapFlags = LINEADDRCAPFLAGS_BLOCKIDDEFAULT |
+ LINEADDRCAPFLAGS_DIALED |
+ LINEADDRCAPFLAGS_PARTIALDIAL;
+ lpAddressCaps->dwCallFeatures = LINECALLFEATURE_DIAL |
+ LINECALLFEATURE_DROP;
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineGetAddressID (
+HDRVLINE hdLine,
+LPDWORD lpdwAddressID,
+DWORD dwAddressMode,
+LPCSTR lpsAddress,
+DWORD dwSize)
+{
+ DebugMsg (("Entering TSPI_lineGetAddressID"));
+
+ if (hdLine != (HDRVLINE) &line)
+ return LINEERR_INVALLINEHANDLE;
+
+ assert (dwAddressMode == LINEADDRESSMODE_DIALABLEADDR);
+
+ if (lstrcmp (line.lineaddr, lpsAddress))
+ return LINEERR_INVALADDRESS;
+ else
+ {
+ *lpdwAddressID = 0; // we support only 1 line
+ return 0;
+ }
+}
+
+LONG TSPIAPI TSPI_lineGetAddressStatus (
+HDRVLINE hdLine,
+DWORD dwAddressID,
+LPLINEADDRESSSTATUS lpAddressStatus)
+{
+ DebugMsg (("Entering TSPI_lineGetAddressStatus"));
+
+ if (dwAddressID)
+ return LINEERR_INVALADDRESSID;
+
+ lpAddressStatus->dwUsedSize =
+ lpAddressStatus->dwNeededSize = sizeof (LINEADDRESSSTATUS);
+
+ // if we are idle a call can be made
+
+ if (line.callState == 0) // our internal flag that line is not in use
+ lpAddressStatus->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
+ else
+ {
+ lpAddressStatus->dwNumInUse = 1;
+ lpAddressStatus->dwNumActiveCalls = 1;
+ }
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineGetCallAddressID (
+HDRVCALL hdCall,
+LPDWORD lpdwAddressID)
+{
+ DebugMsg (("Entering TSPI_lineGetCallAddressID"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+ // There is but a single address where a call may exist.
+ *lpdwAddressID = 0;
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineGetCallInfo (
+HDRVCALL hdCall,
+LPLINECALLINFO lpCallInfo)
+{
+ int cbDestAddr = lstrlen (line.DestAddress) + 1;
+
+ DebugMsg (("Entering TSPI_lineGetCallInfo"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+
+ lpCallInfo->dwUsedSize = sizeof (LINECALLINFO);
+ lpCallInfo->dwNeededSize = sizeof (LINECALLINFO) + cbDestAddr;
+
+ if (lpCallInfo->dwTotalSize >= lpCallInfo->dwNeededSize)
+ {
+ CopyMemory((char *) lpCallInfo + sizeof (LINECALLINFO),
+ line.DestAddress, cbDestAddr);
+
+ lpCallInfo->dwDisplayableAddressSize = cbDestAddr;
+ lpCallInfo->dwDisplayableAddressOffset = sizeof (LINECALLINFO);
+ lpCallInfo->dwUsedSize = lpCallInfo->dwNeededSize;
+ }
+
+ lpCallInfo->dwLineDeviceID = line.lineID;
+ lpCallInfo->dwBearerMode = LINEBEARERMODE_VOICE;
+ lpCallInfo->dwMediaMode = line.dwMediaMode;
+ lpCallInfo->dwAppSpecific = line.dwAppSpecific;
+ lpCallInfo->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE |
+ LINECALLPARAMFLAGS_BLOCKID;
+ lpCallInfo->dwCallStates = LINECALLSTATE_IDLE |
+ LINECALLSTATE_CONNECTED;
+ lpCallInfo->dwOrigin = LINECALLORIGIN_OUTBOUND;
+ lpCallInfo->dwReason = LINECALLREASON_UNAVAIL;
+ lpCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineGetCallStatus (
+HDRVCALL hdCall,
+LPLINECALLSTATUS lpCallStatus)
+{
+ DebugMsg (("Entering TSPI_lineGetCallStatus"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+ lpCallStatus->dwCallState = line.callState;
+
+ if (line.callState == LINECALLSTATE_CONNECTED)
+ lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP;
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineGetDevCaps (
+DWORD dwDeviceID,
+DWORD dwTSPIVersion,
+DWORD dwExtVersion,
+LPLINEDEVCAPS lpLineDevCaps)
+{
+ int cbname = lstrlen (line.linename) + 1;
+ int cbinfo = lstrlen (gszProviderInfo) + 1;
+
+ DebugMsg (("Entering TSPI_lineGetDevCaps"));
+
+ if (dwDeviceID != line.lineID)
+ return LINEERR_BADDEVICEID;
+
+
+ lpLineDevCaps->dwUsedSize = sizeof (LINEDEVCAPS);
+ lpLineDevCaps->dwNeededSize = sizeof (LINEDEVCAPS) + cbinfo + cbname;
+
+
+ if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwUsedSize + cbinfo)
+ {
+ // Copy in the provider info
+
+ CopyMemory ((char *)lpLineDevCaps + lpLineDevCaps->dwUsedSize,
+ gszProviderInfo, cbinfo);
+
+ lpLineDevCaps->dwProviderInfoSize = cbinfo;
+ lpLineDevCaps->dwProviderInfoOffset = lpLineDevCaps->dwUsedSize;
+ lpLineDevCaps->dwUsedSize += cbinfo;
+ }
+
+ if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwUsedSize + cbname)
+ {
+ // Copy in the line name
+
+ CopyMemory((char *) lpLineDevCaps + lpLineDevCaps->dwUsedSize,
+ line.linename, cbname);
+
+ lpLineDevCaps->dwLineNameSize = cbname;
+ lpLineDevCaps->dwLineNameOffset = lpLineDevCaps->dwUsedSize;
+ lpLineDevCaps->dwUsedSize += cbname;
+ }
+
+
+ lpLineDevCaps->dwPermanentLineID = (line.dwppID << 16) + 0;
+
+ // TAPI.DLL fills in APIVersion and ExtVersion.
+
+ lpLineDevCaps->dwNumAddresses = 1;
+ lpLineDevCaps->dwMaxNumActiveCalls = 1;
+ lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII;
+ lpLineDevCaps->dwBearerModes = LINEBEARERMODE_VOICE;
+ lpLineDevCaps->dwMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE;
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineGetID (
+HDRVLINE hdLine,
+DWORD dwAddressID,
+HDRVCALL hdCall,
+DWORD dwSelect,
+LPVARSTRING lpDeviceID,
+LPCSTR lpszDeviceClass,
+HANDLE hHandle)
+{
+ DebugMsg (("Entering TSPI_lineGetID"));
+
+ // Since we have only one device, we don't have to
+ // check the location of the line, address, or call.
+
+ if (hdLine != (HDRVLINE) &line)
+ return LINEERR_INVALLINEHANDLE;
+
+ if (lstrcmp (lpszDeviceClass, "tapi/line") == 0)
+ {
+ lpDeviceID->dwNeededSize = sizeof (VARSTRING) + sizeof (DWORD);
+
+ if (lpDeviceID->dwTotalSize >= lpDeviceID->dwNeededSize)
+ {
+ lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof (DWORD);
+ lpDeviceID->dwStringOffset = sizeof (VARSTRING);
+
+ *((DWORD *) ((char *) lpDeviceID + sizeof (VARSTRING))) =
+ line.lineID;
+ }
+
+ return 0;
+ }
+
+#ifdef COMMSUPPORT
+ if (lstrcmp (lpszDeviceClass, "comm") == 0)
+ {
+ int cbport = lstrlen (line.port) + 1;
+
+ lpDeviceID->dwNeededSize = sizeof (VARSTRING) + cbport;
+
+ if (lpDeviceID->dwTotalSize >= lpDeviceID->dwNeededSize)
+ {
+ lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_ASCII;
+ lpDeviceID->dwStringSize = cbport;
+ lpDeviceID->dwStringOffset = sizeof (VARSTRING);
+
+ CopyMemory ((char *) lpDeviceID + sizeof (VARSTRING),
+ line.port, cbport);
+ }
+
+ return 0;
+ }
+#endif
+
+ return LINEERR_NODEVICE;
+}
+
+LONG TSPIAPI TSPI_lineGetLineDevStatus (
+HDRVLINE hdLine,
+LPLINEDEVSTATUS lpLineDevStatus)
+{
+ DebugMsg (("Entering TSPI_lineGetLineDevStatus"));
+
+ if (hdLine != (HDRVLINE) &line)
+ return LINEERR_INVALLINEHANDLE;
+
+ lpLineDevStatus->dwUsedSize =
+ lpLineDevStatus->dwNeededSize = sizeof (LINEDEVSTATUS);
+
+ lpLineDevStatus->dwOpenMediaModes = line.dwLineMediaModes;
+ lpLineDevStatus->dwRoamMode = LINEROAMMODE_UNAVAIL;
+
+ if (line.callState == 0)
+ {
+ lpLineDevStatus->dwNumActiveCalls = 0;
+ lpLineDevStatus->dwLineFeatures = LINEFEATURE_MAKECALL;
+ }
+ else
+ {
+ lpLineDevStatus->dwNumActiveCalls = 1;
+ lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
+ LINEDEVSTATUSFLAGS_INSERVICE;
+ }
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineGetNumAddressIDs (
+HDRVLINE hdLine,
+LPDWORD lpNumAddressIDs)
+{
+ DebugMsg (("Entering TSPI_lineGetNumAddressIDs"));
+
+ if (hdLine != (HDRVLINE) &line)
+ return LINEERR_INVALLINEHANDLE;
+
+ *lpNumAddressIDs = 1; // We only support one address
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineMakeCall (
+DRV_REQUESTID dwRequestID,
+HDRVLINE hdLine,
+HTAPICALL htCall,
+LPHDRVCALL lphdCall,
+LPCSTR lpszDestAddress,
+DWORD dwCountryCode,
+LPLINECALLPARAMS const lpCallParams)
+{
+ DebugMsg (("Entering TSPI_lineMakeCall"));
+
+#ifdef TESTING
+ LogDestAddress(lpszDestAddress);
+#endif
+
+ if (lpszDestAddress &&
+ lstrlen (lpszDestAddress) > TAPIMAXDESTADDRESSSIZE)
+ return LINEERR_INVALPOINTER;
+
+ if (line.callState != 0)
+ return LINEERR_RESOURCEUNAVAIL;
+
+ if (lpCallParams)
+ {
+ if (lpCallParams->dwCallParamFlags &
+ ~(LINECALLPARAMFLAGS_IDLE | LINECALLPARAMFLAGS_BLOCKID))
+ return LINEERR_INVALCALLPARAMS;
+ }
+
+ // fill in fields of the call record
+
+ line.htCall = htCall; // we have no hdcall of our own
+ *lphdCall = (HDRVCALL) htCall;
+
+ if (lpszDestAddress)
+ lstrcpy (line.DestAddress, lpszDestAddress);
+ else
+ line.DestAddress[0] = 0;
+
+ return appCall (msgMakeCall, line.DestAddress, dwRequestID);
+}
+
+long appCall (int msg, char *str, long dwRequestID)
+{
+#ifndef TESTING
+ long wait;
+#endif
+
+ if (msg == msgMakeCall)
+ {
+#ifdef TESTING
+ line.hcd = 1;
+#else
+ line.hcd = SerialOpenComms (line.port, "9600");
+#endif
+ if (line.hcd < 0)
+ return LINEERR_RESOURCEUNAVAIL;
+ else
+ {
+ char dial[255];
+ wsprintf (dial, "ATMH9D%s;\r", str);
+#ifdef TESTING
+ DebugMsg (("Sent: %s", dial));
+ PostMessage(HWND_BROADCAST, WM_USER + 945, 0, 0);
+
+ line.callState = LINECALLSTATE_CONNECTED;
+ line.lpfnCompletion (dwRequestID, 0);
+ line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLSTATE,
+ LINECALLSTATE_CONNECTED, 0, 0);
+#else
+ if (WriteComm (line.hcd, dial, lstrlen (dial)) > 0)
+ {
+ DebugMsg (("Sent: %s", dial));
+
+ line.callState = LINECALLSTATE_CONNECTED;
+ line.lpfnCompletion (dwRequestID, 0);
+ line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLSTATE,
+ LINECALLSTATE_CONNECTED, 0, 0);
+ }
+ else
+ {
+ DebugMsg (("failed to write string"));
+ return GetCommError (line.hcd, NULL);
+ }
+#endif /* TESTING */
+
+ }
+ }
+ else // must be linedrop
+ {
+ if (line.hcd < 0)
+ DebugMsg (("idle"));
+ else
+ {
+#ifndef TESTING
+ wait = GetTickCount();
+ WriteComm (line.hcd, "\r", 1);
+ while (GetTickCount() - wait < 250);
+
+ if (WriteComm (line.hcd, "ATH8\r", 6) > 0)
+ DebugMsg (("Sent: %s", str));
+ else
+ DebugMsg (("failed to hang up"));
+
+ wait = GetTickCount();
+ while (GetTickCount() - wait < 250);
+
+ EscapeCommFunction (line.hcd, CLRDTR); // drop DTR
+
+ if (CloseComm (line.hcd))
+ DebugMsg (("Couldn't close the serial port"));
+#endif /* TESTING */
+ line.hcd = -1;
+ line.callState = LINECALLSTATE_IDLE;
+ line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLSTATE,
+ LINECALLSTATE_IDLE, 0, 0);
+ }
+
+ if (dwRequestID)
+ line.lpfnCompletion (dwRequestID, 0);
+ }
+
+ return dwRequestID;
+}
+
+
+LONG TSPIAPI TSPI_lineOpen (
+DWORD dwDeviceID,
+HTAPILINE htLine,
+LPHDRVLINE lphdLine,
+DWORD dwTSPIVersion,
+LINEEVENT lpfnEventProc)
+{
+ DebugMsg (("Entering TSPI_lineOpen"));
+
+ if (dwDeviceID != line.lineID)
+ return LINEERR_BADDEVICEID;
+
+ // Since we only support outgoing calls, we
+ // don't open the serial port until we need to make a call
+
+ line.lpfnEventProc = lpfnEventProc;
+ line.htLine = htLine;
+ *lphdLine = (HDRVLINE) &line;
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineSetAppSpecific (
+HDRVCALL hdCall,
+DWORD dwAppSpecific)
+{
+ DebugMsg (("Entering TSPI_lineSetAppSpecific"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+ line.dwAppSpecific = dwAppSpecific;
+
+ line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLINFO,
+ LINECALLINFOSTATE_APPSPECIFIC, 0, 0);
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineConditionalMediaDetection (
+HDRVLINE hdLine,
+DWORD dwMediaModes,
+LPLINECALLPARAMS const lpCallParams)
+{
+ DebugMsg (("Entering TSPI_lineConditionalMediaDetection"));
+
+ if (hdLine != (HDRVLINE) &line)
+ return LINEERR_INVALLINEHANDLE;
+
+ if (dwMediaModes != LINEMEDIAMODE_INTERACTIVEVOICE)
+ return LINEERR_INVALMEDIAMODE;
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineSetDefaultMediaDetection (
+HDRVLINE hdLine,
+DWORD dwMediaModes)
+{
+ DebugMsg (("Entering TSPI_lineSetDefaultMediaDetection"));
+
+ if (hdLine != (HDRVLINE) &line)
+ return LINEERR_INVALLINEHANDLE;
+
+ if (dwMediaModes && dwMediaModes != LINEMEDIAMODE_INTERACTIVEVOICE)
+ return LINEERR_INVALMEDIAMODE;
+
+ line.dwLineMediaModes = dwMediaModes;
+
+ return 0;
+}
+
+LONG TSPIAPI TSPI_lineSetMediaMode (
+HDRVCALL hdCall,
+DWORD dwMediaMode)
+{
+ DebugMsg (("Entering TSPI_lineSetMediaMode"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+ if (dwMediaMode != LINEMEDIAMODE_INTERACTIVEVOICE)
+ return LINEERR_INVALMEDIAMODE;
+
+ line.dwMediaMode = dwMediaMode;
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////
+// The configuration trio
+///////////////////////////////////////////////////////////
+
+// These routines are called from the control panel applet
+// TAPI may not be running at this point, so one cannot assume
+// we have been initialised
+
+LONG TSPIAPI TSPI_providerConfig (HWND hwnd, DWORD dwPermanentProviderId)
+{
+ DebugMsg (("Entering TSPI_providerConfig"));
+
+ if (!initialised)
+ LoadIniStrings (dwPermanentProviderId);
+ else if (dwPermanentProviderId != line.dwppID)
+ return LINEERR_NOMULTIPLEINSTANCE;
+
+#ifndef TESTING
+ DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc);
+#endif
+
+ return 0;
+}
+
+
+LONG TSPIAPI TSPI_providerInstall (HWND hwnd, DWORD dwPermanentProviderId)
+{
+ int res;
+ char szProvider[sizeof (s_providerx) + 5]; // room for 65535
+
+ DebugMsg (("Entering TSPI_providerInstall"));
+
+ if (!initialised)
+ LoadIniStrings (dwPermanentProviderId);
+ else if (dwPermanentProviderId != line.dwppID)
+ {
+ res = ID_MULTIPLE_INST;
+ goto error;
+ }
+
+ wsprintf (szProvider, s_providerx, (int) dwPermanentProviderId);
+
+ // we support 1 line and 0 phones
+
+ WritePrivateProfileString (szProvider, s_numlines, s_one, s_telephon_ini);
+ WritePrivateProfileString (szProvider, s_numphones, s_zero, s_telephon_ini);
+
+ // Flush the ini file cache.
+ WritePrivateProfileString (0, 0, 0, s_telephon_ini);
+
+#ifndef TESTING
+ // display the config screen
+ if (DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG),
+ hwnd, ConfigDlgProc) == 0)
+ return 0;
+ else
+ return LINEERR_OPERATIONFAILED;
+
+#else
+ return 0;
+#endif
+
+error:
+ {
+ char szerr[255];
+ char title[255];
+
+ LoadString (hInst, res, szerr, sizeof (szerr));
+ LoadString (hInst, ID_ATSP_ERROR, title, sizeof (title));
+
+ MessageBox (hwnd, szerr, title, MB_APPLMODAL | MB_ICONEXCLAMATION);
+
+ return LINEERR_OPERATIONFAILED;
+ }
+}
+
+
+LONG TSPIAPI TSPI_providerRemove (HWND hwnd, DWORD dwPermanentProviderId)
+{
+ DebugMsg (("Entering TSPI_providerRemove"));
+
+ // The control panel removes all of our junk for us
+ // (and then some) when the provider is removed.
+
+ return 0;
+}
+
+
+
+///////////////////////////////////////////////////////////
+// Internal support routines
+///////////////////////////////////////////////////////////
+
+
+void LoadIniStrings (DWORD ppID)
+{
+ char section[sizeof (s_providerx) + 5]; // room for 65535
+
+ wsprintf (section, s_providerx, (int) ppID);
+ line.dwppID = ppID;
+#ifdef TESTING
+ lstrcpy(line.port, "COM1");
+ lstrcpy(line.linename, "Testing SP");
+ lstrcpy(line.lineaddr, "");
+#else
+ // user preferences come from the telephon.ini file
+
+ GetPrivateProfileString (section, s_port, "COM1", line.port,
+ sizeof (line.port), s_telephon_ini);
+ GetPrivateProfileString (section, s_linename, "", line.linename,
+ sizeof (line.linename), s_telephon_ini);
+ GetPrivateProfileString (section, s_lineaddr, "", line.lineaddr,
+ sizeof (line.lineaddr), s_telephon_ini);
+#endif /* TESTING */
+
+ // the provider info string comes from the resource file
+
+ gszProviderInfo[0] = 0; // in case loadstring fails
+
+ LoadString (hInst, ID_PROVIDER_INFO, gszProviderInfo, sizeof (gszProviderInfo));
+
+ return;
+}
+
+
+BOOL CALLBACK
+ConfigDlgProc (HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+ int CurrSel;
+
+ switch (uiMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ for (CurrSel = 0; CurrSel < NUMPORTS; CurrSel++)
+ {
+ // List the port in the combo box.
+ SendDlgItemMessage (hDlg, ID_PORT, CB_ADDSTRING,
+ 0, (LPARAM) ((LPSTR) lpszCommDevArray[CurrSel]));
+ }
+
+ CurrSel = (int) SendDlgItemMessage (hDlg, ID_PORT, CB_FINDSTRING,
+ 0, (LPARAM) (LPSTR) line.port);
+ SendDlgItemMessage (hDlg, ID_PORT, CB_SETCURSEL, CurrSel, 0);
+
+ SendDlgItemMessage (hDlg, ID_LINENAME, WM_SETTEXT, 0,
+ (LPARAM) (LPSTR) line.linename);
+ SendDlgItemMessage (hDlg, ID_LINEADDR, WM_SETTEXT, 0,
+ (LPARAM) (LPSTR) line.lineaddr);
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (wParam)
+ {
+ case IDOK:
+ {
+ char szp[sizeof (s_providerx) + 5]; // room for 65535
+ wsprintf (szp, s_providerx, (int) line.dwppID);
+
+ // Port
+
+ CurrSel = (int) SendDlgItemMessage (hDlg, ID_PORT,
+ CB_GETCURSEL, 0, 0);
+ SendDlgItemMessage (hDlg, ID_PORT, CB_GETLBTEXT, CurrSel,
+ (LPARAM) (LPSTR) line.port);
+ WritePrivateProfileString (szp, s_port, line.port, s_telephon_ini);
+
+ // Line Name
+
+ SendDlgItemMessage (hDlg, ID_LINENAME, WM_GETTEXT,
+ sizeof (line.linename), (LPARAM) (LPSTR) line.linename);
+ WritePrivateProfileString (szp, s_linename, line.linename,
+ s_telephon_ini);
+
+ // Line Address
+
+ SendDlgItemMessage (hDlg, ID_LINEADDR, WM_GETTEXT,
+ sizeof (line.lineaddr), (LPARAM) (LPSTR) line.lineaddr);
+ WritePrivateProfileString (szp, s_lineaddr, line.lineaddr,
+ s_telephon_ini);
+
+ // Flush the ini file cache
+
+ WritePrivateProfileString (0, 0, 0, s_telephon_ini);
+ EndDialog (hDlg, 0);
+ }
+ break;
+
+ case IDCANCEL:
+ EndDialog (hDlg, -1);
+ break;
+ }
+ }
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+#ifdef DEBUG
+void CDECL SPTrace(LPCSTR pszFormat, ...)
+{
+ static char szBuffer[512];
+ static char fmtBuffer[1024];
+ static char szModuleBuffer[_MAX_PATH];
+ static char szTemp[_MAX_PATH];
+ static char szFName[_MAX_FNAME];
+ const char* pszLocalFormat;
+
+ int nBuf, count, localCount;
+ va_list args;
+
+ pszLocalFormat = pszFormat;
+
+ va_start (args, pszFormat);
+
+ nBuf = wvsprintf (szBuffer, pszLocalFormat, args);
+
+ // Convert formatting to readable format.
+ for (count = 0, localCount = 0; count < nBuf; count++, localCount++)
+ {
+ if (szBuffer[count] == '\r')
+ {
+ fmtBuffer[localCount++] = '\\';
+ fmtBuffer[localCount] = 'r';
+ }
+ else if (szBuffer[count] == '\n')
+ {
+ fmtBuffer[localCount++] = '\\';
+ fmtBuffer[localCount] = 'n';
+ }
+ else
+ fmtBuffer[localCount] = szBuffer[count];
+ }
+
+ fmtBuffer[localCount] = '\0';
+
+ GetModuleFileName (hInst, szModuleBuffer, sizeof (szModuleBuffer));
+ _splitpath (szModuleBuffer, szTemp, szTemp, szFName, szTemp);
+ wsprintf (szBuffer, "%s: %s\n\r", (LPSTR) szFName, (LPSTR) fmtBuffer);
+
+ OutputDebugString (szBuffer);
+}
+#endif
+
+
+
+UINT myatoi (LPSTR speed)
+{
+ UINT i;
+
+ for (i = 0; *speed; speed++)
+ i = i * 10 + (*speed - '0');
+
+ return i;
+}
+
+#define TXQUEUE 512
+#define RXQUEUE 512
+
+int SerialOpenComms (LPSTR port, LPSTR speed)
+{
+
+
+#if 0
+BJM-09/06/95
+BJM-09/06/95
+BJM-09/06/95
+ int hcd = OpenComm (port, RXQUEUE, TXQUEUE);
+
+ if (hcd >= 0)
+ {
+ DCB dcb;
+
+ if (GetCommState (hcd, &dcb) == 0)
+ {
+ ZeroMemory (&dcb.BaudRate, sizeof (DCB) - sizeof (dcb.Id));
+
+ dcb.BaudRate = myatoi (speed);
+ dcb.ByteSize = 8;
+ dcb.fBinary = TRUE;
+// dcb.fChEvt = TRUE;
+ dcb.XonChar = 17;
+ dcb.XoffChar = 19;
+// dcb.EvtChar = '\n';
+
+ if (SetCommState (&dcb) == 0)
+ {
+ DebugMsg (("Opened: %s:%s", port, speed));
+ return hcd;
+ }
+ }
+
+ CloseComm (hcd);
+ }
+
+ DebugMsg (("***Comm port failed to open"));
+ return -1;
+BJM-09/06/95
+BJM-09/06/95
+#endif
+}
+
+
+#ifdef TESTING
+//
+// report last dialable address sent in to SP
+//
+
+static char gszLastDestAddress[256];
+static BOOL gbLastAddressValid = 0;
+
+void FAR PASCAL LogDestAddress(LPCSTR szDestAddress)
+{
+ if (gbLastAddressValid == 0)
+ {
+ strncpy(gszLastDestAddress, szDestAddress, sizeof(gszLastDestAddress)-1);
+ gszLastDestAddress[sizeof(gszLastDestAddress)-1] = 0;
+ gbLastAddressValid = 1;
+ }
+}
+
+void FAR PASCAL GetLastDestAddress (LPSTR szLastAddrBuffer, int cb)
+{
+ if ((szLastAddrBuffer != NULL) && (cb > 0))
+ {
+ strncpy(szLastAddrBuffer, gszLastDestAddress, cb-1);
+ szLastAddrBuffer[cb-1] = 0;
+ gbLastAddressValid = 0;
+ }
+}
+
+void FAR PASCAL ClearLastDestAddressBuffer()
+{
+ gbLastAddressValid = 0;
+ gszLastDestAddress[0] = 0;
+}
+#endif /* TESTING */
diff --git a/private/tapi/dev/sp/hmtsp/hmtsp.def b/private/tapi/dev/sp/hmtsp/hmtsp.def
new file mode 100644
index 000000000..b77e8f8ad
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/hmtsp.def
@@ -0,0 +1,36 @@
+LIBRARY HMTSP32
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE
+
+SEGMENTS
+ "_TEXT" PRELOAD
+
+EXPORTS
+ WEP
+
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerConfig @590
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_providerInit @591
+ TSPI_providerShutdown @594
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineConditionalMediaDetection @508
+ TSPI_lineConfigDialog @509
+ TSPI_lineDrop @513
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineMakeCall @532
+ TSPI_lineOpen @538
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetMediaMode @552
diff --git a/private/tapi/dev/sp/hmtsp/hmtsp.h b/private/tapi/dev/sp/hmtsp/hmtsp.h
new file mode 100644
index 000000000..94874e0f0
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/hmtsp.h
@@ -0,0 +1,50 @@
+#include <windows.h>
+#include "TSPI.H"
+#include "hmtsprc.h"
+
+#define ATSP_VERSION 0x00010004
+
+#define SMALLBUFFER 40
+
+typedef struct lineInfo
+{
+ // We have only a single call on a single address on a single line
+ // This structure is constructed in TSPI_Initialize
+
+ LINEEVENT lpfnEventProc; // TAPI event callback function
+ ASYNC_COMPLETION lpfnCompletion; // TAPI Completion callback
+
+ DWORD lineID; // the tapi ID of our line
+ DWORD dwLineMediaModes;
+ DWORD dwppID; // Our permanent provider ID
+ HTAPILINE htLine; // TAPI opaque line handle
+ HTAPICALL htCall; // TAPI opaque call handle
+
+ DWORD callState; // The state of this call
+// DWORD dwRequestID; // for async requests
+ DWORD dwMediaMode;
+ DWORD dwAppSpecific;
+
+ int hcd; // the associated COM device
+ char port[SMALLBUFFER]; // "COM1"
+ char linename[SMALLBUFFER]; // "My Phone"
+ char lineaddr[SMALLBUFFER]; // "555-1212"
+
+ char DestAddress[TAPIMAXDESTADDRESSSIZE];
+
+} ATSPLineData;
+
+
+// Debug Message Macro
+
+#ifdef DEBUG
+#include <stdarg.h>
+#include <stdio.h>
+void CDECL SPTrace(LPCSTR pszFormat, ...);
+#define DebugMsg(_x_) SPTrace _x_
+#else
+#define DebugMsg(_x_)
+#endif
+
+
+
diff --git a/private/tapi/dev/sp/hmtsp/hmtsp.rc b/private/tapi/dev/sp/hmtsp/hmtsp.rc
new file mode 100644
index 000000000..860df28b4
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/hmtsp.rc
@@ -0,0 +1,47 @@
+#include <windows.h>
+#include "hmtsprc.h"
+
+IDD_CFGDLG DIALOG DISCARDABLE 20, 15, 177, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "PDI Configuration"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "&Communications Port",ID_STATIC,9,7,70,9,NOT WS_GROUP
+ COMBOBOX ID_PORT,9,18,90,52,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "&Line Name",ID_STATIC,8,36,100,8
+ EDITTEXT ID_LINENAME,9,46,90,12,ES_AUTOHSCROLL
+ LTEXT "Phone &Number",ID_STATIC,8,64,94,9
+ EDITTEXT ID_LINEADDR,9,73,90,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,111,16,56,14
+ PUSHBUTTON "Cancel",IDCANCEL,111,36,56,14
+END
+
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_PROVIDER_INFO "Microsoft Internal Use Happy Modem Testing Service Provider"
+ ID_MULTIPLE_INST "The selected service provider is already installed in the system and cannot support multiple instances."
+ ID_ATSP_ERROR "Happy Modem Testing Service Provider Error"
+END
+
+
+/* Version Numbering stuff */
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#define VER_FILEDESCRIPTION_STR "Happy Modem Testing SP (HMSP)"
+#define VER_INTERNALNAME_STR "hmtsp"
+#define VER_ORIGINALFILENAME_STR "HMTSP.TSP"
+#define VER_TYPE VFT_DLL
+#define DLL
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/hmtsp/hmtsprc.h b/private/tapi/dev/sp/hmtsp/hmtsprc.h
new file mode 100644
index 000000000..888328e6f
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/hmtsprc.h
@@ -0,0 +1,18 @@
+// dialog IDs
+
+#define ID_PROVIDER_INFO 2
+#define ID_MULTIPLE_INST 3
+#define ID_NO_DRIVER 4
+#define ID_ATSP_ERROR 5
+
+#define IDI_MODEM 10
+
+#define IDD_CFGDLG 101
+
+#define ID_PORT 1000
+#define ID_LINENAME 1002
+#define ID_LINEADDR 1003
+
+#define ID_STATIC -1
+
+
diff --git a/private/tapi/dev/sp/hmtsp/makefile b/private/tapi/dev/sp/hmtsp/makefile
new file mode 100644
index 000000000..9f6b20824
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# telephon.cpl Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/hmtsp/makefile.def b/private/tapi/dev/sp/hmtsp/makefile.def
new file mode 100644
index 000000000..01eb7c309
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/makefile.def
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# HMTSP Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..\..
+
+
+WANT_C932=1
+IS_32 = TRUE
+WIN32=1
+IS_OEM = TRUE
+
+DEFENTRY=main
+
+BUILDDLL=1
+DLLENTRY=DllMain
+
+DEPENDNAME=..\depend.mk
+
+DRVNAME=hmtsp32
+TARGETS=hmtsp32.TSP
+
+CLEANLIST=*.tsp
+
+SRCDIR=..
+
+L32EXE=hmtsp32.tsp # Name of exe.
+L32DEF=..\hmtsp.def # Our def file.
+#L32MAP=hmtsp.map # Our map file.
+L32LIBS=$(W32LIBID)\kernel32.lib \
+ $(W32LIBID)\user32.lib \
+ $(W32LIBID)\comctl32.lib \
+ $(W32LIBID)\advapi32.lib \
+ $(ROOT)\dev\tools\c932\lib\msvcrt.lib
+# $(ROOT)\dev\tools\c932\lib\rpcndr.lib \
+# $(ROOT)\dev\tools\c932\lib\rpcrt4.lib
+# $(ROOT)\dev\tools\c932\lib\msvcrt.lib
+# $(ROOT)\dev\tools\c932\lib\oldnames.lib \
+
+L32RES=hmtsp.res # Resource file.
+
+
+#-----------------------------------------------------------------------
+# Object files
+#-----------------------------------------------------------------------
+L32OBJS = hmtsp.obj
+
+
+L32FLAGS=$(L32FLAGS) /PDB:hmtsp.pdb
+
+
+!include $(ROOT)\dev\master.mk
+
+
+CFLAGS=$(CFLAGS) -DWIN32=100 -DWIN_32=100
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
+
diff --git a/private/tapi/dev/sp/hmtsp/makefile.old b/private/tapi/dev/sp/hmtsp/makefile.old
new file mode 100644
index 000000000..8baebcc3e
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/makefile.old
@@ -0,0 +1,96 @@
+# Project makefile for ATSP chicago build from
+# unified code base.
+
+# release build makefile for chicago release
+
+!ifndef TAPIROOT
+TAPIROOT=\telephon\tapi
+!endif
+
+!ifndef TARGETDIR
+TARGETDIR =$(TAPIROOT)
+!endif
+
+!ifdef CHICAGO
+CC = cl
+RC = $(TAPIROOT)\bin\rc.exe
+MAKE = nmake
+FLAGS = $(FLAGS) /DCHICAGO
+TINC = /I $(TAPIROOT)\inc /I $(TAPIROOT)\chicoinc
+!else
+CC = cl
+RC = rc
+MAKE = nmake
+TINC = /I $(TAPIROOT)\inc
+!endif
+
+
+!ifdef DEBUG
+FLAGS = $(FLAGS) /DDEBUG
+!ifdef DIAGNOSTIC
+FLAGS = $(FLAGS) /DDIAGNOSTIC
+!endif
+!ifdef MSDEBUG
+FLAGS = $(FLAGS) /DMSDEBUG
+!endif
+CFLAGS = /nologo /G2 /W3 /Zi /ALw /Od $(FLAGS) /FR /GD $(TINC)
+APPCFLAGS = /nologo /G2 /W3 /Zi /Zp1 /AL /Od $(FLAGS) /GA $(TINC)
+LFLAGS = /nologo /ONERROR:NOEXE /NOD /CO /NOE /ALIGN:4 /MAP:FULL
+RESFLAGS = /K $(TINC) $(FLAGS)
+!else
+FLAGS = $(FLAGS) /DNDEBUG
+CFLAGS = /nologo /G3 /W3 /Zp1 /ALw /O1 /Ox $(FLAGS) /GD $(TINC)
+APPCFLAGS = /nologo /G3 /W3 /Zp1 /AL /O1 /Ox $(FLAGS) /GA $(TINC)
+LFLAGS = /nologo /ONERROR:NOEXE /NOD /NOE /ALIGN:4 /NONULLS /PACKD /PACKF /MAP:FULL
+RESFLAGS = /K $(TINC)
+!endif
+
+!ifdef CHICAGO
+RESFLAGS= $(RESFLAGS) /DCHICAGO
+!endif
+
+LIBS = libw ldllcew toolhelp ver commdlg
+APPLIBS = libw llibcew $(TARGETDIR)\tapi
+
+
+all: clean release
+
+clean:
+ del *.obj
+ del *.dll
+ del *.map
+ del *.sym
+ del *.cpl
+ del *.res
+ del *.exe
+ del *.lib
+ del *.sbr
+ del *.bsc
+ del *.hlp
+ del *.tsp
+ del *.asm
+ del *.pdb
+ del *.aps
+
+
+release: hmtsp.tsp
+
+
+hmtsp.tsp:: $(@B).obj $(@B).def $(@B).rc
+ echo >NUL @<<$(@B).CRF
+$(@B).obj
+$@
+$(@B).map
+c:\msvc\lib\+
+$(LIBS)
+$(@B).def;
+<<
+ link $(LFLAGS) /NOPACKC @$(@B).CRF
+ $(RC) /D$(MYFLAGS) $(RESFLAGS) $(@B).rc $@
+ implib /nologo /nowep $(@B).LIB $@
+ mapsym $(@B)
+ copy $(@B).tsp $(TARGETDIR)
+ copy $(@B).sym $(TARGETDIR)
+
+
+ \ No newline at end of file
diff --git a/private/tapi/dev/sp/hmtsp/sources b/private/tapi/dev/sp/hmtsp/sources
new file mode 100644
index 000000000..1266682a0
--- /dev/null
+++ b/private/tapi/dev/sp/hmtsp/sources
@@ -0,0 +1,58 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=hmtsp32
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=tsp
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib
+
+C_DEFINES=-DTAPI_NT=1
+
+DLLBASE=0x60000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+DLLDEF=hmtsp.def
+
+USE_CRTDLL=1
+
+SOURCES=hmtsp.c \
+ hmtsp.rc
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/kmddsp/kmddsp.c b/private/tapi/dev/sp/kmddsp/kmddsp.c
new file mode 100644
index 000000000..9eb6d688c
--- /dev/null
+++ b/private/tapi/dev/sp/kmddsp/kmddsp.c
@@ -0,0 +1,4792 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ kmddsp.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 11-Apr-1995
+
+Revision History:
+
+
+
+Notes:
+
+ 1. NdisTapi.sys needs to be modified to support IOCTL_DISCONNECT so we
+ don't have to close all the driver handles etc each time we get a
+ providerShutdown request (ideally we ought only have to close handles,
+ etc on a dll process detach).
+
+ 2. There's the hack in TSPI_providerInit where tapisrv has to pass in
+ pointer to dwNumLines & dwNumPhones, becuase we determine the # of
+ devs when we send the CONNECT IOCTL
+
+ 3. Ndistapi.h is not in sync w/ tapi.h & tspi.h, so make sure to use
+ the definitions in ndistapi.h as appropriate (like LINE_DEV_CAPS
+ instead of LINEDEVCAPS).
+
+ 4. A slight perf gain might be realized by caching dev caps info for
+ each line (but can/will it chg on the fly?)
+
+ 5. To keep bad 2.0 apps from blowing up if they try to look at version
+ 1.4 or 2.0 structure fields we pad the area between the end of the
+ 1.0 structure and the variable-length data with 0's. This is done
+ in GetAddrCaps, GetCallInfo, GetCallStatus, GetDevCaps, &
+ GetLineDevStatus.
+
+ 6. Since TAPI 2.0 service providers are required to be 100% unicode,
+ kmddsp munge all incoming unicode strings to ascii before passing
+ them to an underlying driver, and also converts all returned ascii
+ strings (embedded in structures) to unicode.
+
+--*/
+
+
+#include "windows.h"
+#include "winioctl.h"
+#include "stdarg.h"
+#include "stdio.h"
+#define ULONGLONG DWORDLONG
+#include "ntddndis.h"
+#include "ndistapi.h"
+#include "intrface.h"
+
+//
+// Note: the following are defined in both ndistapi.h & tapi.h (or tspi.h)
+// and cause (more or less non-interesting) build warnings, so we
+// undefine them after the first #include to do away with this
+//
+
+#undef LAST_LINEMEDIAMODE
+#undef TSPI_MESSAGE_BASE
+#undef LINE_NEWCALL
+#undef LINE_CALLDEVSPECIFIC
+
+#include "tapi.h"
+#include "tspi.h"
+#include "kmddsp.h"
+
+
+#define MYHACK
+
+
+void
+AsyncEventsThread(
+ LPVOID lpParams
+ );
+
+LONG
+WINAPI
+TranslateDriverResult(
+ ULONG ulResult
+ );
+
+//BOOL
+//WINAPI
+//_CRT_INIT(
+// HINSTANCE hDLL,
+// DWORD dwReason,
+// LPVOID lpReserved
+// );
+
+#if DBG
+
+#define DBGOUT(arg) DbgPrt arg
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+DWORD gdwDebugLevel;
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
+LPVOID
+WINAPI
+DrvAlloc(
+ DWORD dwSize
+ );
+
+VOID
+WINAPI
+DrvFree(
+ LPVOID lp
+ );
+
+void
+WINAPI
+ProcessEvent(
+ PNDIS_TAPI_EVENT pEvent
+ );
+
+LONG
+WINAPI
+PrepareSyncRequest(
+ ULONG Oid,
+ LPDWORD lphWidget,
+ DWORD dwWidgetType,
+ PNDISTAPI_REQUEST *ppNdisTapiRequest,
+ DWORD dwDataSize
+ );
+
+LONG
+WINAPI
+PrepareAsyncRequest(
+ ULONG Oid,
+ LPDWORD lphWidget,
+ DWORD dwWidgetType,
+ DWORD dwRequestID,
+ PASYNC_REQUEST_WRAPPER *ppAsyncRequestWrapper,
+ DWORD dwDataSize
+ );
+
+LONG
+WINAPI
+SyncDriverRequest(
+ DWORD dwIoControlCode,
+ PNDISTAPI_REQUEST pNdisTapiRequest
+ );
+
+LONG
+WINAPI
+AsyncDriverRequest(
+ DWORD dwIoControlCode,
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper
+ );
+
+
+//
+// Global vars
+//
+
+DWORD gdwTlsIndex, gdwRequestID;
+HANDLE ghDriverSync, ghDriverAsync, ghCompletionPort;
+LINEEVENT gpfnLineEvent;
+ASYNC_COMPLETION gpfnCompletionProc;
+PASYNC_EVENTS_THREAD_INFO gpAsyncEventsThreadInfo;
+CRITICAL_SECTION gInboundCallsCritSec, gRequestIDCritSec;
+
+
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+
+#if DBG
+
+ {
+ HKEY hKey;
+ DWORD dwDataSize, dwDataType;
+ TCHAR szTelephonyKey[] =
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony",
+ szKmddspDebugLevel[] = "KmddspDebugLevel";
+
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ szTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof (DWORD);
+ gdwDebugLevel=0;
+
+ RegQueryValueEx(
+ hKey,
+ szKmddspDebugLevel,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwDebugLevel,
+ &dwDataSize
+ );
+
+ RegCloseKey (hKey);
+ }
+
+#endif
+
+// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+// {
+// return FALSE;
+// }
+
+ DBGOUT((4, "DLL_PROCESS_ATTACH"));
+
+
+ //
+ // Get a thread local storage entry
+ //
+
+ if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff)
+ {
+ DBGOUT((1, "TlsAlloc() failed"));
+
+ return FALSE;
+ }
+
+
+ //
+ // Init global sync objects
+ //
+
+ InitializeCriticalSection (&gInboundCallsCritSec);
+ InitializeCriticalSection (&gRequestIDCritSec);
+
+ break;
+ }
+ case DLL_PROCESS_DETACH:
+ {
+ //
+ // Free resources
+ //
+
+ PREQUEST_THREAD_INFO pRequestThreadInfo;
+
+
+ DBGOUT((4, "DLL_PROCESS_DETACH"));
+
+ if ((pRequestThreadInfo = TlsGetValue (gdwTlsIndex)))
+ {
+ DrvFree (pRequestThreadInfo->pBuf);
+ DrvFree (pRequestThreadInfo);
+ }
+
+ TlsFree (gdwTlsIndex);
+
+ DeleteCriticalSection (&gInboundCallsCritSec);
+ DeleteCriticalSection (&gRequestIDCritSec);
+
+// _CRT_INIT (hDLL, dwReason, lpReserved);
+
+ break;
+ }
+ case DLL_THREAD_ATTACH:
+ {
+ PREQUEST_THREAD_INFO pRequestThreadInfo;
+
+
+// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+// {
+// DBGOUT((1, "DLL_THREAD_ATTACH, _CRT_INIT failed"));
+// }
+
+ TlsSetValue (gdwTlsIndex, NULL);
+
+ break;
+ }
+ case DLL_THREAD_DETACH:
+ {
+ //
+ // Free resources
+ //
+
+ PREQUEST_THREAD_INFO pRequestThreadInfo;
+
+
+ if ((pRequestThreadInfo = TlsGetValue (gdwTlsIndex)))
+ {
+ DrvFree (pRequestThreadInfo->pBuf);
+ DrvFree (pRequestThreadInfo);
+ }
+
+// _CRT_INIT (hDLL, dwReason, lpReserved);
+
+ break;
+ }
+ } // switch
+
+ return TRUE;
+}
+
+
+#if DBG
+
+#define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e,f)
+
+void
+PASCAL
+InsertVarDataString(
+ LPVOID pStruct,
+ LPDWORD pdwXxxSize,
+ LPVOID pNewStruct,
+ LPDWORD pdwNewXxxSize,
+ DWORD dwFixedStructSize,
+ char *pszFieldName
+ )
+
+#else
+
+#define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e)
+
+void
+PASCAL
+InsertVarDataString(
+ LPVOID pStruct,
+ LPDWORD pdwXxxSize,
+ LPVOID pNewStruct,
+ LPDWORD pdwNewXxxSize,
+ DWORD dwFixedStructSize
+ )
+
+#endif
+{
+ DWORD dwXxxSize, dwTotalSize, dwXxxOffset;
+
+
+ //
+ // If the dwXxxSize field of the old struct is non-zero, then
+ // we need to do a ascii->unicode conversion on it. Check to
+ // make sure that the size/offset are valid (if not set the
+ // data size/offset in the new struct to 0) and then convert.
+ //
+
+ if ((dwXxxSize = *pdwXxxSize))
+ {
+ dwXxxOffset = *(pdwXxxSize + 1);
+
+//#if DBG
+ dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
+
+ if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
+ dwXxxOffset < dwFixedStructSize ||
+ dwXxxOffset >= dwTotalSize ||
+ (dwXxxSize + dwXxxOffset) > dwTotalSize)
+ {
+ DBGOUT((
+ 0,
+ "ERROR! bad %s values, size=x%x, offset=x%x",
+ pszFieldName,
+ dwXxxSize,
+ dwXxxOffset
+ ));
+
+ *pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
+ return;
+ }
+//#endif
+
+ MultiByteToWideChar(
+ CP_ACP,
+ MB_PRECOMPOSED,
+ ((LPBYTE) pStruct) + dwXxxOffset,
+ dwXxxSize,
+ (LPWSTR) (((LPBYTE) pNewStruct) +
+ ((LPVARSTRING) pNewStruct)->dwUsedSize),
+ dwXxxSize * sizeof (WCHAR)
+ );
+
+ *pdwNewXxxSize = dwXxxSize * sizeof (WCHAR);
+ *(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
+ ((LPVARSTRING) pNewStruct)->dwUsedSize += (dwXxxSize * sizeof (WCHAR));
+ }
+}
+
+
+#if DBG
+
+#define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e,f)
+
+void
+PASCAL
+InsertVarData(
+ LPVOID pStruct,
+ LPDWORD pdwXxxSize,
+ LPVOID pNewStruct,
+ LPDWORD pdwNewXxxSize,
+ DWORD dwFixedStructSize,
+ char *pszFieldName
+ )
+
+#else
+
+#define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e)
+
+void
+PASCAL
+InsertVarData(
+ LPVOID pStruct,
+ LPDWORD pdwXxxSize,
+ LPVOID pNewStruct,
+ LPDWORD pdwNewXxxSize,
+ DWORD dwFixedStructSize
+ )
+
+#endif
+{
+ DWORD dwTotalSize, dwXxxSize, dwXxxOffset;
+
+
+ if ((dwXxxSize = *pdwXxxSize))
+ {
+ dwXxxOffset = *(pdwXxxSize + 1);
+
+//#if DBG
+ dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
+
+ if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
+ dwXxxOffset < dwFixedStructSize ||
+ dwXxxOffset >= dwTotalSize ||
+ (dwXxxSize + dwXxxOffset) > dwTotalSize)
+ {
+ DBGOUT((
+ 0,
+ "ERROR! bad %s values, size=x%x, offset=x%x",
+ pszFieldName,
+ dwXxxSize,
+ dwXxxOffset
+ ));
+
+ *pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
+ return;
+ }
+//#endif
+ CopyMemory(
+ ((LPBYTE) pNewStruct) + ((LPVARSTRING) pNewStruct)->dwUsedSize,
+ ((LPBYTE) pStruct) + dwXxxOffset,
+ dwXxxSize
+ );
+
+ *pdwNewXxxSize = dwXxxSize;
+ *(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
+ ((LPVARSTRING) pNewStruct)->dwUsedSize += dwXxxSize;
+ }
+}
+
+
+//
+// TSPI_lineXxx funcs
+//
+
+LONG
+TSPIAPI
+TSPI_lineAccept(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_ACCEPT, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_ACCEPT) + dwSize // size of drv request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_ACCEPT pNdisTapiAccept =
+ (PNDIS_TAPI_ACCEPT) pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiAccept->hdCall = (HDRV_CALL) hdCall;
+
+ if ((pNdisTapiAccept->ulUserUserInfoSize = (ULONG) dwSize))
+ {
+ CopyMemory(
+ pNdisTapiAccept->UserUserInfo,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAnswer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_ANSWER, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_ANSWER) + dwSize // size of drv request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_ANSWER pNdisTapiAnswer =
+ (PNDIS_TAPI_ANSWER) pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiAnswer->hdCall = (HDRV_CALL) hdCall;
+
+ if ((pNdisTapiAnswer->ulUserUserInfoSize = (ULONG) dwSize))
+ {
+ CopyMemory(
+ pNdisTapiAnswer->UserUserInfo,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+{
+ LONG lResult;
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_CLOSE, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_CLOSE) // size of drve req data
+
+ )) == TAPI_SUCCESS)
+ {
+ //
+ // Note that this is a command rather than a request, in that
+ // TAPI considers the line closed regardless of the request result.
+ //
+
+ PNDIS_TAPI_CLOSE pNdisTapiClose =
+ (PNDIS_TAPI_CLOSE) pNdisTapiRequest->Data;
+
+
+ //
+ // Mark line as invalid so any related events that show up
+ // will be discarded
+ //
+
+ pLine->dwKey = INVALID_KEY;
+
+ pNdisTapiClose->hdLine = (HDRV_LINE) hdLine;
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+
+
+ //
+ // Clean up our pLine. Make sure to clean up any calls in the
+ // inbound list that may not have been explicitly closed
+ // (i.e. new calls that showed up after TAPI had already
+ // started closing down this line)
+ //
+
+ EnterCriticalSection (&gInboundCallsCritSec);
+
+ {
+ PDRVCALL pCall;
+
+
+ while ((pCall = pLine->pInboundCalls))
+ {
+ pLine->pInboundCalls = pCall->pNext;
+
+ DrvFree (pCall);
+ }
+ }
+
+ LeaveCriticalSection (&gInboundCallsCritSec);
+
+ DrvFree (pLine);
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+{
+ LONG lResult;
+ HDRVCALL hdCallDrop = hdCall;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_CLOSE_CALL, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof (NDIS_TAPI_CLOSE_CALL) // size of drve req data
+
+ )) == TAPI_SUCCESS)
+ {
+ //
+ // Note that this is a command rather than a request, in that
+ // TAPI considers the call closed regardless of the request
+ // result.
+ //
+
+ BOOL bInboundCall;
+ PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall;
+
+
+ //
+ // Safely determine if call is inbound or outbound, & if the
+ // latter then if necessary wait until the make call request
+ // has completed so we don't send a bad hdCall down to the
+ // driver with the close call request.
+ //
+ // We'll just return 0 if the call is bad or we AV (meaning
+ // a make call request failed & call struct was freed in post
+ // processing).
+ //
+
+ try
+ {
+ bInboundCall = (pCall->dwKey == INBOUND_CALL_KEY ? TRUE : FALSE);
+
+ if (bInboundCall == FALSE)
+ {
+ while (pCall->dwKey == OUTBOUND_CALL_KEY)
+ {
+ if (pCall->bIncomplete == FALSE)
+ {
+ hdCall = (HDRVCALL) pCall->hd_Call;
+ break;
+ }
+ else
+ {
+ Sleep (0);
+ }
+ }
+
+ if (pCall->dwKey != OUTBOUND_CALL_KEY)
+ {
+ return 0;
+ }
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ return 0;
+ }
+
+
+ //
+ // HACKHACK: the following is for legacy ndis wan isdn miniports
+ //
+ // Since there's no more "automatic" call dropping in TAPI when
+ // an app has closed the line & there are existing non-IDLE calls,
+ // and legacy NDIS WAN ISDN miniports rely on seeing an OID_TAPI_DROP,
+ // we need to synthesize this behavior if the call has not previously
+ // be dropped.
+ //
+ // Note: we do a sync rather than an async drop here
+ //
+
+ if (pCall->bDropped == FALSE)
+ {
+ HDRVCALL hdCallClose2 = hdCallDrop;
+ PNDISTAPI_REQUEST pNdisTapiRequestDrop;
+
+
+ if (PrepareSyncRequest(
+ OID_TAPI_DROP, // opcode
+ (LPDWORD) &hdCallDrop, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequestDrop, // ptr to ptr to request buffer
+ sizeof (NDIS_TAPI_DROP) // size of driver request data
+
+ ) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_DROP pNdisTapiDrop = (PNDIS_TAPI_DROP)
+ pNdisTapiRequestDrop->Data;
+
+
+ //
+ // Mark the call as bad so any events get discarded
+ //
+
+ pCall->dwKey = INVALID_KEY;
+
+ pNdisTapiDrop->hdCall = (HDRV_CALL) hdCallDrop;
+
+ SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequestDrop
+ );
+ }
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_CLOSE_CALL, // opcode
+ (LPDWORD) &hdCallClose2, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof (NDIS_TAPI_CLOSE_CALL) // size of drve req data
+
+ )) != TAPI_SUCCESS)
+ {
+ return lResult;
+ }
+ }
+
+
+ //
+ // Mark the call as bad so any events get discarded
+ //
+
+ pCall->dwKey = INVALID_KEY;
+
+
+ //
+ // Set up the params & call the driver
+ //
+
+ pNdisTapiCloseCall = (PNDIS_TAPI_CLOSE_CALL) pNdisTapiRequest->Data;
+
+ pNdisTapiCloseCall->hdCall = (HDRV_CALL) hdCall;
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+
+
+ //
+ // Clean up our drv call
+ //
+
+ if (bInboundCall)
+ {
+ PDRVLINE pLine = (PDRVLINE) pCall->pLine;
+
+
+ EnterCriticalSection (&gInboundCallsCritSec);
+
+ if (pCall->pNext)
+ {
+ pCall->pNext->pPrev = pCall->pPrev;
+ }
+
+ if (pCall->pPrev)
+ {
+ pCall->pPrev->pNext = pCall->pNext;
+ }
+ else
+ {
+ pLine->pInboundCalls = pCall->pNext;
+ }
+
+ LeaveCriticalSection (&gInboundCallsCritSec);
+ }
+
+ DrvFree (pCall);
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_CONDITIONAL_MEDIA_DETECTION, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to req buffer
+ // size of drv request data
+ sizeof(NDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) +
+ (lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS))
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION
+ pNdisTapiConditionalMediaDetection =
+ (PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) pNdisTapiRequest->Data;
+
+
+ pNdisTapiConditionalMediaDetection->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiConditionalMediaDetection->ulMediaModes = (ULONG)
+ dwMediaModes;
+
+ CopyMemory(
+ &pNdisTapiConditionalMediaDetection->LineCallParams,
+ lpCallParams,
+ lpCallParams->dwTotalSize
+ );
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+PASCAL
+TSPI_lineDevSpecific_postProcess(
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper,
+ LONG lResult,
+ LPDWORD callStateMsgParams
+ )
+{
+ if (lResult == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific =(PNDIS_TAPI_DEV_SPECIFIC)
+ pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ CopyMemory(
+ (LPVOID) pAsyncRequestWrapper->dwRequestSpecific,
+ pNdisTapiDevSpecific->Params,
+ pNdisTapiDevSpecific->ulParamsSize
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ //
+ // Init the request
+ //
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_DEV_SPECIFIC, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_DEV_SPECIFIC)+ // size of drv request data
+ (dwSize - 1)
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific =(PNDIS_TAPI_DEV_SPECIFIC)
+ pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiDevSpecific->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiDevSpecific->ulAddressID = (ULONG) dwAddressID;
+
+ if (hdCall)
+ {
+ LONG lResult = 0;
+
+
+ try
+ {
+ pNdisTapiDevSpecific->hdCall = ((PDRVCALL)(hdCall))->hd_Call;
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ if (lResult)
+ {
+ DrvFree (pAsyncRequestWrapper);
+ return lResult;
+ }
+ }
+ else
+ {
+ pNdisTapiDevSpecific->hdCall = (HDRV_CALL) NULL;
+ }
+
+ pNdisTapiDevSpecific->ulParamsSize = (ULONG) dwSize;
+
+ CopyMemory (pNdisTapiDevSpecific->Params, lpParams, dwSize);
+
+ pAsyncRequestWrapper->dwRequestSpecific = (DWORD) lpParams;
+ pAsyncRequestWrapper->pfnPostProcess =
+ TSPI_lineDevSpecific_postProcess;
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDial(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ LONG lResult;
+ DWORD dwLength = lstrlenW (lpszDestAddress) + 1;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_DIAL, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_DIAL) + dwLength // size of driver request data
+
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_DIAL pNdisTapiDial =
+ (PNDIS_TAPI_DIAL) pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiDial->hdCall = (HDRV_CALL) hdCall;
+ pNdisTapiDial->ulDestAddressSize = (ULONG) dwLength;
+
+
+ //
+ // Note: old miniports expect strings to be ascii
+ //
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDestAddress,
+ -1,
+ (LPSTR) pNdisTapiDial->szDestAddress,
+ dwLength,
+ NULL,
+ NULL
+ );
+
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+PASCAL
+TSPI_lineDrop_postProcess(
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper,
+ LONG lResult,
+ LPDWORD callStateMsgParams
+ )
+{
+ PDRVCALL pCall = (PDRVCALL) pAsyncRequestWrapper->dwRequestSpecific;
+ HTAPICALL htCall;
+ HTAPILINE htLine;
+
+
+ //
+ // HACK ALERT!!!
+ //
+ // Some old-style miniports, notably pcimac, don't indicate IDLE msgs
+ // when they get a drop request- so we synthesize this for them.
+ //
+
+ if (lResult == TAPI_SUCCESS)
+ {
+ try
+ {
+ htCall = pCall->htCall;
+ htLine = ((PDRVLINE) pCall->pLine)->htLine;
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ return lResult;
+ }
+
+ (*gpfnLineEvent)(
+ htLine,
+ htCall,
+ LINE_CALLSTATE,
+ LINECALLSTATE_IDLE,
+ 0,
+ 0
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ PDRVCALL pCall = (PDRVCALL) hdCall;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_DROP, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_DROP) + dwSize // size of driver request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_DROP pNdisTapiDrop =
+ (PNDIS_TAPI_DROP) pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ //
+ // HACKHACK: the following is for legacy ndis wan isdn miniports
+ //
+ // Safely mark the call as dropped so the CloseCall code won't follow
+ // up with another "automatic" drop
+ //
+
+ try
+ {
+ pCall->bDropped = TRUE;
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ if (lResult == 0)
+ {
+ pNdisTapiDrop->hdCall = (HDRV_CALL) hdCall;
+
+ if ((pNdisTapiDrop->ulUserUserInfoSize = (ULONG) dwSize))
+ {
+ CopyMemory(
+ pNdisTapiDrop->UserUserInfo,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+ pAsyncRequestWrapper->dwRequestSpecific = (DWORD) pCall;
+ pAsyncRequestWrapper->pfnPostProcess = TSPI_lineDrop_postProcess;
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+ else
+ {
+ DrvFree (pAsyncRequestWrapper);
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_ADDRESS_CAPS, // opcode
+ &dwDeviceID, // target handle
+ HT_DEVICEID, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_ADDRESS_CAPS) + // size of drv request data
+ (lpAddressCaps->dwTotalSize - sizeof(LINE_ADDRESS_CAPS))
+
+ )) == TAPI_SUCCESS)
+ {
+ PLINE_ADDRESS_CAPS pCaps;
+ PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps =
+ (PNDIS_TAPI_GET_ADDRESS_CAPS) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetAddressCaps->ulDeviceID = (ULONG) dwDeviceID;
+ pNdisTapiGetAddressCaps->ulAddressID = (ULONG) dwAddressID;
+ pNdisTapiGetAddressCaps->ulExtVersion = (ULONG) dwExtVersion;
+
+ pCaps = &pNdisTapiGetAddressCaps->LineAddressCaps;
+
+ pCaps->ulTotalSize = lpAddressCaps->dwTotalSize;
+ pCaps->ulNeededSize =
+ pCaps->ulUsedSize = sizeof (LINE_ADDRESS_CAPS);
+
+ ZeroMemory(
+ &pCaps->ulLineDeviceID,
+ sizeof (LINE_ADDRESS_CAPS) - 3 * sizeof (ULONG)
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ //
+ // Do some post processing to the returned data structure
+ // before passing it back to tapi:
+ // 1. Pad the area between the fixed 1.0 structure and the
+ // var data that the miniports pass back with 0's so a
+ // bad app that disregards the 1.0 version negotiation &
+ // references new 1.4 or 2.0 structure fields won't blow up
+ // 2. Convert ascii strings to unicode, & rebase all var data
+ //
+
+ //
+ // The real needed size is the sum of that requested by the
+ // underlying driver, plus padding for the new TAPI 1.4/2.0
+ // structure fields, plus the size of the var data returned
+ // by the driver to account for the ascii->unicode conversion.
+ // (Granted, we are very liberal in computing the value for
+ // this last part, but at least this way it's fast & we'll
+ // never have too little buffer space.
+ //
+
+ lpAddressCaps->dwNeededSize =
+ pCaps->ulNeededSize +
+ (sizeof (LINEADDRESSCAPS) - // v2.0 struct
+ sizeof (LINE_ADDRESS_CAPS)) + // v1.0 struct
+ (pCaps->ulNeededSize - sizeof (LINE_ADDRESS_CAPS));
+
+
+ //
+ // Copy over the fixed fields that don't need changing, i.e.
+ // everything from dwAddressSharing to dwCallCompletionModes
+ //
+
+ lpAddressCaps->dwLineDeviceID = dwDeviceID;
+
+ CopyMemory(
+ &lpAddressCaps->dwAddressSharing,
+ &pCaps->ulAddressSharing,
+ sizeof (LINE_ADDRESS_CAPS) - (12 * sizeof (DWORD))
+ );
+
+ if (lpAddressCaps->dwNeededSize > lpAddressCaps->dwTotalSize)
+ {
+ lpAddressCaps->dwUsedSize =
+ (lpAddressCaps->dwTotalSize < sizeof (LINEADDRESSCAPS) ?
+ lpAddressCaps->dwTotalSize : sizeof (LINEADDRESSCAPS));
+ }
+ else
+ {
+ lpAddressCaps->dwUsedSize = sizeof (LINEADDRESSCAPS);
+ // v2.0 struct
+ INSERTVARDATASTRING(
+ pCaps,
+ &pCaps->ulAddressSize,
+ lpAddressCaps,
+ &lpAddressCaps->dwAddressSize,
+ sizeof (LINE_ADDRESS_CAPS),
+ "LINE_ADDRESS_CAPS.Address"
+ );
+
+ INSERTVARDATA(
+ pCaps,
+ &pCaps->ulDevSpecificSize,
+ lpAddressCaps,
+ &lpAddressCaps->dwDevSpecificSize,
+ sizeof (LINE_ADDRESS_CAPS),
+ "LINE_ADDRESS_CAPS.DevSpecific"
+ );
+
+ if (pCaps->ulCompletionMsgTextSize != 0)
+ {
+// BUGBUG TSPI_lineGetAddressCaps: convert ComplMsgText to unicode???
+
+ INSERTVARDATA(
+ pCaps,
+ &pCaps->ulCompletionMsgTextSize,
+ lpAddressCaps,
+ &lpAddressCaps->dwCompletionMsgTextSize,
+ sizeof (LINE_ADDRESS_CAPS),
+ "LINE_ADDRESS_CAPS.CompletionMsgText"
+ );
+
+ lpAddressCaps->dwNumCompletionMessages =
+ pCaps->ulNumCompletionMessages;
+ lpAddressCaps->dwCompletionMsgTextEntrySize =
+ pCaps->ulCompletionMsgTextEntrySize;
+ }
+ }
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCWSTR lpsAddress,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+// BUGBUG unicode
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_ADDRESS_ID, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_ADDRESS_ID) + // size of drv request data
+ dwSize/2 - 1
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_GET_ADDRESS_ID pNdisTapiGetAddressID =
+ (PNDIS_TAPI_GET_ADDRESS_ID) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetAddressID->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiGetAddressID->ulAddressMode = (ULONG) dwAddressMode;
+ pNdisTapiGetAddressID->ulAddressSize = (ULONG) dwSize/2;
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpsAddress,
+ dwSize,
+ (LPSTR) pNdisTapiGetAddressID->szAddress,
+ dwSize/2,
+ NULL,
+ NULL
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ *lpdwAddressID = pNdisTapiGetAddressID->ulAddressID;
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_ADDRESS_STATUS, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_ADDRESS_STATUS) + // size of drv request data
+ (lpAddressStatus->dwTotalSize - sizeof(LINE_ADDRESS_STATUS))
+
+ )) == TAPI_SUCCESS)
+ {
+ PLINE_ADDRESS_STATUS pStatus;
+ PNDIS_TAPI_GET_ADDRESS_STATUS pNdisTapiGetAddressStatus =
+ (PNDIS_TAPI_GET_ADDRESS_STATUS) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetAddressStatus->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiGetAddressStatus->ulAddressID = (ULONG) dwAddressID;
+
+ pStatus = &pNdisTapiGetAddressStatus->LineAddressStatus;
+
+ pStatus->ulTotalSize = (ULONG) lpAddressStatus->dwTotalSize;
+ pStatus->ulNeededSize =
+ pStatus->ulUsedSize = sizeof (LINE_ADDRESS_STATUS);
+
+ ZeroMemory(
+ &pStatus->ulNumInUse,
+ sizeof (LINE_ADDRESS_STATUS) - 3 * sizeof (ULONG)
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ CopyMemory(
+ lpAddressStatus,
+ &pNdisTapiGetAddressStatus->LineAddressStatus,
+ pNdisTapiGetAddressStatus->LineAddressStatus.ulUsedSize
+ );
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_CALL_ADDRESS_ID, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_CALL_ADDRESS_ID) // size of drv request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_GET_CALL_ADDRESS_ID pNdisTapiGetCallAddressID =
+ (PNDIS_TAPI_GET_CALL_ADDRESS_ID) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetCallAddressID->hdCall = (HDRV_CALL) hdCall;
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ *lpdwAddressID = (DWORD) pNdisTapiGetCallAddressID->ulAddressID;
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_CALL_INFO, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_CALL_INFO) + // size of driver request data
+ (lpCallInfo->dwTotalSize - sizeof(LINE_CALL_INFO))
+
+ )) == TAPI_SUCCESS)
+ {
+ PLINE_CALL_INFO pInfo;
+ PNDIS_TAPI_GET_CALL_INFO pNdisTapiGetCallInfo =
+ (PNDIS_TAPI_GET_CALL_INFO) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetCallInfo->hdCall = (HDRV_CALL) hdCall;
+
+ pInfo = &pNdisTapiGetCallInfo->LineCallInfo;
+
+ pInfo->ulTotalSize = (ULONG) lpCallInfo->dwTotalSize;
+ pInfo->ulNeededSize =
+ pInfo->ulUsedSize = sizeof (LINE_CALL_INFO);
+
+ ZeroMemory(
+ &pInfo->hLine,
+ sizeof (LINE_CALL_INFO) - 3 * sizeof (ULONG)
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ //
+ // Do some post processing to the returned data structure
+ // before passing it back to tapi:
+ // 1. Pad the area between the fixed 1.0 structure and the
+ // var data that the miniports pass back with 0's so a
+ // bad app that disregards the 1.0 version negotiation &
+ // references new 1.4 or 2.0 structure fields won't blow up
+ // 2. Convert ascii strings to unicode, & rebase all var data
+ //
+
+ //
+ // The real needed size is the sum of that requested by the
+ // underlying driver, plus padding for the new TAPI 1.4/2.0
+ // structure fields, plus the size of the var data returned
+ // by the driver to account for the ascii->unicode conversion.
+ // (Granted, we are very liberal in computing the value for
+ // this last part, but at least this way it's fast & we'll
+ // never have too little buffer space.
+ //
+
+ lpCallInfo->dwNeededSize =
+ pInfo->ulNeededSize +
+ (sizeof (LINECALLINFO) - // v2.0 struct
+ sizeof (LINE_CALL_INFO)) + // v1.0 struct
+ (pInfo->ulNeededSize - sizeof (LINE_CALL_INFO));
+
+
+ //
+ // Copy over the fixed fields that don't need changing,
+ // i.e. everything from dwLineDeviceID to dwTrunk
+ //
+
+ CopyMemory(
+ &lpCallInfo->dwLineDeviceID,
+ &pInfo->ulLineDeviceID,
+ 23 * sizeof (DWORD)
+ );
+
+ if (lpCallInfo->dwNeededSize > lpCallInfo->dwTotalSize)
+ {
+ lpCallInfo->dwUsedSize =
+ (lpCallInfo->dwTotalSize < sizeof (LINECALLINFO) ?
+ lpCallInfo->dwTotalSize : sizeof (LINECALLINFO));
+ }
+ else
+ {
+ lpCallInfo->dwUsedSize = sizeof (LINECALLINFO); // v2.0 struct
+
+ lpCallInfo->dwCallerIDFlags = pInfo->ulCallerIDFlags;
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulCallerIDSize,
+ lpCallInfo,
+ &lpCallInfo->dwCallerIDSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.CallerID"
+ );
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulCallerIDNameSize,
+ lpCallInfo,
+ &lpCallInfo->dwCallerIDNameSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.CallerIDName"
+ );
+
+ lpCallInfo->dwCalledIDFlags = pInfo->ulCalledIDFlags;
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulCalledIDSize,
+ lpCallInfo,
+ &lpCallInfo->dwCalledIDSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.CalledID"
+ );
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulCalledIDNameSize,
+ lpCallInfo,
+ &lpCallInfo->dwCalledIDNameSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.CalledIDName"
+ );
+
+ lpCallInfo->dwConnectedIDFlags = pInfo->ulConnectedIDFlags;
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulConnectedIDSize,
+ lpCallInfo,
+ &lpCallInfo->dwConnectedIDSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.ConnectID"
+ );
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulConnectedIDNameSize,
+ lpCallInfo,
+ &lpCallInfo->dwConnectedIDNameSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.ConnectIDName"
+ );
+
+ lpCallInfo->dwRedirectionIDFlags = pInfo->ulRedirectionIDFlags;
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulRedirectionIDSize,
+ lpCallInfo,
+ &lpCallInfo->dwRedirectionIDSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.RedirectionID"
+ );
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulRedirectionIDNameSize,
+ lpCallInfo,
+ &lpCallInfo->dwRedirectionIDNameSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.RedirectionIDName"
+ );
+
+ lpCallInfo->dwRedirectingIDFlags = pInfo->ulRedirectingIDFlags;
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulRedirectingIDSize,
+ lpCallInfo,
+ &lpCallInfo->dwRedirectingIDSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.RedirectingID"
+ );
+
+ INSERTVARDATASTRING(
+ pInfo,
+ &pInfo->ulRedirectingIDNameSize,
+ lpCallInfo,
+ &lpCallInfo->dwRedirectingIDNameSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.RedirectingIDName"
+ );
+
+ INSERTVARDATA(
+ pInfo,
+ &pInfo->ulDisplaySize,
+ lpCallInfo,
+ &lpCallInfo->dwDisplaySize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.Display"
+ );
+
+ INSERTVARDATA(
+ pInfo,
+ &pInfo->ulUserUserInfoSize,
+ lpCallInfo,
+ &lpCallInfo->dwUserUserInfoSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.UserUserInfo"
+ );
+
+ INSERTVARDATA(
+ pInfo,
+ &pInfo->ulHighLevelCompSize,
+ lpCallInfo,
+ &lpCallInfo->dwHighLevelCompSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.HighLevelComp"
+ );
+
+ INSERTVARDATA(
+ pInfo,
+ &pInfo->ulLowLevelCompSize,
+ lpCallInfo,
+ &lpCallInfo->dwLowLevelCompSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.LowLevelComp"
+ );
+
+ INSERTVARDATA(
+ pInfo,
+ &pInfo->ulChargingInfoSize,
+ lpCallInfo,
+ &lpCallInfo->dwChargingInfoSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.ChargingInfo"
+ );
+
+ INSERTVARDATA(
+ pInfo,
+ &pInfo->ulTerminalModesSize,
+ lpCallInfo,
+ &lpCallInfo->dwTerminalModesSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.TerminalModes"
+ );
+
+ INSERTVARDATA(
+ pInfo,
+ &pInfo->ulDevSpecificSize,
+ lpCallInfo,
+ &lpCallInfo->dwDevSpecificSize,
+ sizeof (LINE_CALL_INFO),
+ "LINE_CALL_INFO.DevSpecific"
+ );
+ }
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_CALL_STATUS, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_CALL_STATUS) + // size of driver request data
+ (lpCallStatus->dwTotalSize - sizeof(LINE_CALL_STATUS))
+
+ )) == TAPI_SUCCESS)
+ {
+ PLINE_CALL_STATUS pStatus;
+ PNDIS_TAPI_GET_CALL_STATUS pNdisTapiGetCallStatus =
+ (PNDIS_TAPI_GET_CALL_STATUS) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetCallStatus->hdCall = (HDRV_CALL) hdCall;
+
+ pStatus = &pNdisTapiGetCallStatus->LineCallStatus;
+
+ pStatus->ulTotalSize = (ULONG) lpCallStatus->dwTotalSize;
+ pStatus->ulNeededSize =
+ pStatus->ulUsedSize = sizeof (LINE_CALL_STATUS);
+
+ ZeroMemory(
+ &pStatus->ulCallState,
+ sizeof (LINE_CALL_STATUS) - 3 * sizeof (ULONG)
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ //
+ // Do some post processing to the returned data structure
+ // before passing it back to tapi:
+ // 1. Pad the area between the fixed 1.0 structure and the
+ // var data that the miniports pass back with 0's so a
+ // bad app that disregards the 1.0 version negotiation &
+ // references new 1.4 or 2.0 structure fields won't blow up
+ // (no embedded ascii strings to convert to unicode)
+ //
+
+ //
+ // The real needed size is the sum of that requested by the
+ // underlying driver, plus padding for the new TAPI 1.4/2.0
+ // structure fields. (There are no embedded ascii strings to
+ // convert to unicode, so no extra space needed for that.)
+ //
+
+ lpCallStatus->dwNeededSize =
+ pStatus->ulNeededSize +
+ (sizeof (LINECALLSTATUS) - // v2.0 struct
+ sizeof (LINE_CALL_STATUS)); // v1.0 struct
+
+
+ //
+ // Copy over the fixed fields that don't need changing,
+ // i.e. everything from dwLineDeviceID to dwCallCompletionModes
+ //
+
+ CopyMemory(
+ &lpCallStatus->dwCallState,
+ &pStatus->ulCallState,
+ 4 * sizeof (DWORD)
+ );
+
+ if (lpCallStatus->dwNeededSize > lpCallStatus->dwTotalSize)
+ {
+ lpCallStatus->dwUsedSize =
+ (lpCallStatus->dwTotalSize < sizeof (LINECALLSTATUS) ?
+ lpCallStatus->dwTotalSize : sizeof (LINECALLSTATUS));
+ }
+ else
+ {
+ lpCallStatus->dwUsedSize = sizeof (LINECALLSTATUS);
+ // v2.0 struct
+ INSERTVARDATA(
+ pStatus,
+ &pStatus->ulDevSpecificSize,
+ lpCallStatus,
+ &lpCallStatus->dwDevSpecificSize,
+ sizeof (LINE_CALL_STATUS),
+ "LINE_CALL_STATUS.DevSpecific"
+ );
+
+ }
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_DEV_CAPS, // opcode
+ &dwDeviceID, // target handle
+ HT_DEVICEID, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_DEV_CAPS) + // size of driver request data
+ (lpLineDevCaps->dwTotalSize - sizeof(LINE_DEV_CAPS))
+
+ )) == TAPI_SUCCESS)
+ {
+ PLINE_DEV_CAPS pCaps;
+ PNDIS_TAPI_GET_DEV_CAPS pNdisTapiGetDevCaps =
+ (PNDIS_TAPI_GET_DEV_CAPS) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetDevCaps->ulDeviceID = (ULONG) dwDeviceID;
+ pNdisTapiGetDevCaps->ulExtVersion = (ULONG) dwExtVersion;
+
+ pCaps = &pNdisTapiGetDevCaps->LineDevCaps;
+
+ pCaps->ulTotalSize = (ULONG) lpLineDevCaps->dwTotalSize;
+ pCaps->ulNeededSize =
+ pCaps->ulUsedSize = sizeof (LINE_DEV_CAPS);
+
+ ZeroMemory(
+ &pCaps->ulProviderInfoSize,
+ sizeof (LINE_DEV_CAPS) - 3 * sizeof (ULONG)
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ //
+ // Do some post processing to the returned data structure
+ // before passing it back to tapi:
+ // 1. Pad the area between the fixed 1.0 structure and the
+ // var data that the miniports pass back with 0's so a
+ // bad app that disregards the 1.0 version negotiation &
+ // references new 1.4 or 2.0 structure fields won't blow up
+ // 2. Convert ascii strings to unicode, & rebase all var data
+ //
+
+ //
+ // The real needed size is the sum of that requested by the
+ // underlying driver, plus padding for the new TAPI 1.4/2.0
+ // structure fields, plus the size of the var data returned
+ // by the driver to account for the ascii->unicode conversion.
+ // (Granted, we are very liberal in computing the value for
+ // this last part, but at least this way it's fast & we'll
+ // never have too little buffer space.
+ //
+
+ lpLineDevCaps->dwNeededSize =
+ pCaps->ulNeededSize +
+ (sizeof (LINEDEVCAPS) - // v2.0 struct
+ sizeof (LINE_DEV_CAPS)) + // v1.0 struct
+ (pCaps->ulNeededSize - sizeof (LINE_DEV_CAPS));
+
+
+ //
+ // Copy over the fixed fields that don't need changing,
+ // i.e. everything from dwPermanentLineID to dwNumTerminals
+ //
+
+ CopyMemory(
+ &lpLineDevCaps->dwPermanentLineID,
+ &pCaps->ulPermanentLineID,
+ sizeof (LINE_DEV_CAPS) - (14 * sizeof (DWORD))
+ );
+
+ if (lpLineDevCaps->dwNeededSize > lpLineDevCaps->dwTotalSize)
+ {
+ lpLineDevCaps->dwUsedSize =
+ (lpLineDevCaps->dwTotalSize < sizeof (LINEDEVCAPS) ?
+ lpLineDevCaps->dwTotalSize : sizeof (LINEDEVCAPS));
+
+ lpLineDevCaps->dwLineNameSize =
+ lpLineDevCaps->dwLineNameOffset = 0;
+ }
+ else
+ {
+ lpLineDevCaps->dwUsedSize = sizeof (LINEDEVCAPS);
+ // v2.0 struct
+
+ INSERTVARDATASTRING(
+ pCaps,
+ &pCaps->ulProviderInfoSize,
+ lpLineDevCaps,
+ &lpLineDevCaps->dwProviderInfoSize,
+ sizeof (LINE_DEV_CAPS),
+ "LINE_DEV_CAPS.ProviderInfo"
+ );
+
+ INSERTVARDATASTRING(
+ pCaps,
+ &pCaps->ulSwitchInfoSize,
+ lpLineDevCaps,
+ &lpLineDevCaps->dwSwitchInfoSize,
+ sizeof (LINE_DEV_CAPS),
+ "LINE_DEV_CAPS.SwitchInfo"
+ );
+
+ INSERTVARDATASTRING(
+ pCaps,
+ &pCaps->ulLineNameSize,
+ lpLineDevCaps,
+ &lpLineDevCaps->dwLineNameSize,
+ sizeof (LINE_DEV_CAPS),
+ "LINE_DEV_CAPS.LineName"
+ );
+
+ INSERTVARDATA(
+ pCaps,
+ &pCaps->ulTerminalCapsSize,
+ lpLineDevCaps,
+ &lpLineDevCaps->dwTerminalCapsSize,
+ sizeof (LINE_DEV_CAPS),
+ "LINE_DEV_CAPS.TerminalCaps"
+ );
+
+// BUGBUG TSPI_lineGetDevCaps: convert DevCaps.TermText to unicode???
+
+ lpLineDevCaps->dwTerminalTextEntrySize =
+ pCaps->ulTerminalTextEntrySize;
+
+ INSERTVARDATA(
+ pCaps,
+ &pCaps->ulTerminalTextSize,
+ lpLineDevCaps,
+ &lpLineDevCaps->dwTerminalTextSize,
+ sizeof (LINE_DEV_CAPS),
+ "LINE_DEV_CAPS.TerminalText"
+ );
+
+ INSERTVARDATA(
+ pCaps,
+ &pCaps->ulDevSpecificSize,
+ lpLineDevCaps,
+ &lpLineDevCaps->dwDevSpecificSize,
+ sizeof (LINE_DEV_CAPS),
+ "LINE_DEV_CAPS.DevSpecific"
+ );
+ }
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevConfig(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_DEV_CONFIG, // opcode
+ &dwDeviceID, // target handle
+ HT_DEVICEID, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_DEV_CONFIG) + // size of driver request data
+ (lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING)) + dwLength
+
+ )) == TAPI_SUCCESS)
+ {
+ PVAR_STRING pConfig;
+ PNDIS_TAPI_GET_DEV_CONFIG pNdisTapiGetDevConfig =
+ (PNDIS_TAPI_GET_DEV_CONFIG) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetDevConfig->ulDeviceID = (ULONG) dwDeviceID;
+ pNdisTapiGetDevConfig->ulDeviceClassSize = (ULONG) dwLength;
+ pNdisTapiGetDevConfig->ulDeviceClassOffset = (ULONG)
+ sizeof(NDIS_TAPI_GET_DEV_CONFIG) +
+ (lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING));
+
+ pConfig = &pNdisTapiGetDevConfig->DeviceConfig;
+
+ pConfig->ulTotalSize = (ULONG) lpDeviceConfig->dwTotalSize;
+ pConfig->ulNeededSize =
+ pConfig->ulUsedSize = sizeof (VAR_STRING);
+ pConfig->ulStringFormat =
+ pConfig->ulStringSize =
+ pConfig->ulStringOffset = 0;
+
+
+ //
+ // Note: old miniports expect strings to be ascii
+ //
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDeviceClass,
+ -1,
+ (LPSTR) (((LPBYTE) pNdisTapiGetDevConfig) +
+ pNdisTapiGetDevConfig->ulDeviceClassOffset),
+ dwLength,
+ NULL,
+ NULL
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ CopyMemory(
+ lpDeviceConfig,
+ &pNdisTapiGetDevConfig->DeviceConfig,
+ pNdisTapiGetDevConfig->DeviceConfig.ulUsedSize
+ );
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPLINEEXTENSIONID lpExtensionID
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_EXTENSION_ID, // opcode
+ &dwDeviceID, // target handle
+ HT_DEVICEID, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_EXTENSION_ID) // size of driver request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_GET_EXTENSION_ID pNdisTapiGetExtensionID =
+ (PNDIS_TAPI_GET_EXTENSION_ID) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetExtensionID->ulDeviceID = (ULONG) dwDeviceID;
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ CopyMemory(
+ lpExtensionID,
+ &pNdisTapiGetExtensionID->LineExtensionID,
+ sizeof(LINE_EXTENSION_ID)
+ );
+ }
+ else
+ {
+ //
+ // Rather than indicating a failure, we'll just zero out the
+ // ext id (implying driver doesn't support extensions) and
+ // return success to tapisrv so it'll complete the open ok
+ //
+
+ ZeroMemory(
+ lpExtensionID,
+ sizeof(LINE_EXTENSION_ID)
+ );
+
+ lResult = TAPI_SUCCESS;
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+{
+ LONG lResult;
+ DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_ID, // opcode
+ (LPDWORD)(dwSelect == LINECALLSELECT_CALL ? // target handle
+ (LPDWORD) &hdCall : (LPDWORD) &hdLine),
+ (dwSelect == LINECALLSELECT_CALL ? // target handle type
+ HT_HDCALL : HT_HDLINE),
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_ID) + // size of driver request data
+ (lpDeviceID->dwTotalSize - sizeof(VAR_STRING)) + dwLength
+
+ )) == TAPI_SUCCESS)
+ {
+ PVAR_STRING pID;
+ PNDIS_TAPI_GET_ID pNdisTapiGetID =
+ (PNDIS_TAPI_GET_ID) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetID->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiGetID->ulAddressID = (ULONG) dwAddressID;
+ pNdisTapiGetID->hdCall = (HDRV_CALL) hdCall;
+ pNdisTapiGetID->ulSelect = (ULONG) dwSelect;
+ pNdisTapiGetID->ulDeviceClassSize = (ULONG) dwLength;
+ pNdisTapiGetID->ulDeviceClassOffset = (ULONG)
+ sizeof(NDIS_TAPI_GET_ID) +
+ (lpDeviceID->dwTotalSize - sizeof(VAR_STRING));
+
+ pID = &pNdisTapiGetID->DeviceID;
+
+ pID->ulTotalSize = (ULONG) lpDeviceID->dwTotalSize;
+ pID->ulNeededSize =
+ pID->ulUsedSize = sizeof (VAR_STRING);
+ pID->ulStringFormat =
+ pID->ulStringSize =
+ pID->ulStringOffset = 0;
+
+
+ //
+ // Note: old miniports expect strings to be ascii
+ //
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDeviceClass,
+ -1,
+ (LPSTR) (((LPBYTE) pNdisTapiGetID) +
+ pNdisTapiGetID->ulDeviceClassOffset),
+ dwLength,
+ NULL,
+ NULL
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ CopyMemory(
+ lpDeviceID,
+ &pNdisTapiGetID->DeviceID,
+ pNdisTapiGetID->DeviceID.ulUsedSize
+ );
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_GET_LINE_DEV_STATUS, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_GET_LINE_DEV_STATUS) + // size of drv request data
+ (lpLineDevStatus->dwTotalSize - sizeof(LINE_DEV_STATUS))
+
+ )) == TAPI_SUCCESS)
+ {
+ PLINE_DEV_STATUS pStatus;
+ PNDIS_TAPI_GET_LINE_DEV_STATUS pNdisTapiGetLineDevStatus =
+ (PNDIS_TAPI_GET_LINE_DEV_STATUS) pNdisTapiRequest->Data;
+
+
+ pNdisTapiGetLineDevStatus->hdLine = (HDRV_LINE) hdLine;
+
+ pStatus = &pNdisTapiGetLineDevStatus->LineDevStatus;
+
+ pStatus->ulTotalSize = (ULONG) lpLineDevStatus->dwTotalSize;
+ pStatus->ulNeededSize =
+ pStatus->ulUsedSize = sizeof (LINE_DEV_STATUS);
+
+ ZeroMemory(
+ &pStatus->ulNumOpens,
+ sizeof (LINE_DEV_STATUS) - 3 * sizeof (ULONG)
+ );
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ //
+ // Do some post processing to the returned data structure
+ // before passing it back to tapi:
+ // 1. Pad the area between the fixed 1.0 structure and the
+ // var data that the miniports pass back with 0's so a
+ // bad app that disregards the 1.0 version negotiation &
+ // references new 1.4 or 2.0 structure fields won't blow up
+ // (no embedded ascii strings to convert to unicode)
+ //
+
+ //
+ // The real needed size is the sum of that requested by the
+ // underlying driver, plus padding for the new TAPI 1.4/2.0
+ // structure fields. (There are no embedded ascii strings to
+ // convert to unicode, so no extra space needed for that.)
+ //
+
+ lpLineDevStatus->dwNeededSize =
+ pStatus->ulNeededSize +
+ (sizeof (LINEDEVSTATUS) - // v2.0 struct
+ sizeof (LINE_DEV_STATUS)); // v1.0 struct
+
+
+ //
+ // Copy over the fixed fields that don't need changing,
+ // i.e. everything from dwNumActiveCalls to dwDevStatusFlags
+ //
+
+ CopyMemory(
+ &lpLineDevStatus->dwNumActiveCalls,
+ &pStatus->ulNumActiveCalls,
+ sizeof (LINE_DEV_STATUS) - (9 * sizeof (DWORD))
+ );
+
+ if (lpLineDevStatus->dwNeededSize > lpLineDevStatus->dwTotalSize)
+ {
+ lpLineDevStatus->dwUsedSize =
+ (lpLineDevStatus->dwTotalSize < sizeof (LINEDEVSTATUS) ?
+ lpLineDevStatus->dwTotalSize : sizeof (LINEDEVSTATUS));
+ }
+ else
+ {
+ lpLineDevStatus->dwUsedSize = sizeof (LINEDEVSTATUS);
+ // v2.0 struct
+ INSERTVARDATA(
+ pStatus,
+ &pStatus->ulTerminalModesSize,
+ lpLineDevStatus,
+ &lpLineDevStatus->dwTerminalModesSize,
+ sizeof (LINE_DEV_STATUS),
+ "LINE_DEV_STATUS.TerminalModes"
+ );
+
+ INSERTVARDATA(
+ pStatus,
+ &pStatus->ulDevSpecificSize,
+ lpLineDevStatus,
+ &lpLineDevStatus->dwDevSpecificSize,
+ sizeof (LINE_DEV_STATUS),
+ "LINE_DEV_STATUS.DevSpecific"
+ );
+ }
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+{
+ //
+ // Since there isn't an OID_TAPI_GET_NUM_ADDRESS_IDS at this point
+ // we need to synthesize it by getting the dev caps and looking at
+ // the dwNumAddresses field of that structure. We first do this
+ // with a fixed size (+) structure, then if that doesn't cut it
+ // (i.e. the provider hasn't chg'd the dwNumAddresses field) we
+ // alloc a larger buffer (as per the returned dwNeededSize field)
+ // and try again. If we get an error along the way we just return
+ // 1 address- kludgy, but say "la vee".
+ //
+ // Note that we use the (P)LINE_DEV_CAPS types from ndistapi.h.
+ //
+
+ BOOL bTryAgain = TRUE;
+ DWORD dwTotalSize = sizeof (LINE_DEV_CAPS) + 128;
+ PDRVLINE pLine = (PDRVLINE) hdLine;
+ PLINE_DEV_CAPS pLineDevCaps;
+
+
+TSPI_lineGetNumAddressIDs_allocBuffer:
+
+ if ((pLineDevCaps = DrvAlloc (dwTotalSize)))
+ {
+ pLineDevCaps->ulTotalSize = dwTotalSize;
+ pLineDevCaps->ulNeededSize =
+ pLineDevCaps->ulUsedSize = sizeof (LINE_DEV_CAPS);
+
+ if (TSPI_lineGetDevCaps(
+ pLine->dwDeviceID,
+ 0x10003,
+ 0,
+ (LPLINEDEVCAPS) pLineDevCaps
+
+ ) == 0)
+ {
+ DWORD dwNumAddresses = (DWORD) pLineDevCaps->ulNumAddresses,
+ dwNeededSize = (DWORD) pLineDevCaps->ulNeededSize;
+
+
+ DrvFree (pLineDevCaps);
+
+ if (dwNumAddresses != 0)
+ {
+ *lpdwNumAddressIDs = dwNumAddresses;
+
+ return 0;
+ }
+ else if (bTryAgain && (dwNeededSize > dwTotalSize))
+ {
+ dwTotalSize = dwNeededSize;
+
+ bTryAgain = FALSE;
+
+ goto TSPI_lineGetNumAddressIDs_allocBuffer;
+ }
+ }
+ else
+ {
+ DrvFree (pLineDevCaps);
+ }
+ }
+
+ *lpdwNumAddressIDs = 1; // if here an error occured, default to 1 addr
+
+ return 0;
+}
+
+
+LONG
+PASCAL
+TSPI_lineMakeCall_postProcess(
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper,
+ LONG lResult,
+ LPDWORD callStateMsgParams
+ )
+{
+ PDRVCALL pCall = (PDRVCALL) pAsyncRequestWrapper->dwRequestSpecific;
+
+
+ if (lResult == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
+ pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ //
+ // Check to see if a call state msg was received before we had
+ // the chance to process the completion notification, & if so
+ // fill in the msg params
+ //
+
+ if (pCall->dwPendingCallState)
+ {
+ callStateMsgParams[0] = (DWORD) ((PDRVLINE) pCall->pLine)->htLine;
+ callStateMsgParams[1] = (DWORD) pCall->htCall;
+ callStateMsgParams[2] = pCall->dwPendingCallState;
+ callStateMsgParams[3] = pCall->dwPendingCallStateMode;
+ callStateMsgParams[4] = pCall->dwPendingMediaMode;
+ }
+
+ pCall->hd_Call = pNdisTapiMakeCall->hdCall;
+ pCall->bIncomplete = FALSE;
+ }
+ else
+ {
+ pCall->dwKey = INVALID_KEY;
+ DrvFree (pCall);
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD dwLength;
+ PDRVCALL pCall;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ //
+ // First alloc & init a DRVCALL
+ //
+
+ if (!(pCall = DrvAlloc (sizeof(DRVCALL))))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ pCall->dwKey = OUTBOUND_CALL_KEY;
+ pCall->dwDeviceID = ((PDRVLINE) hdLine)->dwDeviceID;
+ pCall->htCall = htCall;
+ pCall->pLine = (LPVOID) hdLine;
+ pCall->bIncomplete = TRUE;
+
+
+ //
+ // Init the request
+ //
+
+ dwLength = (lpszDestAddress ? lstrlenW (lpszDestAddress) + 1 : 0);
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_MAKE_CALL, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_MAKE_CALL) + // size of drv request data
+ dwLength + (lpCallParams ?
+ (lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS)) : 0)
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
+ pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiMakeCall->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiMakeCall->htCall = (HTAPI_CALL) pCall;
+
+ pNdisTapiMakeCall->ulDestAddressSize = (ULONG) dwLength;
+
+ if (lpszDestAddress)
+ {
+ pNdisTapiMakeCall->ulDestAddressOffset =
+ sizeof(NDIS_TAPI_MAKE_CALL) +
+ (lpCallParams ? (lpCallParams->dwTotalSize -
+ sizeof(LINE_CALL_PARAMS)) : 0);
+
+ //
+ // Note: old miniports expect strings to be ascii
+ //
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDestAddress,
+ dwLength,
+ (LPSTR) (((LPBYTE) pNdisTapiMakeCall) +
+ pNdisTapiMakeCall->ulDestAddressOffset),
+ dwLength,
+ NULL,
+ NULL
+ );
+ }
+ else
+ {
+ pNdisTapiMakeCall->ulDestAddressOffset = 0;
+ }
+
+ if (lpCallParams)
+ {
+ pNdisTapiMakeCall->bUseDefaultLineCallParams = FALSE;
+
+ CopyMemory(
+ &pNdisTapiMakeCall->LineCallParams,
+ lpCallParams,
+ lpCallParams->dwTotalSize
+ );
+
+ if (lpCallParams->dwOrigAddressSize != 0)
+ {
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ (LPCWSTR) (((LPBYTE) lpCallParams) +
+ lpCallParams->dwOrigAddressOffset),
+ lpCallParams->dwOrigAddressSize / sizeof (WCHAR),
+ (LPSTR) (((LPBYTE) &pNdisTapiMakeCall->LineCallParams) +
+ lpCallParams->dwOrigAddressOffset),
+ lpCallParams->dwOrigAddressSize,
+ NULL,
+ NULL
+ );
+
+ pNdisTapiMakeCall->LineCallParams.ulOrigAddressSize /= 2;
+ }
+ }
+ else
+ {
+ pNdisTapiMakeCall->bUseDefaultLineCallParams = TRUE;
+ }
+
+ pAsyncRequestWrapper->dwRequestSpecific = (DWORD) pCall;
+ pAsyncRequestWrapper->pfnPostProcess = TSPI_lineMakeCall_postProcess;
+
+ *lphdCall = (HDRVCALL) pCall;
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_NEGOTIATE_EXT_VERSION, // opcode
+ (LPDWORD) &dwDeviceID, // target handle
+ HT_DEVICEID, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_NEGOTIATE_EXT_VERSION) // size of drv req data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion =
+ (PNDIS_TAPI_NEGOTIATE_EXT_VERSION) pNdisTapiRequest->Data;
+
+
+ pNdisTapiNegotiateExtVersion->ulDeviceID = (ULONG) dwDeviceID;
+ pNdisTapiNegotiateExtVersion->ulLowVersion = (ULONG) dwLowVersion;
+ pNdisTapiNegotiateExtVersion->ulHighVersion = (ULONG) dwHighVersion;
+
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ *lpdwExtVersion = pNdisTapiNegotiateExtVersion->ulExtVersion;
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ *lpdwTSPIVersion = 0x00010003; // until the ndistapi spec widened
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+{
+ LONG lResult;
+ PDRVLINE pLine;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+
+ //
+ // First alloc & init a DRVLINE
+ //
+
+ if (!(pLine = DrvAlloc (sizeof(DRVLINE))))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ pLine->dwKey = LINE_KEY;
+ pLine->dwDeviceID = dwDeviceID;
+ pLine->htLine = htLine;
+
+
+ //
+ // Init the request
+ //
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_OPEN, // opcode
+ (LPDWORD) &dwDeviceID, // target handle
+ HT_DEVICEID, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_OPEN) // size of drve req data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_OPEN pNdisTapiOpen =
+ (PNDIS_TAPI_OPEN) pNdisTapiRequest->Data;
+
+
+ pNdisTapiOpen->ulDeviceID = (ULONG) dwDeviceID;
+ pNdisTapiOpen->htLine = (HTAPI_LINE) pLine;
+
+
+ if ((lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_QUERY_INFO,
+ pNdisTapiRequest
+
+ )) == TAPI_SUCCESS)
+ {
+ pLine->hd_Line = pNdisTapiOpen->hdLine;
+
+ *lphdLine = (HDRVLINE) pLine;
+ }
+ else
+ {
+ DrvFree (pLine);
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSecureCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ LONG lResult;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_SECURE_CALL, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_SECURE_CALL) // size of drv request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SECURE_CALL pNdisTapiSecureCall =
+ (PNDIS_TAPI_SECURE_CALL)
+ pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiSecureCall->hdCall = (HDRV_CALL) hdCall;
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSelectExtVersion(
+ HDRVLINE hdLine,
+ DWORD dwExtVersion
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_SELECT_EXT_VERSION, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_SELECT_EXT_VERSION) // size of drve req data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SELECT_EXT_VERSION pNdisTapiSelectExtVersion =
+ (PNDIS_TAPI_SELECT_EXT_VERSION) pNdisTapiRequest->Data;
+
+
+ pNdisTapiSelectExtVersion->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiSelectExtVersion->ulExtVersion = (ULONG) dwExtVersion;
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSendUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_SEND_USER_USER_INFO, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_SEND_USER_USER_INFO) + // size of drv request data
+ dwSize
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SEND_USER_USER_INFO pNdisTapiSendUserUserInfo =
+ (PNDIS_TAPI_SEND_USER_USER_INFO)
+ pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiSendUserUserInfo->hdCall = (HDRV_CALL) hdCall;
+
+ if ((pNdisTapiSendUserUserInfo->ulUserUserInfoSize = (ULONG) dwSize))
+ {
+ CopyMemory(
+ pNdisTapiSendUserUserInfo->UserUserInfo,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_SET_APP_SPECIFIC, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_SET_APP_SPECIFIC) // size of driver request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific =
+ (PNDIS_TAPI_SET_APP_SPECIFIC) pNdisTapiRequest->Data;
+
+
+ pNdisTapiSetAppSpecific->hdCall = (HDRV_CALL) hdCall;
+ pNdisTapiSetAppSpecific->ulAppSpecific = (ULONG) dwAppSpecific;
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallParams(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwBearerMode,
+ DWORD dwMinRate,
+ DWORD dwMaxRate,
+ LPLINEDIALPARAMS const lpDialParams
+ )
+{
+ LONG lResult;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ if ((lResult = PrepareAsyncRequest(
+ OID_TAPI_SET_CALL_PARAMS, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ dwRequestID, // request id
+ &pAsyncRequestWrapper, // ptr to ptr to request buffer
+ sizeof(NDIS_TAPI_SET_CALL_PARAMS) // size of drv request data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SET_CALL_PARAMS pNdisTapiSetCallParams =
+ (PNDIS_TAPI_SET_CALL_PARAMS)
+ pAsyncRequestWrapper->NdisTapiRequest.Data;
+
+
+ pNdisTapiSetCallParams->hdCall = (HDRV_CALL) hdCall;
+ pNdisTapiSetCallParams->ulBearerMode = (ULONG) dwBearerMode;
+ pNdisTapiSetCallParams->ulMinRate = (ULONG) dwMinRate;
+ pNdisTapiSetCallParams->ulMaxRate = (ULONG) dwMaxRate;
+
+ if (lpDialParams)
+ {
+ pNdisTapiSetCallParams->bSetLineDialParams = TRUE;
+
+ CopyMemory(
+ &pNdisTapiSetCallParams->LineDialParams,
+ lpDialParams,
+ sizeof(LINE_DIAL_PARAMS)
+ );
+ }
+ else
+ {
+ pNdisTapiSetCallParams->bSetLineDialParams = FALSE;
+ }
+
+ lResult = AsyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pAsyncRequestWrapper
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult =PrepareSyncRequest(
+ OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to req buffer
+ sizeof(NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION) // sizeof req data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION
+ pNdisTapiSetDefaultMediaDetection =
+ (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)
+ pNdisTapiRequest->Data;
+
+
+ pNdisTapiSetDefaultMediaDetection->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiSetDefaultMediaDetection->ulMediaModes = (ULONG) dwMediaModes;
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDevConfig(
+ DWORD dwDeviceID,
+ LPVOID const lpDeviceConfig,
+ DWORD dwSize,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult =PrepareSyncRequest(
+ OID_TAPI_SET_DEV_CONFIG, // opcode
+ &dwDeviceID, // target handle
+ HT_DEVICEID, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to req buffer
+ sizeof(NDIS_TAPI_SET_DEV_CONFIG) + // sizeof req data
+ dwLength + dwSize
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SET_DEV_CONFIG pNdisTapiSetDevConfig =
+ (PNDIS_TAPI_SET_DEV_CONFIG) pNdisTapiRequest->Data;
+
+
+ pNdisTapiSetDevConfig->ulDeviceID = (ULONG) dwDeviceID;
+ pNdisTapiSetDevConfig->ulDeviceClassSize = (ULONG) dwLength;
+ pNdisTapiSetDevConfig->ulDeviceClassOffset =
+ sizeof(NDIS_TAPI_SET_DEV_CONFIG) + dwSize - 1;
+ pNdisTapiSetDevConfig->ulDeviceConfigSize = dwSize;
+
+ CopyMemory(
+ pNdisTapiSetDevConfig->DeviceConfig,
+ lpDeviceConfig,
+ dwSize
+ );
+
+ //
+ // Note: old miniports expect strings to be ascii
+ //
+
+ WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ lpszDeviceClass,
+ -1,
+ (LPSTR) (((LPBYTE) pNdisTapiSetDevConfig) +
+ pNdisTapiSetDevConfig->ulDeviceClassOffset),
+ dwLength,
+ NULL,
+ NULL
+ );
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_SET_MEDIA_MODE, // opcode
+ (LPDWORD) &hdCall, // target handle
+ HT_HDCALL, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to req buffer
+ sizeof(NDIS_TAPI_SET_MEDIA_MODE) // size of drv req data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode =
+ (PNDIS_TAPI_SET_MEDIA_MODE) pNdisTapiRequest->Data;
+
+
+ pNdisTapiSetMediaMode->hdCall = (HDRV_CALL) hdCall;
+ pNdisTapiSetMediaMode->ulMediaMode = (ULONG) dwMediaMode;
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetStatusMessages(
+ HDRVLINE hdLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+{
+ LONG lResult;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+
+
+ if ((lResult = PrepareSyncRequest(
+ OID_TAPI_SET_STATUS_MESSAGES, // opcode
+ (LPDWORD) &hdLine, // target handle
+ HT_HDLINE, // target handle type
+ &pNdisTapiRequest, // ptr to ptr to req buffer
+ sizeof(NDIS_TAPI_SET_STATUS_MESSAGES) // size of drv req data
+
+ )) == TAPI_SUCCESS)
+ {
+ PNDIS_TAPI_SET_STATUS_MESSAGES pNdisTapiSetStatusMessages =
+ (PNDIS_TAPI_SET_STATUS_MESSAGES) pNdisTapiRequest->Data;
+
+
+ pNdisTapiSetStatusMessages->hdLine = (HDRV_LINE) hdLine;
+ pNdisTapiSetStatusMessages->ulLineStates = (ULONG) dwLineStates;
+ pNdisTapiSetStatusMessages->ulAddressStates = (ULONG) dwAddressStates;
+
+ lResult = SyncDriverRequest(
+ (DWORD) IOCTL_NDISTAPI_SET_INFO,
+ pNdisTapiRequest
+ );
+ }
+
+ return lResult;
+}
+
+
+
+//
+// TAPI_providerXxx funcs
+//
+
+LONG
+TSPIAPI
+TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+{
+ //
+ // Note: We really enum devs in providerInit, see the
+ // special case note there
+ //
+
+ *lpdwNumLines = 0;
+ *lpdwNumPhones = 0;
+
+ gpfnLineEvent = lpfnLineCreateProc;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc,
+ LPDWORD lpdwTSPIOptions
+ )
+{
+ LONG lResult= LINEERR_OPERATIONFAILED;
+ char szDeviceName[] = "NDISTAPI";
+ char szTargetPath[] = "\\Device\\NdisTapi";
+ char szCompleteDeviceName[] = "\\\\.\\NDISTAPI";
+ DWORD cbReturned, dwThreadID;
+
+
+ DBGOUT((3, "TSPI_providerInit: enter"));
+
+
+ //
+ // Inform tapisrv that we support multiple simultaneous requests
+ // (the WAN wrapper handles request serialization for miniports)
+ //
+
+ *lpdwTSPIOptions = 0;
+
+
+ //
+ // Create symbolic link to the kernel-mode driver
+ //
+
+ DefineDosDevice (DDD_RAW_TARGET_PATH, szDeviceName, szTargetPath);
+
+
+ //
+ // Open driver
+ //
+
+ if ((ghDriverSync = CreateFileA(
+ szCompleteDeviceName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, // no security attrs
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL // no template file
+ )) == INVALID_HANDLE_VALUE)
+ {
+ DBGOUT((
+ 0,
+ "CreateFile (%s, non-overlapped) failed, err=%ld",
+ szCompleteDeviceName,
+ GetLastError()
+ ));
+
+ goto providerInit_error0;
+ }
+
+
+ if ((ghDriverAsync = CreateFileA(
+ szCompleteDeviceName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, // no security attrs
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL // no template file
+ )) == INVALID_HANDLE_VALUE)
+ {
+ DBGOUT((
+ 0,
+ "CreateFile (%s, overlapped) failed, err=%ld",
+ szCompleteDeviceName,
+ GetLastError()
+ ));
+
+ goto providerInit_error1;
+ }
+
+
+ //
+ // Create io completion port
+ //
+
+ if ((ghCompletionPort = CreateIoCompletionPort(
+ ghDriverAsync,
+ NULL,
+ 0,
+ 0
+
+ )) == INVALID_HANDLE_VALUE)
+ {
+ DBGOUT((
+ 0,
+ "CreateIoCompletionPort failed, err=%ld",
+ GetLastError()
+ ));
+
+ goto providerInit_error2;
+ }
+
+
+ //
+ // Connect to driver- we send it a device ID base & it returns
+ // the number of devices it supports
+ //
+
+ {
+ DWORD adwConnectInfo[2] = { 1, 1 };
+
+
+ if (!DeviceIoControl(
+ ghDriverSync,
+ (DWORD) IOCTL_NDISTAPI_CONNECT,
+ adwConnectInfo, // BUGBUG
+ 2*sizeof(DWORD),
+ &dwLineDeviceIDBase, // BUGBUG
+ sizeof(DWORD),
+ &cbReturned,
+ (LPOVERLAPPED) NULL
+ ) ||
+
+ (cbReturned < sizeof(DWORD)))
+ {
+ DBGOUT((0, "CONNECT failed, err=%ld", GetLastError()));
+
+ goto providerInit_error3;
+ }
+ }
+
+
+ //
+ // Alloc the resources needed by the AsyncEventThread, and then
+ // create the thread
+ //
+
+ if ((gpAsyncEventsThreadInfo = (PASYNC_EVENTS_THREAD_INFO)
+ DrvAlloc (sizeof(ASYNC_EVENTS_THREAD_INFO))) == NULL)
+ {
+ goto providerInit_error4;
+ }
+
+ gpAsyncEventsThreadInfo->dwBufSize = INITIAL_TLS_BUF_SIZE;
+
+ if ((gpAsyncEventsThreadInfo->pBuf1 = (PNDISTAPI_EVENT_DATA)
+ DrvAlloc (INITIAL_TLS_BUF_SIZE)) == NULL)
+ {
+ goto providerInit_error5;
+ }
+
+ if ((gpAsyncEventsThreadInfo->pBuf2 = (PNDISTAPI_EVENT_DATA)
+ DrvAlloc (INITIAL_TLS_BUF_SIZE)) == NULL)
+ {
+ goto providerInit_error6;
+ }
+
+ if ((gpAsyncEventsThreadInfo->hThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES) NULL, // no security attrs
+ 0, // default stack size
+ (LPTHREAD_START_ROUTINE) // func addr
+ AsyncEventsThread,
+ (LPVOID) NULL, // thread param
+ 0, // create flags
+ &dwThreadID // thread id
+
+ )) == NULL)
+ {
+ DBGOUT((1, "CreateThread (GetAsyncEventsThread) failed"));
+
+ goto providerInit_error7;
+ }
+
+
+ //
+ //
+ //
+
+ gdwRequestID = 1;
+
+
+ //
+ // !!! Special case for KMDDSP.TSP only !!!
+ //
+ // For KMDDSP.TSP only, TAPISRV.EXE will pass pointers in the
+ // dwNumLines/dwNumPhones variables rather than an actual
+ // number of lines/phones, thereby allowing the driver to tell
+ // TAPISRV.EXE how many devices are currently registered.
+ //
+ // This is really due to a design/interface problem in NDISTAPI.SYS.
+ // Since the current CONNECT IOCTLS expects both a device ID base &
+ // returns the num devs, we can't really do this in
+ // TSPI_providerEnumDevices as the device ID base is unknown
+ // at that point
+ //
+
+ *((LPDWORD)dwNumLines) = dwLineDeviceIDBase;
+ *((LPDWORD)dwNumPhones) = 0; // BUGBUG until we get OIDs for phones
+
+
+ //
+ // If here success
+ //
+
+ gpfnCompletionProc = lpfnCompletionProc;
+
+ lResult = TAPI_SUCCESS;
+
+ goto providerInit_return;
+
+
+ //
+ // Clean up resources if an error occured & then return
+ //
+
+providerInit_error7:
+
+ DrvFree (gpAsyncEventsThreadInfo->pBuf2);
+
+providerInit_error6:
+
+ DrvFree (gpAsyncEventsThreadInfo->pBuf1);
+
+providerInit_error5:
+
+ DrvFree (gpAsyncEventsThreadInfo);
+
+providerInit_error4:
+providerInit_error3:
+
+ CloseHandle (ghCompletionPort);
+
+providerInit_error2:
+
+ CloseHandle (ghDriverAsync);
+
+providerInit_error1:
+
+ CloseHandle (ghDriverSync);
+
+providerInit_error0:
+
+ DefineDosDevice (DDD_REMOVE_DEFINITION, szDeviceName, NULL);
+
+providerInit_return:
+
+ DBGOUT((3, "TSPI_providerInit: exit, result=x%x", lResult));
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ return TAPI_SUCCESS;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ return TAPI_SUCCESS;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID
+ )
+{
+ char deviceName[] = "NDISTAPI";
+ LONG lResult = TAPI_SUCCESS;
+ BOOL bResult;
+ ASYNC_REQUEST_WRAPPER asyncRequestWrapper;
+
+
+ DBGOUT((3, "TSPI_providerShutdown: enter"));
+
+
+ // BUGBUG all we ought to have to do here is send a DISCONNECT IOCTL
+
+ //
+ // Post an async request that, once completed, will cause the async
+ // request thread to kill itself. Wait until we're sure the thread
+ // is gone, then clean it's resources.
+ //
+
+ FillMemory (&asyncRequestWrapper, sizeof (ASYNC_REQUEST_WRAPPER), 0);
+
+ asyncRequestWrapper.dwKey = ASYNCREQWRAPPER_KEY;
+ asyncRequestWrapper.dwRequestID = 0xffffffff;
+
+ bResult = PostQueuedCompletionStatus(
+ ghCompletionPort,
+ sizeof (ASYNC_REQUEST_WRAPPER),
+ 0,
+ &asyncRequestWrapper.Overlapped
+ );
+
+ if (bResult== FALSE)
+ {
+ //
+ // Failed to post a completion msg to the async event thread,
+ // so we have to manually nuke the thread. This is not the
+ // preferred method since resources can be left lying around
+ // (i.e. the thread stack isn't freed).
+ //
+
+ DBGOUT((
+ 1,
+ "TSPI_providerShutdown: ERROR- manually terminating " \
+ "AsyncEventsThread, err=%d",
+ GetLastError()
+ ));
+
+ TerminateThread (gpAsyncEventsThreadInfo->hThread, 0);
+ }
+ else
+ {
+ WaitForSingleObject (gpAsyncEventsThreadInfo->hThread, INFINITE);
+ }
+
+ CloseHandle (gpAsyncEventsThreadInfo->hThread);
+ DrvFree (gpAsyncEventsThreadInfo->pBuf2);
+ DrvFree (gpAsyncEventsThreadInfo->pBuf1);
+ DrvFree (gpAsyncEventsThreadInfo);
+
+
+ //
+ // Close the driver & remove the symbolic link
+ //
+
+ CloseHandle (ghCompletionPort);
+ CloseHandle (ghDriverSync);
+ CloseHandle (ghDriverAsync);
+
+ DefineDosDevice (DDD_REMOVE_DEFINITION, deviceName, NULL);
+
+ DBGOUT((3, "TSPI_providerShutdown: exit, lResult=x%x", lResult));
+
+ return lResult;
+}
+
+
+//
+// Private support funcs
+//
+
+void
+AsyncEventsThread(
+ LPVOID lpParams
+ )
+{
+ BOOL bReceivedLineEvents;
+ OVERLAPPED overlapped;
+ PNDISTAPI_EVENT_DATA pNewEventsBuf, pCurrentEventsBuf;
+
+
+ DBGOUT((3, "AsyncEventsThread: enter"));
+
+
+ // BUGBUG bufsize ought be based on reg setting for drivers
+
+ //
+ // There are 2 event data buffers so we can be getting new line events
+ // while processing current line events. Mark the current events buf
+ // (buf2 in this case) as having 0 events the 1st time thru.
+ //
+
+ pNewEventsBuf = gpAsyncEventsThreadInfo->pBuf1;
+
+ gpAsyncEventsThreadInfo->pBuf2->ulUsedSize = 0;
+
+ pCurrentEventsBuf = gpAsyncEventsThreadInfo->pBuf2;
+
+ bReceivedLineEvents = TRUE;
+
+
+ //
+ // Loop waiting for completed requests and retrieving async events
+ //
+
+ while (1)
+ {
+ DWORD i, cbReturned;
+ LPOVERLAPPED lpOverlapped;
+ PNDIS_TAPI_EVENT pEvent;
+
+
+ //
+ // Start an overlapped request to get new events
+ // (while we're processing the current ones)
+ //
+
+ if (bReceivedLineEvents)
+ {
+ //
+ // Don't need events when using completion ports
+ //
+
+ overlapped.hEvent = NULL;
+
+ pNewEventsBuf->ulTotalSize = gpAsyncEventsThreadInfo->dwBufSize -
+ sizeof(NDISTAPI_EVENT_DATA) + 1;
+
+ pNewEventsBuf->ulUsedSize = 0;
+
+ DBGOUT((4, "AsyncEventsThread: sending GET_LINE_EVENTS"));
+
+ if (DeviceIoControl(
+ ghDriverAsync,
+ (DWORD) IOCTL_NDISTAPI_GET_LINE_EVENTS,
+ pNewEventsBuf,
+ sizeof(NDISTAPI_EVENT_DATA),
+ pNewEventsBuf,
+ gpAsyncEventsThreadInfo->dwBufSize,
+ &cbReturned,
+ &overlapped
+
+ ) == FALSE)
+ {
+ }
+
+
+ //
+ // Handle the current events
+ //
+
+ pEvent = (PNDIS_TAPI_EVENT) pCurrentEventsBuf->Data;
+
+ for(i = 0;
+ i < (pCurrentEventsBuf->ulUsedSize / sizeof(NDIS_TAPI_EVENT));
+ i++
+ )
+ {
+ ProcessEvent (pEvent);
+ pEvent++;
+ }
+ }
+
+
+ //
+ // Wait for a request to complete
+ //
+
+ do
+ {
+ DWORD dwNumBytesTransferred, dwCompletionKey;
+
+
+ DBGOUT((3, "Calling GetQComplStat"));
+
+ if (GetQueuedCompletionStatus(
+ ghCompletionPort,
+ &dwNumBytesTransferred,
+ &dwCompletionKey,
+ &lpOverlapped,
+ (DWORD) -1 // infinite wait
+
+ ) == FALSE && (lpOverlapped == NULL))
+ {
+ DBGOUT((
+ 1,
+ "AsyncEventsThread: GetQComplStat failed, err=%d",
+ GetLastError()
+ ));
+ }
+
+ } while (lpOverlapped == NULL);
+
+
+ //
+ // Check the returned overlapped struct to determine if
+ // we have some events to process or a completed request
+ //
+
+ if (lpOverlapped == &overlapped)
+ {
+ bReceivedLineEvents = TRUE;
+
+ pNewEventsBuf = pCurrentEventsBuf;
+
+ pCurrentEventsBuf =
+ (pCurrentEventsBuf == gpAsyncEventsThreadInfo->pBuf1 ?
+ gpAsyncEventsThreadInfo->pBuf2 :
+ gpAsyncEventsThreadInfo->pBuf1);
+ }
+ else
+ {
+ LONG lResult;
+ DWORD dwRequestID, callStateMsgParams[5];
+ PASYNC_REQUEST_WRAPPER pAsyncReqWrapper = (PASYNC_REQUEST_WRAPPER)
+ lpOverlapped;
+
+
+ bReceivedLineEvents = FALSE;
+
+
+ //
+ // Verify that pointer is valid
+ //
+
+ try
+ {
+ if (pAsyncReqWrapper->dwKey != ASYNCREQWRAPPER_KEY)
+ {
+ DBGOUT((3,
+ "AsyncEventsThread: bogus pReq x%x completed!",
+ pAsyncReqWrapper
+ ));
+
+ continue;
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ DBGOUT((3,
+ "AsyncEventsThread: bogus pReq x%x completed!",
+ pAsyncReqWrapper
+ ));
+
+ continue;
+ }
+
+
+ //
+ //
+ //
+
+ if ((dwRequestID = pAsyncReqWrapper->dwRequestID) == 0xffffffff)
+ {
+ DBGOUT((3, "AsyncEventsThread: exit"));
+
+ ExitThread (0);
+ }
+
+ lResult = TranslateDriverResult(
+ pAsyncReqWrapper->NdisTapiRequest.ulReturnValue
+ );
+
+ DBGOUT((3,
+ "AsyncEventsThread: pReq=x%x completed, reqID=x%x, lResult=x%x",
+ pAsyncReqWrapper,
+ dwRequestID,
+ lResult
+ ));
+
+
+ //
+ // Call the post processing proc if appropriate
+ //
+
+ callStateMsgParams[0] = 0;
+
+ if (pAsyncReqWrapper->pfnPostProcess)
+ {
+ (*pAsyncReqWrapper->pfnPostProcess)(
+ pAsyncReqWrapper,
+ lResult,
+ callStateMsgParams
+ );
+ }
+
+
+
+ //
+ // Free the async request wrapper
+ //
+
+ DrvFree (pAsyncReqWrapper);
+
+
+ //
+ // Call completion proc
+ //
+
+ (*gpfnCompletionProc)(dwRequestID, lResult);
+
+ if (callStateMsgParams[0])
+ {
+ (*gpfnLineEvent)(
+ (HTAPILINE) callStateMsgParams[0],
+ (HTAPICALL) callStateMsgParams[1],
+ (DWORD) LINE_CALLSTATE,
+ (DWORD) callStateMsgParams[2],
+ (DWORD) callStateMsgParams[3],
+ (DWORD) callStateMsgParams[4]
+ );
+ }
+ }
+
+ } // while
+}
+
+
+LONG
+WINAPI
+PrepareSyncRequest(
+ ULONG Oid,
+ LPDWORD lphWidget,
+ DWORD dwWidgetType,
+ PNDISTAPI_REQUEST *ppNdisTapiRequest,
+ DWORD dwDataSize
+ )
+{
+ LONG lResult = 0;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+ PREQUEST_THREAD_INFO pRequestThreadInfo;
+
+
+ //
+ // Retrieve the thread local storage (if there is none then create some)
+ //
+
+ if ((pRequestThreadInfo = TlsGetValue (gdwTlsIndex)) == NULL)
+ {
+ if (!(pRequestThreadInfo = DrvAlloc (sizeof(REQUEST_THREAD_INFO))))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ pRequestThreadInfo->dwBufSize = INITIAL_TLS_BUF_SIZE;
+
+ if (!(pRequestThreadInfo->pBuf = DrvAlloc (INITIAL_TLS_BUF_SIZE)))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ TlsSetValue (gdwTlsIndex, (LPVOID) pRequestThreadInfo);
+ }
+
+
+ //
+ // Check to make sure our driver request buffer is big enough to
+ // hold all the data for this request
+ //
+
+ if (pRequestThreadInfo->dwBufSize < (dwDataSize+sizeof(NDISTAPI_REQUEST)))
+ {
+ PNDISTAPI_REQUEST pTmpDrvReqBuf;
+
+
+ if (!(pTmpDrvReqBuf = DrvAlloc (dwDataSize+sizeof(NDISTAPI_REQUEST))))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ DrvFree (pRequestThreadInfo->pBuf);
+
+ pRequestThreadInfo->pBuf = pTmpDrvReqBuf;
+
+ pRequestThreadInfo->dwBufSize = dwDataSize;
+ }
+
+ pNdisTapiRequest = pRequestThreadInfo->pBuf;
+
+
+ //
+ // Safely initialize thie driver request
+ //
+
+ pNdisTapiRequest->Oid = Oid;
+ pNdisTapiRequest->ulDataSize = (DWORD) dwDataSize;
+
+ try
+ {
+ switch (dwWidgetType)
+ {
+ case HT_HDCALL:
+ {
+ PDRVCALL pCall = (PDRVCALL)(*lphWidget);
+
+
+ pNdisTapiRequest->ulDeviceID = pCall->dwDeviceID;
+ *lphWidget = pCall->hd_Call;
+
+ if (pCall->dwKey != INBOUND_CALL_KEY &&
+ pCall->dwKey != OUTBOUND_CALL_KEY)
+ {
+ lResult = LINEERR_INVALCALLHANDLE;
+ }
+
+ break;
+ }
+ case HT_HDLINE:
+ {
+ PDRVLINE pLine = (PDRVLINE)(*lphWidget);
+
+
+ pNdisTapiRequest->ulDeviceID = pLine->dwDeviceID;
+ *lphWidget = pLine->hd_Line;
+
+ if (pLine->dwKey != LINE_KEY)
+ {
+ lResult = LINEERR_INVALLINEHANDLE;
+ }
+
+ break;
+ }
+ case HT_DEVICEID:
+
+ pNdisTapiRequest->ulDeviceID = *((ULONG *) lphWidget);
+ break;
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ lResult = (dwWidgetType == HT_HDCALL ? LINEERR_INVALCALLHANDLE :
+ LINEERR_INVALLINEHANDLE);
+ }
+
+ // Note: since request buf is tls we don't have to free it on error
+
+ EnterCriticalSection (&gRequestIDCritSec);
+
+ if (( *((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID) >= 0x7fffffff)
+ {
+ gdwRequestID = 1;
+ }
+
+ LeaveCriticalSection (&gRequestIDCritSec);
+
+ *ppNdisTapiRequest = pNdisTapiRequest;
+
+ return lResult;
+}
+
+
+LONG
+WINAPI
+PrepareAsyncRequest(
+ ULONG Oid,
+ LPDWORD lphWidget,
+ DWORD dwWidgetType,
+ DWORD dwRequestID,
+ PASYNC_REQUEST_WRAPPER *ppAsyncRequestWrapper,
+ DWORD dwDataSize
+ )
+{
+ LONG lResult = 0;
+ PNDISTAPI_REQUEST pNdisTapiRequest;
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
+
+
+ //
+ // Alloc & init an async request wrapper
+ //
+
+ if (!(pAsyncRequestWrapper = DrvAlloc(
+ dwDataSize + sizeof(ASYNC_REQUEST_WRAPPER)
+ )))
+ {
+ return LINEERR_NOMEM;
+ }
+
+
+ //
+ // Don't need to create an event when using completion ports
+ //
+
+ pAsyncRequestWrapper->Overlapped.hEvent = (HANDLE) NULL;
+
+ pAsyncRequestWrapper->dwKey = ASYNCREQWRAPPER_KEY;
+ pAsyncRequestWrapper->dwRequestID = dwRequestID;
+ pAsyncRequestWrapper->pfnPostProcess = (POSTPROCESSPROC) NULL;
+
+
+ //
+ // Safely initialize the driver request
+ //
+
+ pNdisTapiRequest = &(pAsyncRequestWrapper->NdisTapiRequest);
+
+ pNdisTapiRequest->Oid = Oid;
+ pNdisTapiRequest->ulDataSize = (ULONG) dwDataSize;
+
+ try
+ {
+ if (dwWidgetType == HT_HDCALL)
+ {
+ pNdisTapiRequest->ulDeviceID =
+ ((PDRVCALL)(*lphWidget))->dwDeviceID;
+ *lphWidget = ((PDRVCALL)(*lphWidget))->hd_Call;
+ }
+ else // HT_HDLINE
+ {
+ pNdisTapiRequest->ulDeviceID =
+ ((PDRVLINE)(*lphWidget))->dwDeviceID;
+ *lphWidget = ((PDRVLINE)(*lphWidget))->hd_Line;
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ lResult = (dwWidgetType == HT_HDCALL ? LINEERR_INVALCALLHANDLE :
+ LINEERR_INVALLINEHANDLE);
+ }
+
+ if (lResult == 0)
+ {
+ EnterCriticalSection (&gRequestIDCritSec);
+
+ if (( *((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID)
+ >= 0x7fffffff)
+ {
+ gdwRequestID = 1;
+ }
+
+ LeaveCriticalSection (&gRequestIDCritSec);
+
+ *ppAsyncRequestWrapper = pAsyncRequestWrapper;
+ }
+ else
+ {
+ DrvFree (pAsyncRequestWrapper);
+ }
+
+ return lResult;
+}
+
+
+#if DBG
+static char *pszOidNames[] =
+{
+ "Accept",
+ "Answer",
+ "Close",
+ "CloseCall",
+ "ConditionalMediaDetection",
+ "ConfigDialog",
+ "DevSpecific",
+ "Dial",
+ "Drop",
+ "GetAddressCaps",
+ "GetAddressID",
+ "GetAddressStatus",
+ "GetCallAddressID",
+ "GetCallInfo",
+ "GetCallStatus",
+ "GetDevCaps",
+ "GetDevConfig",
+ "GetExtensionID",
+ "GetID",
+ "GetLineDevStatus",
+ "MakeCall",
+ "NegotiateExtVersion",
+ "Open",
+ "ProviderInitialize",
+ "ProviderShutdown",
+ "SecureCall",
+ "SelectExtVersion",
+ "SendUserUserInfo",
+ "SetAppSpecific",
+ "StCallParams",
+ "StDefaultMediaDetection",
+ "SetDevConfig",
+ "SetMediaMode",
+ "SetStatusMessages"
+};
+#endif
+
+LONG
+WINAPI
+SyncDriverRequest(
+ DWORD dwIoControlCode,
+ PNDISTAPI_REQUEST pNdisTapiRequest
+ )
+{
+ //
+ // This routine makes a non-overlapped request to NdisTapi.sys (so it
+ // doesn't return until the request is completed)
+ //
+
+ BOOL bResult;
+ DWORD cbReturned;
+
+
+ DBGOUT((
+ 3,
+ "SyncDrvReq: Oid=%s, devID=%d, dataSize=%d, reqID=x%x, p1=x%x",
+ pszOidNames[pNdisTapiRequest->Oid - OID_TAPI_ACCEPT],
+ pNdisTapiRequest->ulDeviceID,
+ pNdisTapiRequest->ulDataSize,
+ *((ULONG *)pNdisTapiRequest->Data),
+ *(((ULONG *)pNdisTapiRequest->Data) + 1)
+ ));
+
+ if (DeviceIoControl(
+ ghDriverSync,
+ dwIoControlCode,
+ pNdisTapiRequest,
+ (DWORD) (sizeof(NDISTAPI_REQUEST) + pNdisTapiRequest->ulDataSize),
+ pNdisTapiRequest,
+ (DWORD) (sizeof(NDISTAPI_REQUEST) + pNdisTapiRequest->ulDataSize),
+ &cbReturned,
+ 0
+
+ ) == FALSE)
+ {
+ }
+
+ //
+ // The errors returned by NdisTapi.sys don't match the TAPI LINEERR_'s,
+ // so return the translated value (but preserve the original driver
+ // return val so it's possible to distinguish between
+ // NDISTAPIERR_DEVICEOFFLINE & LINEERR_OPERATIONUNAVAIL, etc.)
+ //
+
+ return (TranslateDriverResult (pNdisTapiRequest->ulReturnValue));
+}
+
+
+LONG
+WINAPI
+AsyncDriverRequest(
+ DWORD dwIoControlCode,
+ PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper
+ )
+{
+ BOOL bResult;
+ LONG lResult;
+ DWORD dwRequestSize, cbReturned, dwLastError;
+
+
+ DBGOUT((
+ 3,
+ "AsyncDrvReq: pReq=x%x, Oid=%s, devID=%d, dataSize=%d, reqID=x%x, ddReqID=x%x, p1=x%x",
+ pAsyncRequestWrapper,
+ pszOidNames
+ [pAsyncRequestWrapper->NdisTapiRequest.Oid - OID_TAPI_ACCEPT],
+ pAsyncRequestWrapper->NdisTapiRequest.ulDeviceID,
+ pAsyncRequestWrapper->NdisTapiRequest.ulDataSize,
+ pAsyncRequestWrapper->dwRequestID,
+ *((ULONG *)pAsyncRequestWrapper->NdisTapiRequest.Data),
+ *(((ULONG *)pAsyncRequestWrapper->NdisTapiRequest.Data) + 1)
+ ));
+
+ lResult = (LONG) pAsyncRequestWrapper->dwRequestID;
+
+ dwRequestSize = sizeof(NDISTAPI_REQUEST) +
+ (pAsyncRequestWrapper->NdisTapiRequest.ulDataSize - 1);
+
+ bResult = DeviceIoControl(
+ ghDriverAsync,
+ dwIoControlCode,
+ &pAsyncRequestWrapper->NdisTapiRequest,
+ dwRequestSize,
+ &pAsyncRequestWrapper->NdisTapiRequest,
+ dwRequestSize,
+ &cbReturned,
+ &pAsyncRequestWrapper->Overlapped
+ );
+
+ dwLastError = GetLastError();
+
+ if ((bResult == FALSE) && (dwLastError == ERROR_IO_PENDING))
+ {
+ //
+ // Request is pending, just return (async events thread will
+ // take care of it when it completes)
+ //
+ }
+ else if (bResult == TRUE)
+ {
+ //
+ // Request completed synchronously, so call the completion proc
+ // & clean up
+ //
+
+ (*gpfnCompletionProc)(
+ pAsyncRequestWrapper->dwRequestID,
+ TranslateDriverResult(
+ pAsyncRequestWrapper->NdisTapiRequest.ulReturnValue
+ )
+ );
+
+ DrvFree (pAsyncRequestWrapper);
+ }
+ else
+ {
+ //
+ // Error
+ //
+
+ DBGOUT((1, "AsyncDrvReq: DevIoCtl failed, err=%d", dwLastError));
+ }
+
+ return lResult;
+}
+
+
+BOOL
+WINAPI
+ConvertLineAndCallHandles(
+ HTAPI_LINE *pht_Line,
+ HTAPI_CALL *pht_Call
+ )
+{
+ PDRVCALL pCall;
+ PDRVLINE pLine = (PDRVLINE) *pht_Line;
+
+
+ //
+ // Check to see that pLine is 64-bit aligned & has a good key
+ //
+
+ {
+ BOOL bBadLine;
+
+
+ try
+ {
+ if (!((DWORD) pLine & 0x7) && pLine->dwKey == LINE_KEY)
+ {
+ *pht_Line = (HTAPI_LINE) pLine->htLine;
+ bBadLine = FALSE;
+ }
+ else
+ {
+ bBadLine = TRUE;
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ bBadLine = TRUE;
+ }
+
+ if (bBadLine)
+ {
+ return FALSE;
+ }
+ }
+
+
+ //
+ // Incoming calls will have a pCall with the high bit set (a value
+ // created by ndistapi), while outgoing calls won't have the high
+ // bit set (since they're real ptrs in app space [the low 2 gig])
+ //
+
+ pCall = (PDRVCALL) *pht_Call;
+
+ if ((DWORD) pCall < 0x80000000)
+ {
+ BOOL bResult;
+
+
+ try
+ {
+ //
+ // Check that pCall is 64-bit aligned & has a good key
+ //
+
+ if (!((DWORD) pCall & 0x7) &&
+ pCall->dwKey == OUTBOUND_CALL_KEY)
+ {
+ *pht_Call = (HTAPI_CALL) pCall->htCall;
+ bResult = TRUE;
+ }
+ else
+ {
+ bResult = FALSE;
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ bResult = FALSE;
+ }
+
+ return bResult;
+ }
+
+
+ //
+ // If here it's an inbound call, so we need to walk the list
+ // of inbound pCalls on this line & find the right one
+ //
+
+ {
+ BOOL bInCriticalSection;
+
+
+ try
+ {
+ HTAPI_CALL ht_Call;
+
+
+ EnterCriticalSection (&gInboundCallsCritSec);
+
+ bInCriticalSection = TRUE;
+
+ if ((pCall = pLine->pInboundCalls))
+ {
+ ht_Call = *pht_Call;
+
+ while (pCall && (pCall->ht_Call != ht_Call))
+ {
+ pCall = pCall->pNext;
+ }
+ }
+
+ LeaveCriticalSection (&gInboundCallsCritSec);
+
+ bInCriticalSection = FALSE;
+
+ *pht_Call = (pCall ? (HTAPI_CALL)pCall->htCall : (HTAPI_CALL)NULL);
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ if (bInCriticalSection)
+ {
+ LeaveCriticalSection (&gInboundCallsCritSec);
+ }
+
+ pCall = NULL;
+ }
+ }
+
+ return (pCall ? TRUE : FALSE);
+}
+
+
+BOOL
+WINAPI
+ConvertLineHandle(
+ HTAPI_LINE *pht_Line
+ )
+{
+ PDRVLINE pLine = (PDRVLINE) *pht_Line;
+
+
+ //
+ // Check to see that pLine is 64-bit aligned & has a good key
+ //
+
+ try
+ {
+ if (!((DWORD) pLine & 0x7) && pLine->dwKey == LINE_KEY)
+ {
+ *pht_Line = (HTAPI_LINE) pLine->htLine;
+ return TRUE;
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ // just fall thru
+ }
+
+ DBGOUT((4, "ConvertLineHandle: bad htLine=x%x", *pht_Line));
+
+ return FALSE;
+}
+
+
+LPVOID
+WINAPI
+DrvAlloc(
+ DWORD dwSize
+ )
+{
+ LPBYTE p;
+ LPDWORD pAligned;
+
+
+ //
+ // Alloc 16 extra bytes so we can make sure the pointer we pass back
+ // is 64-bit aligned & have space to store the original pointer
+ //
+
+ if ((p = (LPBYTE) LocalAlloc (LPTR, dwSize + 16)))
+ {
+ pAligned = (LPDWORD) (p + 8 - (((DWORD) p) & 0x7));
+ *pAligned = (DWORD) p;
+ pAligned++;
+ pAligned++;
+ }
+ else
+ {
+ // send reinit msg?
+
+ DBGOUT((
+ 1,
+ "ServerAlloc: LocalAlloc (x%lx) failed, err=x%lx",
+ dwSize,
+ GetLastError())
+ );
+
+ pAligned = NULL;
+ }
+
+ return ((LPVOID) pAligned);
+}
+
+
+VOID
+WINAPI
+DrvFree(
+ LPVOID p
+ )
+{
+ LPVOID pOrig = (LPVOID) *(((LPDWORD) p) - 2);
+
+
+ LocalFree (pOrig);
+}
+
+
+VOID
+WINAPI
+ProcessEvent(
+ PNDIS_TAPI_EVENT pEvent
+ )
+{
+ ULONG ulMsg = pEvent->ulMsg;
+ HTAPI_LINE ht_Line = (HTAPI_LINE) pEvent->htLine;
+
+
+ DBGOUT((
+ 4,
+ "ProcessEvent: enter, msg=x%x, pLine=x%x, ht_call=x%x",
+ ulMsg,
+ ht_Line,
+ pEvent->htCall
+ ));
+
+ DBGOUT((
+ 4,
+ "ProcessEvent: \tp1=x%x, p2=x%x, p3=x%x",
+ pEvent->ulParam1,
+ pEvent->ulParam2,
+ pEvent->ulParam3
+ ));
+
+ switch (ulMsg)
+ {
+ case LINE_ADDRESSSTATE:
+ case LINE_CLOSE:
+ case LINE_DEVSPECIFIC:
+ case LINE_LINEDEVSTATE:
+
+ if (ConvertLineHandle (&ht_Line))
+ {
+ (*gpfnLineEvent)(
+ (HTAPILINE) ht_Line,
+ (HTAPICALL) NULL,
+ (DWORD) ulMsg,
+ (DWORD) pEvent->ulParam1,
+ (DWORD) pEvent->ulParam2,
+ (DWORD) pEvent->ulParam3
+ );
+ }
+
+ break;
+
+ case LINE_CALLDEVSPECIFIC:
+ case LINE_CALLINFO:
+
+ if (ConvertLineAndCallHandles (&ht_Line, &pEvent->htCall))
+ {
+ (*gpfnLineEvent)(
+ (HTAPILINE) ht_Line,
+ (HTAPICALL) pEvent->htCall,
+ (DWORD) ulMsg,
+ (DWORD) pEvent->ulParam1,
+ (DWORD) pEvent->ulParam2,
+ (DWORD) pEvent->ulParam3
+ );
+ }
+
+ break;
+
+ case LINE_CALLSTATE:
+ {
+ //
+ // For outgoing calls there exists a race condition between
+ // receiving the first call state msg(s) and receiving the
+ // make call completion notification (if we pass a call state
+ // msg on to tapi for a call that hasn't been completed yet
+ // tapi will just discard the msg since the htCall really
+ // isn't valid at that point). So if htCall references a
+ // valid outgoing call which hasn't completed yet, we'll save
+ // the call state params, and pass them on to tapi after we
+ // get & indicate a (successful) completion notification.
+ //
+ // (Note: incoming calls have high bit turned off)
+ //
+
+ PDRVCALL pCall = (PDRVCALL) pEvent->htCall;
+
+
+ if ((DWORD) pCall < 0x80000000 && !((DWORD) pCall & 0x7))
+ {
+ try
+ {
+ if (pCall->dwKey == OUTBOUND_CALL_KEY &&
+ pCall->bIncomplete == TRUE)
+ {
+ pCall->dwPendingCallState = pEvent->ulParam1;
+ pCall->dwPendingCallStateMode = pEvent->ulParam2;
+ pCall->dwPendingMediaMode = pEvent->ulParam3;
+
+ break;
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ break;
+ }
+ }
+
+ if (ConvertLineAndCallHandles (&ht_Line, &pEvent->htCall))
+ {
+ (*gpfnLineEvent)(
+ (HTAPILINE) ht_Line,
+ (HTAPICALL) pEvent->htCall,
+ (DWORD) ulMsg,
+ (DWORD) pEvent->ulParam1,
+ (DWORD) pEvent->ulParam2,
+ (DWORD) pEvent->ulParam3
+ );
+
+
+ //
+ // For old style miniports we want to indicate an IDLE
+ // immediately following the disconnected (several of
+ // the initial NDIS WAN miniports did not indicate an
+ // IDLE call state due to doc confusion)
+ //
+ // BUGBUG make sure we don't do this for new style
+ // drivers (new style == anything that supports
+ // OID_TAPI_NEGOTIATE_API_VERSION)
+ //
+
+ if (pEvent->ulParam1 == LINECALLSTATE_DISCONNECTED)
+ {
+ (*gpfnLineEvent)(
+ (HTAPILINE) ht_Line,
+ (HTAPICALL) pEvent->htCall,
+ (DWORD) ulMsg,
+ (DWORD) LINECALLSTATE_IDLE,
+ (DWORD) 0,
+ (DWORD) pEvent->ulParam3
+ );
+ }
+ }
+
+ break;
+ }
+ case LINE_NEWCALL:
+ {
+ BOOL bInCriticalSection = FALSE;
+ PDRVCALL pCall;
+ PDRVLINE pLine = (PDRVLINE) ht_Line;
+
+
+ if (!(pCall = DrvAlloc (sizeof(DRVCALL))))
+ {
+// BUGBUG LINE_NEWCALL: couldn't alloc drvCall, send drop/dealloc call OIDs
+
+ break;
+ }
+
+ pCall->dwKey = INBOUND_CALL_KEY;
+ pCall->ht_Call = (HTAPI_CALL) pEvent->ulParam2;
+ pCall->hd_Call = (HDRV_CALL) pEvent->ulParam1;
+ pCall->pLine = pLine;
+ //pCall->bIncomplete = FALSE; (already 0'd by alloc)
+
+ try
+ {
+ pCall->dwDeviceID = pLine->dwDeviceID;
+
+ EnterCriticalSection (&gInboundCallsCritSec);
+
+ bInCriticalSection = TRUE;
+
+ if (pLine->dwKey == LINE_KEY)
+ {
+ //
+ // Insert new call into inbound calls list
+ //
+
+ if ((pCall->pNext = pLine->pInboundCalls))
+ {
+ pCall->pNext->pPrev = pCall;
+ }
+
+ pLine->pInboundCalls = pCall;
+ }
+ else
+ {
+ //
+ // Line was closed after this msg was sent, so clean up
+ //
+
+ DrvFree (pCall);
+ pCall = NULL;
+ }
+
+ LeaveCriticalSection (&gInboundCallsCritSec);
+
+ bInCriticalSection = FALSE;
+
+ if (pCall)
+ {
+ (*gpfnLineEvent)(
+ (HTAPILINE) pLine->htLine,
+ (HTAPICALL) NULL,
+ ulMsg,
+ (DWORD) pCall,
+ (DWORD) &pCall->htCall,
+ 0
+ );
+ }
+ }
+ except (EXCEPTION_EXECUTE_HANDLER)
+ // we expect some AVs and alignment faults
+ {
+ if (bInCriticalSection)
+ {
+ LeaveCriticalSection (&gInboundCallsCritSec);
+ }
+
+ DrvFree (pCall);
+ }
+
+// BUGBUG check if pCall->htCall is NULL (tapi couldn't deal w/ newcall)
+
+ break;
+ }
+ default:
+
+ DBGOUT((2, "ProcessEvent: unknown msg, x%x", ulMsg));
+
+ break;
+
+ } // switch
+}
+
+
+LONG
+WINAPI
+TranslateDriverResult(
+ ULONG ulResult
+ )
+{
+ typedef struct _RESULT_LOOKUP
+ {
+ ULONG NdisTapiResult;
+
+ LONG TapiResult;
+
+ } RESULT_LOOKUP, *PRESULT_LOOKUP;
+
+#ifdef MYHACK
+
+ typedef ULONG NDIS_STATUS;
+
+ #define NDIS_STATUS_SUCCESS 0x00000000L
+ #define NDIS_STATUS_RESOURCES 0xC000009AL
+ #define NDIS_STATUS_FAILURE 0xC0000001L
+
+#endif
+
+ static RESULT_LOOKUP aResults[] =
+ {
+
+ //
+ // Defined in NDIS.H
+ //
+
+ { NDIS_STATUS_SUCCESS ,0 },
+
+ //
+ // These errors are defined in NDISTAPI.H
+ //
+
+ { NDIS_STATUS_TAPI_ADDRESSBLOCKED ,LINEERR_ADDRESSBLOCKED },
+ { NDIS_STATUS_TAPI_BEARERMODEUNAVAIL ,LINEERR_BEARERMODEUNAVAIL },
+ { NDIS_STATUS_TAPI_CALLUNAVAIL ,LINEERR_CALLUNAVAIL },
+ { NDIS_STATUS_TAPI_DIALBILLING ,LINEERR_DIALBILLING },
+ { NDIS_STATUS_TAPI_DIALDIALTONE ,LINEERR_DIALDIALTONE },
+ { NDIS_STATUS_TAPI_DIALPROMPT ,LINEERR_DIALPROMPT },
+ { NDIS_STATUS_TAPI_DIALQUIET ,LINEERR_DIALQUIET },
+ { NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION,LINEERR_INCOMPATIBLEEXTVERSION},
+ { NDIS_STATUS_TAPI_INUSE ,LINEERR_INUSE },
+ { NDIS_STATUS_TAPI_INVALADDRESS ,LINEERR_INVALADDRESS },
+ { NDIS_STATUS_TAPI_INVALADDRESSID ,LINEERR_INVALADDRESSID },
+ { NDIS_STATUS_TAPI_INVALADDRESSMODE ,LINEERR_INVALADDRESSMODE },
+ { NDIS_STATUS_TAPI_INVALBEARERMODE ,LINEERR_INVALBEARERMODE },
+ { NDIS_STATUS_TAPI_INVALCALLHANDLE ,LINEERR_INVALCALLHANDLE },
+ { NDIS_STATUS_TAPI_INVALCALLPARAMS ,LINEERR_INVALCALLPARAMS },
+ { NDIS_STATUS_TAPI_INVALCALLSTATE ,LINEERR_INVALCALLSTATE },
+ { NDIS_STATUS_TAPI_INVALDEVICECLASS ,LINEERR_INVALDEVICECLASS },
+ { NDIS_STATUS_TAPI_INVALLINEHANDLE ,LINEERR_INVALLINEHANDLE },
+ { NDIS_STATUS_TAPI_INVALLINESTATE ,LINEERR_INVALLINESTATE },
+ { NDIS_STATUS_TAPI_INVALMEDIAMODE ,LINEERR_INVALMEDIAMODE },
+ { NDIS_STATUS_TAPI_INVALRATE ,LINEERR_INVALRATE },
+ { NDIS_STATUS_TAPI_NODRIVER ,LINEERR_NODRIVER },
+ { NDIS_STATUS_TAPI_OPERATIONUNAVAIL ,LINEERR_OPERATIONUNAVAIL },
+ { NDIS_STATUS_TAPI_RATEUNAVAIL ,LINEERR_RATEUNAVAIL },
+ { NDIS_STATUS_TAPI_RESOURCEUNAVAIL ,LINEERR_RESOURCEUNAVAIL },
+ { NDIS_STATUS_TAPI_STRUCTURETOOSMALL ,LINEERR_STRUCTURETOOSMALL },
+ { NDIS_STATUS_TAPI_USERUSERINFOTOOBIG ,LINEERR_USERUSERINFOTOOBIG },
+ { NDIS_STATUS_TAPI_ALLOCATED ,LINEERR_ALLOCATED },
+ { NDIS_STATUS_TAPI_INVALADDRESSSTATE ,LINEERR_INVALADDRESSSTATE },
+ { NDIS_STATUS_TAPI_INVALPARAM ,LINEERR_INVALPARAM },
+ { NDIS_STATUS_TAPI_NODEVICE ,LINEERR_NODEVICE },
+
+ //
+ // These errors are defined in NDIS.H
+ //
+
+ { NDIS_STATUS_RESOURCES ,LINEERR_NOMEM },
+ { NDIS_STATUS_FAILURE ,LINEERR_OPERATIONFAILED },
+
+ //
+ //
+ //
+
+ { NDISTAPIERR_UNINITIALIZED ,LINEERR_OPERATIONFAILED },
+ { NDISTAPIERR_BADDEVICEID ,LINEERR_OPERATIONFAILED },
+ { NDISTAPIERR_DEVICEOFFLINE ,LINEERR_OPERATIONFAILED },
+
+ //
+ // The terminating fields
+ //
+
+ { 0xffffffff, 0xffffffff }
+
+ };
+
+ int i;
+
+
+ for (i = 0; aResults[i].NdisTapiResult != 0xffffffff; i++)
+ {
+ if (ulResult == aResults[i].NdisTapiResult)
+ {
+ return (aResults[i].TapiResult);
+ }
+ }
+
+ DBGOUT((1, "TranslateDriverResult: unknown driver result x%x", ulResult));
+
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+#if DBG
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & callsOutputDebugStringA
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+{
+ if (dwDbgLevel <= gdwDebugLevel)
+ {
+ int iNumChars;
+ char buf[192] = "KMDDSP: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ iNumChars = wvsprintfA (&buf[8], lpszFormat, ap);
+
+ buf[iNumChars] = '\n';
+ buf[iNumChars + 1] = 0;
+
+ OutputDebugStringA (buf);
+
+ va_end(ap);
+ }
+}
+#endif
diff --git a/private/tapi/dev/sp/kmddsp/kmddsp.def b/private/tapi/dev/sp/kmddsp/kmddsp.def
new file mode 100644
index 000000000..5c302d179
--- /dev/null
+++ b/private/tapi/dev/sp/kmddsp/kmddsp.def
@@ -0,0 +1,107 @@
+LIBRARY KMDDSP
+
+DATA READ WRITE
+
+EXPORTS
+
+ TSPI_lineAccept
+; TSPI_lineAddToConference
+ TSPI_lineAnswer
+; TSPI_lineBlindTransfer
+ TSPI_lineClose
+ TSPI_lineCloseCall
+; TSPI_lineCompleteCall
+; TSPI_lineCompleteTransfer
+ TSPI_lineConditionalMediaDetection
+ TSPI_lineDevSpecific
+; TSPI_lineDevSpecificFeature
+ TSPI_lineDial
+ TSPI_lineDrop
+; TSPI_lineForward
+; TSPI_lineGatherDigits
+; TSPI_lineGenerateDigits
+; TSPI_lineGenerateTone
+ TSPI_lineGetAddressCaps
+ TSPI_lineGetAddressID
+ TSPI_lineGetAddressStatus
+ TSPI_lineGetCallAddressID
+ TSPI_lineGetCallInfo
+ TSPI_lineGetCallStatus
+ TSPI_lineGetDevCaps
+ TSPI_lineGetDevConfig
+ TSPI_lineGetExtensionID
+; TSPI_lineGetIcon
+ TSPI_lineGetID
+ TSPI_lineGetLineDevStatus
+ TSPI_lineGetNumAddressIDs
+; TSPI_lineHold
+ TSPI_lineMakeCall
+; TSPI_lineMonitorDigits
+; TSPI_lineMonitorMedia
+; TSPI_lineMonitorTones
+ TSPI_lineNegotiateExtVersion
+ TSPI_lineNegotiateTSPIVersion
+ TSPI_lineOpen
+; TSPI_linePark
+; TSPI_linePickup
+; TSPI_linePrepareAddToConference
+; TSPI_lineRedirect
+; TSPI_lineRemoveFromConference
+ TSPI_lineSecureCall
+ TSPI_lineSelectExtVersion
+ TSPI_lineSendUserUserInfo
+ TSPI_lineSetAppSpecific
+ TSPI_lineSetCallParams
+ TSPI_lineSetDefaultMediaDetection
+ TSPI_lineSetDevConfig
+; TSPI_lineSetMediaControl
+ TSPI_lineSetMediaMode
+ TSPI_lineSetStatusMessages
+; TSPI_lineSetTerminal
+; TSPI_lineSetupConference
+; TSPI_lineSetupTransfer
+; TSPI_lineSwapHold
+; TSPI_lineUncompleteCall
+; TSPI_lineUnhold
+; TSPI_lineUnpark
+
+; TSPI_phoneClose
+; TSPI_phoneDevSpecific
+; TSPI_phoneGetButtonInfo
+; TSPI_phoneGetData
+; TSPI_phoneGetDevCaps
+; TSPI_phoneGetDisplay
+; TSPI_phoneGetExtensionID
+; TSPI_phoneGetGain
+; TSPI_phoneGetHookSwitch
+; TSPI_phoneGetIcon
+; TSPI_phoneGetID
+; TSPI_phoneGetLamp
+; TSPI_phoneGetRing
+; TSPI_phoneGetStatus
+; TSPI_phoneGetVolume
+; TSPI_phoneNegotiateExtVersion
+; TSPI_phoneNegotiateTSPIVersion
+; TSPI_phoneOpen
+; TSPI_phoneSelectExtVersion
+; TSPI_phoneSetButtonInfo
+; TSPI_phoneSetData
+; TSPI_phoneSetDisplay
+; TSPI_phoneSetGain
+; TSPI_phoneSetHookSwitch
+; TSPI_phoneSetLamp
+; TSPI_phoneSetRing
+; TSPI_phoneSetStatusMessages
+; TSPI_phoneSetVolume
+
+; TSPI_providerConfig
+ TSPI_providerInit
+; TSPI_providerInstall
+; TSPI_providerRemove
+ TSPI_providerShutdown
+
+ TSPI_providerEnumDevices
+; TSPI_providerCreateLineDevice
+; TSPI_providerCreatePhoneDevice
+; TSPI_lineSetCurrentLocation
+; TSPI_lineReleaseUserUserInfo
diff --git a/private/tapi/dev/sp/kmddsp/kmddsp.h b/private/tapi/dev/sp/kmddsp/kmddsp.h
new file mode 100644
index 000000000..6f970b8e4
--- /dev/null
+++ b/private/tapi/dev/sp/kmddsp/kmddsp.h
@@ -0,0 +1,152 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ kmddsp.h
+
+Abstract:
+
+ Header file for tapi client module
+
+Author:
+
+ Dan Knudson (DanKn) 11-Apr-1995
+
+Revision History:
+
+--*/
+
+
+#define OUTBOUND_CALL_KEY ((DWORD) 'OCAL')
+#define INBOUND_CALL_KEY ((DWORD) 'ICAL')
+#define LINE_KEY ((DWORD) 'KLIN')
+#define ASYNCREQWRAPPER_KEY ((DWORD) 'ARWK')
+#define INVALID_KEY ((DWORD) 'XXXX')
+
+#define HT_HDCALL 1
+#define HT_HDLINE 2
+#define HT_DEVICEID 3
+
+#define TAPI_SUCCESS 0
+#define INITIAL_TLS_BUF_SIZE 1024
+
+
+typedef LONG (*POSTPROCESSPROC)(PASYNC_REQUEST_WRAPPER, LONG, LPDWORD);
+
+
+typedef struct _REQUEST_THREAD_INFO
+{
+ //
+ // Size of following buffer
+ //
+
+ DWORD dwBufSize;
+
+ //
+ // Pointer to a buffer used for making synchronous kernel-mode
+ // driver requests
+ //
+
+ LPVOID pBuf;
+
+} REQUEST_THREAD_INFO, *PREQUEST_THREAD_INFO;
+
+
+typedef struct _ASYNC_REQUEST_WRAPPER
+{
+ //
+ // Note: Overlapped must remain 1st field in this struct
+ //
+
+ OVERLAPPED Overlapped;
+
+ DWORD dwKey;
+
+ DWORD dwRequestID;
+
+ DWORD dwRequestSpecific;
+
+ POSTPROCESSPROC pfnPostProcess;
+
+ NDISTAPI_REQUEST NdisTapiRequest;
+
+} ASYNC_REQUEST_WRAPPER, *PASYNC_REQUEST_WRAPPER;
+
+
+typedef struct _ASYNC_EVENTS_THREAD_INFO
+{
+ //
+ // Thread handle (used when terminating thread)
+ //
+
+ HANDLE hThread;
+
+ //
+ // Size of following buffers
+ //
+
+ DWORD dwBufSize;
+
+ //
+ // Pointers to buffers used for gathering async events for driver
+ //
+
+ PNDISTAPI_EVENT_DATA pBuf1;
+
+ PNDISTAPI_EVENT_DATA pBuf2;
+
+} ASYNC_EVENTS_THREAD_INFO, *PASYNC_EVENTS_THREAD_INFO;
+
+
+typedef struct _DRVCALL
+{
+ DWORD dwKey;
+
+ DWORD dwDeviceID;
+
+ HTAPICALL htCall;
+
+ HTAPI_CALL ht_Call;
+
+ HDRV_CALL hd_Call;
+
+ LPVOID pLine;
+
+ BOOL bIncomplete;
+
+ BOOL bDropped;
+
+ union
+ {
+ struct _DRVCALL *pPrev; // for incoming calls
+
+ DWORD dwPendingCallState; // for outgoing calls
+ };
+
+ union
+ {
+ struct _DRVCALL *pNext; // for incoming calls
+
+ DWORD dwPendingCallStateMode; // for outgoing calls
+ };
+
+ DWORD dwPendingMediaMode; // for outgoing calls
+
+} DRVCALL, *PDRVCALL;
+
+
+typedef struct _DRVLINE
+{
+ DWORD dwKey;
+
+ DWORD dwDeviceID;
+
+ HTAPILINE htLine;
+
+ HDRV_LINE hd_Line;
+
+ PDRVCALL pInboundCalls;
+
+} DRVLINE, *PDRVLINE;
diff --git a/private/tapi/dev/sp/kmddsp/kmddsp.rc b/private/tapi/dev/sp/kmddsp/kmddsp.rc
new file mode 100644
index 000000000..5fd14998d
--- /dev/null
+++ b/private/tapi/dev/sp/kmddsp/kmddsp.rc
@@ -0,0 +1,17 @@
+#include "windows.h"
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "TAPI Kernel-Mode Service Provider"
+#define VER_INTERNALNAME_STR "kmddsp"
+#define VER_ORIGINALFILENAME_STR "KMDDSP.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/kmddsp/makefile b/private/tapi/dev/sp/kmddsp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/tapi/dev/sp/kmddsp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/tapi/dev/sp/kmddsp/sources b/private/tapi/dev/sp/kmddsp/sources
new file mode 100644
index 000000000..0befc8f37
--- /dev/null
+++ b/private/tapi/dev/sp/kmddsp/sources
@@ -0,0 +1,53 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=kmddsp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=TSP
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+DLLBASE=0x60000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc;$(BASEDIR)\private\ntos\inc;$(BASEDIR)\private\ntos\ndis\ndistapi
+
+SOURCES=kmddsp.c \
+ kmddsp.rc
+
+C_DEFINES=-DTAPI_NT=1
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/kmesp/dirs b/private/tapi/dev/sp/kmesp/dirs
new file mode 100644
index 000000000..0173083c2
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/dirs
@@ -0,0 +1,25 @@
+!IF 0
+
+Copyright (c) 1989-92 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=\
+ sys \
+ exe
diff --git a/private/tapi/dev/sp/kmesp/exe/kmesp.c b/private/tapi/dev/sp/kmesp/exe/kmesp.c
new file mode 100644
index 000000000..42b2a3841
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/kmesp.c
@@ -0,0 +1,1927 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ kmesp.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 12-Apr-1995
+
+Revision History:
+
+
+
+Notes:
+
+
+--*/
+
+
+#include "windows.h"
+#include "winioctl.h"
+#include "stdio.h"
+#include "stdarg.h"
+#include "string.h"
+#include "ndistapi.h"
+#include "kmesp.h"
+#include "resource.h"
+#include "..\sys\intrface.h"
+
+
+int
+WINAPI
+WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow
+ )
+{
+ ghInst = hInstance;
+
+ DialogBox(
+ ghInst,
+ (LPCSTR) MAKEINTRESOURCE(IDD_DIALOG1),
+ (HWND) NULL,
+ (DLGPROC) MainWndProc
+ );
+
+ return 0;
+}
+
+
+void
+DoRequestUI(
+ PREQUEST_PARAMS pRequestParams
+ )
+{
+ LONG i, count = SendMessage (ghwndList1, LB_GETCOUNT, 0, 0);
+ char buf[64];
+
+
+ switch (pRequestParams->Oid)
+ {
+ case OID_TAPI_CLOSE:
+ {
+ char szLineName[8];
+
+
+ sprintf (szLineName, "Line%d", pRequestParams->hWidget);
+
+ for (i = 0; i < count; i++)
+ {
+ SendMessage (ghwndList1, LB_GETTEXT, (WPARAM) i, (LPARAM) buf);
+
+ if (strstr (buf, szLineName))
+ {
+ break;
+ }
+ }
+
+ sprintf (buf, "%s (closed)", szLineName);
+
+ SendMessage (ghwndList1, LB_DELETESTRING, (WPARAM) i, 0);
+ SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM) i, (LPARAM) buf);
+
+ break;
+ }
+ case OID_TAPI_CLOSE_CALL:
+ {
+ char szhdCall[16];
+
+
+ sprintf (szhdCall, "x%x", pRequestParams->hWidget);
+
+ for (i = 0; i < count; i++)
+ {
+ SendMessage (ghwndList1, LB_GETTEXT, (WPARAM) i, (LPARAM) buf);
+
+ if (strstr (buf, szhdCall))
+ {
+ break;
+ }
+ }
+
+ SendMessage (ghwndList1, LB_DELETESTRING, (WPARAM) i, 0);
+
+ break;
+ }
+ case OID_TAPI_MAKE_CALL:
+ {
+ if (pRequestParams->Status == NDIS_STATUS_SUCCESS)
+ {
+ char szLineName[8];
+
+
+ sprintf (szLineName, "Line%d", pRequestParams->hWidget);
+
+ for (i = 0; i < count; i++)
+ {
+ SendMessage (ghwndList1, LB_GETTEXT, (WPARAM) i, (LPARAM) buf);
+
+ if (strstr (buf, szLineName))
+ {
+ break;
+ }
+ }
+
+ i++;
+
+ sprintf (buf, " hdCall = x%x", pRequestParams->ulRequestSpecific);
+
+ SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM) i, (LPARAM) buf);
+ }
+ }
+ case OID_TAPI_OPEN:
+ {
+ if (pRequestParams->Status == NDIS_STATUS_SUCCESS)
+ {
+ PMYWIDGET pWidget;
+
+
+ for (i = 0; i < count; i++)
+ {
+ pWidget = (PMYWIDGET) SendMessage(
+ ghwndList1,
+ LB_GETITEMDATA,
+ (WPARAM) i,
+ 0
+ );
+
+ if (pWidget->LineID == pRequestParams->hWidget)
+ {
+ break;
+ }
+ }
+
+ sprintf (buf, "%s (open)", szLineName);
+
+ SendMessage (ghwndList1, LB_DELETESTRING, (WPARAM) i, 0);
+ SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM) i, (LPARAM) buf);
+ }
+
+ break;
+ }
+ case OID_TAPI_PROVIDER_INITIALIZE:
+ {
+ if (pRequestParams->Status == NDIS_STATUS_SUCCESS)
+ {
+ for (i = 0; i < pRequestParams->ulRequestSpecific; i++)
+ {
+ PMYWIDGET pWidget = MyAlloc (sizeod(MYWIDGET));
+
+
+ pWidget->LineID = pRequestParams->hWidget + i;
+
+ sprintf (buf, "Line%d (closed)", pRequestParams->hWidget + i);
+
+ SendMessage (ghwndList1, LB_ADDSTRING, 0, (LPARAM) buf);
+ SendMessage (ghwndList1, LB_SETITEMDATA, i, (LPARAM) pWidget);
+ }
+ }
+
+ break;
+ }
+ case OID_TAPI_PROVIDER_SHUTDOWN:
+ {
+ while ((pWidget = SendMessage (ghwndList1, LB_GETITEMDATA, 0, 0))
+ != LB_ERR)
+ {
+ MyFree (pWidget);
+
+ SendMessage (ghwndList1, LB_DELETESTRING, 0, 0);
+ }
+
+ break;
+ }
+ default:
+
+ break;
+ }
+}
+
+
+BOOL
+CALLBACK
+MainWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ static HICON hIcon;
+ static int icyButton, icyBorder;
+
+ static BOOL bCaptured = FALSE;
+ static LONG xCapture, cxVScroll;
+ static int cyWnd;
+ static HFONT hFont;
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ char buf[64];
+ RECT rect;
+
+
+ //
+ // Init some globals
+ //
+
+#ifdef WIN32
+
+// ghShowStrBufMutex = CreateMutex(
+// NULL, // no security attrs
+// FALSE, // unowned
+// NULL // unnamed
+// );
+
+#endif
+
+ hIcon = LoadIcon (ghInst, MAKEINTRESOURCE(IDI_ICON1));
+
+ ghwndMain = hwnd;
+ ghwndList1 = GetDlgItem (hwnd, IDC_LIST1);
+ ghwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ ghwndEdit = GetDlgItem (hwnd, IDC_EDIT1);
+ ghMenu = GetMenu (hwnd);
+
+ icyBorder = GetSystemMetrics (SM_CYFRAME);
+ GetWindowRect (GetDlgItem (hwnd, IDC_BUTTON1), &rect);
+ icyButton = (rect.bottom - rect.top) + icyBorder + 3;
+ cxVScroll = 2*GetSystemMetrics (SM_CXVSCROLL);
+
+
+ //
+ // Get ini file settings
+ //
+
+ gbManualResults = FALSE;
+
+ gdwCompletionMode = (DWORD) GetProfileInt(
+ szMySection,
+ "CompletionMode",
+ 1
+ );
+
+ PostMessage (hwnd, WM_COMMAND, IDM_SYNCCOMPL + gdwCompletionMode, 0);
+
+
+ //
+ // Set control fonts
+ //
+
+ {
+ HWND hwndCtrl = GetDlgItem (hwnd, IDC_BUTTON1);
+ hFont = CreateFont(
+ 13, 5, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 34, "MS Sans Serif"
+ );
+
+ do
+ {
+ SendMessage(
+ hwndCtrl,
+ WM_SETFONT,
+ (WPARAM) hFont,
+ 0
+ );
+
+ } while ((hwndCtrl = GetNextWindow (hwndCtrl, GW_HWNDNEXT)));
+ }
+
+
+ //
+ // Read in control size ratios
+ //
+
+ cxWnd = GetProfileInt (szMySection, "cxWnd", 100);
+ cxList1 = GetProfileInt (szMySection, "cxList1", 25);
+
+
+ //
+ // Send self WM_SIZE to position child controls correctly
+ //
+
+ GetProfileString(
+ szMySection,
+ "Left",
+ "0",
+ buf,
+ 63
+ );
+
+ if (strcmp (buf, "max") == 0)
+ {
+ ShowWindow (hwnd, SW_SHOWMAXIMIZED);
+ }
+ else if (strcmp (buf, "min") == 0)
+ {
+ ShowWindow (hwnd, SW_SHOWMINIMIZED);
+ }
+ else
+ {
+ int left, top, right, bottom;
+ int cxScreen = GetSystemMetrics (SM_CXSCREEN);
+ int cyScreen = GetSystemMetrics (SM_CYSCREEN);
+
+
+ left = GetProfileInt (szMySection, "Left", 0);
+ top = GetProfileInt (szMySection, "Top", 3*cyScreen/4);
+ right = GetProfileInt (szMySection, "Right", cxScreen);
+ bottom = GetProfileInt (szMySection, "Bottom", cyScreen);
+
+ SetWindowPos(
+ hwnd,
+ HWND_TOP,
+ left,
+ top,
+ right - left,
+ bottom - top,
+ SWP_SHOWWINDOW
+ );
+
+ GetClientRect (hwnd, &rect);
+
+ SendMessage(
+ hwnd,
+ WM_SIZE,
+ 0,
+ MAKELONG((rect.right-rect.left),(rect.bottom-rect.top))
+ );
+
+ ShowWindow (hwnd, SW_SHOW);
+ }
+
+ if ((ghDriver = CreateFile(
+ "\\\\.\\STUBMP",
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL
+
+ )) == INVALID_HANDLE_VALUE)
+ {
+ ShowStr (
+ "Error opening stubmp driver, lastErr=%ld",
+ GetLastError()
+ );
+ }
+ else
+ {
+ DWORD dwThreadID;
+
+
+ ShowStr ("Stubmp driver opened");
+
+ ghThread = CreateThread(
+ NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE) EventsThread,
+ NULL,
+ 0,
+ &dwThreadID
+ );
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+
+ switch (LOWORD((DWORD)wParam))
+ {
+ case IDM_REGISTER:
+ {
+ DWORD params = RT_REGISTER;
+
+
+ DevIoCtl (&params, sizeof(DWORD));
+
+ ShowStr ("Stubmp driver registered with connection wrapper");
+
+ break;
+ }
+ case IDM_DEREGISTER:
+ {
+ DWORD params = RT_DEREGISTER;
+
+
+ DevIoCtl (&params, sizeof(DWORD));
+
+ ShowStr ("Stubmp driver deregistered from connection wrapper");
+
+ break;
+ }
+ case IDM_SYNCCOMPL:
+ case IDM_ASYNCCOMPL:
+ case IDM_MANUALCOMPL:
+
+ gdwCompletionMode = LOWORD((DWORD)wParam) - IDM_SYNCCOMPL;
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_SYNCCOMPL,
+ MF_BYCOMMAND | (gdwCompletionMode == SYNC_COMPLETIONS ?
+ MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_ASYNCCOMPL,
+ MF_BYCOMMAND | (gdwCompletionMode == ASYNC_COMPLETIONS ?
+ MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_MANUALCOMPL,
+ MF_BYCOMMAND | (gdwCompletionMode == MANUAL_COMPLETIONS ?
+ MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_MANUALRESULTS:
+
+ gbManualResults = (gbManualResults ? FALSE : TRUE);
+
+ CheckMenuItem(
+ ghMenu,
+ IDM_MANUALRESULTS,
+ MF_BYCOMMAND | (gbManualResults ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ break;
+
+ case IDM_EXIT:
+
+ PostMessage (hwnd, WM_CLOSE, 0, 0);
+ break;
+
+ case IDM_ABOUT:
+
+ DialogBox(
+ ghInst,
+ (LPCSTR) MAKEINTRESOURCE(IDD_DIALOG2),
+ hwnd,
+ (DLGPROC) AboutDlgProc
+ );
+
+ break;
+
+ case IDC_LIST2:
+
+ if (HIWORD(wParam) == LBN_DBLCLK)
+ {
+ LONG lSel = SendMessage (ghwndList2, LB_GETCURSEL, 0, 0);
+ ULONG args[3];
+ PREQUEST_PARAMS pRequestParams;
+
+
+ pRequestParams = (PREQUEST_PARAMS) SendMessage(
+ ghwndList2,
+ LB_GETITEMDATA,
+ (WPARAM) lSel,
+ 0
+ );
+
+ args[0] = RT_COMPLETEREQUEST;
+ args[1] = pRequestParams->pNdisRequest;
+ args[2] = pRequestParams->Status;
+
+ if (gbManualResults)
+ {
+ char szDlgTitle[] = "Request result";
+ PARAM_INFO params[] =
+ {
+ { "Status", PT_ORDINAL, pRequestParams->Status, aStatus }
+ };
+ PARAM_INFO_HEADER paramsHeader =
+ { 1, szDlgTitle, 0, params };
+
+
+ if (DialogBoxParam(
+ ghInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) ghwndMain,
+ (DLGPROC) ParamsDlgProc,
+ (LPARAM) &paramsHeader
+
+ ) != IDOK)
+ {
+ break;
+ }
+
+ args[2] =
+ pRequestParams->Status = params[0].dwValue;
+ }
+
+ DoRequestUI (pRequestParams);
+
+ DevIoCtl (args, 3 * sizeof(ULONG));
+
+ SendMessage (ghwndList2, LB_DELETESTRING, lSel, 0);
+
+ MyFree (pRequestParams);
+ }
+
+ break;
+
+ case IDC_BUTTON1:
+ {
+ LONG sel = SendMessage (ghwndList1, LB_GETCURSEL, 0, 0);
+
+
+ if (sel != LB_ERR)
+ {
+ PARAM_INFO params[] =
+ {
+ { "Line", PT_DWORD, 0, NULL },
+ { "hdCall", PT_DWORD, 0, NULL },
+ { "dwMsg", PT_ORDINAL, 0, aLineMsgs },
+ { "dwParam1", PT_DWORD, 0, NULL },
+ { "dwParam2", PT_DWORD, 0, NULL },
+ { "dwParam3", PT_DWORD, 0, NULL }
+ };
+ PARAM_INFO_HEADER paramsHeader =
+ { 6, "Line event", 0, params };
+ char buf[64];
+
+
+ SendMessage(
+ ghwndList1,
+ LB_GETTEXT,
+ (WPARAM) sel,
+ (LPARAM) buf
+ );
+
+ if (strstr (buf, "Line"))
+ {
+ }
+
+ if (DialogBoxParam(
+ ghInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) hwnd,
+ (DLGPROC) ParamsDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ }
+ }
+
+ break;
+ }
+ case IDC_BUTTON2:
+
+ MessageBox (hwnd, "new call", "xxx", MB_OK);
+
+ break;
+
+ case IDC_BUTTON3:
+
+ SetWindowText (ghwndEdit, "");
+ break;
+ }
+
+ break;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ case WM_MOUSEMOVE:
+ {
+ LONG x = (LONG)((short)LOWORD(lParam));
+ int y = (int)((short)HIWORD(lParam));
+ int cxList1New;
+
+
+ if (((y > icyButton) && (x > cxList1)) || bCaptured)
+ {
+ SetCursor(
+ LoadCursor ((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_SIZEWE))
+ );
+ }
+
+ if (bCaptured)
+ {
+ x = (x < cxVScroll ? cxVScroll : x);
+ x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x);
+
+ cxList1New = (int) (cxList1 + x - xCapture);
+
+ SetWindowPos(
+ ghwndList1,
+ GetNextWindow (ghwndList1, GW_HWNDPREV),
+ 0,
+ icyButton,
+ cxList1New,
+ 2*cyWnd/3,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndList2,
+ GetNextWindow (ghwndList2, GW_HWNDPREV),
+ 0,
+ icyButton + 2*cyWnd/3 + icyBorder,
+ cxList1New,
+ cyWnd/3 - icyBorder,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndEdit,
+ GetNextWindow (ghwndEdit, GW_HWNDPREV),
+ (int) cxList1New + icyBorder,
+ icyButton,
+ (int)cxWnd - (cxList1New + icyBorder),
+ cyWnd,
+ SWP_SHOWWINDOW
+ );
+ }
+
+ break;
+ }
+ case WM_LBUTTONDOWN:
+ {
+ if (((int)((short)HIWORD(lParam)) > icyButton) &&
+ ((int)((short)LOWORD(lParam)) > cxList1))
+ {
+ xCapture = (LONG)LOWORD(lParam);
+
+ SetCapture (hwnd);
+
+ bCaptured = TRUE;
+ }
+
+ break;
+ }
+ case WM_LBUTTONUP:
+ {
+ if (bCaptured)
+ {
+ POINT p;
+ LONG x;
+
+ GetCursorPos (&p);
+ MapWindowPoints (HWND_DESKTOP, hwnd, &p, 1);
+ x = (LONG) p.x;
+
+ ReleaseCapture();
+
+ x = (x < cxVScroll ? cxVScroll : x);
+ x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x);
+
+ cxList1 = cxList1 + (x - xCapture);
+
+ bCaptured = FALSE;
+
+ InvalidateRect (hwnd, NULL, TRUE);
+ }
+
+ break;
+ }
+ case WM_SIZE:
+ {
+ LONG width = (LONG)LOWORD(lParam);
+
+
+ //
+ // Adjust globals based on new size
+ //
+
+ cxList1 = (cxList1 * width) / cxWnd;
+ cxWnd = width;
+ cyWnd = ((int)HIWORD(lParam)) - icyButton;
+
+
+ //
+ // Now reposition the child windows
+ //
+
+ SetWindowPos(
+ ghwndList1,
+ GetNextWindow (ghwndList1, GW_HWNDPREV),
+ 0,
+ icyButton,
+ (int) cxList1,
+ 2*cyWnd/3,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndList2,
+ GetNextWindow (ghwndList2, GW_HWNDPREV),
+ 0,
+ icyButton + 2*cyWnd/3 + icyBorder,
+ (int) cxList1,
+ cyWnd/3 - icyBorder,
+ SWP_SHOWWINDOW
+ );
+
+ SetWindowPos(
+ ghwndEdit,
+ GetNextWindow (ghwndEdit, GW_HWNDPREV),
+ (int) cxList1 + icyBorder,
+ icyButton,
+ (int)width - ((int)cxList1 + icyBorder),
+ cyWnd,
+ SWP_SHOWWINDOW
+ );
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ break;
+ }
+ case WM_CLOSE:
+
+ SaveIniSettings();
+ DestroyIcon (hIcon);
+ EndDialog (hwnd, 0);
+ DeleteObject (hFont);
+ CloseHandle (ghDriver);
+ TerminateThread (ghThread, 0);
+ break;
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+CALLBACK
+AboutDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ EndDialog (hwnd, 0);
+ break;
+ }
+ break;
+
+#ifdef WIN32
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+#else
+ case WM_CTLCOLOR:
+ {
+ if (HIWORD(lParam) == CTLCOLOR_STATIC)
+ {
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+ }
+ break;
+ }
+#endif
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+void
+ShowStr(
+ LPCSTR format,
+ ...
+ )
+{
+ char buf[256];
+
+ va_list ap;
+
+ va_start(ap, format);
+
+ vsprintf (buf,
+ format,
+ ap
+ );
+
+ strcat (buf, "\r\n");
+
+ SendMessage (ghwndEdit, EM_SETSEL, (WPARAM)0x7fffffe, (LPARAM)0x7ffffff);
+ SendMessage (ghwndEdit, EM_REPLACESEL, 0, (LPARAM) buf);
+
+ va_end(ap);
+}
+
+
+LPVOID
+MyAlloc(
+ DWORD dwSize
+ )
+{
+ return (LocalAlloc (LPTR, dwSize));
+}
+
+
+void
+MyFree(
+ LPVOID p
+ )
+{
+ LocalFree (p);
+}
+
+
+void
+DevIoCtl(
+ LPVOID pData,
+ DWORD dwSize
+ )
+{
+ if (ghDriver != INVALID_HANDLE_VALUE)
+ {
+ DWORD cbReturned;
+
+ DeviceIoControl (
+ ghDriver,
+ (DWORD) IOCTL_STUBMP_APPREQUEST,
+ pData,
+ dwSize,
+ NULL,
+ 0,
+ &cbReturned,
+ 0
+ );
+ }
+}
+
+
+void
+SaveIniSettings(
+ void
+ )
+{
+ char buf[32];
+ RECT rect;
+
+
+ GetWindowRect (ghwndMain, &rect);
+
+ {
+ typedef struct _SAVE_VALUE
+ {
+ char *lpszVal;
+
+ DWORD dwValue;
+
+ } SAVE_VALUE, *PSAVE_VALUE;
+
+ SAVE_VALUE aValues[] =
+ {
+ { "CompletionMode", gdwCompletionMode },
+ { "Left", (DWORD) rect.left },
+ { "Top", (DWORD) rect.top },
+ { "Right", (DWORD) rect.right },
+ { "Bottom", (DWORD) rect.bottom },
+ { "cxWnd", (DWORD) cxWnd },
+ { "cxList1", (DWORD) cxList1 },
+ { NULL, 0 }
+ };
+ int i;
+
+
+ for (i = 0; aValues[i].lpszVal; i++)
+ {
+ wsprintf (buf, "%ld", aValues[i].dwValue); // decimal
+
+ WriteProfileString(
+ szMySection,
+ aValues[i].lpszVal,
+ (LPCSTR) buf
+ );
+ }
+
+ if (IsIconic (ghwndMain))
+ {
+ WriteProfileString(
+ szMySection,
+ "Left",
+ "min"
+ );
+ }
+ else if (IsZoomed (ghwndMain))
+ {
+ WriteProfileString(
+ szMySection,
+ "Left",
+ "max"
+ );
+ }
+ }
+}
+
+
+void
+EventsThread(
+ LPVOID p
+ )
+{
+ ULONG *pFullBuf, *pEmptyBuf, *pBuf1, *pBuf2;
+ DWORD dwBufSize = 1024;
+ OVERLAPPED overlapped;
+
+
+ pFullBuf = pBuf1 = LocalAlloc (LPTR, dwBufSize);
+ pEmptyBuf = pBuf2 = LocalAlloc (LPTR, dwBufSize);
+
+ *pFullBuf = 0;
+
+ overlapped.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+ while (1)
+ {
+ DWORD cbReturned, dwNumBytes;
+
+
+ *pEmptyBuf = dwBufSize;
+
+ DeviceIoControl (
+ ghDriver,
+ (DWORD) IOCTL_STUBMP_GETEVENTS,
+ pEmptyBuf,
+ dwBufSize,
+ pEmptyBuf,
+ dwBufSize,
+ &cbReturned,
+ &overlapped
+ );
+
+ dwNumBytes = *pFullBuf;
+
+ pFullBuf++;
+
+ while (dwNumBytes)
+ {
+ switch (*pFullBuf)
+ {
+ case ET_REQUEST:
+ {
+ //
+ // Stubmp received request, show it
+ //
+
+ static char *pszLookup[] =
+ {
+ "Accept: hdCall=x%x",
+ "Answer: hdCall=x%x",
+ "Close: hdLine=x%x",
+ "CloseCall: hdCall=x%x",
+ "ConditionalMediaDetection: ",
+ "ConfigDialog: DeviceID=x%lx",
+ "DevSpecific: hdLine=x%lx",
+ "Dial: hdCall=x%lx",
+ "Drop: hdCall=x%lx",
+ "GetAddressCaps: DeviceID=x%lx",
+ "GetAddressID: hdLine=x%lx",
+ "GetAddressStatus: hdline=x%lx",
+ "GetCallAddressID: hdCall=x%lx",
+ "GetCallInfo: hdCall=x%lx",
+ "GetCallStatus: hdCall=x%lx",
+ "GetDevCaps: DeviceID=x%lx",
+ "GetDevConfig: DeviceID=x%lx",
+ "GetExtensionID: DeviceID=x%lx",
+ "GetID: hXxx=x%lx",
+ "GetLineDevStatus: hdLine=x%lx",
+ "MakeCall: hdLine=x%lx",
+ "NegotiateExtVersion: DeviceID=x%lx",
+ "Open: DeviceID=x%lx",
+ "Initialize: DeviceIDBase=x%lx",
+ "Shutdown",
+ "SecureCall: hdCall=x%lx",
+ "SelectExtVersion: hdLine=x%lx",
+ "SendUserUserInfo: hdCall=x%lx",
+ "SetAppSpecific: hdCall=x%lx",
+ "SetCallParams: hdCall=x%lx",
+ "SetDefaultMediaDetection: hdLine=x%lx",
+ "SetDevConfig: DeviceID=x%lx",
+ "SetMediaMode: hdCall=x%lx",
+ "SetStatusMessages: hdLine=x%lx"
+ };
+ PREQUEST_PARAMS pRequestParams = (PREQUEST_PARAMS) pFullBuf;
+
+
+ ShowStr(
+ pszLookup[pRequestParams->Oid - OID_TAPI_ACCEPT],
+ pRequestParams->hWidget
+ );
+
+ if (pRequestParams->bNeedsCompleting)
+ {
+ PREQUEST_PARAMS pRequestParamsSav;
+
+
+ if ((gdwCompletionMode == MANUAL_COMPLETIONS) &&
+ (pRequestParamsSav = MyAlloc (sizeof(REQUEST_PARAMS))))
+ {
+ char buf[128];
+ int i;
+ LONG index;
+
+
+ sprintf(
+ buf,
+ "pReq=x%x: ",
+ pRequestParams->pNdisRequest
+ );
+
+ i = strlen (buf);
+
+ sprintf(
+ buf + i,
+ pszLookup[pRequestParams->Oid - OID_TAPI_ACCEPT],
+ pRequestParams->hWidget
+ );
+
+ index = SendMessage(
+ ghwndList2,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) buf
+ );
+
+ memcpy(
+ pRequestParamsSav,
+ pRequestParams,
+ sizeof(REQUEST_PARAMS)
+ );
+
+ SendMessage(
+ ghwndList2,
+ LB_SETITEMDATA,
+ (WPARAM) index,
+ (LPARAM) pRequestParamsSav
+ );
+ }
+ else
+ {
+ ULONG args[3] =
+ {
+ RT_COMPLETEREQUEST,
+ pRequestParams->pNdisRequest,
+ pRequestParams->Status
+ };
+
+
+ if (gbManualResults)
+ {
+ char szDlgTitle[] = "Request result";
+ PARAM_INFO params[] =
+ {
+ { "Status", PT_ORDINAL, args[2], aStatus }
+ };
+ PARAM_INFO_HEADER paramsHeader =
+ { 1, szDlgTitle, 0, params };
+
+
+ if (DialogBoxParam(
+ ghInst,
+ (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
+ (HWND) ghwndMain,
+ (DLGPROC) ParamsDlgProc,
+ (LPARAM) &paramsHeader
+ ) == IDOK)
+ {
+ args[2] =
+ pRequestParams->Status = params[0].dwValue;
+ }
+ }
+
+ DoRequestUI (pRequestParams);
+
+ DevIoCtl (args, 3 * sizeof(ULONG));
+ }
+ }
+ else
+ {
+ DoRequestUI (pRequestParams);
+ }
+
+ pFullBuf += (sizeof(REQUEST_PARAMS) / sizeof(ULONG));
+ dwNumBytes -= sizeof(REQUEST_PARAMS);
+
+ break;
+ }
+ } // switch
+ }
+
+ WaitForSingleObject (overlapped.hEvent, INFINITE);
+
+ pFullBuf = pEmptyBuf;
+
+ pEmptyBuf = (pFullBuf == pBuf1 ? pBuf2 : pBuf1);
+ }
+
+ CloseHandle (overlapped.hEvent);
+
+ ExitThread (0);
+}
+
+
+BOOL
+CALLBACK
+ParamsDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ DWORD i;
+
+ typedef struct _DLG_INST_DATA
+ {
+ PPARAM_INFO_HEADER pParamsHeader;
+
+ LONG lLastSel;
+
+ char szComboText[MAX_STRING_PARAM_SIZE];
+
+ HGLOBAL hComboDS;
+
+ LPVOID pComboSeg;
+
+ HWND hwndCombo;
+
+ } DLG_INST_DATA, *PDLG_INST_DATA;
+
+ PDLG_INST_DATA pDlgInstData = (PDLG_INST_DATA)
+ GetWindowLong (hwnd, DWL_USER);
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ //
+ // Alloc a dlg instance data struct, init it, & save a ptr to it
+ //
+
+ pDlgInstData = (PDLG_INST_DATA) MyAlloc (sizeof(DLG_INST_DATA));
+
+ // BUGBUG if (!pDlgInstData)
+
+ pDlgInstData->pParamsHeader = (PPARAM_INFO_HEADER) lParam;
+ pDlgInstData->lLastSel = -1;
+
+ SetWindowLong (hwnd, DWL_USER, (LONG) pDlgInstData);
+
+
+ //
+ // Limit the max text length for the combobox's edit field
+ // (NOTE: A combobox ctrl actually has two child windows: a
+ // edit ctrl & a listbox. We need to get the hwnd of the
+ // child edit ctrl & send it the LIMITTEXT msg.)
+ //
+
+ {
+ HWND hwndChild = GetWindow (pDlgInstData->hwndCombo, GW_CHILD);
+
+
+ while (hwndChild)
+ {
+ char buf[8];
+
+
+ GetClassName (hwndChild, buf, 7);
+
+ if (_stricmp (buf, "edit") == 0)
+ {
+ break;
+ }
+
+ hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
+ }
+
+ SendMessage(
+ hwndChild,
+ EM_LIMITTEXT,
+ (WPARAM) MAX_STRING_PARAM_SIZE - 1,
+ 0
+ );
+ }
+
+
+ //
+ // Misc other init
+ //
+
+ pDlgInstData->pParamsHeader = (PPARAM_INFO_HEADER) lParam;
+
+ SetWindowText (hwnd, pDlgInstData->pParamsHeader->pszDlgTitle);
+
+ for (i = 0; i < pDlgInstData->pParamsHeader->dwNumParams; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pDlgInstData->pParamsHeader->aParams[i].szName
+ );
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ LONG lLastSel = pDlgInstData->lLastSel;
+ char far *lpszComboText = pDlgInstData->szComboText;
+ PPARAM_INFO_HEADER pParamsHeader = pDlgInstData->pParamsHeader;
+
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ if (lLastSel != -1)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ //
+ // Save val of currently selected param
+ //
+
+ i = GetDlgItemText (hwnd, IDC_COMBO1, buf, MAX_STRING_PARAM_SIZE-1);
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD) 0;
+ }
+ else // "Valid string"
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].u.buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].u.buf[MAX_STRING_PARAM_SIZE-1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].u.buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!sscanf(
+ buf,
+ "%08lx",
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+ // Drop thru to IDCANCEL cleanup code
+
+ case IDCANCEL:
+
+ MyFree (pDlgInstData);
+ EndDialog (hwnd, (int)LOWORD(wParam));
+ break;
+
+ case IDC_LIST1:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ char buf[MAX_STRING_PARAM_SIZE] = "";
+ LPCSTR lpstr = buf;
+ LONG lSel =
+ SendDlgItemMessage (hwnd, IDC_LIST1, LB_GETCURSEL, 0, 0);
+
+
+ if (lLastSel != -1)
+ {
+ //
+ // Save the old param value
+ //
+
+ i = GetDlgItemText(
+ hwnd,
+ IDC_COMBO1,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_STRING:
+ {
+ LONG lComboSel;
+
+
+ lComboSel = SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
+ {
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)0;
+ }
+ else // "Valid string" or no sel
+ {
+ strncpy(
+ pParamsHeader->aParams[lLastSel].u.buf,
+ buf,
+ MAX_STRING_PARAM_SIZE - 1
+ );
+
+ pParamsHeader->aParams[lLastSel].u.buf[MAX_STRING_PARAM_SIZE - 1] = 0;
+
+ pParamsHeader->aParams[lLastSel].dwValue = (DWORD)
+ pParamsHeader->aParams[lLastSel].u.buf;
+ }
+
+ break;
+ }
+ case PT_DWORD:
+ case PT_FLAGS:
+ case PT_ORDINAL:
+ {
+ if (!sscanf(
+ buf,
+ "%08lx",
+ &pParamsHeader->aParams[lLastSel].dwValue
+ ))
+ {
+ //
+ // Default to 0
+ //
+
+ pParamsHeader->aParams[lLastSel].dwValue = 0;
+ }
+
+ break;
+ }
+ } // switch
+ }
+
+
+ SendDlgItemMessage (hwnd, IDC_LIST2, LB_RESETCONTENT, 0, 0);
+ SendDlgItemMessage (hwnd, IDC_COMBO1, CB_RESETCONTENT, 0, 0);
+
+ switch (pParamsHeader->aParams[lSel].dwType)
+ {
+ case PT_STRING:
+ {
+ char * aszOptions[] =
+ {
+ "NUL (dwXxxSize=0)",
+ "Valid string"
+ };
+
+
+ for (i = 0; i < 2; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) aszOptions[i]
+ );
+ }
+
+ if (pParamsHeader->aParams[lSel].dwValue == 0)
+ {
+ i = 0;
+ buf[0] = 0;
+ }
+ else
+ {
+ i = 1;
+ lpstr = (LPCSTR) pParamsHeader->aParams[lSel].dwValue;
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_SETCURSEL,
+ (WPARAM) i,
+ 0
+ );
+
+ break;
+ }
+ case PT_DWORD:
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "0000000"
+ );
+
+ if (pParamsHeader->aParams[lSel].u.dwDefValue)
+ {
+ //
+ // Add the default val string to the combo
+ //
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].u.dwDefValue
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) buf
+ );
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "ffffffff"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_ORDINAL:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].u.pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].lpszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue ==
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ case PT_FLAGS:
+ {
+ //
+ // Stick the bit flag strings in the list box
+ //
+
+ HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lSel].u.pLookup;
+
+ for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
+ {
+ SendMessage(
+ hwndList2,
+ LB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) pLookup[i].lpszVal
+ );
+
+ if (pParamsHeader->aParams[lSel].dwValue &
+ pLookup[i].dwVal)
+ {
+ SendMessage(
+ hwndList2,
+ LB_SETSEL,
+ (WPARAM) TRUE,
+ (LPARAM) MAKELPARAM((WORD)i,0)
+ );
+ }
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select none"
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_COMBO1,
+ CB_INSERTSTRING,
+ (WPARAM) -1,
+ (LPARAM) (char far *) "select all"
+ );
+
+ wsprintf(
+ buf,
+ "%08lx",
+ pParamsHeader->aParams[lSel].dwValue
+ );
+
+ break;
+ }
+ } //switch
+
+ SetDlgItemText (hwnd, IDC_COMBO1, lpstr);
+
+ pDlgInstData->lLastSel = lSel;
+ }
+ break;
+
+ case IDC_LIST2:
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ //
+ // BUGBUG in the PT_ORDINAL case we should compare the
+ // currently selected item(s) against the previous DWORD
+ // val and figure out which item we need to deselect,
+ // if any, in order to maintain a mutex of values
+ //
+
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].u.pLookup;
+ char buf[16];
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendDlgItemMessage (hwnd, IDC_LIST2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) MyAlloc ((size_t)lSelCount * sizeof(int));
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_FLAGS)
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+ }
+ else // if (.dwType == PT_ORDINAL)
+ {
+ if (lSelCount == 1)
+ {
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ else if (lSelCount == 2)
+ {
+ //
+ // Figure out which item we need to de-select, since
+ // we're doing ordinals & only want 1 item selected
+ // at a time
+ //
+
+ GetDlgItemText (hwnd, IDC_COMBO1, buf, 16);
+
+ if (sscanf (buf, "%08lx", &dwValue))
+ {
+ if (pLookup[ai[0]].dwVal == dwValue)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[0]
+ );
+
+ dwValue = pLookup[ai[1]].dwVal;
+ }
+ else
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[1]
+ );
+
+ dwValue = pLookup[ai[0]].dwVal;
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ else if (lSelCount > 2)
+ {
+ //
+ // Determine previous selection & de-select all the
+ // latest selections
+ //
+
+ GetDlgItemText (hwnd, IDC_COMBO1, buf, 16);
+
+ if (sscanf (buf, "%08lx", &dwValue))
+ {
+ for (i = 0; i < lSelCount; i++)
+ {
+ if (pLookup[ai[i]].dwVal != dwValue)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ 0,
+ (LPARAM) ai[i]
+ );
+ }
+ }
+ }
+ else
+ {
+ // BUGBUG de-select items???
+
+ dwValue = 0;
+ }
+ }
+ }
+
+ MyFree (ai);
+ wsprintf (buf, "%08lx", dwValue);
+ SetDlgItemText (hwnd, IDC_COMBO1, buf);
+ }
+ break;
+
+ case IDC_COMBO1:
+
+ switch (HIWORD(wParam))
+ {
+ case CBN_SELCHANGE:
+ {
+ LONG lSel =
+ SendDlgItemMessage (hwnd, IDC_COMBO1, CB_GETCURSEL, 0, 0);
+
+
+ switch (pParamsHeader->aParams[lLastSel].dwType)
+ {
+ case PT_ORDINAL:
+
+ //
+ // The only option here is "select none"
+ //
+
+ strcpy (lpszComboText, "00000000");
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+ break;
+
+ case PT_FLAGS:
+ {
+ BOOL bSelect = (lSel ? TRUE : FALSE);
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_SETSEL,
+ (WPARAM) bSelect,
+ (LPARAM) -1
+ );
+
+ if (bSelect)
+ {
+ PLOOKUP pLookup = (PLOOKUP)
+ pParamsHeader->aParams[lLastSel].u.pLookup;
+ DWORD dwValue = 0;
+ int far *ai;
+ LONG i, lSelCount =
+ SendDlgItemMessage (hwnd, IDC_LIST2, LB_GETSELCOUNT, 0, 0);
+
+
+ ai = (int far *) MyAlloc(
+ (size_t)lSelCount * sizeof(int)
+ );
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST2,
+ LB_GETSELITEMS,
+ (WPARAM) lSelCount,
+ (LPARAM) ai
+ );
+
+ for (i = 0; i < lSelCount; i++)
+ {
+ dwValue |= pLookup[ai[i]].dwVal;
+ }
+
+ MyFree (ai);
+ wsprintf (lpszComboText, "%08lx", dwValue);
+
+ }
+ else
+ {
+ strcpy (lpszComboText, "00000000");
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+ }
+ case PT_STRING:
+
+ if (lSel == 1)
+ {
+ strncpy(
+ lpszComboText,
+ pParamsHeader->aParams[lLastSel].u.buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ lpszComboText[MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ else
+ {
+ lpszComboText[0] = 0;
+ }
+
+ PostMessage (hwnd, WM_USER+55, 0, 0);
+
+ break;
+
+ case PT_DWORD:
+
+ break;
+
+ } // switch
+ break;
+ }
+ case CBN_EDITCHANGE:
+ {
+ //
+ // If user entered text in the edit field then copy the
+ // text to our buffer
+ //
+
+ if (pParamsHeader->aParams[lLastSel].dwType == PT_STRING)
+ {
+ char buf[MAX_STRING_PARAM_SIZE];
+
+
+ GetDlgItemText(
+ hwnd,
+ IDC_COMBO1,
+ buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ strncpy(
+ pParamsHeader->aParams[lLastSel].u.buf,
+ buf,
+ MAX_STRING_PARAM_SIZE
+ );
+
+ pParamsHeader->aParams[lLastSel].u.buf
+ [MAX_STRING_PARAM_SIZE-1] = 0;
+ }
+ break;
+ }
+ } // switch
+
+ } // switch
+
+ break;
+ }
+ case WM_USER+55:
+
+ SetDlgItemText (hwnd, IDC_COMBO1, pDlgInstData->szComboText);
+ break;
+
+ case WM_CTLCOLORSTATIC:
+
+ SetBkColor ((HDC) wParam, RGB (192,192,192));
+ return (BOOL) GetStockObject (LTGRAY_BRUSH);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/private/tapi/dev/sp/kmesp/exe/kmesp.def b/private/tapi/dev/sp/kmesp/exe/kmesp.def
new file mode 100644
index 000000000..1118020aa
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/kmesp.def
@@ -0,0 +1,11 @@
+NAME kmesp
+STUB 'WINSTUB.EXE'
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE MULTIPLE
+HEAPSIZE 1024
+STACKSIZE 8192
+
+EXPORTS
+ MainWndProc
+ AboutDlgProc
+ ParamsDlgProc
diff --git a/private/tapi/dev/sp/kmesp/exe/kmesp.h b/private/tapi/dev/sp/kmesp/exe/kmesp.h
new file mode 100644
index 000000000..3e7eab0fa
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/kmesp.h
@@ -0,0 +1,246 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ kmesp.h
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 12-Apr-1995
+
+Revision History:
+
+
+
+Notes:
+
+
+--*/
+
+
+#define SYNC_COMPLETIONS 0
+#define ASYNC_COMPLETIONS 1
+#define MANUAL_COMPLETIONS 2
+
+#define PT_DWORD 1
+#define PT_FLAGS 2
+#define PT_STRING 3
+#define PT_ORDINAL 4
+
+#define MAX_STRING_PARAM_SIZE 32
+
+
+typedef struct _LOOKUP
+{
+ DWORD dwVal;
+
+ char far *lpszVal;
+
+} LOOKUP, *PLOOKUP;
+
+
+typedef struct _PARAM_INFO
+{
+ char far *szName;
+
+ DWORD dwType;
+
+ DWORD dwValue;
+
+ union
+ {
+ PLOOKUP pLookup;
+
+ char far *buf;
+
+ LPVOID ptr;
+
+ DWORD dwDefValue;
+
+ } u;
+
+} PARAM_INFO, far *PPARAM_INFO;
+
+
+typedef struct _PARAM_INFO_HEADER
+{
+ DWORD dwNumParams;
+
+ LPSTR pszDlgTitle;
+
+ DWORD dwEventType;
+
+ PPARAM_INFO aParams;
+
+} PARAM_INFO_HEADER, far *PPARAM_INFO_HEADER;
+
+
+typedef struct _MYWIDGET
+{
+ ULONG LineID;
+
+ ULONG hdCall;
+
+} MYWIDGET, *PMYWIDGET;
+
+BOOL gbManualResults;
+HWND ghwndMain,
+ ghwndList1,
+ ghwndList2,
+ ghwndEdit;
+DWORD gdwCompletionMode;
+HMENU ghMenu;
+HANDLE ghInst, ghThread;
+char szMySection[] = "KMESP";
+LONG cxList1, cxWnd;
+HANDLE ghDriver = INVALID_HANDLE_VALUE;
+
+
+BOOL
+CALLBACK
+MainWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+BOOL
+CALLBACK
+AboutDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+void
+ShowStr(
+ LPCSTR format,
+ ...
+ );
+
+void
+DevIoCtl(
+ LPVOID pData,
+ DWORD dwSize
+ );
+
+void
+SaveIniSettings(
+ void
+ );
+
+void
+EventsThread(
+ LPVOID p
+ );
+
+BOOL
+CALLBACK
+ParamsDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+LPVOID
+MyAlloc(
+ DWORD dwSize
+ );
+
+void
+MyFree(
+ LPVOID p
+ );
+
+
+//
+// BUGBUG Hack alert
+//
+
+typedef ULONG NDIS_STATUS;
+
+#define NDIS_STATUS_SUCCESS 0x00000000L
+#define NDIS_STATUS_RESOURCES 0xC000009AL
+#define NDIS_STATUS_FAILURE 0xC0000001L
+
+
+LOOKUP aStatus[] =
+{
+ //
+ // Defined in NDIS.H
+ //
+
+ { NDIS_STATUS_SUCCESS ,"SUCCESS" },
+
+ //
+ // These errors are defined in NDISTAPI.H
+ //
+
+ { NDIS_STATUS_TAPI_ADDRESSBLOCKED ,"ADDRESSBLOCKED" },
+ { NDIS_STATUS_TAPI_BEARERMODEUNAVAIL ,"BEARERMODEUNAVAIL" },
+ { NDIS_STATUS_TAPI_CALLUNAVAIL ,"CALLUNAVAIL" },
+ { NDIS_STATUS_TAPI_DIALBILLING ,"DIALBILLING" },
+ { NDIS_STATUS_TAPI_DIALDIALTONE ,"DIALDIALTONE" },
+ { NDIS_STATUS_TAPI_DIALPROMPT ,"DIALPROMPT" },
+ { NDIS_STATUS_TAPI_DIALQUIET ,"DIALQUIET" },
+ { NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION,"INCOMPATIBLEEXTVERSION" },
+ { NDIS_STATUS_TAPI_INUSE ,"INUSE" },
+ { NDIS_STATUS_TAPI_INVALADDRESS ,"INVALADDRESS" },
+ { NDIS_STATUS_TAPI_INVALADDRESSID ,"INVALADDRESSID" },
+ { NDIS_STATUS_TAPI_INVALADDRESSMODE ,"INVALADDRESSMODE" },
+ { NDIS_STATUS_TAPI_INVALBEARERMODE ,"INVALBEARERMODE" },
+ { NDIS_STATUS_TAPI_INVALCALLHANDLE ,"INVALCALLHANDLE" },
+ { NDIS_STATUS_TAPI_INVALCALLPARAMS ,"INVALCALLPARAMS" },
+ { NDIS_STATUS_TAPI_INVALCALLSTATE ,"INVALCALLSTATE" },
+ { NDIS_STATUS_TAPI_INVALDEVICECLASS ,"INVALDEVICECLASS" },
+ { NDIS_STATUS_TAPI_INVALLINEHANDLE ,"INVALLINEHANDLE" },
+ { NDIS_STATUS_TAPI_INVALLINESTATE ,"INVALLINESTATE" },
+ { NDIS_STATUS_TAPI_INVALMEDIAMODE ,"INVALMEDIAMODE" },
+ { NDIS_STATUS_TAPI_INVALRATE ,"INVALRATE" },
+ { NDIS_STATUS_TAPI_NODRIVER ,"NODRIVER" },
+ { NDIS_STATUS_TAPI_OPERATIONUNAVAIL ,"OPERATIONUNAVAIL" },
+ { NDIS_STATUS_TAPI_RATEUNAVAIL ,"RATEUNAVAIL" },
+ { NDIS_STATUS_TAPI_RESOURCEUNAVAIL ,"RESOURCEUNAVAIL" },
+ { NDIS_STATUS_TAPI_STRUCTURETOOSMALL ,"STRUCTURETOOSMALL" },
+ { NDIS_STATUS_TAPI_USERUSERINFOTOOBIG ,"USERUSERINFOTOOBIG" },
+ { NDIS_STATUS_TAPI_ALLOCATED ,"ALLOCATED" },
+ { NDIS_STATUS_TAPI_INVALADDRESSSTATE ,"INVALADDRESSSTATE" },
+ { NDIS_STATUS_TAPI_INVALPARAM ,"INVALPARAM" },
+ { NDIS_STATUS_TAPI_NODEVICE ,"NODEVICE" },
+
+ //
+ // These errors are defined in NDIS.H
+ //
+
+ { NDIS_STATUS_RESOURCES ,"RESOURCES" },
+ { NDIS_STATUS_FAILURE ,"FAILURE" },
+
+ //
+ //
+ //
+
+ { 0xffffffff ,"" }
+};
+
+
+LOOKUP aLineMsgs[] =
+{
+ { LINE_ADDRESSSTATE ,"ADDRESSSTATE" },
+ { LINE_CALLINFO ,"CALLINFO" },
+ { LINE_CALLSTATE ,"CALLSTATE" },
+ { LINE_CLOSE ,"CLOSE" },
+ { LINE_DEVSPECIFIC ,"DEVSPECIFIC" },
+ { LINE_LINEDEVSTATE ,"LINEDEVSTATE" },
+ { LINE_CALLDEVSPECIFIC ,"CALLDEVSPECIFIC" },
+
+ { 0xffffffff ,"" }
+};
diff --git a/private/tapi/dev/sp/kmesp/exe/kmesp.ico b/private/tapi/dev/sp/kmesp/exe/kmesp.ico
new file mode 100644
index 000000000..516eb3f84
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/kmesp.ico
Binary files differ
diff --git a/private/tapi/dev/sp/kmesp/exe/kmesp.rc b/private/tapi/dev/sp/kmesp/exe/kmesp.rc
new file mode 100644
index 000000000..c940efe95
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/kmesp.rc
@@ -0,0 +1,164 @@
+//Microsoft App Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifdef WIN32
+#include "windows.h"
+#else
+#include "afxres.h"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+//////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // APSTUDIO_INVOKED
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 292, 217
+STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU |
+ WS_THICKFRAME
+CAPTION "KMESP"
+MENU IDR_MENU1
+FONT 6, "Courier"
+BEGIN
+ PUSHBUTTON "LEvt",IDC_BUTTON1,1,1,16,16
+ PUSHBUTTON "Call+",IDC_BUTTON2,19,1,16,16
+ PUSHBUTTON "Clear",IDC_BUTTON3,37,1,16,16
+ EDITTEXT IDC_EDIT1,129,19,117,195,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL | 0x1000
+ LISTBOX IDC_LIST1,62,17,65,197,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+ LISTBOX IDC_LIST2,0,0,0,0,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+END
+
+IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 185, 69
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "About KMESP"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,69,50,50,14
+ LTEXT "KMESP v1.0",38,88,12,70,7
+ LTEXT "Copyright (c) 1995 Microsoft Corporation",70,24,30,160,
+ 12
+ ICON IDI_ICON1,IDC_STATIC1,60,5,18,20
+END
+
+IDD_DIALOG3 DIALOG DISCARDABLE 0, 0, 205, 192
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Parameters:",55,4,6,42,7
+ LISTBOX IDC_LIST1,4,16,100,148,LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Value:",56,116,6,30,7
+ COMBOBOX IDC_COMBO1,116,16,80,47,CBS_SIMPLE | CBS_AUTOHSCROLL |
+ CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Bit flags:",57,116,66,40,9
+ LISTBOX IDC_LIST2,116,75,80,89,LBS_MULTIPLESEL |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",IDOK,116,171,36,14
+ PUSHBUTTON "Cancel",IDCANCEL,160,171,37,14
+END
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "Register provider", IDM_REGISTER
+ MENUITEM "Deregister provider", IDM_DEREGISTER
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_EXIT
+ END
+ POPUP "&Options"
+ BEGIN
+ MENUITEM "&Outgoing call state progress...", IDM_OUTCALLSTATEPROG
+ MENUITEM SEPARATOR
+ POPUP "Complete async requests"
+ BEGIN
+ MENUITEM "Synchronously", IDM_SYNCCOMPL
+ MENUITEM "Asynchronously", IDM_ASYNCCOMPL
+ MENUITEM "Manually", IDM_MANUALCOMPL
+ END
+ MENUITEM "User-specified request results", IDM_MANUALRESULTS
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Using KMESP...", IDM_USAGE
+ MENUITEM SEPARATOR
+ MENUITEM "&About...", IDM_ABOUT
+ END
+END
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+IDI_ICON1 ICON DISCARDABLE "KMESP.ICO"
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ VK_F1, IDC_F1HELP, VIRTKEY
+ VK_TAB, IDC_PREVCTRL, VIRTKEY, SHIFT
+ VK_TAB, IDC_NEXTCTRL, VIRTKEY
+ VK_RETURN, IDC_ENTER, VIRTKEY
+END
+
+
+#ifndef APSTUDIO_INVOKED
+////////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/private/tapi/dev/sp/kmesp/exe/makefile b/private/tapi/dev/sp/kmesp/exe/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/tapi/dev/sp/kmesp/exe/resource.h b/private/tapi/dev/sp/kmesp/exe/resource.h
new file mode 100644
index 000000000..45cab7e79
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/resource.h
@@ -0,0 +1,49 @@
+//{{NO_DEPENDENCIES}}
+// App Studio generated include file.
+// Used by ESP.RC
+//
+#define IDD_DIALOG1 101
+#define IDD_DIALOG2 102
+#define IDD_DIALOG3 103
+#define IDR_MENU1 104
+#define IDI_ICON1 105
+#define IDR_ACCELERATOR1 106
+#define IDC_LIST1 1000
+#define IDC_LIST2 1001
+#define IDC_LIST3 1002
+#define IDC_EDIT1 1003
+#define IDC_STATIC1 1004
+#define IDC_BUTTON1 1005
+#define IDC_BUTTON2 1006
+#define IDC_BUTTON3 1007
+#define IDC_COMBO1 1008
+#define IDC_F1HELP 1009
+#define IDC_PREVCTRL 1010
+#define IDC_NEXTCTRL 1011
+#define IDC_ENTER 1012
+#define IDM_ABOUT 40000
+#define IDM_EXIT 40001
+#define IDM_DEFAULTS 40002
+#define IDM_OUTCALLSTATEPROG 40003
+#define IDM_INSTALL 40004
+#define IDM_UNINSTALL 40005
+#define IDM_USAGE 40006
+#define IDM_DUMPGLOBALS 40007
+#define IDM_SYNCCOMPL 40008
+#define IDM_ASYNCCOMPL 40009
+#define IDM_MANUALCOMPL 40010
+#define IDM_MANUALRESULTS 40011
+#define IDM_REGISTER 40012
+#define IDM_DEREGISTER 40013
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40014
+#define _APS_NEXT_CONTROL_VALUE 1013
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/private/tapi/dev/sp/kmesp/exe/sources b/private/tapi/dev/sp/kmesp/exe/sources
new file mode 100644
index 000000000..534eb3023
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/exe/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=kmesp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=PROGRAM
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc;$(BASEDIR)\private\ntos\inc;$(BASEDIR)\private\ntos\ndis\ndistapi
+
+USE_CRTDLL=1
+
+SOURCES=kmesp.c \
+ kmesp.rc
+
+UMTYPE=windows
+
+UMENTRY=winmain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/kmesp/sys/intrface.h b/private/tapi/dev/sp/kmesp/sys/intrface.h
new file mode 100644
index 000000000..ad481827b
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/sys/intrface.h
@@ -0,0 +1,138 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ intrface.h
+
+Abstract:
+
+
+Environment:
+
+ Kernel & user mode
+
+Revision History:
+
+--*/
+
+
+//
+//
+//
+
+#define RT_REGISTER 1
+#define RT_DEREGISTER 2
+#define RT_COMPLETEREQUEST 3
+#define RT_SYNCCOMPLETIONS 4
+#define RT_ASYNCCOMPLETIONS 5
+#define RT_INCOMINGCALL 6
+#define RT_EVENT 7
+
+#define ET_REQUEST 1
+
+
+//
+// Define the various device type values. Note that values used by Microsoft
+// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
+// by customers.
+//
+
+#define FILE_DEVICE_STUBMP 0x00008300
+
+
+
+//
+// Macro definition for defining IOCTL and FSCTL function control codes. Note
+// that function codes 0-2047 are reserved for Microsoft Corporation, and
+// 2048-4095 are reserved for customers.
+//
+
+#define STUBMP_IOCTL_INDEX 0x830
+
+
+
+//
+// IOCTL defs
+//
+
+#define IOCTL_STUBMP_APPREQUEST CTL_CODE(FILE_DEVICE_STUBMP, \
+ STUBMP_IOCTL_INDEX, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_STUBMP_GETEVENTS CTL_CODE(FILE_DEVICE_STUBMP, \
+ STUBMP_IOCTL_INDEX+1, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+
+//
+// From ntddndis.h
+//
+
+#define OID_TAPI_ACCEPT 0x07030101
+#define OID_TAPI_ANSWER 0x07030102
+#define OID_TAPI_CLOSE 0x07030103
+#define OID_TAPI_CLOSE_CALL 0x07030104
+#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105
+#define OID_TAPI_CONFIG_DIALOG 0x07030106
+#define OID_TAPI_DEV_SPECIFIC 0x07030107
+#define OID_TAPI_DIAL 0x07030108
+#define OID_TAPI_DROP 0x07030109
+#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A
+#define OID_TAPI_GET_ADDRESS_ID 0x0703010B
+#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C
+#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D
+#define OID_TAPI_GET_CALL_INFO 0x0703010E
+#define OID_TAPI_GET_CALL_STATUS 0x0703010F
+#define OID_TAPI_GET_DEV_CAPS 0x07030110
+#define OID_TAPI_GET_DEV_CONFIG 0x07030111
+#define OID_TAPI_GET_EXTENSION_ID 0x07030112
+#define OID_TAPI_GET_ID 0x07030113
+#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114
+#define OID_TAPI_MAKE_CALL 0x07030115
+#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116
+#define OID_TAPI_OPEN 0x07030117
+#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118
+#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119
+#define OID_TAPI_SECURE_CALL 0x0703011A
+#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B
+#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C
+#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D
+#define OID_TAPI_SET_CALL_PARAMS 0x0703011E
+#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F
+#define OID_TAPI_SET_DEV_CONFIG 0x07030120
+#define OID_TAPI_SET_MEDIA_MODE 0x07030121
+#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122
+
+
+typedef struct _REQUESTBLOCK
+{
+ ULONG ulRequestType;
+
+ char Data[1];
+
+} REQUESTBLOCK, *PREQUESTBLOCK;
+
+
+typedef struct _REQUEST_PARAMS
+{
+ ULONG ulRequestType;
+
+ ULONG bNeedsCompleting;
+
+ ULONG pNdisRequest;
+
+ ULONG Status;
+
+ ULONG Oid;
+
+ ULONG RequestID;
+
+ ULONG hWidget;
+
+ ULONG ulRequestSpecific;
+
+} REQUEST_PARAMS, *PREQUEST_PARAMS;
diff --git a/private/tapi/dev/sp/kmesp/sys/makefile b/private/tapi/dev/sp/kmesp/sys/makefile
new file mode 100644
index 000000000..58189757d
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/sys/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/tapi/dev/sp/kmesp/sys/sources b/private/tapi/dev/sp/kmesp/sys/sources
new file mode 100644
index 000000000..7e06f7bbb
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/sys/sources
@@ -0,0 +1,34 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+TARGETNAME=stubmp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=$(BASEDIR)\private\ntos\inc
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndistapi.lib
+
+SOURCES=stubmp.c
diff --git a/private/tapi/dev/sp/kmesp/sys/stubmp.c b/private/tapi/dev/sp/kmesp/sys/stubmp.c
new file mode 100644
index 000000000..690c14899
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/sys/stubmp.c
@@ -0,0 +1,1465 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ stubmp.c
+
+Abstract:
+
+
+
+Author:
+
+ Dan Knudson (DanKn) 11-Apr-1995
+
+Environment:
+
+ kernel mode only
+
+Revision History:
+
+
+Notes:
+
+
+--*/
+
+#include "ntddk.h"
+//#include "ntos.h"
+#include "ndismain.h"
+#include "stdarg.h"
+#include "stdio.h"
+#include "ndistapi.h"
+#include "stubmp.h"
+#include "intrface.h"
+
+
+
+PDEVICE_EXTENSION DeviceExtension;
+
+
+#ifdef DBG
+
+//ULONG StubmpDebugLevel = 3;
+ULONG StubmpDebugLevel = 0;
+
+#define DBGOUT(arg) DbgPrt arg
+
+VOID
+DbgPrt(
+ IN ULONG DbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
+
+
+NTSTATUS
+StubmpDispatch(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+NDIS_STATUS
+StubmpRequest(
+ NDIS_HANDLE NdisBindingHandle,
+ PNDIS_REQUEST NdisRequest
+ );
+
+VOID
+StubmpUnload(
+ IN PDRIVER_OBJECT DriverObject
+ );
+
+VOID
+StubmpCancel(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+WriteRingBuffer(
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+
+ Installable driver initialization entry point.
+ This entry point is called directly by the I/O system.
+
+Arguments:
+
+ DriverObject - pointer to the driver object
+
+ RegistryPath - pointer to a unicode string representing the path
+ to driver-specific key in the registry
+
+Return Value:
+
+ STATUS_SUCCESS if successful,
+ STATUS_UNSUCCESSFUL otherwise
+
+--*/
+{
+ ULONG i, ulNumLines = 4,
+ ulNumAddrsPerLine = 4,
+ ulNumCallsPerLine = 4;
+ PDEVICE_OBJECT deviceObject = NULL;
+ NTSTATUS ntStatus;
+ WCHAR deviceNameBuffer[] = L"\\Device\\Stubmp";
+ UNICODE_STRING deviceNameUnicodeString;
+ WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Stubmp";
+ UNICODE_STRING deviceLinkUnicodeString;
+
+
+ DBGOUT ((2, "DriverEntry: enter"));
+
+
+ //
+ // Create an EXCLUSIVE device, i.e. only 1 thread at a time can send
+ // i/o requests.
+ //
+
+ RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer);
+
+ ntStatus = IoCreateDevice(
+ DriverObject,
+ sizeof(DEVICE_EXTENSION) + (ulNumLines - 1) * sizeof(PDRVLINE),
+ &deviceNameUnicodeString,
+ FILE_DEVICE_STUBMP,
+ 0,
+ FALSE, // not exclusive
+ &deviceObject
+ );
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ ULONG numBytesPerLine = sizeof(DRVLINE) +
+ (ulNumCallsPerLine - 1) * sizeof(DRVCALL);
+
+ DeviceExtension = (PDEVICE_EXTENSION)
+ deviceObject->DeviceExtension;
+
+ RtlZeroMemory (DeviceExtension, sizeof (DEVICE_EXTENSION));
+
+ DeviceExtension->CompleteAsync = TRUE;
+
+ DeviceExtension->ulNumLines = ulNumLines;
+ DeviceExtension->ulNumAddrsPerLine = ulNumAddrsPerLine;
+ DeviceExtension->ulNumCallsPerLine = ulNumCallsPerLine;
+
+
+ KeInitializeSpinLock (&DeviceExtension->EventSpinLock);
+
+ DeviceExtension->EventDataQueueLength = 1024;
+
+ DeviceExtension->EventDataQueue =
+ DeviceExtension->DataIn =
+ DeviceExtension->DataOut = ExAllocatePoolWithTag(
+ NonPagedPool,
+ DeviceExtension->EventDataQueueLength,
+ 'TAPI'
+ );
+
+
+ //
+ //
+ //
+
+ for (i = 0; i < ulNumLines; i++)
+ {
+ DeviceExtension->apLines[i] = ExAllocatePoolWithTag(
+ NonPagedPool,
+ numBytesPerLine,
+ 'TAPI'
+ );
+
+ RtlZeroMemory (DeviceExtension->apLines[i], numBytesPerLine);
+ }
+
+
+ //
+ // Create a symbolic link that Win32 apps can specify to gain access
+ // to this driver/device
+ //
+
+ RtlInitUnicodeString (&deviceLinkUnicodeString, deviceLinkBuffer);
+
+ ntStatus = IoCreateSymbolicLink(
+ &deviceLinkUnicodeString,
+ &deviceNameUnicodeString
+ );
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DBGOUT ((0, "DriverEntry: IoCreateSymbolicLink failed"));
+ }
+
+
+
+ //
+ // Init dispatch points for device control, create, close.
+ //
+
+ DriverObject->MajorFunction[IRP_MJ_CREATE] =
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] =
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = StubmpDispatch;
+ DriverObject->DriverUnload = StubmpUnload;
+ }
+
+
+done_DriverEntry:
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ //
+ // Something went wrong, so clean up (free resources, etc.)
+ //
+
+ if (deviceObject)
+ {
+ IoDeleteDevice (deviceObject);
+ }
+ }
+
+ return ntStatus;
+}
+
+
+
+NTSTATUS
+StubmpDispatch(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+/*++
+
+Routine Description:
+
+ Process the IRPs sent to this device.
+
+Arguments:
+
+ DeviceObject - pointer to a device object
+
+ Irp - pointer to an I/O Request Packet
+
+Return Value:
+
+
+--*/
+{
+
+ PVOID ioBuffer;
+ ULONG inputBufferLength;
+ ULONG outputBufferLength;
+ ULONG ioControlCode;
+ NTSTATUS ntStatus;
+ NDIS_TAPI_EVENT event;
+ PIO_STACK_LOCATION irpStack;
+
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+
+
+ //
+ // Get a pointer to the current location in the Irp. This is where
+ // the function codes and parameters are located.
+ //
+
+ irpStack = IoGetCurrentIrpStackLocation (Irp);
+
+
+
+ //
+ // Get the pointer to the input/output buffer and it's length
+ //
+
+ ioBuffer = Irp->AssociatedIrp.SystemBuffer;
+ inputBufferLength =
+ irpStack->Parameters.DeviceIoControl.InputBufferLength;
+ outputBufferLength =
+ irpStack->Parameters.DeviceIoControl.OutputBufferLength;
+
+
+
+ switch (irpStack->MajorFunction)
+ {
+ case IRP_MJ_CREATE:
+
+ DBGOUT ((2, "IRP_MJ_CREATE"));
+
+ break;
+
+ case IRP_MJ_CLOSE:
+
+ DBGOUT ((2, "IRP_MJ_CLOSE"));
+
+ break;
+
+ case IRP_MJ_DEVICE_CONTROL:
+
+ ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
+
+ switch (ioControlCode)
+ {
+ case IOCTL_STUBMP_APPREQUEST:
+ {
+ PREQUESTBLOCK pRequestBlock = (PREQUESTBLOCK) ioBuffer;
+
+
+ DBGOUT ((2, "IOCTL_STUBMP_APPREQUEST"));
+
+ switch (pRequestBlock->ulRequestType)
+ {
+ case RT_REGISTER:
+
+ NdisTapiRegisterProvider(
+ (NDIS_HANDLE) 0x55,
+ (REQUEST_PROC) StubmpRequest
+ );
+
+ break;
+
+ case RT_DEREGISTER:
+
+ NdisTapiDeregisterProvider ((NDIS_HANDLE) 0x55);
+
+ break;
+
+ case RT_COMPLETEREQUEST:
+ {
+ ULONG *args = (ULONG *) (pRequestBlock->Data);
+
+
+ DBGOUT ((2, "completing req x%x", *args));
+
+ NdisTapiCompleteRequest(
+ (NDIS_HANDLE) 0x55,
+ (PNDIS_REQUEST) *args,
+ (NDIS_STATUS) *(args + 1)
+ );
+
+ break;
+ }
+ case RT_SYNCCOMPLETIONS:
+
+ DeviceExtension->CompleteAsync = FALSE;
+ break;
+
+ case RT_ASYNCCOMPLETIONS:
+
+ DeviceExtension->CompleteAsync = TRUE;
+ break;
+
+ case RT_INCOMINGCALL:
+
+ //BUGBUG
+ break;
+
+ case RT_EVENT:
+
+ //BUGBUG
+ break;
+
+ default:
+
+ break;
+ }
+
+ break;
+ }
+ case IOCTL_STUBMP_GETEVENTS:
+ {
+ KIRQL oldIrql;
+ KIRQL cancelIrql;
+ BOOLEAN satisfiedRequest = FALSE;
+
+
+ //
+ // Sync event buf access by acquiring EventSpinLock
+ //
+
+ KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql);
+
+
+ //
+ // Inspect DeviceExtension to see if there's any data available
+ //
+
+ DBGOUT((
+ 2,
+ "IOCTL_STUBMP_GETEVENTS, Irp=x%x, bytesInQ=x%x",
+ Irp,
+ DeviceExtension->BytesInQueue
+ ));
+
+ if (DeviceExtension->BytesInQueue != 0)
+ {
+ ULONG bytesInQueue;
+ ULONG bytesToMove;
+ ULONG moveSize;
+ PCHAR EventBuffer = (PCHAR) ((ULONG *) ioBuffer + 1);
+
+
+ bytesInQueue = DeviceExtension->BytesInQueue;
+
+ bytesToMove = *((ULONG *) ioBuffer);
+
+ bytesToMove = (bytesInQueue < bytesToMove) ? bytesInQueue : bytesToMove;
+
+
+ //
+ // moveSize <- MIN(Number of bytes to be moved from the event data queue,
+ // Number of bytes to end of event data queue).
+ //
+
+ bytesInQueue =
+ ((PCHAR) DeviceExtension->EventDataQueue +
+ DeviceExtension->EventDataQueueLength) -
+ (PCHAR) DeviceExtension->DataOut;
+
+ moveSize = (bytesToMove < bytesInQueue) ? bytesToMove : bytesInQueue;
+
+
+ //
+ // Move bytes from the class input data queue to SystemBuffer, until
+ // the request is satisfied or we wrap the class input data buffer.
+ //
+
+ RtlMoveMemory(
+ EventBuffer,
+ (PCHAR) DeviceExtension->DataOut,
+ moveSize
+ );
+
+ EventBuffer += moveSize;
+
+
+ //
+ // If the data wraps in the event data buffer, copy the rest
+ // of the data from the start of the input data queue
+ // buffer through the end of the queued data.
+ //
+
+ if ((bytesToMove - moveSize) > 0)
+ {
+ //
+ // moveSize <- Remaining number bytes to move.
+ //
+
+ moveSize = bytesToMove - moveSize;
+
+ //
+ // Move the bytes from the
+ //
+
+ RtlMoveMemory(
+ EventBuffer,
+ (PCHAR) DeviceExtension->EventDataQueue,
+ moveSize
+ );
+
+ //
+ // Update the class input data queue removal pointer.
+ //
+
+ DeviceExtension->DataOut =
+ ((PCHAR) DeviceExtension->EventDataQueue) + moveSize;
+ }
+ else
+ {
+ //
+ // Update the input data queue removal pointer.
+ //
+
+ DeviceExtension->DataOut =
+ ((PCHAR) DeviceExtension->DataOut) + moveSize;
+ }
+
+
+ //
+ // Update the event data queue EventCount.
+ //
+
+ DeviceExtension->BytesInQueue -= bytesToMove;
+
+
+ //
+ //
+ //
+
+ *((ULONG *) ioBuffer) = bytesToMove;
+
+
+ //
+ //
+ //
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(ULONG) + bytesToMove;
+
+ satisfiedRequest = TRUE;
+ }
+ else
+ {
+ //
+ // Hold the request pending. It remains in the cancelable
+ // state. When new line event input is received
+ // (NdisTapiIndicateStatus) or generated (i.e.
+ // LINEDEVSTATE_REINIT) the data will get copied & the
+ // request completed.
+ //
+
+ DeviceExtension->EventsRequestIrp = Irp;
+
+ Irp->IoStatus.Status = STATUS_PENDING;
+
+ IoAcquireCancelSpinLock (&cancelIrql);
+ IoSetCancelRoutine (Irp, StubmpCancel);
+ IoReleaseCancelSpinLock (cancelIrql);
+ }
+
+ KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql);
+
+
+ //
+ // If request not satisfied just return pending
+ //
+
+ if (!satisfiedRequest)
+ {
+ return STATUS_PENDING;
+ }
+
+ break;
+ }
+ default:
+
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+
+ DBGOUT ((2, "unknown IRP_MJ_DEVICE_CONTROL"));
+
+ break;
+
+ }
+
+ break;
+ }
+
+
+ //
+ // DON'T get cute and try to use the status field of
+ // the irp in the return status. That IRP IS GONE as
+ // soon as you call IoCompleteRequest.
+ //
+
+ ntStatus = Irp->IoStatus.Status;
+
+ IoCompleteRequest (Irp, IO_NO_INCREMENT);
+
+
+ //
+ // We never have pending operation so always return the status code.
+ //
+
+ return ntStatus;
+}
+
+
+PDRVLINE
+GetpLine(
+ HDRV_LINE hdLine
+ )
+{
+ return (DeviceExtension->apLines
+ [(ULONG) hdLine - DeviceExtension->DeviceIDBase]);
+
+}
+
+
+NDIS_STATUS
+StubmpRequest(
+ NDIS_HANDLE NdisBindingHandle,
+ PNDIS_REQUEST NdisRequest
+ )
+{
+ BOOLEAN completeAsync = DeviceExtension->CompleteAsync;
+ ULONG i, j, ulRequestSpecific = 0;
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ NDIS_TAPI_EVENT event;
+
+
+ //
+ // Handle the request
+ //
+
+ if (NdisRequest->RequestType == NdisRequestQueryInformation)
+ {
+ switch (NdisRequest->DATA.QUERY_INFORMATION.Oid)
+ {
+ case OID_TAPI_CONFIG_DIALOG:
+ {
+ PNDIS_TAPI_CONFIG_DIALOG pConfigDialog =
+ (PNDIS_TAPI_CONFIG_DIALOG)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_DEV_SPECIFIC:
+ {
+ PNDIS_TAPI_DEV_SPECIFIC pDevSpecific =
+ (PNDIS_TAPI_DEV_SPECIFIC)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_ADDRESS_CAPS:
+ {
+ PNDIS_TAPI_GET_ADDRESS_CAPS pGetAddressCaps =
+ (PNDIS_TAPI_GET_ADDRESS_CAPS)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_ADDRESS_ID:
+ {
+ PNDIS_TAPI_GET_ADDRESS_ID pGetAddressID =
+ (PNDIS_TAPI_GET_ADDRESS_ID)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_ADDRESS_STATUS:
+ {
+ PNDIS_TAPI_GET_ADDRESS_STATUS pGetAddressStatus =
+ (PNDIS_TAPI_GET_ADDRESS_STATUS)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_CALL_ADDRESS_ID:
+ {
+ PNDIS_TAPI_GET_CALL_ADDRESS_ID pGetCallAddressID =
+ (PNDIS_TAPI_GET_CALL_ADDRESS_ID)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_CALL_INFO:
+ {
+ PNDIS_TAPI_GET_CALL_INFO pGetCallInfo =
+ (PNDIS_TAPI_GET_CALL_INFO)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_CALL_STATUS:
+ {
+ PNDIS_TAPI_GET_CALL_STATUS pGetCallStatus =
+ (PNDIS_TAPI_GET_CALL_STATUS)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_DEV_CAPS:
+ {
+ PNDIS_TAPI_GET_DEV_CAPS pGetDevCaps = (PNDIS_TAPI_GET_DEV_CAPS)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_DEV_CONFIG:
+ {
+ PNDIS_TAPI_GET_DEV_CONFIG pGetDevConfig =
+ (PNDIS_TAPI_GET_DEV_CONFIG)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_EXTENSION_ID:
+ {
+ PNDIS_TAPI_GET_EXTENSION_ID pGetExtensionID =
+ (PNDIS_TAPI_GET_EXTENSION_ID)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_ID:
+ {
+ PNDIS_TAPI_GET_ID pGetID = (PNDIS_TAPI_GET_ID)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_GET_LINE_DEV_STATUS:
+ {
+ PNDIS_TAPI_GET_LINE_DEV_STATUS pGetLineDevStatus =
+ (PNDIS_TAPI_GET_LINE_DEV_STATUS)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_MAKE_CALL:
+ {
+ PNDIS_TAPI_MAKE_CALL pMakeCall = (PNDIS_TAPI_MAKE_CALL)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+ PDRVLINE pLine = GetpLine (pMakeCall->hdLine);
+
+
+ for (i = 0; i < DeviceExtension->ulNumCallsPerLine; i++)
+ {
+ if (!pLine->aCalls[i].htCall)
+ {
+ pLine->aCalls[i].htCall = pMakeCall->htCall;
+ pLine->aCalls[i].pLine = pLine;
+
+ pMakeCall->hdCall = (HDRV_CALL) (pLine->aCalls + i);
+
+ break;
+ }
+ }
+
+ if (i == DeviceExtension->ulNumCallsPerLine)
+ {
+ status = NDIS_STATUS_TAPI_CALLUNAVAIL;
+ }
+
+ ulRequestSpecific = (ULONG) (pLine->aCalls + i);
+
+ break;
+ }
+ case OID_TAPI_NEGOTIATE_EXT_VERSION:
+ {
+ PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNegotiateExtVersion =
+ (PNDIS_TAPI_NEGOTIATE_EXT_VERSION)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_OPEN:
+ {
+ PNDIS_TAPI_OPEN pOpen = (PNDIS_TAPI_OPEN)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+ PDRVLINE pLine = DeviceExtension->apLines
+ [pOpen->ulDeviceID - DeviceExtension->DeviceIDBase];
+
+
+ ulRequestSpecific =
+ pLine->htLine = pOpen->htLine;
+
+ pOpen->hdLine = (HDRV_LINE) pOpen->ulDeviceID;
+
+ break;
+ }
+ case OID_TAPI_PROVIDER_INITIALIZE:
+ {
+ PNDIS_TAPI_PROVIDER_INITIALIZE pInitialize =
+ (PNDIS_TAPI_PROVIDER_INITIALIZE)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+
+
+ DeviceExtension->DeviceIDBase = pInitialize->ulDeviceIDBase;
+
+ for (i = 0; i < DeviceExtension->ulNumLines; i++)
+ {
+ DeviceExtension->apLines[i]->ulDeviceID =
+ pInitialize->ulDeviceIDBase + i;
+
+ for (j = 0; j < DeviceExtension->ulNumCallsPerLine; j++)
+ {
+ DeviceExtension->apLines[i]->aCalls[j].htCall =
+ (HTAPI_CALL) NULL;
+ }
+ }
+
+ ulRequestSpecific =
+ pInitialize->ulNumLineDevs = DeviceExtension->ulNumLines;
+
+ break;
+ }
+ default:
+
+ break;
+
+ } // switch
+
+
+ //
+ // Send info about this request to the app
+ //
+
+ {
+ ULONG *args = (ULONG *)
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+ ULONG requestData[8] =
+ {
+ ET_REQUEST,
+ (ULONG) completeAsync,
+ (ULONG) NdisRequest,
+ (ULONG) status,
+ (ULONG) NdisRequest->DATA.QUERY_INFORMATION.Oid,
+ *args,
+ *(args+1),
+ ulRequestSpecific
+ };
+
+
+ WriteRingBuffer (requestData, 8 * sizeof(ULONG));
+ }
+ }
+
+ else if (NdisRequest->RequestType == NdisRequestSetInformation)
+ {
+ switch (NdisRequest->DATA.SET_INFORMATION.Oid)
+ {
+ case OID_TAPI_ACCEPT:
+ {
+ PNDIS_TAPI_ACCEPT pAccept = (PNDIS_TAPI_ACCEPT)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_ANSWER:
+ {
+ PNDIS_TAPI_ANSWER pAnswer = (PNDIS_TAPI_ANSWER)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_CLOSE:
+ {
+ PNDIS_TAPI_CLOSE pClose = (PNDIS_TAPI_CLOSE)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+ PDRVLINE pLine = GetpLine (pClose->hdLine);
+
+
+ pLine->htLine = 0;
+
+ break;
+ }
+ case OID_TAPI_CLOSE_CALL:
+ {
+ PNDIS_TAPI_CLOSE_CALL pCloseCall = (PNDIS_TAPI_CLOSE_CALL)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+ PDRVCALL pCall = (PDRVCALL) pCloseCall->hdCall;
+
+
+ pCall->htCall = (HTAPI_CALL) NULL;
+
+ break;
+ }
+ case OID_TAPI_CONDITIONAL_MEDIA_DETECTION:
+ {
+ PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION pConditionalMediaDetection =
+ (PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_DIAL:
+ {
+ PNDIS_TAPI_DIAL pDial = (PNDIS_TAPI_DIAL)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_DROP:
+ {
+ PNDIS_TAPI_DROP pDrop = (PNDIS_TAPI_DROP)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_PROVIDER_SHUTDOWN:
+ {
+ PNDIS_TAPI_PROVIDER_SHUTDOWN pShutdown =
+ (PNDIS_TAPI_PROVIDER_SHUTDOWN)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SECURE_CALL:
+ {
+ PNDIS_TAPI_SECURE_CALL pSecureCall = (PNDIS_TAPI_SECURE_CALL)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SELECT_EXT_VERSION:
+ {
+ PNDIS_TAPI_SELECT_EXT_VERSION pSelectExtVersion =
+ (PNDIS_TAPI_SELECT_EXT_VERSION)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SEND_USER_USER_INFO:
+ {
+ PNDIS_TAPI_SEND_USER_USER_INFO pSendUserUserInfo =
+ (PNDIS_TAPI_SEND_USER_USER_INFO)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SET_APP_SPECIFIC:
+ {
+ PNDIS_TAPI_SET_APP_SPECIFIC pSetApSpecific =
+ (PNDIS_TAPI_SET_APP_SPECIFIC)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SET_CALL_PARAMS:
+ {
+ PNDIS_TAPI_SET_CALL_PARAMS pSetCallParams =
+ (PNDIS_TAPI_SET_CALL_PARAMS)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SET_DEFAULT_MEDIA_DETECTION:
+ {
+ PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pSetDefaultMediaDetection =
+ (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SET_DEV_CONFIG:
+ {
+ PNDIS_TAPI_SET_DEV_CONFIG pSetDevConfig =
+ (PNDIS_TAPI_SET_DEV_CONFIG)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SET_MEDIA_MODE:
+ {
+ PNDIS_TAPI_SET_MEDIA_MODE pSetMediaMode =
+ (PNDIS_TAPI_SET_MEDIA_MODE)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ case OID_TAPI_SET_STATUS_MESSAGES:
+ {
+ PNDIS_TAPI_SET_STATUS_MESSAGES pSetStatusMessages =
+ (PNDIS_TAPI_SET_STATUS_MESSAGES)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+
+ break;
+ }
+ default:
+
+ break;
+
+ } // switch
+
+
+ //
+ // Send info about this request to the app
+ //
+
+ {
+ ULONG *args = (ULONG *)
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+ REQUEST_PARAMS requestParams =
+ {
+ ET_REQUEST,
+ (ULONG) completeAsync,
+ (ULONG) NdisRequest,
+ (ULONG) status,
+ (ULONG) NdisRequest->DATA.SET_INFORMATION.Oid,
+ *args,
+ *(args+1),
+ ulRequestSpecific
+ };
+
+
+ WriteRingBuffer (&requestParams, sizeof(REQUEST_PARAMS));
+ }
+ }
+ else
+ {
+ DBGOUT((1, "StubmpRequest: unknown NdisRequest->RequestType"));
+ }
+
+
+ if (completeAsync)
+ {
+ status = NDIS_STATUS_PENDING;
+
+ DBGOUT((2, "StubmpRequest: Req x%x pending", NdisRequest));
+ }
+ else
+ {
+ DBGOUT((2, "StubmpRequest: Req x%x completing sync", NdisRequest));
+ }
+
+ return status;
+}
+
+
+
+VOID
+StubmpUnload(
+ IN PDRIVER_OBJECT DriverObject
+ )
+/*++
+
+Routine Description:
+
+ Free all the allocated resources, etc.
+
+Arguments:
+
+ DriverObject - pointer to a driver object
+
+Return Value:
+
+
+--*/
+{
+ ULONG i;
+ WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Stubmp";
+ UNICODE_STRING deviceLinkUnicodeString;
+
+
+ DBGOUT ((2, "StubmpUnload: enter"));
+
+
+ //
+ // Delete the symbolic link
+ //
+
+ RtlInitUnicodeString (&deviceLinkUnicodeString,
+ deviceLinkBuffer
+ );
+
+ IoDeleteSymbolicLink (&deviceLinkUnicodeString);
+
+
+ //
+ // Free all the resources
+ //
+
+ for (i = 0; i < DeviceExtension->ulNumLines; i++)
+ {
+ ExFreePool (DeviceExtension->apLines[i]);
+ }
+
+
+ //
+ // Delete the device object
+ //
+
+ IoDeleteDevice (DriverObject->DeviceObject);
+}
+
+
+VOID
+StubmpCancel(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+{
+ KIRQL oldIrql;
+
+
+ DBGOUT((2,"StubmpCancel: enter"));
+
+
+ //
+ // Release the cancel spinlock
+ //
+
+ IoReleaseCancelSpinLock (Irp->CancelIrql);
+
+
+ //
+ // Acquire the EventSpinLock & check to see if we're canceling a
+ // pending get-events Irp
+ //
+
+ KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql);
+
+ if (Irp == DeviceExtension->EventsRequestIrp)
+ {
+ DeviceExtension->EventsRequestIrp = NULL;
+ }
+
+ KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql);
+
+
+StubmpCancel_done:
+
+ //
+ // Complete the request with STATUS_CANCELLED.
+ //
+
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest (Irp, IO_NO_INCREMENT);
+
+ DBGOUT((2,"StubmpCancel: exit (completing irp=x%x)", Irp));
+
+ return;
+}
+
+
+#ifdef DBG
+VOID
+DbgPrt(
+ IN ULONG DbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+{
+ if (DbgLevel <= StubmpDebugLevel)
+ {
+ char buf[256] = "STUBMP.SYS: ";
+ va_list ap;
+
+ va_start (ap, DbgMessage);
+
+ vsprintf (&buf[12], DbgMessage, ap);
+
+ strcat (buf, "\n");
+
+ DbgPrint (buf);
+
+ va_end(ap);
+ }
+
+ return;
+}
+#endif
+
+
+VOID
+WriteRingBuffer(
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ )
+/*++
+
+Routine Description:
+
+ This func gets called by Ndis when a miniport driver calls
+ NdisIndicateStatus to notify us of an async event
+ (i.e. new call, call state chg, dev state chg, etc.)
+
+Arguments:
+
+
+
+Return Value:
+
+
+--*/
+
+{
+ PIRP irp;
+ KIRQL oldIrql;
+ KIRQL cancelIrql;
+ ULONG bytesInQueue;
+ ULONG bytesToMove;
+ ULONG moveSize;
+ BOOLEAN satisfiedPendingEventsRequest = FALSE;
+ PCHAR ioBuffer;
+
+
+ DBGOUT((2,"WriteRingBuffer: enter"));
+
+ bytesInQueue = StatusBufferSize;
+
+ moveSize = 0;
+
+
+ //
+ // Sync event buf access by acquiring EventSpinLock
+ //
+
+ KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql);
+
+
+ //
+ // Check of there is an outstanding request to satisfy
+ //
+
+ if (DeviceExtension->EventsRequestIrp)
+ {
+ //
+ // Acquire the cancel spinlock, remove the request from the
+ // cancellable state, and free the cancel spinlock.
+ //
+
+ IoAcquireCancelSpinLock (&cancelIrql);
+ irp = DeviceExtension->EventsRequestIrp;
+ IoSetCancelRoutine (irp, NULL);
+ DeviceExtension->EventsRequestIrp = NULL;
+ IoReleaseCancelSpinLock (cancelIrql);
+
+
+ //
+ // Copy as much of the input data possible from the input data
+ // queue to the SystemBuffer to satisfy the read.
+ //
+
+ ioBuffer = irp->AssociatedIrp.SystemBuffer;
+
+ bytesToMove = *((ULONG *) ioBuffer);
+
+ moveSize = (bytesInQueue < bytesToMove) ? bytesInQueue : bytesToMove;
+
+ RtlMoveMemory (
+ ioBuffer + sizeof(ULONG),
+ (PCHAR) StatusBuffer,
+ moveSize
+ );
+
+
+ //
+ // Set the flag so that we start the next packet and complete
+ // this read request (with STATUS_SUCCESS) prior to return.
+ //
+
+ *((ULONG *) ioBuffer) = moveSize;
+
+ irp->IoStatus.Status = STATUS_SUCCESS;
+
+ irp->IoStatus.Information = sizeof(ULONG) + moveSize;
+
+ satisfiedPendingEventsRequest = TRUE;
+ }
+
+
+ //
+ // If there is still data in the input data queue, move it
+ // to the event data queue
+ //
+
+ StatusBuffer = ((PCHAR) StatusBuffer) + moveSize;
+
+ moveSize = bytesInQueue - moveSize;
+
+ if (moveSize > 0)
+ {
+ //
+ // Move the remaining data from the status data queue to the
+ // event data queue. The move will happen in two parts in
+ // the case where the event data buffer wraps.
+ //
+
+ bytesInQueue = DeviceExtension->EventDataQueueLength -
+ DeviceExtension->BytesInQueue;
+
+ bytesToMove = moveSize;
+
+ if (bytesInQueue == 0)
+ {
+ //
+ // Refuse to move any bytes that would cause an event data
+ // queue overflow. Just drop the bytes on the floor, and
+ // log an overrun error.
+ //
+
+ DBGOUT((1,"WriteRingBuffer: event queue overflow"));
+ }
+ else
+ {
+ //
+ // There is room in the event data queue, so move the
+ // remaining status data to it.
+ //
+ // bytesToMove <- MIN(Number of unused bytes in event data queue,
+ // Number of bytes remaining in status buffer)
+ //
+ // This is the total number of bytes that actually will move from
+ // the status data buffer to the event data queue.
+ //
+
+ bytesToMove = (bytesInQueue < bytesToMove) ?
+ bytesInQueue : bytesToMove;
+
+
+ //
+ // bytesInQueue <- Number of unused bytes from insertion pointer
+ // to the end of the event data queue (i.e., until the buffer
+ // wraps)
+ //
+
+ bytesInQueue =
+ ((PCHAR) DeviceExtension->EventDataQueue +
+ DeviceExtension->EventDataQueueLength) -
+ (PCHAR) DeviceExtension->DataIn;
+
+
+ //
+ // moveSize <- Number of bytes to handle in the first move.
+ //
+
+ moveSize = (bytesToMove < bytesInQueue) ?
+ bytesToMove : bytesInQueue;
+
+
+ //
+ // Do the move from the status data buffer to the event data queue
+ //
+
+ RtlMoveMemory(
+ (PCHAR) DeviceExtension->DataIn,
+ (PCHAR) StatusBuffer,
+ moveSize
+ );
+
+ //
+ // Increment the event data queue pointer and the status data
+ // buffer insertion pointer. Wrap the insertion pointer,
+ // if necessary.
+ //
+
+ StatusBuffer = ((PCHAR) StatusBuffer) + moveSize;
+
+ DeviceExtension->DataIn =
+ ((PCHAR) DeviceExtension->DataIn) + moveSize;
+
+ if ((PCHAR) DeviceExtension->DataIn >=
+ ((PCHAR) DeviceExtension->EventDataQueue +
+ DeviceExtension->EventDataQueueLength))
+ {
+ DeviceExtension->DataIn =
+ DeviceExtension->EventDataQueue;
+ }
+
+ if ((bytesToMove - moveSize) > 0)
+ {
+ //
+ // Special case. The data must wrap in the event data
+ // buffer. Copy the rest of the status data into the
+ // beginning of the event data queue.
+ //
+
+ //
+ // moveSize <- Number of bytes to handle in the second move.
+ //
+
+ moveSize = bytesToMove - moveSize;
+
+
+ //
+ // Do the move from the status data buffer to the event data
+ // queue
+ //
+
+ RtlMoveMemory(
+ (PCHAR) DeviceExtension->DataIn,
+ (PCHAR) StatusBuffer,
+ moveSize
+ );
+
+ //
+ // Update the event data queue insertion pointer
+ //
+
+ DeviceExtension->DataIn =
+ ((PCHAR) DeviceExtension->DataIn) + moveSize;
+ }
+
+ //
+ // Update the event data queue counter
+ //
+
+ DeviceExtension->BytesInQueue += bytesToMove;
+ }
+ }
+
+
+ //
+ // Release the spinlock
+ //
+
+ KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql);
+
+
+ //
+ // If we satisfied an outstanding get events request then complete it
+ //
+
+ if (satisfiedPendingEventsRequest)
+ {
+ IoCompleteRequest (irp, IO_NO_INCREMENT);
+
+ DBGOUT((2, "WriteRingBuffer: completing req x%x", irp));
+ }
+
+
+ DBGOUT((2,"WriteRingBuffer: exit"));
+
+ return;
+}
diff --git a/private/tapi/dev/sp/kmesp/sys/stubmp.h b/private/tapi/dev/sp/kmesp/sys/stubmp.h
new file mode 100644
index 000000000..baaa77638
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/sys/stubmp.h
@@ -0,0 +1,109 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ stubmp.h
+
+Abstract:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+typedef struct _DRVCALL
+{
+ PVOID pLine;
+
+ HTAPI_CALL htCall;
+
+ ULONG ulAddressID;
+
+ ULONG ulCallState;
+
+ ULONG ulMediaMode;
+
+ ULONG ulAppSpecific;
+
+} DRVCALL, *PDRVCALL;
+
+
+typedef struct _DRVLINE
+{
+ ULONG ulDeviceID;
+
+ HTAPI_LINE htLine;
+
+ DRVCALL aCalls[1];
+
+} DRVLINE, *PDRVLINE;
+
+
+typedef struct _DEVICE_EXTENSION
+{
+ PIRP EventsRequestIrp;
+
+ KSPIN_LOCK EventSpinLock;
+
+ PVOID EventDataQueue;
+
+ ULONG EventDataQueueLength;
+
+ PVOID DataIn;
+
+ PVOID DataOut;
+
+ ULONG BytesInQueue;
+
+ ULONG DeviceIDBase;
+
+ BOOLEAN CompleteAsync;
+
+ ULONG ulNumLines;
+
+ ULONG ulNumAddrsPerLine;
+
+ ULONG ulNumCallsPerLine;
+
+ PDRVLINE apLines[1];
+
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+
+//
+// The following are types/exports from ndistapi.sys
+//
+
+typedef VOID (*REQUEST_PROC)(PNDIS_STATUS, NDIS_HANDLE, PNDIS_REQUEST);
+
+VOID
+NdisTapiRegisterProvider(
+ IN NDIS_HANDLE ProviderHandle,
+ IN REQUEST_PROC RequestProc
+ );
+
+VOID
+NdisTapiDeregisterProvider(
+ IN NDIS_HANDLE ProviderHandle
+ );
+
+VOID
+NdisTapiCompleteRequest(
+ IN NDIS_HANDLE NdisHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN NDIS_STATUS NdisStatus
+ );
+
+VOID
+NdisTapiIndicateStatus(
+ IN ULONG DriverHandle,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
diff --git a/private/tapi/dev/sp/kmesp/sys/stubmp.ini b/private/tapi/dev/sp/kmesp/sys/stubmp.ini
new file mode 100644
index 000000000..ed306d876
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/sys/stubmp.ini
@@ -0,0 +1,4 @@
+\registry\machine\system\currentcontrolset\services\Stubmp
+ Type = REG_DWORD 0x00000001
+ Start = REG_DWORD 0x00000003
+ ErrorControl = REG_DWORD 0x00000001
diff --git a/private/tapi/dev/sp/kmesp/sys/stubmp.src b/private/tapi/dev/sp/kmesp/sys/stubmp.src
new file mode 100644
index 000000000..bc4acf939
--- /dev/null
+++ b/private/tapi/dev/sp/kmesp/sys/stubmp.src
@@ -0,0 +1,2 @@
+NAME STUBMP.SYS
+DESCRIPTION 'STUBMP.SYS'
diff --git a/private/tapi/dev/sp/makefile b/private/tapi/dev/sp/makefile
new file mode 100644
index 000000000..2c4195dfe
--- /dev/null
+++ b/private/tapi/dev/sp/makefile
@@ -0,0 +1,27 @@
+!if "$(OS)" == "Windows_NT"
+
+clean:
+ echo "Clean target null in this directory"
+
+!else
+
+##########################################################################
+#
+# Microsoft Confidential
+# Copyright (C) Microsoft Corporation 1995
+# All Rights Reserved.
+#
+##########################################################################
+
+
+ROOT = ..\..\..\..
+DIR = sp
+
+IS_OEM=1
+
+DIRLIST = tsp3216
+#DIRLIST = atsp32 esp.new remotesp tsp3216
+
+!include $(ROOT)\root.mk
+
+!endif
diff --git a/private/tapi/dev/sp/pdisp32/makefile b/private/tapi/dev/sp/pdisp32/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/tapi/dev/sp/pdisp32/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/tapi/dev/sp/pdisp32/pdisp.c b/private/tapi/dev/sp/pdisp32/pdisp.c
new file mode 100644
index 000000000..5e2a5605d
--- /dev/null
+++ b/private/tapi/dev/sp/pdisp32/pdisp.c
@@ -0,0 +1,1594 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ pdisp.c
+
+Abstract:
+
+
+
+Author:
+
+ ??? dd-Mmm-1995
+
+Revision History:
+
+--*/
+
+
+#include <windows.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "pdisp.h"
+
+BOOL CALLBACK __export ConfigDlgProc(HWND, UINT, WPARAM, LPARAM);
+
+HANDLE SerialOpenComms (LPSTR, LPSTR);
+void LoadIniStrings (DWORD);
+long appCall (int, char *, long);
+
+
+#define msgMakeCall 1
+#define msgDrop 2
+
+
+// The number of entries in the devices and speed array.
+
+#define NUMPORTS 4
+
+char *lpszCommDevArray[NUMPORTS] = { "COM1", "COM2", "COM3", "COM4" };
+
+
+// Various tags in the ini file.
+
+char s_telephon_ini[] = "telephon.ini";
+
+char s_one[] = "1";
+char s_zero[] = "0";
+char s_numlines[] = "NumLines";
+char s_numphones[] = "NumPhones";
+char s_providerx[] = "Provider%d";
+
+char s_port[] = "Port";
+char s_linename[] = "LineName";
+char s_lineaddr[] = "LineAddress";
+
+HANDLE hInst = NULL;
+ATSPLineData line;
+char gszProviderInfo[255];
+
+
+long
+appCall(
+ int msg,
+ char *str,
+ long dwRequestID
+ );
+
+long
+lineDropCore(
+ ATSPLineData *theLine,
+ DWORD dwRequestID
+ );
+
+#ifdef WIN32
+
+BOOL
+WINAPI
+_CRT_INIT(
+ HINSTANCE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ );
+
+
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ if (!_CRT_INIT (hInst, dwReason, lpReserved))
+ {
+ OutputDebugString ("PDISP32: DllMain: _CRT_INIT() failed\n\r");
+ }
+
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+ hInst = hDLL;
+
+ break;
+
+ case DLL_PROCESS_DETACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+
+ break;
+ }
+
+ return TRUE;
+}
+
+#else
+
+int
+FAR
+PASCAL
+LibMain(
+ HANDLE hInstance,
+ WORD wDataSegment,
+ WORD wHeapSize,
+ LPSTR lpszCmdLine
+ )
+{
+ if (hInst != NULL)
+ return FALSE;
+
+ hInst = hInstance;
+
+ return TRUE;
+}
+
+VOID
+FAR
+PASCAL
+__export
+WEP(
+ int bSystemExit
+ )
+{
+ hInst = NULL;
+}
+
+#endif // WIN32
+
+
+static BOOL initialised = FALSE;
+
+
+//
+// -------------------------- TSPI_lineXxx funcs ------------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ DebugMsg (("Entering TSPI_lineConditionalMediaDetection"));
+
+ if (hdLine != (HDRVLINE) &line)
+ {
+ return LINEERR_INVALLINEHANDLE;
+ }
+
+ if (dwMediaModes != LINEMEDIAMODE_INTERACTIVEVOICE)
+ {
+ return LINEERR_INVALMEDIAMODE;
+ }
+
+ return 0;
+}
+
+/* BUGBUG needs to use new TUISPI stuff
+LONG
+TSPIAPI
+TSPI_lineConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+{
+ DebugMsg (("Entering TSPI_lineConfigDialog"));
+
+ if (dwDeviceID != line.lineID)
+ {
+ return LINEERR_BADDEVICEID;
+ }
+
+ DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwndOwner, ConfigDlgProc);
+
+ return 0;
+}
+*/
+
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+{
+ DebugMsg (("Entering TSPI_lineClose"));
+
+ if (hdLine != (HDRVLINE) &line)
+ {
+ return LINEERR_INVALLINEHANDLE;
+ }
+
+
+ //
+ // call drop in case there is still an active call on the line
+ //
+
+ lineDropCore (&line, 0);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+{
+ DebugMsg (("Entering TSPI_lineCloseCall"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ {
+ return LINEERR_INVALCALLHANDLE;
+ }
+
+
+ //
+ // call drop in case there is still an active call on the line
+ //
+
+ lineDropCore (&line, 0);
+
+ line.callState = 0;
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ // Transition a call to the IDLE state.
+
+ DebugMsg (("Entering TSPI_lineDrop"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ return LINEERR_INVALCALLHANDLE;
+
+ return lineDropCore (&line, dwRequestID); // it was our active call
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+{
+ int cbLineAddr;
+
+ DebugMsg (("Entering TSPI_lineGetAddressCaps"));
+
+ // We support only one line and one address.
+
+ if (dwDeviceID != line.lineID)
+ {
+ return LINEERR_BADDEVICEID;
+ }
+
+ if (dwAddressID != 0)
+ {
+ return LINEERR_INVALADDRESSID;
+ }
+
+ cbLineAddr = strlen (line.lineaddr) + 1;
+
+ lpAddressCaps->dwNeededSize = sizeof (LINEADDRESSCAPS) + cbLineAddr;
+
+ if (lpAddressCaps->dwTotalSize < lpAddressCaps->dwNeededSize)
+ {
+ lpAddressCaps->dwUsedSize = sizeof (LINEADDRESSCAPS);
+ }
+ else
+ {
+ memcpy(
+ (char *) lpAddressCaps + sizeof (LINEADDRESSCAPS),
+ line.lineaddr,
+ cbLineAddr
+ );
+
+ lpAddressCaps->dwAddressSize = cbLineAddr;
+ lpAddressCaps->dwAddressOffset = sizeof (LINEADDRESSCAPS);
+ lpAddressCaps->dwUsedSize = lpAddressCaps->dwNeededSize;
+ }
+
+ lpAddressCaps->dwLineDeviceID = line.lineID;
+
+ lpAddressCaps->dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
+ lpAddressCaps->dwAddressStates = LINEADDRESSSTATE_OTHER |
+ LINEADDRESSSTATE_INUSEZERO |
+ LINEADDRESSSTATE_INUSEONE |
+ LINEADDRESSSTATE_NUMCALLS;
+ lpAddressCaps->dwCallInfoStates = LINECALLINFOSTATE_OTHER |
+ LINECALLINFOSTATE_APPSPECIFIC |
+ LINECALLINFOSTATE_NUMOWNERINCR |
+ LINECALLINFOSTATE_NUMOWNERDECR |
+ LINECALLINFOSTATE_NUMMONITORS |
+ LINECALLINFOSTATE_DIALPARAMS;
+ lpAddressCaps->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpAddressCaps->dwCallStates = LINECALLSTATE_IDLE |
+ LINECALLSTATE_DIALTONE |
+ LINECALLSTATE_DIALING |
+ LINECALLSTATE_BUSY |
+ LINECALLSTATE_CONNECTED |
+ LINECALLSTATE_PROCEEDING |
+ LINECALLSTATE_UNKNOWN;
+ lpAddressCaps->dwDialToneModes = LINEDIALTONEMODE_UNAVAIL;
+ lpAddressCaps->dwBusyModes = LINEBUSYMODE_UNAVAIL;
+ lpAddressCaps->dwSpecialInfo = LINESPECIALINFO_UNAVAIL;
+ lpAddressCaps->dwDisconnectModes = LINEDISCONNECTMODE_UNKNOWN;
+ lpAddressCaps->dwMaxNumActiveCalls = 1;
+ lpAddressCaps->dwAddrCapFlags = LINEADDRCAPFLAGS_BLOCKIDDEFAULT |
+ LINEADDRCAPFLAGS_DIALED |
+ LINEADDRCAPFLAGS_PARTIALDIAL;
+ lpAddressCaps->dwCallFeatures = LINECALLFEATURE_DIAL |
+ LINECALLFEATURE_DROP;
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCSTR lpsAddress,
+ DWORD dwSize
+ )
+{
+ DebugMsg (("Entering TSPI_lineGetAddressID"));
+
+ if (hdLine != (HDRVLINE) &line)
+ {
+ return LINEERR_INVALLINEHANDLE;
+ }
+
+ assert (dwAddressMode == LINEADDRESSMODE_DIALABLEADDR);
+
+ if (strcmp (line.lineaddr, lpsAddress))
+ {
+ return LINEERR_INVALADDRESS;
+ }
+ else
+ {
+ *lpdwAddressID = 0; // we support only 1 line
+ return 0;
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+{
+ DebugMsg (("Entering TSPI_lineGetAddressStatus"));
+
+ if (dwAddressID)
+ {
+ return LINEERR_INVALADDRESSID;
+ }
+
+ lpAddressStatus->dwUsedSize =
+ lpAddressStatus->dwNeededSize = sizeof (LINEADDRESSSTATUS);
+
+ // if we are idle a call can be made
+
+ if (line.callState == 0) // our internal flag that line is not in use
+ {
+ lpAddressStatus->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
+ }
+ else
+ {
+ lpAddressStatus->dwNumInUse = 1;
+ lpAddressStatus->dwNumActiveCalls = 1;
+ }
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+{
+ DebugMsg (("Entering TSPI_lineGetCallAddressID"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ {
+ return LINEERR_INVALCALLHANDLE;
+ }
+
+
+ //
+ // There is but a single address where a call may exist.
+ //
+
+ *lpdwAddressID = 0;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+{
+ int cbDestAddr = strlen (line.DestAddress) + 1;
+
+ DebugMsg (("Entering TSPI_lineGetCallInfo"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ {
+ return LINEERR_INVALCALLHANDLE;
+ }
+
+ lpCallInfo->dwUsedSize = sizeof (LINECALLINFO);
+ lpCallInfo->dwNeededSize = sizeof (LINECALLINFO) + cbDestAddr;
+
+ if (lpCallInfo->dwTotalSize >= lpCallInfo->dwNeededSize)
+ {
+ memcpy(
+ (char *) lpCallInfo + sizeof (LINECALLINFO),
+ line.DestAddress,
+ cbDestAddr
+ );
+
+ lpCallInfo->dwDisplayableAddressSize = cbDestAddr;
+ lpCallInfo->dwDisplayableAddressOffset = sizeof (LINECALLINFO);
+ lpCallInfo->dwUsedSize = lpCallInfo->dwNeededSize;
+ }
+
+ lpCallInfo->dwLineDeviceID = line.lineID;
+ lpCallInfo->dwBearerMode = LINEBEARERMODE_VOICE;
+ lpCallInfo->dwMediaMode = line.dwMediaMode;
+ lpCallInfo->dwAppSpecific = line.dwAppSpecific;
+ lpCallInfo->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE |
+ LINECALLPARAMFLAGS_BLOCKID;
+ lpCallInfo->dwCallStates = LINECALLSTATE_IDLE |
+ LINECALLSTATE_CONNECTED;
+ lpCallInfo->dwOrigin = LINECALLORIGIN_OUTBOUND;
+ lpCallInfo->dwReason = LINECALLREASON_UNAVAIL;
+ lpCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
+ lpCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+{
+ DebugMsg (("Entering TSPI_lineGetCallStatus"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ {
+ return LINEERR_INVALCALLHANDLE;
+ }
+
+ lpCallStatus->dwCallState = line.callState;
+
+ if (line.callState == LINECALLSTATE_CONNECTED)
+ {
+ lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP;
+ }
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+{
+ int cbname = strlen (line.linename) + 1;
+ int cbinfo = strlen (gszProviderInfo) + 1;
+
+
+ DebugMsg (("Entering TSPI_lineGetDevCaps"));
+
+ if (dwDeviceID != line.lineID)
+ {
+ return LINEERR_BADDEVICEID;
+ }
+
+ lpLineDevCaps->dwUsedSize = sizeof (LINEDEVCAPS);
+ lpLineDevCaps->dwNeededSize = sizeof (LINEDEVCAPS) + cbinfo + cbname;
+
+ if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwUsedSize + cbinfo)
+ {
+ // Copy in the provider info
+
+ memcpy(
+ (char *)lpLineDevCaps + lpLineDevCaps->dwUsedSize,
+ gszProviderInfo,
+ cbinfo
+ );
+
+ lpLineDevCaps->dwProviderInfoSize = cbinfo;
+ lpLineDevCaps->dwProviderInfoOffset = lpLineDevCaps->dwUsedSize;
+ lpLineDevCaps->dwUsedSize += cbinfo;
+ }
+
+ if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwUsedSize + cbname)
+ {
+ // Copy in the line name
+
+ memcpy(
+ (char *) lpLineDevCaps + lpLineDevCaps->dwUsedSize,
+ line.linename,
+ cbname
+ );
+
+ lpLineDevCaps->dwLineNameSize = cbname;
+ lpLineDevCaps->dwLineNameOffset = lpLineDevCaps->dwUsedSize;
+ lpLineDevCaps->dwUsedSize += cbname;
+ }
+
+
+ lpLineDevCaps->dwPermanentLineID = (line.dwppID << 16) + 0;
+
+ // TAPI.DLL fills in APIVersion and ExtVersion.
+
+ lpLineDevCaps->dwNumAddresses = 1;
+ lpLineDevCaps->dwMaxNumActiveCalls = 1;
+ lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII;
+ lpLineDevCaps->dwBearerModes = LINEBEARERMODE_VOICE;
+ lpLineDevCaps->dwMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+{
+ DebugMsg (("Entering TSPI_lineGetID"));
+
+
+ // Since we have only one device, we don't have to
+ // check the location of the line, address, or call.
+
+ if (hdLine != (HDRVLINE) &line)
+ {
+ return LINEERR_INVALLINEHANDLE;
+ }
+
+ if (strcmp (lpszDeviceClass, "tapi/line") == 0)
+ {
+ lpDeviceID->dwNeededSize = sizeof (VARSTRING) + sizeof (DWORD);
+
+ if (lpDeviceID->dwTotalSize >= lpDeviceID->dwNeededSize)
+ {
+ lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof (DWORD);
+ lpDeviceID->dwStringOffset = sizeof (VARSTRING);
+
+ *((DWORD *) ((char *) lpDeviceID + sizeof (VARSTRING))) =
+ line.lineID;
+ }
+
+ return 0;
+ }
+
+#ifdef COMMSUPPORT
+
+ if (strcmp (lpszDeviceClass, "comm") == 0)
+ {
+ int cbport = strlen (line.port) + 1;
+
+
+ lpDeviceID->dwNeededSize = sizeof (VARSTRING) + cbport;
+
+ if (lpDeviceID->dwTotalSize >= lpDeviceID->dwNeededSize)
+ {
+ lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
+ lpDeviceID->dwStringFormat = STRINGFORMAT_ASCII;
+ lpDeviceID->dwStringSize = cbport;
+ lpDeviceID->dwStringOffset = sizeof (VARSTRING);
+
+ memcpy(
+ (char *) lpDeviceID + sizeof (VARSTRING),
+ line.port,
+ cbport
+ );
+ }
+
+ return 0;
+ }
+
+#endif
+
+ return LINEERR_NODEVICE;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+{
+ DebugMsg (("Entering TSPI_lineGetLineDevStatus"));
+
+ if (hdLine != (HDRVLINE) &line)
+ {
+ return LINEERR_INVALLINEHANDLE;
+ }
+
+ lpLineDevStatus->dwUsedSize =
+ lpLineDevStatus->dwNeededSize = sizeof (LINEDEVSTATUS);
+
+ lpLineDevStatus->dwOpenMediaModes = line.dwLineMediaModes;
+ lpLineDevStatus->dwRoamMode = LINEROAMMODE_UNAVAIL;
+
+ if (line.callState == 0)
+ {
+ lpLineDevStatus->dwNumActiveCalls = 0;
+ lpLineDevStatus->dwLineFeatures = LINEFEATURE_MAKECALL;
+ }
+ else
+ {
+ lpLineDevStatus->dwNumActiveCalls = 1;
+ lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
+ LINEDEVSTATUSFLAGS_INSERVICE;
+ }
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpNumAddressIDs
+ )
+{
+ DebugMsg (("Entering TSPI_lineGetNumAddressIDs"));
+
+ if (hdLine != (HDRVLINE) &line)
+ {
+ return LINEERR_INVALLINEHANDLE;
+ }
+
+ *lpNumAddressIDs = 1; // We only support one address
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ DebugMsg (("Entering TSPI_lineMakeCall"));
+
+ if (lpszDestAddress &&
+ (strlen (lpszDestAddress) > TAPIMAXDESTADDRESSSIZE))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+
+ if (line.callState != 0)
+ {
+ return LINEERR_RESOURCEUNAVAIL;
+ }
+
+ if (lpCallParams)
+ {
+ if (lpCallParams->dwCallParamFlags &
+ ~(LINECALLPARAMFLAGS_IDLE | LINECALLPARAMFLAGS_BLOCKID))
+ {
+ return LINEERR_INVALCALLPARAMS;
+ }
+ }
+
+ // fill in fields of the call record
+
+ line.htCall = htCall; // we have no hdcall of our own
+ *lphdCall = (HDRVCALL) htCall;
+
+ if (lpszDestAddress)
+ {
+ strcpy (line.DestAddress, lpszDestAddress);
+ }
+ else
+ {
+ line.DestAddress[0] = 0;
+ }
+
+ return appCall (msgMakeCall, line.DestAddress, dwRequestID);
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ DebugMsg (("Entering TSPI_lineNegotiateTSPIVersion"));
+
+ // line.lineID will contain garbage before provider_init has
+ // been called (ie. first time through). However, we can guarantee
+ // that the first call will be with INITIALIZE_NEGOTIATION and that
+ // is followed immediately by provider_init. This would be a problem
+ // if the line data structure was dynamically allocated !
+
+ // we support only one line
+
+ if (dwDeviceID == INITIALIZE_NEGOTIATION || dwDeviceID == line.lineID)
+ {
+ *lpdwTSPIVersion = 0x00010003;
+
+ if (dwLowVersion > 0x00010003 || // the app is too new for us
+ dwHighVersion < 0x00010003) // we are too new for the app
+ {
+ return LINEERR_INCOMPATIBLEAPIVERSION;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ return LINEERR_BADDEVICEID; // The requested device doesn't exist
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+{
+ DebugMsg (("Entering TSPI_lineOpen"));
+
+ if (dwDeviceID != line.lineID)
+ {
+ return LINEERR_BADDEVICEID;
+ }
+
+
+ //
+ // Since we only support outgoing calls, we don't open
+ // the serial port until we need to make a call
+ //
+
+ line.lpfnEventProc = lpfnEventProc;
+ line.htLine = htLine;
+ *lphdLine = (HDRVLINE) &line;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+{
+ DebugMsg (("Entering TSPI_lineSetAppSpecific"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ {
+ return LINEERR_INVALCALLHANDLE;
+ }
+
+ line.dwAppSpecific = dwAppSpecific;
+
+ line.lpfnEventProc(
+ line.htLine,
+ line.htCall,
+ LINE_CALLINFO,
+ LINECALLINFOSTATE_APPSPECIFIC,
+ 0,
+ 0
+ );
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+{
+ DebugMsg (("Entering TSPI_lineSetDefaultMediaDetection"));
+
+ if (hdLine != (HDRVLINE) &line)
+ {
+ return LINEERR_INVALLINEHANDLE;
+ }
+
+ if (dwMediaModes && dwMediaModes != LINEMEDIAMODE_INTERACTIVEVOICE)
+ {
+ return LINEERR_INVALMEDIAMODE;
+ }
+
+ line.dwLineMediaModes = dwMediaModes;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+{
+ DebugMsg (("Entering TSPI_lineSetMediaMode"));
+
+ if (hdCall != (HDRVCALL) line.htCall)
+ {
+ return LINEERR_INVALCALLHANDLE;
+ }
+
+ if (dwMediaMode != LINEMEDIAMODE_INTERACTIVEVOICE)
+ {
+ return LINEERR_INVALMEDIAMODE;
+ }
+
+ line.dwMediaMode = dwMediaMode;
+
+ return 0;
+}
+
+
+//
+// ------------------------- TSPI_providerXxx funcs ---------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwnd,
+ DWORD dwPermanentProviderId
+ )
+{
+ DebugMsg (("Entering TSPI_providerConfig"));
+
+ if (!initialised)
+ {
+ LoadIniStrings (dwPermanentProviderId);
+ }
+ else if (dwPermanentProviderId != line.dwppID)
+ {
+ return LINEERR_NOMULTIPLEINSTANCE;
+ }
+
+ DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc,
+ LPDWORD lpdwTSPIOptions
+ )
+{
+ DebugMsg (("Entering TSPI_providerInit"));
+
+// assert (dwTSPIVersion == ATSP_VERSION);
+// assert (dwNumLines == 1);
+// assert (dwNumPhones == 0);
+
+ if (initialised)
+ {
+ return LINEERR_NOMULTIPLEINSTANCE;
+ }
+
+ // initialise our internal structures
+
+ memset (&line, 0, sizeof (ATSPLineData));
+
+ line.lpfnCompletion = lpfnCompletionProc;
+ line.lineID = dwLineDeviceIDBase;
+ line.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
+ line.hcd = INVALID_HANDLE_VALUE;
+
+ LoadIniStrings (dwPermanentProviderID);
+
+ initialised = TRUE;
+
+ *lpdwTSPIOptions = LINETSPIOPTION_NONREENTRANT;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwnd,
+ DWORD dwPermanentProviderId
+ )
+{
+ int res;
+ char szProvider[sizeof (s_providerx) + 5]; // room for 65535
+
+
+ DebugMsg (("Entering TSPI_providerInstall"));
+
+ if (!initialised)
+ {
+ LoadIniStrings (dwPermanentProviderId);
+ }
+ else if (dwPermanentProviderId != line.dwppID)
+ {
+ res = ID_MULTIPLE_INST;
+ goto error;
+ }
+
+ wsprintf (szProvider, s_providerx, (int) dwPermanentProviderId);
+
+
+ //
+ // we support 1 line and 0 phones
+ //
+
+ WritePrivateProfileString(
+ szProvider,
+ s_numlines,
+ s_one,
+ s_telephon_ini
+ );
+
+ WritePrivateProfileString(
+ szProvider,
+ s_numphones,
+ s_zero,
+ s_telephon_ini
+ );
+
+
+ //
+ // Flush the ini file cache
+ //
+
+ WritePrivateProfileString (0, 0, 0, s_telephon_ini);
+
+
+ //
+ // display the config dlg
+ //
+
+ if (DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc)
+ == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return LINEERR_OPERATIONFAILED;
+ }
+
+
+error:
+
+ {
+ char szerr[255];
+ char title[255];
+
+
+ LoadString (hInst, res, szerr, sizeof (szerr));
+ LoadString (hInst, ID_ATSP_ERROR, title, sizeof (title));
+
+ MessageBox (hwnd, szerr, title, MB_APPLMODAL | MB_ICONEXCLAMATION);
+
+ return LINEERR_OPERATIONFAILED;
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwnd,
+ DWORD dwPermanentProviderId
+ )
+{
+ DebugMsg (("Entering TSPI_providerRemove"));
+
+ // BUGBUG: need to nuke the ProviderN section
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID
+ )
+{
+ DebugMsg (("Entering TSPI_providerShutdown"));
+
+ initialised = FALSE;
+
+ return 0;
+}
+
+
+//
+// ------------------------ Private support routines --------------------------
+//
+
+void
+LoadIniStrings(
+ DWORD ppID
+ )
+{
+ char section[sizeof (s_providerx) + 5]; // room for 65535
+
+
+ wsprintf (section, s_providerx, (int) ppID);
+ line.dwppID = ppID;
+
+ // user preferences come from the telephon.ini file
+
+ GetPrivateProfileString(
+ section,
+ s_port,
+ "COM1",
+ line.port,
+ sizeof (line.port),
+ s_telephon_ini
+ );
+
+ GetPrivateProfileString(
+ section,
+ s_linename,
+ "",
+ line.linename,
+ sizeof (line.linename),
+ s_telephon_ini
+ );
+
+ GetPrivateProfileString(
+ section,
+ s_lineaddr,
+ "",
+ line.lineaddr,
+ sizeof (line.lineaddr),
+ s_telephon_ini
+ );
+
+ // the provider info string comes from the resource file
+
+ gszProviderInfo[0] = 0; // in case loadstring fails
+
+ LoadString(
+ hInst,
+ ID_PROVIDER_INFO,
+ gszProviderInfo,
+ sizeof (gszProviderInfo)
+ );
+
+ return;
+}
+
+
+BOOL
+CALLBACK
+__export
+ConfigDlgProc(
+ HWND hDlg,
+ UINT uiMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ int CurrSel;
+
+ switch (uiMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ for (CurrSel = 0; CurrSel < NUMPORTS; CurrSel++)
+ {
+ //
+ // List the port in the combo box.
+ //
+
+ SendDlgItemMessage(
+ hDlg,
+ ID_PORT,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) ((LPSTR) lpszCommDevArray[CurrSel])
+ );
+ }
+
+ CurrSel = (int) SendDlgItemMessage(
+ hDlg,
+ ID_PORT,
+ CB_FINDSTRING,
+ 0,
+ (LPARAM) (LPSTR) line.port
+ );
+
+ SendDlgItemMessage (hDlg, ID_PORT, CB_SETCURSEL, CurrSel, 0);
+
+ SendDlgItemMessage(
+ hDlg,
+ ID_LINENAME,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) (LPSTR) line.linename
+ );
+
+ SendDlgItemMessage(
+ hDlg,
+ ID_LINEADDR,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) (LPSTR) line.lineaddr
+ );
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch (wParam)
+ {
+ case IDOK:
+ {
+ char szp[sizeof (s_providerx) + 5]; // room for 65535
+ wsprintf (szp, s_providerx, (int) line.dwppID);
+
+
+ //
+ // Port
+ //
+
+ CurrSel = (int) SendDlgItemMessage(
+ hDlg,
+ ID_PORT,
+ CB_GETCURSEL,
+ 0,
+ 0
+ );
+
+ SendDlgItemMessage(
+ hDlg,
+ ID_PORT,
+ CB_GETLBTEXT,
+ CurrSel,
+ (LPARAM) (LPSTR) line.port
+ );
+
+ WritePrivateProfileString (szp, s_port, line.port, s_telephon_ini);
+
+
+ //
+ // Line Name
+ //
+
+ SendDlgItemMessage(
+ hDlg,
+ ID_LINENAME,
+ WM_GETTEXT,
+ sizeof (line.linename),
+ (LPARAM) (LPSTR) line.linename
+ );
+
+ WritePrivateProfileString(
+ szp,
+ s_linename,
+ line.linename,
+ s_telephon_ini
+ );
+
+
+ //
+ // Line Address
+ //
+
+ SendDlgItemMessage(
+ hDlg,
+ ID_LINEADDR,
+ WM_GETTEXT,
+ sizeof (line.lineaddr),
+ (LPARAM) (LPSTR) line.lineaddr
+ );
+
+ WritePrivateProfileString(
+ szp,
+ s_lineaddr,
+ line.lineaddr,
+ s_telephon_ini
+ );
+
+
+ //
+ // Flush the ini file cache
+ //
+
+ WritePrivateProfileString (0, 0, 0, s_telephon_ini);
+ EndDialog (hDlg, 0);
+
+ break;
+ }
+ case IDCANCEL:
+
+ EndDialog (hDlg, -1);
+ break;
+ }
+
+ break;
+ }
+
+ default:
+
+ return FALSE;
+
+ } // switch
+
+ return TRUE;
+}
+
+
+#if DBG
+void
+CDECL
+SPTrace(
+ LPCSTR lpszFormat,
+ ...
+ )
+{
+#ifdef WIN32
+ char buf[128] = "PDISP32: ";
+#else
+ char buf[128] = "PDISP: ";
+#endif
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+#ifdef WIN32
+ wvsprintf (&buf[9], lpszFormat, ap);
+#else
+ wvsprintf (&buf[7], lpszFormat, ap);
+#endif
+
+ strcat (buf, "\n");
+
+ OutputDebugString (buf);
+
+ va_end(ap);
+}
+#endif
+
+
+UINT
+myatoi(
+ LPSTR speed
+ )
+{
+ UINT i;
+
+ for (i = 0; *speed; speed++)
+ {
+ i = i * 10 + (*speed - '0');
+ }
+
+ return i;
+}
+
+
+#define TXQUEUE 512
+#define RXQUEUE 512
+
+HANDLE
+SerialOpenComms(
+ LPSTR port,
+ LPSTR speed
+ )
+{
+#ifdef WIN32
+
+ HANDLE hcd = CreateFile(
+ port,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, // no sharing
+ NULL, // no security attrs
+ OPEN_EXISTING,
+ 0, // no attrs/flags
+ NULL // no template file
+ );
+
+ if (hcd == INVALID_HANDLE_VALUE)
+ {
+ DebugMsg (("CreateFile(%s) failed, err=%ld", port, GetLastError()));
+ }
+
+#else
+
+ int hcd = OpenComm (port, RXQUEUE, TXQUEUE);
+
+#endif
+
+
+ if (hcd >= 0)
+ {
+ DCB dcb;
+
+#ifdef WIN32
+ if (GetCommState (hcd, &dcb))
+#else
+ if (GetCommState (hcd, &dcb) == 0)
+#endif
+ {
+ memset (&dcb.BaudRate, 0, sizeof (DCB) - sizeof (dcb.DCBlength));
+
+ dcb.BaudRate = myatoi (speed);
+ dcb.ByteSize = 8;
+ dcb.fBinary = TRUE;
+// dcb.fChEvt = TRUE;
+ dcb.XonChar = 17;
+ dcb.XoffChar = 19;
+// dcb.EvtChar = '\n';
+
+ if (SetCommState (hcd, &dcb))
+ {
+ DebugMsg (("Opened: %s:%s", port, speed));
+ return hcd;
+ }
+ }
+
+#ifdef WIN32
+ CloseHandle (hcd);
+#else
+ CloseComm (hcd);
+
+ DebugMsg (("***Comm port failed to open"));
+#endif
+
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+long
+appCall(
+ int msg,
+ char *str,
+ long dwRequestID
+ )
+{
+ long wait;
+#ifdef WIN32
+ DWORD dwBytesWritten;
+#endif
+
+
+ if (msg == msgMakeCall)
+ {
+ line.hcd = SerialOpenComms (line.port, "9600");
+
+ if (line.hcd == INVALID_HANDLE_VALUE)
+ {
+ return LINEERR_RESOURCEUNAVAIL;
+ }
+ else
+ {
+ char dial[255];
+
+
+ wsprintf (dial, "ATMH9D%s;\r", str);
+
+#ifdef WIN32
+ if (WriteFile(
+ line.hcd,
+ dial,
+ strlen (dial),
+ &dwBytesWritten,
+ NULL
+ ))
+#else
+ if (WriteComm (line.hcd, dial, strlen (dial)) > 0)
+#endif
+ {
+ DebugMsg (("Sent: %s", dial));
+
+ line.callState = LINECALLSTATE_CONNECTED;
+
+ line.lpfnCompletion (dwRequestID, 0);
+
+ line.lpfnEventProc(
+ line.htLine,
+ line.htCall,
+ LINE_CALLSTATE,
+ LINECALLSTATE_CONNECTED,
+ 0,
+ 0
+ );
+ }
+ else
+ {
+ DebugMsg (("failed to write string"));
+#ifdef WIN32
+ return -1; // BUGBUG
+#else
+ return GetCommError (line.hcd, NULL);
+#endif
+ }
+ }
+ }
+ else // must be linedrop
+ {
+ if (line.hcd == INVALID_HANDLE_VALUE)
+ {
+ DebugMsg (("idle"));
+ }
+ else
+ {
+ wait = GetTickCount();
+
+#ifdef WIN32
+ WriteFile (line.hcd, "\r", 1, &dwBytesWritten, NULL);
+#else
+ WriteComm (line.hcd, "\r", 1);
+#endif
+
+ while (GetTickCount() - wait < 250);
+
+#ifdef WIN32
+ if (WriteFile (line.hcd, "ATH8\r", 6, &dwBytesWritten, NULL))
+#else
+ if (WriteComm (line.hcd, "ATH8\r", 6) > 0)
+#endif
+ {
+ DebugMsg (("Sent: %s", str));
+ }
+ else
+ {
+ DebugMsg (("failed to hang up"));
+ }
+
+ wait = GetTickCount();
+ while (GetTickCount() - wait < 250);
+
+ EscapeCommFunction (line.hcd, CLRDTR); // drop DTR
+
+#ifdef WIN32
+ if (!CloseHandle (line.hcd))
+#else
+ if (CloseComm (line.hcd))
+#endif
+ {
+ DebugMsg (("Couldn't close the serial port"));
+ }
+
+ line.hcd = INVALID_HANDLE_VALUE;
+ line.callState = LINECALLSTATE_IDLE;
+ line.lpfnEventProc(
+ line.htLine,
+ line.htCall,
+ LINE_CALLSTATE,
+ LINECALLSTATE_IDLE,
+ 0,
+ 0
+ );
+ }
+
+ if (dwRequestID)
+ {
+ line.lpfnCompletion (dwRequestID, 0);
+ }
+ }
+
+ return dwRequestID;
+}
+
+
+long
+lineDropCore(
+ ATSPLineData *theLine,
+ DWORD dwRequestID
+ )
+{
+ // if the call is not idle, transition to idle and close the comms port
+
+ return appCall (msgDrop, 0, dwRequestID);
+}
diff --git a/private/tapi/dev/sp/pdisp32/pdisp.h b/private/tapi/dev/sp/pdisp32/pdisp.h
new file mode 100644
index 000000000..02af3a478
--- /dev/null
+++ b/private/tapi/dev/sp/pdisp32/pdisp.h
@@ -0,0 +1,62 @@
+#include <windows.h>
+
+#define __far
+#define __pascal
+#define __export
+#define TSPIAPI WINAPI
+
+
+#include "TSPI.H"
+#include "pdisprc.h"
+
+#define ATSP_VERSION 0x00010003
+
+#define SMALLBUFFER 40
+
+typedef struct lineInfo
+{
+ // We have only a single call on a single address on a single line
+ // This structure is constructed in TSPI_Initialize
+
+ LINEEVENT lpfnEventProc; // TAPI event callback func
+ ASYNC_COMPLETION lpfnCompletion; // TAPI Completion callback
+
+ DWORD lineID; // the tapi ID of our line
+ DWORD dwLineMediaModes;
+ DWORD dwppID; // Our permanent provider ID
+ HTAPILINE htLine; // TAPI opaque line handle
+ HTAPICALL htCall; // TAPI opaque call handle
+
+ DWORD callState; // The state of this call
+// DWORD dwRequestID; // for async requests
+ DWORD dwMediaMode;
+ DWORD dwAppSpecific;
+
+#ifdef WIN32
+ HANDLE hcd; // the associated COM device
+#else
+ int hcd; // the associated COM device
+#endif
+ char port[SMALLBUFFER]; // "COM1"
+ char linename[SMALLBUFFER]; // "My Phone"
+ char lineaddr[SMALLBUFFER]; // "555-1212"
+
+ char DestAddress[TAPIMAXDESTADDRESSSIZE];
+
+} ATSPLineData;
+
+
+// Debug Message Macro
+
+#if DBG
+
+#include <stdarg.h>
+#include <stdio.h>
+void CDECL SPTrace(LPCSTR pszFormat, ...);
+#define DebugMsg(_x_) SPTrace _x_
+
+#else
+
+#define DebugMsg(_x_)
+
+#endif
diff --git a/private/tapi/dev/sp/pdisp32/pdisp.rc b/private/tapi/dev/sp/pdisp32/pdisp.rc
new file mode 100644
index 000000000..c2c8c799e
--- /dev/null
+++ b/private/tapi/dev/sp/pdisp32/pdisp.rc
@@ -0,0 +1,45 @@
+#include <windows.h>
+//#include <tapiver.h>
+#include "pdisprc.h"
+
+
+IDD_CFGDLG DIALOG DISCARDABLE 20, 15, 177, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "PDI Configuration"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "&Communications Port",ID_STATIC,9,7,70,9,NOT WS_GROUP
+ COMBOBOX ID_PORT,9,18,90,52,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "&Line Name",ID_STATIC,8,36,100,8
+ EDITTEXT ID_LINENAME,9,46,90,12,ES_AUTOHSCROLL
+ LTEXT "Phone &Number",ID_STATIC,8,64,94,9
+ EDITTEXT ID_LINEADDR,9,73,90,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,111,16,56,14
+ PUSHBUTTON "Cancel",IDCANCEL,111,36,56,14
+END
+
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_PROVIDER_INFO "Microsoft Internal Use PDI Modem Service Provider"
+ ID_MULTIPLE_INST "The selected service provider is already installed in the system and cannot support multiple instances."
+ ID_ATSP_ERROR "PDI Service Provider Error"
+END
+
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) PDI Modem Service Provider"
+#define VER_INTERNALNAME_STR "pdisp32"
+#define VER_ORIGINALFILENAME_STR "PDISP32.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/pdisp32/pdisp32.def b/private/tapi/dev/sp/pdisp32/pdisp32.def
new file mode 100644
index 000000000..55fa6a3c5
--- /dev/null
+++ b/private/tapi/dev/sp/pdisp32/pdisp32.def
@@ -0,0 +1,31 @@
+LIBRARY PDISP32
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE
+
+EXPORTS
+ TSPI_providerInstall
+ TSPI_providerRemove
+ TSPI_providerConfig
+ TSPI_lineNegotiateTSPIVersion
+ TSPI_providerInit
+ TSPI_providerShutdown
+ TSPI_lineClose
+ TSPI_lineCloseCall
+ TSPI_lineConditionalMediaDetection
+ TSPI_lineDrop
+ TSPI_lineGetAddressCaps
+ TSPI_lineGetAddressID
+ TSPI_lineGetAddressStatus
+ TSPI_lineGetCallAddressID
+ TSPI_lineGetCallInfo
+ TSPI_lineGetCallStatus
+ TSPI_lineGetDevCaps
+ TSPI_lineGetID
+ TSPI_lineGetLineDevStatus
+ TSPI_lineGetNumAddressIDs
+ TSPI_lineMakeCall
+ TSPI_lineOpen
+ TSPI_lineSetAppSpecific
+ TSPI_lineSetDefaultMediaDetection
+ TSPI_lineSetMediaMode
diff --git a/private/tapi/dev/sp/pdisp32/pdisprc.h b/private/tapi/dev/sp/pdisp32/pdisprc.h
new file mode 100644
index 000000000..888328e6f
--- /dev/null
+++ b/private/tapi/dev/sp/pdisp32/pdisprc.h
@@ -0,0 +1,18 @@
+// dialog IDs
+
+#define ID_PROVIDER_INFO 2
+#define ID_MULTIPLE_INST 3
+#define ID_NO_DRIVER 4
+#define ID_ATSP_ERROR 5
+
+#define IDI_MODEM 10
+
+#define IDD_CFGDLG 101
+
+#define ID_PORT 1000
+#define ID_LINENAME 1002
+#define ID_LINEADDR 1003
+
+#define ID_STATIC -1
+
+
diff --git a/private/tapi/dev/sp/pdisp32/sources b/private/tapi/dev/sp/pdisp32/sources
new file mode 100644
index 000000000..29bb081cf
--- /dev/null
+++ b/private/tapi/dev/sp/pdisp32/sources
@@ -0,0 +1,54 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=pdisp32
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=TSP
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+DLLBASE=0x61000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+USE_CRTDLL=1
+
+SOURCES=pdisp.c \
+ pdisp.rc
+
+C_DEFINES=-DTAPI_NT=1
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/remotesp/dialogs.dlg b/private/tapi/dev/sp/remotesp/dialogs.dlg
new file mode 100644
index 000000000..03123d66b
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/dialogs.dlg
@@ -0,0 +1,16 @@
+100 DIALOG 6, 18, 175, 92
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "RemoteSP Configuration"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "TAPI Servers", 109, 4, 2, 167, 69
+ LTEXT "New:", 101, 10, 16, 21, 8
+ EDITTEXT IDC_EDIT1, 10, 24, 48, 12, ES_AUTOHSCROLL
+ PUSHBUTTON "Add >>", IDC_ADD, 64, 24, 44, 12
+ PUSHBUTTON "Remove <<", IDC_REMOVE, 64, 39, 44, 12
+ LTEXT "Connect to:", 102, 116, 16, 41, 8
+ LISTBOX IDC_LIST1, 116, 24, 48, 43, WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "OK", IDOK, 32, 75, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 104, 75, 40, 14
+END
diff --git a/private/tapi/dev/sp/remotesp/line.ico b/private/tapi/dev/sp/remotesp/line.ico
new file mode 100644
index 000000000..6c2186e09
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/line.ico
Binary files differ
diff --git a/private/tapi/dev/sp/remotesp/makefile b/private/tapi/dev/sp/remotesp/makefile
new file mode 100644
index 000000000..7145f6049
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# remotesp Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/remotesp/makefile.def b/private/tapi/dev/sp/remotesp/makefile.def
new file mode 100644
index 000000000..49994e9cb
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/makefile.def
@@ -0,0 +1,77 @@
+##############################################################################
+#
+# remotesp.tsp Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..\..
+
+WANT_C932=1
+#WANT_C1032=1
+IS_32 = TRUE
+WIN32=1
+IS_OEM = TRUE
+
+BUILDDLL=1
+DLLENTRY=DllMain
+
+DEPENDNAME=..\depend.mk
+
+CLEANLIST=*.tsp
+
+TARGETS=remotesp.tsp
+
+SRCDIR=..
+
+BUILD_COFF=1
+
+
+L32EXE=remotesp.tsp # Name of exe.
+L32DEF=..\remotesp.def # Our def file.
+L32MAP=remotesp.map # Our map file.
+L32SYM=remotesp.sym # Our sym file.
+L32LIBS=\
+ $(W32LIBID)\kernel32.lib \
+ $(W32LIBID)\user32.lib \
+# $(W32LIBID)\comctl32.lib \
+ $(W32LIBID)\advapi32.lib \
+# $(W32LIBID)\version.lib \
+# $(W32LIBID)\comdlg32.lib \
+# $(W32LIBID)\comctl32.lib \
+# $(ROOT)\dev\tools\c932\lib\oldnames.lib \
+# $(ROOT)\dev\tools\c932\lib\libc.lib \
+ $(ROOT)\dev\tools\c932\lib\msvcrt.lib \
+ $(ROOT)\dev\tools\c932\lib\rpcrt4.lib
+
+
+
+# $(W32LIBID)\lz32.lib \
+# $(ROOT)\dev\tools\c932\lib\msvcrt.lib \
+# $(ROOT)\dev\tools\c932\lib\oldnames.lib \
+# $(ROOT)\dev\tools\c932\lib\rpcndr.lib \
+
+L32RES=remotesp.res # Resource file.
+
+
+#-----------------------------------------------------------------------
+# Object files
+#-----------------------------------------------------------------------
+L32OBJS = remotesp.obj tapsrv_c.obj rmotsp_s.obj
+
+
+L32FLAGS=$(L32FLAGS)
+
+
+!include $(ROOT)\dev\master.mk
+
+INCLUDE=..;..\..\..\client;..\..\..\server;$(INCLUDE)
+
+#CFLAGS=$(CFLAGS) -DWIN32=100 -DWIN_32=100 -Od -Fc -GD
+CFLAGS=$(CFLAGS) -DWIN32=100 -DWIN_32=100 -Ox
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
+
diff --git a/private/tapi/dev/sp/remotesp/phone.ico b/private/tapi/dev/sp/remotesp/phone.ico
new file mode 100644
index 000000000..ee34203e3
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/phone.ico
Binary files differ
diff --git a/private/tapi/dev/sp/remotesp/remotesp.c b/private/tapi/dev/sp/remotesp/remotesp.c
new file mode 100644
index 000000000..1679bd3fc
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/remotesp.c
@@ -0,0 +1,7677 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ remotesp.c
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) 09-Aug-1995
+
+Revision History:
+
+
+Notes:
+
+ In a nutshell, this service provider connects to tapisrv.exe on remote
+ pc's via the same rpc interface used by tapi32, and sends the remote
+ tapisrv's the same kinds of requests (as defined in \dev\server\line.h
+ & phone.h).
+
+ This service provider also acts as an rpc server, receiving async event
+ notifications from the remote tapisrv's. Remote tapisrv's call our
+ RemoteSPAttach() function at init time (during our call to their
+ ClientAttach() proc) to establish a binding instance, and then can call
+ RemoteSPEventProc() to send async events. Since we don't want to block
+ the servers for any length of time, we immediately queue the events they
+ send us, and a dedicated thread (EventHandlerThread) services this
+ queue.
+
+ Now a brief note on handle resolution. When we open a line or a phone,
+ we alloc our own DRVXXX structure to represent this widget, and pass
+ tapisrv a pointer to this widget in the open request (see the
+ hRemoteLine field in LINEOPEN_PARAMS in line.h). Then, when remote
+ tapisrv's send us events on those lines/phones, they pass us the
+ widget pointer we passed them (instead of the normal hLine/hPhone).
+ This allows us to easily find and reference our data structure
+ associated with this widget. Dealing with calls is a little more
+ problematic, since remote tapisrv's can present incoming calls, and
+ there is no clean way to initially specify our own handle to the call
+ as with lines or phones. (A RemoteSPNewCall() function which would
+ allow for this handle swapping was considered, but not implemented due
+ to possible blocking problems on the remote server.) The solution
+ is to maintain a list of calls in each line structure, and when call
+ events are parsed we resolve the hCall by walking the list of calls in
+ the corresponding line (tapisrv is nice enough to indicate our line
+ pointer in dwParam4 of the relevant messages). Since we expect client
+ machines using remotesp to have a relatively low call bandwidth, this
+ look up method should be pretty fast.
+
+ BUGBUG when an rpc exception is hit we may want to check the return
+ value instead of just blindly doing retries (may be a fatal error
+ that a retry wouldn't help, like server_not_found)
+
+--*/
+
+
+#include "remotesp.h"
+#include "rmotsp.h"
+
+
+const TCHAR gszTelephonyKey[] =
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony";
+
+
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+
+#if DBG
+
+ {
+ HKEY hTelephonyKey;
+ DWORD dwDataSize, dwDataType;
+ TCHAR szRemotespDebugLevel[] = "RemotespDebugLevel";
+
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hTelephonyKey
+ );
+
+ dwDataSize = sizeof (DWORD);
+ gdwDebugLevel=0;
+
+ RegQueryValueEx(
+ hTelephonyKey,
+ szRemotespDebugLevel,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwDebugLevel,
+ &dwDataSize
+ );
+
+ RegCloseKey (hTelephonyKey);
+ }
+
+#endif
+
+ //
+ //
+ //
+
+// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+// {
+// }
+
+ DBGOUT((2, "DLL_PROCESS_ATTACH"));
+
+ ghInst = hDLL;
+
+
+ //
+ // Alloc a Tls index
+ //
+
+ if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff)
+ {
+ DBGOUT((1, "DLL_PROCESS_ATTACH, TlsAlloc() failed"));
+
+ return FALSE;
+ }
+
+
+ //
+ // Initialize Tls to NULL for this thread
+ //
+
+ TlsSetValue (gdwTlsIndex, NULL);
+
+
+ //
+ // Init a couple of critical sections for serializing
+ // access to resources
+ //
+
+ InitializeCriticalSection (&gEventBufferCriticalSection);
+ InitializeCriticalSection (&gCallListCriticalSection);
+
+
+ //
+ // Load the device icons
+ //
+
+ ghLineIcon = LoadIcon (hDLL, MAKEINTRESOURCE(IDI_ICON3));
+ ghPhoneIcon = LoadIcon (hDLL, MAKEINTRESOURCE(IDI_ICON2));
+
+ break;
+ }
+ case DLL_PROCESS_DETACH:
+ {
+ PCLIENT_THREAD_INFO pTls;
+
+
+ DBGOUT((2, "DLL_PROCESS_DETACH"));
+
+
+ //
+ // Clean up any Tls
+ //
+
+ if ((pTls = (PCLIENT_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
+ {
+ if (pTls->pBuf)
+ {
+ DrvFree (pTls->pBuf);
+ }
+
+ DrvFree (pTls);
+ }
+
+ TlsFree (gdwTlsIndex);
+
+// _CRT_INIT (hDLL, dwReason, lpReserved);
+
+
+ //
+ // Free the critical sections & icons
+ //
+
+ DeleteCriticalSection (&gEventBufferCriticalSection);
+ DeleteCriticalSection (&gCallListCriticalSection);
+
+ DestroyIcon (ghLineIcon);
+ DestroyIcon (ghPhoneIcon);
+
+ break;
+ }
+ case DLL_THREAD_ATTACH:
+
+// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+// {
+// }
+
+
+ //
+ // Initialize Tls to NULL for this thread
+ //
+
+ TlsSetValue (gdwTlsIndex, NULL);
+
+ break;
+
+ case DLL_THREAD_DETACH:
+ {
+ PCLIENT_THREAD_INFO pTls;
+
+
+ //
+ // Clean up any Tls
+ //
+
+ if ((pTls = (PCLIENT_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
+ {
+ if (pTls->pBuf)
+ {
+ DrvFree (pTls->pBuf);
+ }
+
+ DrvFree (pTls);
+ }
+
+// _CRT_INIT (hDLL, dwReason, lpReserved);
+
+ break;
+ }
+ } // switch
+
+ return TRUE;
+}
+
+
+PASYNCEVENTMSG
+GetEventFromQueue(
+ void
+ )
+{
+ DWORD dwUsedSize, dwMoveSize, dwMoveSizeWrapped;
+ PASYNCEVENTMSG pMsg = gEventHandlerThreadParams.pMsg;
+
+
+ //
+ // Enter the critical section to serialize access to the event
+ // queue, and grab an event from the queue. Copy it to our local
+ // event buf so that we can leave the critical section asap and
+ // not block other threads writing to the queue.
+ //
+
+ EnterCriticalSection (&gEventBufferCriticalSection);
+
+
+ //
+ // If there are no events in the queue return NULL
+ //
+
+ if (gEventHandlerThreadParams.dwEventBufferUsedSize == 0)
+ {
+ pMsg = NULL;
+
+ goto GetEventFromQueue_done;
+ }
+
+
+ //
+ // Copy the fixed portion of the msg to the local buf
+ //
+
+ dwUsedSize = (gEventHandlerThreadParams.pEventBuffer +
+ gEventHandlerThreadParams.dwEventBufferTotalSize) -
+ gEventHandlerThreadParams.pDataOut;
+
+ if (dwUsedSize >= sizeof (ASYNCEVENTMSG))
+ {
+ dwMoveSize = sizeof (ASYNCEVENTMSG);
+ dwMoveSizeWrapped = 0;
+ }
+ else
+ {
+ dwMoveSize = dwUsedSize;
+ dwMoveSizeWrapped = sizeof (ASYNCEVENTMSG) - dwUsedSize;
+ }
+
+ CopyMemory (pMsg, gEventHandlerThreadParams.pDataOut, dwMoveSize);
+
+ if (dwMoveSizeWrapped)
+ {
+ CopyMemory(
+ ((LPBYTE) pMsg) + dwMoveSize,
+ gEventHandlerThreadParams.pEventBuffer,
+ dwMoveSizeWrapped
+ );
+
+ gEventHandlerThreadParams.pDataOut =
+ gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
+ }
+ else
+ {
+ gEventHandlerThreadParams.pDataOut += dwMoveSize;
+ }
+
+
+ //
+ // See if there's any extra data in this msg
+ //
+
+ if (pMsg->dwTotalSize > sizeof (ASYNCEVENTMSG))
+ {
+ BOOL bCopy = TRUE;
+
+
+ //
+ // See if we need to grow the msg buffer
+ //
+
+ if (pMsg->dwTotalSize > gEventHandlerThreadParams.dwMsgSize)
+ {
+ DWORD dwNewMsgSize = pMsg->dwTotalSize + 256;
+
+
+ if ((pMsg = DrvAlloc (dwNewMsgSize)))
+ {
+ CopyMemory(
+ pMsg,
+ gEventHandlerThreadParams.pMsg,
+ sizeof(ASYNCEVENTMSG)
+ );
+
+ DrvFree (gEventHandlerThreadParams.pMsg);
+
+ gEventHandlerThreadParams.pMsg = pMsg;
+
+ gEventHandlerThreadParams.dwMsgSize = dwNewMsgSize;
+ }
+ else
+ {
+ //
+ // Couldn't alloc a bigger buf, so try to complete this
+ // msg as gracefully as possible
+ //
+
+ bCopy = FALSE;
+
+ switch (pMsg->dwMsg)
+ {
+ case LINE_REPLY:
+
+ pMsg->dwParam2 = LINEERR_NOMEM;
+ break;
+
+ case PHONE_REPLY:
+
+ pMsg->dwParam2 = PHONEERR_NOMEM;
+ break;
+
+ default: // BUGBUG any other msgs to special case?
+
+ break;
+ }
+ }
+ }
+
+
+ dwUsedSize = (gEventHandlerThreadParams.pEventBuffer +
+ gEventHandlerThreadParams.dwEventBufferTotalSize) -
+ gEventHandlerThreadParams.pDataOut;
+
+ if (dwUsedSize >= (pMsg->dwTotalSize - sizeof (ASYNCEVENTMSG)))
+ {
+ dwMoveSize = pMsg->dwTotalSize - sizeof (ASYNCEVENTMSG);
+ dwMoveSizeWrapped = 0;
+ }
+ else
+ {
+ dwMoveSize = dwUsedSize;
+ dwMoveSizeWrapped = (pMsg->dwTotalSize - sizeof (ASYNCEVENTMSG)) -
+ dwUsedSize;
+ }
+
+ if (bCopy)
+ {
+ CopyMemory(
+ pMsg + 1,
+ gEventHandlerThreadParams.pDataOut,
+ dwMoveSize
+ );
+ }
+
+ if (dwMoveSizeWrapped)
+ {
+ if (bCopy)
+ {
+ CopyMemory(
+ ((LPBYTE) (pMsg + 1)) + dwMoveSize,
+ gEventHandlerThreadParams.pEventBuffer,
+ dwMoveSizeWrapped
+ );
+ }
+
+ gEventHandlerThreadParams.pDataOut =
+ gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
+ }
+ else
+ {
+ gEventHandlerThreadParams.pDataOut += dwMoveSize;
+ }
+ }
+
+ gEventHandlerThreadParams.dwEventBufferUsedSize -= pMsg->dwTotalSize;
+
+GetEventFromQueue_done:
+
+ LeaveCriticalSection (&gEventBufferCriticalSection);
+
+ ResetEvent (gEventHandlerThreadParams.hEvent);
+
+ return pMsg;
+}
+
+
+void
+EventHandlerThread(
+ LPVOID pParams
+ )
+{
+ //
+ // NOTES:
+ //
+ // 1. depending on server side implementation, we may experience race
+ // conditions where msgs that we expect to show up in a certain
+ // sequence show up out of sequence (i.e. call state msgs that show
+ // up before make call completion msgs), which could present problems.
+ //
+ // one solution is to to queue call state/info msgs to incomplete
+ // calls (to be sent after call is completed). another is not to send
+ // any call state msgs after the idle is received
+ //
+
+ PASYNCEVENTMSG pMsg;
+
+
+ DBGOUT((3, "EventHandlerThread: enter"));
+
+ while (1)
+ {
+ //
+ // Wait for an event to show up in the queue
+ //
+
+ WaitForSingleObject (gEventHandlerThreadParams.hEvent, INFINITE);
+
+ if (gEventHandlerThreadParams.bExit)
+ {
+ break;
+ }
+
+
+ //
+ // Process the events in the queue
+ //
+
+ while ((pMsg = GetEventFromQueue()))
+ {
+ switch (pMsg->dwMsg)
+ {
+ case LINE_ADDRESSSTATE:
+
+ //assert (((PDRVLINE)(pMsg->hDevice))->dwKey == DRVLINE_KEY);
+
+ (*gpfnLineEventProc)(
+ ((PDRVLINE)(pMsg->hDevice))->htLine,
+ NULL,
+ pMsg->dwMsg,
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ );
+
+ break;
+
+ case LINE_CALLINFO:
+ case LINE_CALLSTATE:
+ case LINE_GENERATE:
+ case LINE_MONITORDIGITS:
+ case LINE_MONITORMEDIA:
+ case LINE_MONITORTONE:
+ {
+ //
+ // For all the msgs where hDevice refers to a call tapisrv
+ // will pass us the pLine (hRemoteLine) for that call in
+ // dwParam4 to make the lookup of the corresponding pCall
+ // easier
+ //
+
+ HCALL hCall = (HCALL) pMsg->hDevice;
+ PDRVCALL pCall;
+ PDRVLINE pLine = (PDRVLINE) pMsg->dwParam4;
+ HTAPICALL htCall;
+
+
+ //assert (pLine->dwKey == DRVLINE_KEY);
+
+ EnterCriticalSection (&gCallListCriticalSection);
+
+ pCall = (PDRVCALL) pLine->pCalls;
+
+ while (pCall && (pCall->hCall != hCall))
+ {
+ pCall = pCall->pNext;
+ }
+
+ htCall = (pCall ? pCall->htCall : NULL);
+
+ LeaveCriticalSection (&gCallListCriticalSection);
+
+ if (!pCall)
+ {
+ continue;
+ }
+
+ (*gpfnLineEventProc)(
+ pLine->htLine,
+ htCall,
+ pMsg->dwMsg,
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ );
+
+ break;
+ }
+ case LINE_DEVSPECIFIC:
+ case LINE_DEVSPECIFICFEATURE:
+ {
+ //
+ // For all the msgs where hDevice refers to a call tapisrv
+ // will pass us the pLine (hRemoteLine) for that call in
+ // dwParam4 to make the lookup of the corresponding pCall
+ // easier
+ //
+
+ HTAPICALL htCall;
+ PDRVLINE pLine;
+
+
+ if (pMsg->dwParam4)
+ {
+ HCALL hCall = (HCALL) pMsg->hDevice;
+ PDRVCALL pCall;
+
+
+ pLine = (PDRVLINE) pMsg->dwParam4;
+
+ //assert (pLine->dwKey == DRVLINE_KEY);
+
+ EnterCriticalSection (&gCallListCriticalSection);
+
+ pCall = (PDRVCALL) pLine->pCalls;
+
+ while (pCall && (pCall->hCall != hCall))
+ {
+ pCall = pCall->pNext;
+ }
+
+ htCall = (pCall ? pCall->htCall : NULL);
+
+ LeaveCriticalSection (&gCallListCriticalSection);
+
+ if (pCall)
+ {
+ pMsg->dwMsg = (pMsg->dwMsg == LINE_DEVSPECIFIC ?
+ LINE_CALLDEVSPECIFIC :
+ LINE_CALLDEVSPECIFICFEATURE);
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ pLine = (PDRVLINE) pMsg->hDevice;
+
+ //assert (pLine->dwKey == DRVLINE_KEY);
+
+ htCall = NULL;
+ }
+
+ (*gpfnLineEventProc)(
+ pLine->htLine,
+ htCall,
+ pMsg->dwMsg,
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ );
+
+ break;
+ }
+ case PHONE_BUTTON:
+ case PHONE_DEVSPECIFIC:
+
+ //assert (((PDRVPHONE)(pMsg->hDevice))->dwKey == DRVPHONE_KEY);
+
+ (*gpfnPhoneEventProc)(
+ ((PDRVPHONE)(pMsg->hDevice))->htPhone,
+ pMsg->dwMsg,
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ );
+
+ break;
+
+ case LINE_LINEDEVSTATE:
+
+ if (pMsg->dwParam1 & LINEDEVSTATE_REINIT)
+ {
+ //
+ // Be on our best behavior and immediately shutdown
+ // our init instances on the server
+ //
+
+ Shutdown ((PDRVSERVER) pMsg->pInitData);
+ }
+
+ //assert (((PDRVLINE)(pMsg->hDevice))->dwKey == DRVLINE_KEY);
+
+ (*gpfnLineEventProc)(
+ ((PDRVLINE)(pMsg->hDevice))->htLine,
+ NULL,
+ pMsg->dwMsg,
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ );
+
+ break;
+
+ case PHONE_STATE:
+
+ if (pMsg->dwParam1 & PHONESTATE_REINIT)
+ {
+ //
+ // Be on our best behavior and immediately shutdown
+ // our init instances on the server
+ //
+
+ Shutdown ((PDRVSERVER) pMsg->pInitData);
+ }
+
+ //assert (((PDRVPHONE)(pMsg->hDevice))->dwKey == DRVPHONE_KEY);
+
+ (*gpfnPhoneEventProc)(
+ ((PDRVPHONE)(pMsg->hDevice))->htPhone,
+ pMsg->dwMsg,
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ );
+
+ break;
+
+ case LINE_CLOSE:
+ {
+ PDRVCALL pCall;
+ PDRVLINE pLine = (PDRVLINE) pMsg->hDevice;
+
+
+ //assert (pLine->dwKey == DRVLINE_KEY);
+
+
+ //
+ // Nullify the hLine field so that when TSPI_Close
+ // is called we know not to call the server
+ //
+
+ pLine->hLine = NULL;
+
+
+ //
+ // Safely walk the call list for this line & nullify
+ // each call's hCall field so that when TSPI_CloseCall
+ // is called we know not to call the server
+ //
+
+ EnterCriticalSection (&gCallListCriticalSection);
+
+ pCall = pLine->pCalls;
+
+ while (pCall)
+ {
+ pCall->hCall = NULL;
+ pCall = pCall->pNext;
+ }
+
+ LeaveCriticalSection (&gCallListCriticalSection);
+
+ (*gpfnLineEventProc)(pLine->htLine, NULL, LINE_CLOSE, 0, 0, 0);
+
+ break;
+ }
+ case PHONE_CLOSE:
+ {
+ PDRVPHONE pPhone = (PDRVPHONE) pMsg->hDevice;
+
+
+ //assert (pPhone->dwKey == DRVPHONE_KEY);
+
+
+ //
+ // Nullify the hPhone field so that when TSPI_Close
+ // is called we know not to call the server
+ //
+
+ pPhone->hPhone = NULL;
+
+ (*gpfnPhoneEventProc)(pPhone->htPhone, PHONE_CLOSE, 0, 0, 0);
+
+ break;
+ }
+ case LINE_GATHERDIGITS: // BUGBUG
+
+ break;
+
+ case LINE_REPLY:
+ case PHONE_REPLY:
+ {
+ if (pMsg->pfnPostProcessProc)
+ {
+ (*((POSTPROCESSPROC)(pMsg->pfnPostProcessProc)))(pMsg);
+ }
+
+ (*gpfnCompletionProc)(pMsg->dwParam1, pMsg->dwParam2);
+
+ break;
+ }
+ case LINE_CREATE:
+
+ // BUGBUG AddLine((PDRVSERVER) pMsg->pInitData, locDevID, srvDevID, FALSE);
+ // (*gpfnLineCreateProc)()
+
+ break;
+
+ case PHONE_CREATE:
+
+ // BUGBUG AddPhone((PDRVSERVER) pMsg->pInitData, locDevID, srvDevID, FALSE);
+ // (*gpfnPhoneCreateProc)()
+
+ break;
+
+ case LINE_APPNEWCALL:
+ {
+ PDRVLINE pLine = (PDRVLINE) pMsg->hDevice;
+ PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
+
+
+ if (pCall)
+ {
+ AddCallToList (pLine, pCall);
+
+ pCall->hCall = (HCALL) pMsg->dwParam2;
+ pCall->dwAddressID = pMsg->dwParam1;
+
+ (*gpfnLineEventProc)(
+ pLine->htLine,
+ NULL,
+ LINE_NEWCALL,
+ (DWORD) pCall,
+ (DWORD) (&pCall->htCall),
+ (DWORD) 0
+ );
+
+ }
+ else
+ {
+ // BUGBUG LINE_APPNEWCALL: err case (pCall == NULL)
+ }
+
+ break;
+ }
+ } // switch (pMsg->dwMsg)
+
+ } // while ((pMsg = GetEventFromQueue()))
+
+ } // while (1)
+
+ DBGOUT((3, "EventHandlerThread: exit"));
+
+ ExitThread (0);
+}
+
+
+PDRVLINE
+GetLineFromID(
+ DWORD dwDeviceID
+ )
+{
+ PDRVLINE pLine;
+
+
+ //
+ // First check to see if it's a "static" device, i.e. a device
+ // that we knew about at start up time, in which case we know
+ // it's exact location in the lookup table
+ //
+
+ if (dwDeviceID < (gdwLineDeviceIDBase + gdwInitialNumLineDevices))
+ {
+ pLine = gpLineLookup->aEntries + dwDeviceID - gdwLineDeviceIDBase;
+ }
+
+
+ //
+ // If here, the id references a "dynamic" device, i.e. one that
+ // we found out about on the fly via a CREATE msg, so we need to
+ // walk the lookup table(s) to find it
+ //
+ // TODO: the for loop down below is not the most efficient
+ //
+
+ else
+ {
+ PDRVLINELOOKUP pLookup = gpLineLookup;
+
+
+ while (pLookup->aEntries[pLookup->dwUsedEntries - 1].
+ dwDeviceIDLocal < dwDeviceID)
+ {
+ pLookup = pLookup->pNext;
+ }
+
+ for(
+ pLine = pLookup->aEntries;
+ pLine->dwDeviceIDLocal != dwDeviceID;
+ pLine++
+ );
+ }
+
+ return pLine;
+}
+
+
+PDRVPHONE
+GetPhoneFromID(
+ DWORD dwDeviceID
+ )
+{
+ PDRVPHONE pPhone;
+
+
+ //
+ // First check to see if it's a "static" device, i.e. a device
+ // that we knew about at start up time, in which case we know
+ // it's exact location in the lookup table
+ //
+
+ if (dwDeviceID < (gdwPhoneDeviceIDBase + gdwInitialNumPhoneDevices))
+ {
+ pPhone = gpPhoneLookup->aEntries + dwDeviceID - gdwPhoneDeviceIDBase;
+ }
+
+
+ //
+ // If here, the id references a "dynamic" device, i.e. one that
+ // we found out about on the fly via a CREATE msg, so we need to
+ // walk the lookup table(s) to find it
+ //
+ // TODO: the for loop down below is not the most efficient
+ //
+
+ else
+ {
+ PDRVPHONELOOKUP pLookup = gpPhoneLookup;
+
+
+ while (pLookup->aEntries[pLookup->dwUsedEntries - 1].
+ dwDeviceIDLocal < dwDeviceID)
+ {
+ pLookup = pLookup->pNext;
+ }
+
+ for(
+ pPhone = pLookup->aEntries;
+ pPhone->dwDeviceIDLocal != dwDeviceID;
+ pPhone++
+ );
+ }
+
+ return pPhone;
+}
+
+
+BOOL
+WINAPI
+GrowBuf(
+ LPBYTE *ppBuf,
+ LPDWORD pdwBufSize,
+ DWORD dwCurrValidBytes,
+ DWORD dwBytesToAdd
+ )
+{
+ DWORD dwNewBufSize = *pdwBufSize * 2;
+ LPBYTE pNewBuf;
+
+
+ //
+ // Try to get a new buffer big enough to hold
+ // (dwCurrValidBytes + dwBytesToAdd)
+ //
+
+ while (dwNewBufSize < (dwCurrValidBytes + dwBytesToAdd))
+ {
+ dwNewBufSize *= 2;
+ }
+
+ if (!(pNewBuf = DrvAlloc (dwNewBufSize)))
+ {
+ return FALSE;
+ }
+
+
+ //
+ // Copy the "valid" bytes in the old buf to the new buf,
+ // then free the old buf
+ //
+
+ CopyMemory (pNewBuf, *ppBuf, dwCurrValidBytes);
+
+ DrvFree (*ppBuf);
+
+
+ //
+ // Reset the pointers to the new buf & buf size
+ //
+
+ *ppBuf = pNewBuf;
+ *pdwBufSize = dwNewBufSize;
+
+ return TRUE;
+}
+
+
+PCLIENT_THREAD_INFO
+WINAPI
+GetTls(
+ void
+ )
+{
+ PCLIENT_THREAD_INFO pClientThreadInfo;
+
+
+ if (!(pClientThreadInfo = TlsGetValue (gdwTlsIndex)))
+ {
+ pClientThreadInfo = (PCLIENT_THREAD_INFO)
+ DrvAlloc (sizeof(CLIENT_THREAD_INFO));
+
+ if (!pClientThreadInfo)
+ {
+ return NULL;
+ }
+
+ pClientThreadInfo->pBuf = DrvAlloc (INITIAL_CLIENT_THREAD_BUF_SIZE);
+
+ if (!pClientThreadInfo->pBuf)
+ {
+ DrvFree (pClientThreadInfo);
+
+ return NULL;
+ }
+
+ pClientThreadInfo->dwBufSize = INITIAL_CLIENT_THREAD_BUF_SIZE;
+
+ TlsSetValue (gdwTlsIndex, (LPVOID) pClientThreadInfo);
+ }
+
+ return pClientThreadInfo;
+}
+
+
+#if DBG
+
+LONG
+WINAPI
+RemoteDoFunc(
+ PREMOTE_FUNC_ARGS pFuncArgs,
+ char *pszFuncName
+ )
+
+#else
+
+LONG
+WINAPI
+RemoteDoFunc(
+ PREMOTE_FUNC_ARGS pFuncArgs
+ )
+
+#endif
+{
+ DWORD dwFuncClassErrorIndex = (pFuncArgs->Flags & 0x00000030) >> 4;
+ LONG lResult;
+ BOOL bCopyOnSuccess = FALSE;
+ DWORD i, j, dwValue, dwUsedSize, dwNeededSize;
+ PDRVSERVER pServer;
+ PCLIENT_THREAD_INFO pTls;
+
+
+ //
+ // Get the tls
+ //
+
+ if (!(pTls = GetTls()))
+ {
+ lResult = gaNoMemErrors[dwFuncClassErrorIndex];
+ goto RemoteDoFunc_return;
+ }
+
+
+ //
+ // Validate all the func args
+ //
+
+ dwNeededSize = dwUsedSize = sizeof (TAPI32_MSG);
+
+ for (i = 0, j = 0; i < (pFuncArgs->Flags & NUM_ARGS_MASK); i++, j++)
+ {
+ dwValue = ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pFuncArgs->Args[i];
+
+ switch (pFuncArgs->ArgTypes[i])
+ {
+ case Dword:
+
+ //
+ // Nothing to check, just continue
+ //
+
+ continue;
+
+ case LineID:
+ {
+ PDRVLINE pLine = GetLineFromID (dwValue);
+
+
+ pServer = pLine->pServer;
+
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pLine->dwDeviceIDServer;
+
+ continue;
+ }
+ case PhoneID:
+ {
+ PDRVPHONE pPhone = GetPhoneFromID (dwValue);
+
+
+ pServer = pPhone->pServer;
+
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pPhone->dwDeviceIDServer;
+
+ continue;
+ }
+ case Hdcall:
+
+ //
+ // Save the pServer & adjust the call handle as understood by
+ // the server
+ //
+
+ pServer = ((PDRVCALL) dwValue)->pServer;
+
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = (DWORD)
+ ((PDRVCALL) dwValue)->hCall;
+
+ continue;
+
+ case Hdline:
+
+ //
+ // Save the pServer & adjust the line handle as understood by
+ // the server
+ //
+
+ pServer = ((PDRVLINE) dwValue)->pServer;
+
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = (DWORD)
+ ((PDRVLINE) dwValue)->hLine;
+
+ continue;
+
+ case Hdphone:
+
+ //
+ // Save the pServer & adjust the phone handle as understood by
+ // the server
+ //
+
+ pServer = ((PDRVPHONE) dwValue)->pServer;
+
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = (DWORD)
+ ((PDRVPHONE) dwValue)->hPhone;
+
+ continue;
+
+ case lpDword:
+
+ bCopyOnSuccess = TRUE;
+
+ continue;
+
+ case lpsz:
+
+ //
+ // Check if dwValue is a valid string ptr and if so
+ // copy the contents of the string to the extra data
+ // buffer passed to the server, else indicate no data
+ //
+
+ if (dwValue)
+ {
+ DWORD n = (lstrlenW ((WCHAR *) dwValue) + 1) *
+ sizeof (WCHAR),
+ nAligned = (n + 3) & 0xfffffffc;
+
+
+ if ((nAligned + dwUsedSize) > pTls->dwBufSize)
+ {
+ if (!GrowBuf(
+ &pTls->pBuf,
+ &pTls->dwBufSize,
+ dwUsedSize,
+ nAligned
+ ))
+ {
+ lResult = gaNoMemErrors[dwFuncClassErrorIndex];
+ goto RemoteDoFunc_return;
+ }
+ }
+
+ CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) dwValue, n);
+
+
+ //
+ // Pass the server the offset of the string in the var data
+ // portion of the buffer
+ //
+
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
+ dwUsedSize - sizeof (TAPI32_MSG);
+
+
+ //
+ // Increment the total number of data bytes
+ //
+
+ dwUsedSize += nAligned;
+ dwNeededSize += nAligned;
+ }
+ else
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
+ }
+
+ continue;
+
+ case lpGet_Struct:
+ case lpGet_SizeToFollow:
+ {
+ BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpGet_SizeToFollow);
+ DWORD dwSize;
+
+
+ if (bSizeToFollow)
+ {
+#if DBG
+ //
+ // Check to make sure the following arg is of type Size
+ //
+
+ if ((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
+ (pFuncArgs->ArgTypes[i + 1] != Size))
+ {
+ DBGOUT((
+ 2,
+ "DoFunc: error, lpGet_SizeToFollow !followed by Size"
+ ));
+
+ lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
+ goto RemoteDoFunc_return;
+ }
+#endif
+ dwSize = pFuncArgs->Args[i + 1];
+ }
+ else
+ {
+ dwSize = *((LPDWORD) dwValue); // lpXxx->dwTotalSize
+ }
+
+ if (bSizeToFollow)
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
+ ((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
+ }
+ else
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = dwSize;
+ }
+
+
+ //
+ // Now set the bCopyOnSuccess flag to indicate that we've data
+ // to copy back on successful completion, and add to the
+ // dwNeededSize field
+ //
+
+ bCopyOnSuccess = TRUE;
+
+ dwNeededSize += dwSize;
+
+ continue;
+ }
+ case lpSet_Struct:
+ case lpSet_SizeToFollow:
+ {
+ BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpSet_SizeToFollow);
+ DWORD dwSize, dwSizeAligned;
+
+#if DBG
+ //
+ // Check to make sure the following arg is of type Size
+ //
+
+ if (bSizeToFollow &&
+ ((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
+ (pFuncArgs->ArgTypes[i + 1] != Size)))
+ {
+ DBGOUT((
+ 2,
+ "DoFunc: error, lpSet_SizeToFollow !followed by Size"
+ ));
+
+ lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
+ goto RemoteDoFunc_return;
+ }
+#endif
+ if (bSizeToFollow)
+ {
+ dwSize = (dwValue ? pFuncArgs->Args[i + 1] : 0);
+ }
+ else
+ {
+ dwSize = (dwValue ? *((LPDWORD) dwValue) : 0);
+ }
+
+ if (dwSize)
+ {
+ //
+ // Grow the buffer if necessary, & do the copy
+ //
+
+ dwSizeAligned = (dwSize + 3) & 0xfffffffc;
+
+ if ((dwSizeAligned + dwUsedSize) > pTls->dwBufSize)
+ {
+ if (!GrowBuf(
+ &pTls->pBuf,
+ &pTls->dwBufSize,
+ dwUsedSize,
+ dwSizeAligned
+ ))
+ {
+ lResult = gaNoMemErrors[dwFuncClassErrorIndex];
+ goto RemoteDoFunc_return;
+ }
+ }
+
+ CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) dwValue, dwSize);
+ }
+ else
+ {
+ dwSizeAligned = 0;
+ }
+
+
+ //
+ // Pass the server the offset of the data in the var data
+ // portion of the buffer
+ //
+
+ if (dwSize)
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
+ dwUsedSize - sizeof (TAPI32_MSG);
+ }
+ else
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
+ }
+
+
+ //
+ // Increment the dwXxxSize vars appropriately
+ //
+
+ dwUsedSize += dwSizeAligned;
+ dwNeededSize += dwSizeAligned;
+
+
+ //
+ // Since we already know the next arg (Size) just handle
+ // it here so we don't have to run thru the loop again
+ //
+
+ if (bSizeToFollow)
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
+ }
+
+ continue;
+ }
+#if DBG
+ case Size:
+
+ DBGOUT((2, "DoFunc: error, hit case Size"));
+
+ continue;
+
+ default:
+
+ DBGOUT((2, "DoFunc: error, unknown arg type"));
+
+ continue;
+#endif
+ } // switch
+
+ } // for
+
+
+ //
+ //
+ //
+
+ if (pServer->bDisconnected)
+ {
+ lResult = gaServerDisconnectedErrors[dwFuncClassErrorIndex];
+ }
+
+
+ //
+ // Now make the request
+ //
+
+ if (dwNeededSize > pTls->dwBufSize)
+ {
+ if (!GrowBuf(
+ &pTls->pBuf,
+ &pTls->dwBufSize,
+ dwUsedSize,
+ dwNeededSize - pTls->dwBufSize
+ ))
+ {
+ lResult = gaNoMemErrors[dwFuncClassErrorIndex];
+ goto RemoteDoFunc_return;
+ }
+ }
+
+ ((PTAPI32_MSG) pTls->pBuf)->u.Req_Func = (DWORD)HIWORD(pFuncArgs->Flags);
+
+ {
+ DWORD dwRetryCount = 0;
+
+
+ do
+ {
+ RpcTryExcept
+ {
+ ClientRequest(
+ pServer->phContext,
+ pTls->pBuf,
+ dwNeededSize,
+ &dwUsedSize
+ );
+
+ lResult = ((PTAPI32_MSG) pTls->pBuf)->u.Ack_ReturnValue;
+
+ dwRetryCount = gdwRetryCount;
+
+
+ //
+ // If this is an async func & success, then munge the result to
+ // be the local async request id
+ //
+
+ if ((pFuncArgs->Flags & ASYNC) && (lResult > 0))
+ {
+ lResult = pFuncArgs->Args[0];
+ }
+ }
+ RpcExcept (1)
+ {
+ if (dwRetryCount++ < gdwRetryCount)
+ {
+ Sleep (gdwRetryTimeout);
+ }
+ else
+ {
+ lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
+ }
+ }
+ RpcEndExcept
+
+ } while (dwRetryCount < gdwRetryCount);
+ }
+
+
+ //
+ // If request completed successfully and the bCopyOnSuccess flag
+ // is set then we need to copy data back to client buffer(s)
+ //
+
+ if ((lResult == TAPI_SUCCESS) && bCopyOnSuccess)
+ {
+ for (i = 0, j = 0; i < (pFuncArgs->Flags & NUM_ARGS_MASK); i++, j++)
+ {
+ PTAPI32_MSG pMsg = (PTAPI32_MSG) pTls->pBuf;
+
+
+ switch (pFuncArgs->ArgTypes[i])
+ {
+ case Dword:
+ case LineID:
+ case PhoneID:
+ case Hdcall:
+ case Hdline:
+ case Hdphone:
+ case lpsz:
+ case lpSet_Struct:
+
+ continue;
+
+ case lpDword:
+
+ //
+ // Fill in the pointer with the return value
+ //
+
+ *((LPDWORD) pFuncArgs->Args[i]) = pMsg->Params[j];
+
+ continue;
+
+ case lpGet_SizeToFollow:
+
+ //
+ // Fill in the buf with the return data
+ //
+
+ CopyMemory(
+ (LPBYTE) pFuncArgs->Args[i],
+ pTls->pBuf + pMsg->Params[j] + sizeof(TAPI32_MSG),
+ pMsg->Params[j+1]
+ );
+
+
+ //
+ // Increment i (and j, since Size passed as arg in msg)
+ // to skip following Size arg in pFuncArgs->Args
+ //
+
+ i++;
+ j++;
+
+ continue;
+
+ case lpSet_SizeToFollow:
+
+ //
+ // Increment i (and j, since Size passed as arg in msg)
+ // to skip following Size arg in pFuncArgs->Args
+ //
+
+ i++;
+ j++;
+
+ continue;
+
+ case lpGet_Struct:
+
+ //
+ // Params[j] contains the offset in the var data
+ // portion of pTls->pBuf of some TAPI struct.
+ // Get the dwUsedSize value from this struct &
+ // copy that many bytes from pTls->pBuf to client buf
+ //
+
+ if (pMsg->Params[j] != TAPI_NO_DATA)
+ {
+
+ LPDWORD pStruct;
+
+
+ pStruct = (LPDWORD) (pTls->pBuf + sizeof(TAPI32_MSG) +
+ pMsg->Params[j]);
+
+ CopyMemory(
+ (LPBYTE) pFuncArgs->Args[i],
+ (LPBYTE) pStruct,
+ *(pStruct + 2) // ptr to dwUsedSize field
+ );
+ }
+
+ continue;
+
+ default:
+
+ continue;
+ }
+ }
+ }
+
+RemoteDoFunc_return:
+
+ DBGOUT((3, "%s: exit, returning x%x", pszFuncName, lResult));
+
+ return lResult;
+}
+
+
+//
+// --------------------------- TAPI_lineXxx funcs -----------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_lineAccept(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpsUserUserInfo,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lAccept),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineAccept"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HDRVCALL hdConsultCall
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ Hdcall
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdConfCall,
+ (DWORD) hdConsultCall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lAddToConference),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineAddToConference"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineAnswer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpsUserUserInfo,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lAnswer),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineAnswer"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineBlindTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpsz,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpszDestAddress,
+ (DWORD) dwCountryCode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lBlindTransfer),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineBlindTransfer"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+{
+ //
+ // Check if the hLine is still valid (could have been zeroed
+ // out on LINE_CLOSE, so no need to call server)
+ //
+
+ if (((PDRVLINE) hdLine)->hLine)
+ {
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdline
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 1, lClose),
+ (LPDWORD) &hdLine,
+ argTypes
+ };
+
+
+ REMOTEDOFUNC (&funcArgs, "lineClose");
+ }
+
+ //assert (((PDRVLINE) hdLine)->pCalls == NULL);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+{
+ //
+ // Check if the hCall is still valid (could have been zeroed
+ // out on LINE_CLOSE, so no need to call server)
+ //
+
+ if (((PDRVCALL) hdCall)->hCall)
+ {
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall), // API differs
+ (LPDWORD) &hdCall,
+ argTypes
+ };
+
+
+ REMOTEDOFUNC (&funcArgs, "lineCloseCall");
+ }
+
+ RemoveCallFromList ((PDRVCALL) hdCall);
+ DrvFree ((LPVOID) hdCall);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPDWORD lpdwCompletionID,
+ DWORD dwCompletionMode,
+ DWORD dwMessageID
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdcall,
+ Dword, // BUGBUG? should be lpDword?
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) 0, // BUGBUG ppproc
+ (DWORD) hdCall,
+ (DWORD) lpdwCompletionID,
+ (DWORD) dwCompletionMode,
+ (DWORD) dwMessageID
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lCompleteCall),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineCompleteCall"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineCompleteTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVCALL hdConsultCall,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ DWORD dwTransferMode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdcall,
+ Hdcall,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) 0,
+ (DWORD) hdCall,
+ (DWORD) hdConsultCall,
+ (DWORD) 0,
+ (DWORD) dwTransferMode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lCompleteTransfer),
+ args,
+ argTypes
+ };
+ LONG lResult;
+ PDRVCALL pConfCall;
+
+
+ if (dwTransferMode == LINETRANSFERMODE_CONFERENCE)
+ {
+ if (!(pConfCall = DrvAlloc (sizeof (DRVCALL))))
+ {
+ return LINEERR_NOMEM;
+ }
+
+
+ //
+ // Assume success & add the call to the line's list before we
+ // even make the request. This makes cleanup alot easier if
+ // the server goes down or some such uncooth event.
+ //
+
+ AddCallToList ((PDRVLINE) ((PDRVCALL) hdCall)->pLine, pConfCall);
+
+ pConfCall->htCall = htConfCall;
+
+ *lphdConfCall = (HDRVCALL) pConfCall;
+
+ args[1] = (DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess);
+ args[4] = (DWORD) pConfCall;
+ }
+ else
+ {
+ pConfCall = NULL;
+ }
+
+ if ((lResult = REMOTEDOFUNC (&funcArgs, "lineCompleteTransfer")) < 0)
+ {
+ if (pConfCall)
+ {
+ RemoveCallFromList (pConfCall);
+ DrvFree (pConfCall);
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ // BUGBUG TSPI_lineConditionalMediaDetection
+
+ // try an open on the specified line w/ the specified media modes
+
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+void
+PASCAL
+TSPI_lineDevSpecific_PostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineDevSpecificPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwTotalSize - sizeof (TAPI32_MSG);
+ LPBYTE pParams = (LPBYTE) pMsg->dwParam3;
+
+
+ CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdline,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineDevSpecific_PostProcess),
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) hdCall,
+ (DWORD) lpParams, // pass the actual pointer (for post processing)
+ (DWORD) lpParams, // pass data
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 8, lDevSpecific),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineDevSpecific"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDevSpecificFeature(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwFeature,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdline,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineDevSpecific_PostProcess),
+ (DWORD) hdLine,
+ (DWORD) dwFeature,
+ (DWORD) lpParams, // pass the actual pointer (for post processing)
+ (DWORD) lpParams, // pass data
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lDevSpecificFeature),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineDevSpecificFeature"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDial(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpsz,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpszDestAddress,
+ (DWORD) dwCountryCode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lDial),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineDial"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpsUserUserInfo,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lDrop),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineDrop"));
+}
+
+/*
+LONG
+TSPIAPI
+TSPI_lineDropOnClose(
+ HDRVCALL hdCall
+ )
+{
+ // BUGBUG TSPI_lineDropOnClose (how about not exporting this?)
+
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineDropNoOwner(
+ HDRVCALL hdCall
+ )
+{
+ // BUGBUG TSPI_lineDropNoOwner (how about not exporting this?)
+
+ return LINEERR_OPERATIONFAILED;
+}
+*/
+
+LONG
+TSPIAPI
+TSPI_lineForward(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD bAllAddresses,
+ DWORD dwAddressID,
+ LPLINEFORWARDLIST const lpForwardList,
+ DWORD dwNumRingsNoAnswer,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ // BUGBUG TSPI_lineForward
+
+ // remember to use ppproc param
+
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGatherDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitModes,
+ LPWSTR lpsDigits,
+ DWORD dwNumDigits,
+ LPCWSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+{
+ // BUGBUG TSPI_lineGatherDigits
+
+ // remember to use ppproc param, the dwEndToEndID presents a problem
+
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGenerateDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitMode,
+ LPCWSTR lpszDigits,
+ DWORD dwDuration
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ Dword,
+ lpsz,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) dwDigitMode,
+ (DWORD) lpszDigits,
+ (DWORD) dwDuration,
+ (DWORD) dwEndToEndID,
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 5, lGenerateDigits),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGenerateDigits"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGenerateTone(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwToneMode,
+ DWORD dwDuration,
+ DWORD dwNumTones,
+ LPLINEGENERATETONE const lpTones
+ )
+{
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) dwToneMode,
+ (DWORD) dwDuration,
+ (DWORD) dwNumTones,
+ (DWORD) TAPI_NO_DATA,
+ (DWORD) 0,
+ (DWORD) dwEndToEndID
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 7, lGenerateTone),
+ args,
+ argTypes
+ };
+
+
+ if (dwToneMode == LINETONEMODE_CUSTOM)
+ {
+ argTypes[4] = lpSet_SizeToFollow;
+ args[4] = (DWORD) lpTones;
+ argTypes[5] = Size;
+ args[5] = dwNumTones * sizeof(LINEGENERATETONE);
+ }
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGenerateTone"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ LineID,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) (GetLineFromID (dwDeviceID))->pServer->hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) dwAddressID,
+ (DWORD) dwTSPIVersion,
+ (DWORD) dwExtVersion,
+ (DWORD) lpAddressCaps,
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 6, lGetAddressCaps),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetAddressCaps"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCWSTR lpsAddress,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdline,
+ lpDword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) lpdwAddressID,
+ (DWORD) dwAddressMode,
+ (DWORD) lpsAddress,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 5, lGetAddressID),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetAddressID"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdline,
+ Dword,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAddressStatus
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 3, lGetAddressStatus),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetAddressStatus"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+{
+ *lpdwAddressID = ((PDRVCALL) hdCall)->dwAddressID;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) lpCallInfo
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lGetCallInfo),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetCallInfo"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) lpCallStatus
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lGetCallStatus),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetCallStatus"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ LineID,
+ Dword,
+ Dword,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) (GetLineFromID (dwDeviceID))->pServer->hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) dwTSPIVersion,
+ (DWORD) dwExtVersion,
+ (DWORD) lpLineDevCaps
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetDevCaps"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetDevConfig(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ LineID,
+ lpGet_Struct,
+ lpsz
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwDeviceID,
+ (DWORD) lpDeviceConfig,
+ (DWORD) lpszDeviceClass
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetDevConfig"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPLINEEXTENSIONID lpExtensionID
+ )
+{
+ CopyMemory(
+ lpExtensionID,
+ &(GetLineFromID (dwDeviceID))->ExtensionID,
+ sizeof (LINEEXTENSIONID)
+ );
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetIcon(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ *lphIcon = ghLineIcon;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+{
+ if (lstrcmpiW (lpszDeviceClass, L"tapi/line") != 0)
+ {
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ (dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
+ Dword,
+ (dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
+ Dword,
+ lpGet_Struct,
+ lpsz
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) hdCall,
+ (DWORD) dwSelect,
+ (DWORD) lpDeviceID,
+ (DWORD) lpszDeviceClass
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 6, lGetID),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetID"));
+ }
+
+ if (lpDeviceID->dwTotalSize <
+ (lpDeviceID->dwNeededSize = sizeof (VARSTRING) + sizeof (DWORD)))
+ {
+ lpDeviceID->dwUsedSize = 3 * sizeof (DWORD);
+ }
+ else
+ {
+ lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
+
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof (DWORD);
+ lpDeviceID->dwStringOffset = sizeof (VARSTRING);
+
+ if (dwSelect == LINECALLSELECT_CALL)
+ {
+ *((LPDWORD)(lpDeviceID + 1)) =
+ ((PDRVCALL) hdCall)->pLine->dwDeviceIDLocal;
+ }
+ else
+ {
+ *((LPDWORD)(lpDeviceID + 1)) =
+ ((PDRVLINE) hdLine)->dwDeviceIDLocal;
+ }
+ }
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdline,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) lpLineDevStatus
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lGetLineDevStatus),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetLineDevStatus"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdline,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) lpdwNumAddressIDs
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lGetNumAddressIDs),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineGetNumAddressIDs"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 2, lHold),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineHold"));
+}
+
+void
+PASCAL
+TSPI_lineMakeCall_PostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ PDRVCALL pCall = (PDRVCALL) pMsg->dwParam4;
+
+
+ DBGOUT((3, "TSPI_lineMakeCall_PostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%x, dwP2=x%x, dwP3=x%x, dwP4=x%x",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ pCall->hCall = (HCALL) pMsg->dwParam3;
+ }
+ else
+ {
+ RemoveCallFromList (pCall);
+
+ DrvFree (pCall);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdline,
+ Dword,
+ lpsz,
+ Dword,
+ lpSet_Struct,
+ Dword
+ };
+ PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
+ (DWORD) hdLine,
+ (DWORD) pCall,
+ (DWORD) lpszDestAddress,
+ (DWORD) dwCountryCode,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwCallParamsCodePage
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 8, lMakeCall),
+ args,
+ argTypes
+ };
+ LONG lResult;
+
+
+ if (pCall)
+ {
+ //
+ // Assume success & add the call to the line's list before we
+ // even make the request. This makes cleanup alot easier if
+ // the server goes down or some such uncooth event.
+ //
+
+ AddCallToList ((PDRVLINE) hdLine, pCall);
+
+ pCall->htCall = htCall;
+
+ *lphdCall = (HDRVCALL) pCall;
+
+ if ((lResult = REMOTEDOFUNC (&funcArgs, "lineMakeCall")) < 0)
+ {
+ RemoveCallFromList (pCall);
+
+ DrvFree (pCall);
+ }
+ }
+ else
+ {
+ lResult = LINEERR_NOMEM;
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorDigits(
+ HDRVCALL hdCall,
+ DWORD dwDigitModes
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) dwDigitModes
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lMonitorDigits),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineMonitorDigits"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorMedia(
+ HDRVCALL hdCall,
+ DWORD dwMediaModes
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) dwMediaModes
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lMonitorMedia),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineMonitorMedia"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineMonitorTones(
+ HDRVCALL hdCall,
+ DWORD dwToneListID,
+ LPLINEMONITORTONE const lpToneList,
+ DWORD dwNumEntries
+ )
+{
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ lpSet_SizeToFollow,
+ Size,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) lpToneList,
+ (DWORD) dwNumEntries * sizeof (LINEMONITORTONE),
+ (DWORD) dwToneListID
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 4, lMonitorTones),
+ args,
+ argTypes
+ };
+
+
+ if (!lpToneList)
+ {
+ funcArgs.ArgTypes[1] = Dword;
+ funcArgs.Args[1] = TAPI_NO_DATA;
+ funcArgs.ArgTypes[2] = Dword;
+ }
+
+ return (REMOTEDOFUNC (&funcArgs, "lineMonitorTones"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ LineID,
+ Dword,
+ Dword,
+ Dword,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) (GetLineFromID (dwDeviceID))->pServer->hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) dwTSPIVersion,
+ (DWORD) dwLowVersion,
+ (DWORD) dwHighVersion,
+ (DWORD) lpdwExtVersion,
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 6, lNegotiateExtVersion),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineNegotiateExtVersion"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ if (dwDeviceID == INITIALIZE_NEGOTIATION)
+ {
+ *lpdwTSPIVersion = TAPI_VERSION_CURRENT;
+ }
+ else
+ {
+ *lpdwTSPIVersion = (GetLineFromID (dwDeviceID))->dwXPIVersion;
+ }
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword, // hLineApp
+ LineID, // dev id
+ lpDword, // lphLine
+ Dword, // API version
+ Dword, // ext version
+ Dword, // callback inst
+ Dword, // privileges
+ Dword, // dw media modes
+ Dword, // call params
+ Dword, // dwAsciiCallParamsCodePage
+ Dword // remote hLine
+ };
+ PDRVLINE pLine = GetLineFromID (dwDeviceID);
+ DWORD args[] =
+ {
+ (DWORD) pLine->pServer->hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) &pLine->hLine,
+ (DWORD) dwTSPIVersion,
+ (DWORD) 0,
+ (DWORD) 0,
+ (DWORD) LINECALLPRIVILEGE_NONE,
+ (DWORD) 0,
+ (DWORD) 0,
+ (DWORD) 0xffffffff,
+ (DWORD) pLine
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 11, lOpen),
+ args,
+ argTypes
+ };
+
+
+ pLine->dwKey = DRVLINE_KEY;
+ pLine->htLine = htLine;
+
+ *lphdLine = (HDRVLINE) pLine;
+
+#if DBG
+
+ {
+ LONG lResult = REMOTEDOFUNC (&funcArgs, "lineOpen");
+
+ return lResult;
+ }
+
+#else
+
+ return (REMOTEDOFUNC (&funcArgs, "lineOpen"));
+
+#endif
+}
+
+
+void
+PASCAL
+TSPI_linePark_PostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineParkPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwTotalSize - sizeof (TAPI32_MSG);
+ LPVARSTRING pNonDirAddress = (LPVARSTRING) pMsg->dwParam3;
+
+
+ CopyMemory (pNonDirAddress, (LPBYTE) (pMsg + 1), dwSize);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePark(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwParkMode,
+ LPCWSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdcall,
+ Dword,
+ lpsz,
+ Dword, // pass ptr as Dword for post processing
+ lpGet_Struct // pass ptr as lpGet_Xx to retrieve dwTotalSize
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_linePark_PostProcess),
+ (DWORD) hdCall,
+ (DWORD) dwParkMode,
+ (DWORD) lpszDirAddress,
+ (DWORD) lpNonDirAddress,
+ (DWORD) lpNonDirAddress
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lPark),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "linePark"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePickup(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ LPCWSTR lpszGroupID
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdline,
+ Dword,
+ Dword,
+ lpsz,
+ lpsz
+ };
+ PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) pCall,
+ (DWORD) lpszDestAddress,
+ (DWORD) lpszGroupID
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lPickup),
+ args,
+ argTypes
+ };
+ LONG lResult;
+
+
+ if (pCall)
+ {
+ AddCallToList ((PDRVLINE) hdLine, pCall);
+
+ pCall->htCall = htCall;
+
+ *lphdCall = (HDRVCALL) pCall;
+
+ if ((lResult = REMOTEDOFUNC (&funcArgs, "linePickup")) < 0)
+ {
+ RemoveCallFromList (pCall);
+
+ DrvFree (pCall);
+ }
+ }
+ else
+ {
+ lResult = LINEERR_NOMEM;
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_linePrepareAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdcall,
+ Dword,
+ lpSet_Struct,
+ Dword
+ };
+ PDRVCALL pConsultCall = DrvAlloc (sizeof (DRVCALL));
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
+ (DWORD) hdConfCall,
+ (DWORD) pConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwAsciiCallParamsCodePage
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lPrepareAddToConference),
+ args,
+ argTypes
+ };
+ LONG lResult;
+
+
+ if (pConsultCall)
+ {
+ AddCallToList (((PDRVCALL) hdConfCall)->pLine, pConsultCall);
+
+ pConsultCall->htCall = htConsultCall;
+
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+
+ if ((lResult = REMOTEDOFUNC (&funcArgs, "linePrepareAddToConference"))
+ < 0)
+ {
+ RemoveCallFromList (pConsultCall);
+
+ DrvFree (pConsultCall);
+ }
+ }
+ else
+ {
+ lResult = LINEERR_NOMEM;
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineRedirect(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpsz,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpszDestAddress,
+ (DWORD) dwCountryCode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lRedirect),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineRedirect"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineReleaseUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 2, lReleaseUserUserInfo),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineReleaseUserUserInfo"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineRemoveFromConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 2, lRemoveFromConference),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineRemoveFromConference"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSecureCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 2, lSecureCall),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSecureCall"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSelectExtVersion(
+ HDRVLINE hdLine,
+ DWORD dwExtVersion
+ )
+{
+ // BUGBUG TSPI_lineSelectExtVersion
+
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSendUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpsUserUserInfo,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lSendUserUserInfo),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSendUserUserInfo"));
+}
+
+/* BUGBUG wait 'til spec is complete for agent SPIs
+LONG
+TSPIAPI
+TSPI_lineSetAgent(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEAGENTLIST lpAgentList
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdline,
+ Dword,
+ lpSet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentList
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgent),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetAgent"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetAgentActivity(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPCSTR lpszAgentActivity
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdline,
+ Dword,
+ lpsz
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdLine,
+ (DWORD) dwAdressID,
+ (DWORD) lpszAgentActivity
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentActivity),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetAgentActivity"));
+}
+
+
+TSPIAPI
+TSPI_lineSetAgentState(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ DWORD dwAgentState,
+ DWORD dwNextAgentState
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdline,
+ Dword,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdLine,
+ (DWORD) dwAdressID,
+ (DWORD) dwAgentState,
+ (DWORD) dwNextAgentState
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lSetAgentState),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetAgentState"));
+}
+*/
+
+LONG
+TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) dwAppSpecific
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lSetAppSpecific),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetAppSpecific"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallData(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPVOID lpCallData,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpCallData,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lSetCallData),
+ (LPDWORD) args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetCallData"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallParams(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwBearerMode,
+ DWORD dwMinRate,
+ DWORD dwMaxRate,
+ LPLINEDIALPARAMS const lpDialParams
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) dwBearerMode,
+ (DWORD) dwMinRate,
+ (DWORD) dwMaxRate,
+ (DWORD) lpDialParams,
+ (DWORD) (lpDialParams ? sizeof (LINEDIALPARAMS) : 0)
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lSetCallParams),
+ (LPDWORD) args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetCallParams"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallQualityOfService(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPVOID lpSendingFlowspec,
+ DWORD dwSendingFlowspecSize,
+ LPVOID lpReceivingFlowspec,
+ DWORD dwReceivingFlowspecSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ lpSet_SizeToFollow,
+ Size,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) lpSendingFlowspec,
+ (DWORD) dwSendingFlowspecSize,
+ (DWORD) lpReceivingFlowspec,
+ (DWORD) dwReceivingFlowspecSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lSetCallQualityOfService),
+ (LPDWORD) args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetCallQualityOfService"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCallTreatment(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwTreatment
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall,
+ (DWORD) dwTreatment
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lSetCallTreatment),
+ (LPDWORD) args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetCallTreatment"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetCurrentLocation(
+ DWORD dwLocation
+ )
+{
+ // BUGBUG TSPI_lineSetCurrentLocation
+
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdline,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) dwMediaModes,
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lSetDefaultMediaDetection),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetDefaultMediaDetection"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetDevConfig(
+ DWORD dwDeviceID,
+ LPVOID const lpDeviceConfig,
+ DWORD dwSize,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ LineID,
+ lpSet_SizeToFollow,
+ Size,
+ lpsz
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwDeviceID,
+ (DWORD) lpDeviceConfig,
+ (DWORD) dwSize,
+ (DWORD) lpszDeviceClass
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 4, lSetDevConfig),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetDevConfig"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetLineDevStatus(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwStatusToChange,
+ DWORD fStatus
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdline,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdLine,
+ (DWORD) dwStatusToChange,
+ (DWORD) fStatus
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lSetLineDevStatus),
+ (LPDWORD) args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetLineDevStatus"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaControl(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPLINEMEDIACONTROLDIGIT const lpDigitList,
+ DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA const lpMediaList,
+ DWORD dwMediaNumEntries,
+ LPLINEMEDIACONTROLTONE const lpToneList,
+ DWORD dwToneNumEntries,
+ LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
+ DWORD dwCallStateNumEntries
+ )
+{
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ (dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
+ Dword,
+ (dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
+ Dword,
+ lpSet_SizeToFollow,
+ Size,
+ lpSet_SizeToFollow,
+ Size,
+ lpSet_SizeToFollow,
+ Size,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) hdCall,
+ (DWORD) dwSelect,
+ (DWORD) lpDigitList,
+ (DWORD) dwDigitNumEntries,
+ (DWORD) lpMediaList,
+ (DWORD) dwMediaNumEntries,
+ (DWORD) lpToneList,
+ (DWORD) dwToneNumEntries,
+ (DWORD) lpCallStateList,
+ (DWORD) dwCallStateNumEntries
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 12, lSetMediaControl),
+ args,
+ argTypes
+ };
+
+
+ dwDigitNumEntries *= sizeof (LINEMEDIACONTROLDIGIT);
+ dwMediaNumEntries *= sizeof (LINEMEDIACONTROLMEDIA);
+ dwToneNumEntries *= sizeof (LINEMEDIACONTROLTONE);
+ dwCallStateNumEntries *= sizeof (LINEMEDIACONTROLCALLSTATE);
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetMediaControl"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdcall,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdCall,
+ (DWORD) dwMediaMode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lSetMediaMode),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetMediaMode"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetStatusMessages(
+ HDRVLINE hdLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdline,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdLine,
+ (DWORD) dwLineStates,
+ (DWORD) dwAddressStates
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 3, lSetStatusMessages),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetStatusMessages"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetTerminal(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ DWORD dwTerminalModes,
+ DWORD dwTerminalID,
+ DWORD bEnable
+ )
+{
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ (dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
+ Dword,
+ (dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
+ Dword,
+ Dword,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) hdCall,
+ (DWORD) dwSelect,
+ (DWORD) dwTerminalModes,
+ (DWORD) dwTerminalID,
+ (DWORD) bEnable
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 8, lSetTerminal),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSetTerminal"));
+}
+
+
+void
+PASCAL
+TSPI_lineSetupConference_PostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ PDRVCALL pConfCall = (PDRVCALL) pMsg->dwParam4,
+ pConsultCall = (PDRVCALL) *(&pMsg->dwParam4 + 2);
+
+ DBGOUT((3, "TSPI_lineSetupConference_PostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%x, dwP2=x%x, dwP3=x%x",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ ));
+ DBGOUT((
+ 3,
+ "\t\tdwP4=x%x, dwP5=x%x, dwP6=x%x",
+ pMsg->dwParam4,
+ *(&pMsg->dwParam4 + 1),
+ pConsultCall
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ HCALL hConfCall = (HCALL) pMsg->dwParam3,
+ hConsultCall = (HCALL) *(&pMsg->dwParam4 + 1);
+
+
+ pConfCall->hCall = hConfCall;
+ pConsultCall->hCall = hConsultCall;
+ }
+ else
+ {
+ RemoveCallFromList (pConfCall);
+ RemoveCallFromList (pConsultCall);
+
+ DrvFree (pConfCall);
+ DrvFree (pConsultCall);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetupConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVLINE hdLine,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ (hdCall ? Hdcall : Dword),
+ (hdCall ? Dword : Hdline),
+ Dword,
+ Dword,
+ Dword,
+ lpSet_Struct,
+ Dword
+ };
+ PDRVCALL pConfCall = DrvAlloc (sizeof (DRVCALL)),
+ pConsultCall = DrvAlloc (sizeof (DRVCALL));
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineSetupConference_PostProcess),
+ (DWORD) hdCall,
+ (DWORD) hdLine,
+ (DWORD) pConfCall,
+ (DWORD) pConsultCall,
+ (DWORD) dwNumParties,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwAsciiCallParamsCodePage
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 9, lSetupConference),
+ args,
+ argTypes
+ };
+ LONG lResult;
+
+
+ if (pConfCall)
+ {
+ if (pConsultCall)
+ {
+ PDRVLINE pLine;
+
+
+ pLine = (hdCall ? ((PDRVCALL) hdCall)->pLine : (PDRVLINE) hdLine);
+
+ AddCallToList (pLine, pConfCall);
+ AddCallToList (pLine, pConsultCall);
+
+ pConfCall->htCall = htConfCall;
+ pConsultCall->htCall = htConsultCall;
+
+ *lphdConfCall = (HDRVCALL) pConfCall;
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+
+ if ((lResult = REMOTEDOFUNC (&funcArgs, "lineSetupConference"))
+ < 0)
+ {
+ RemoveCallFromList (pConfCall);
+ RemoveCallFromList (pConsultCall);
+
+ DrvFree (pConfCall);
+ DrvFree (pConsultCall);
+ }
+ }
+ else
+ {
+ DrvFree (pConfCall);
+ lResult = LINEERR_NOMEM;
+ }
+ }
+ else
+ {
+ lResult = LINEERR_NOMEM;
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSetupTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdcall,
+ Dword,
+ lpSet_Struct,
+ Dword
+ };
+ PDRVCALL pConsultCall = DrvAlloc (sizeof (DRVCALL));
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
+ (DWORD) hdCall,
+ (DWORD) pConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff, // dwAsciiCallParamsCodePage
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lSetupTransfer),
+ args,
+ argTypes
+ };
+ LONG lResult;
+
+
+ if (pConsultCall)
+ {
+ AddCallToList (((PDRVCALL) hdCall)->pLine, pConsultCall);
+
+ pConsultCall->htCall = htConsultCall;
+
+ *lphdConsultCall = (HDRVCALL) pConsultCall;
+
+ if ((lResult = REMOTEDOFUNC (&funcArgs, "lineSetupTransfer")) < 0)
+ {
+ RemoveCallFromList (pConsultCall);
+
+ DrvFree (pConsultCall);
+ }
+ }
+ else
+ {
+ lResult = LINEERR_NOMEM;
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineSwapHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdActiveCall,
+ HDRVCALL hdHeldCall
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdActiveCall,
+ (DWORD) hdHeldCall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lSwapHold),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineSwapHold"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUncompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwCompletionID
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdline,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdLine,
+ (DWORD) dwCompletionID
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lUncompleteCall),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineUncompleteCall"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUnhold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdcall
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdCall
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 2, lUnhold),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "lineUnhold"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_lineUnpark(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress
+ )
+{
+ REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdline,
+ Dword,
+ Dword,
+ lpsz
+ };
+ PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
+ (DWORD) hdLine,
+ (DWORD) dwAddressID,
+ (DWORD) pCall,
+ (DWORD) lpszDestAddress
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lUnpark),
+ args,
+ argTypes
+ };
+ LONG lResult;
+
+
+ if (pCall)
+ {
+ AddCallToList ((PDRVLINE) hdLine, pCall);
+
+ pCall->htCall = htCall;
+
+ *lphdCall = (HDRVCALL) pCall;
+
+ if ((lResult = REMOTEDOFUNC (&funcArgs, "lineUnpark")) < 0)
+ {
+ RemoveCallFromList (pCall);
+
+ DrvFree (pCall);
+ }
+ }
+ else
+ {
+ lResult = LINEERR_NOMEM;
+ }
+
+ return lResult;
+}
+
+
+
+//
+// -------------------------- TSPI_phoneXxx funcs -----------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_phoneClose(
+ HDRVPHONE hdPhone
+ )
+{
+ //
+ // Check if the hPhone is still valid (could have been zeroed
+ // out on PHONE_CLOSE, so no need to call server)
+ //
+
+ if (((PDRVPHONE) hdPhone)->hPhone)
+ {
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 1, pClose),
+ (LPDWORD) &hdPhone,
+ argTypes
+ };
+
+
+ REMOTEDOFUNC (&funcArgs, "phoneClose");
+ }
+
+ return 0;
+}
+
+
+void
+PASCAL
+TSPI_phoneDevSpecific_PostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "phoneDevSpecificPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwTotalSize - sizeof (TAPI32_MSG);
+ LPBYTE pParams = (LPBYTE) pMsg->dwParam3;
+
+
+ CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
+ }
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Dword,
+ Hdphone,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) ((POSTPROCESSPROC) TSPI_phoneDevSpecific_PostProcess),
+ (DWORD) hdPhone,
+ (DWORD) lpParams, // pass the actual pointer (for post processing)
+ (DWORD) lpParams, // pass data
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 6, pDevSpecific),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneDevSpecific"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetButtonInfo(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO lpButtonInfo
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ Dword,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) dwButtonLampID,
+ (DWORD) lpButtonInfo
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetButtonInfo),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetButtonInfo"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetData(
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID lpData,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ Dword,
+ lpGet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) dwDataID,
+ (DWORD) lpData,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 4, pGetData),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetData"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPPHONECAPS lpPhoneCaps
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ PhoneID,
+ Dword,
+ Dword,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) (GetPhoneFromID (dwDeviceID))->pServer->hPhoneApp,
+ (DWORD) dwDeviceID,
+ (DWORD) dwTSPIVersion,
+ (DWORD) dwExtVersion,
+ (DWORD) lpPhoneCaps
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 5, pGetDevCaps),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetDevCaps"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDisplay(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDisplay
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) lpDisplay
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 2, pGetDisplay),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetDisplay"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPPHONEEXTENSIONID lpExtensionID
+ )
+{
+ CopyMemory(
+ lpExtensionID,
+ &(GetPhoneFromID (dwDeviceID))->ExtensionID,
+ sizeof (PHONEEXTENSIONID)
+ );
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetGain(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwGain
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ Dword,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) dwHookSwitchDev,
+ (DWORD) lpdwGain
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetGain),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetGain"));
+}
+
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetHookSwitch(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwHookSwitchDevs
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) lpdwHookSwitchDevs
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 2, pGetHookSwitch),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetHookSwitch"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetIcon(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ *lphIcon = ghPhoneIcon;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetID(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+ )
+{
+ if (lstrcmpiW (lpszDeviceClass, L"tapi/phone") != 0)
+ {
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ lpGet_Struct,
+ lpsz
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) lpDeviceID,
+ (DWORD) lpszDeviceClass
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetID),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetID"));
+ }
+
+ if (lpDeviceID->dwTotalSize <
+ (lpDeviceID->dwNeededSize = sizeof (VARSTRING) + sizeof (DWORD)))
+ {
+ lpDeviceID->dwUsedSize = 3 * sizeof (DWORD);
+ }
+ else
+ {
+ lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
+
+ lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
+ lpDeviceID->dwStringSize = sizeof (DWORD);
+ lpDeviceID->dwStringOffset = sizeof (VARSTRING);
+
+ *((LPDWORD)(lpDeviceID + 1)) =
+ ((PDRVPHONE) hdPhone)->dwDeviceIDLocal;
+ }
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetLamp(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPDWORD lpdwLampMode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ Dword,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) dwButtonLampID,
+ (DWORD) lpdwLampMode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetLamp),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetLamp"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetRing(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwRingMode,
+ LPDWORD lpdwVolume
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ lpDword,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) lpdwRingMode,
+ (DWORD) lpdwVolume
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetRing),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetRing"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetStatus(
+ HDRVPHONE hdPhone,
+ LPPHONESTATUS lpPhoneStatus
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ lpGet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) lpPhoneStatus
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 2, pGetStatus),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetStatus"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetVolume(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwVolume
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ Dword,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) dwHookSwitchDev,
+ (DWORD) lpdwVolume
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetVolume),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneGetVolume"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ PhoneID,
+ Dword,
+ Dword,
+ Dword,
+ lpDword
+ };
+ DWORD args[] =
+ {
+ (DWORD) (GetPhoneFromID (dwDeviceID))->pServer->hPhoneApp,
+ (DWORD) dwDeviceID,
+ (DWORD) dwTSPIVersion,
+ (DWORD) dwLowVersion,
+ (DWORD) dwHighVersion,
+ (DWORD) lpdwExtVersion,
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 6, pNegotiateExtVersion),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneNegotiateExtVersion"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ if (dwDeviceID == INITIALIZE_NEGOTIATION)
+ {
+ *lpdwTSPIVersion = TAPI_VERSION_CURRENT;
+ }
+ else
+ {
+ *lpdwTSPIVersion = (GetPhoneFromID (dwDeviceID))->dwXPIVersion;
+ }
+
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneOpen(
+ DWORD dwDeviceID,
+ HTAPIPHONE htPhone,
+ LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion,
+ PHONEEVENT lpfnEventProc
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword, // hPhoneApp
+ PhoneID, // dev id
+ lpDword, // lphPhone
+ Dword, // API version
+ Dword, // ext version
+ Dword, // callback inst
+ Dword, // privilege
+ Dword // remote hPhone
+ };
+ PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
+ DWORD args[] =
+ {
+ (DWORD) pPhone->pServer->hPhoneApp,
+ (DWORD) dwDeviceID,
+ (DWORD) &pPhone->hPhone,
+ (DWORD) dwTSPIVersion,
+ (DWORD) 0, // BUGBUG
+ (DWORD) 0,
+ (DWORD) PHONEPRIVILEGE_OWNER,
+ (DWORD) pPhone
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 8, pOpen),
+ args,
+ argTypes
+ };
+
+
+ pPhone->htPhone = htPhone;
+
+ *lphdPhone = (HDRVPHONE) pPhone;
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneOpen"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSelectExtVersion(
+ HDRVPHONE hdPhone,
+ DWORD dwExtVersion
+ )
+{
+ // BUGBUG TSPI_phoneSelectExtVersion
+
+ return PHONEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetButtonInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO const lpButtonInfo
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ lpSet_Struct
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwButtonLampID,
+ (DWORD) lpButtonInfo
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 4, pSetButtonInfo),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetButtonInfo"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetData(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID const lpData,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwDataID,
+ (DWORD) lpData,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 5, pSetData),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetData"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetDisplay(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRow,
+ DWORD dwColumn,
+ LPCWSTR lpsDisplay,
+ DWORD dwSize
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwRow,
+ (DWORD) dwColumn,
+ (DWORD) lpsDisplay,
+ (DWORD) dwSize
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 6, pSetDisplay),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetDisplay"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetGain(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwGain
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwHookSwitchDev,
+ (DWORD) dwGain
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 4, pSetGain),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetGain"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetHookSwitch(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDevs,
+ DWORD dwHookSwitchMode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwHookSwitchDevs,
+ (DWORD) dwHookSwitchMode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 4, pSetHookSwitch),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetHookswitch"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetLamp(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ DWORD dwLampMode
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwButtonLampID,
+ (DWORD) dwLampMode
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 4, pSetLamp),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetLamp"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetRing(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRingMode,
+ DWORD dwVolume
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwRingMode,
+ (DWORD) dwVolume
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 4, pSetRing),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetRing"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetStatusMessages(
+ HDRVPHONE hdPhone,
+ DWORD dwPhoneStates,
+ DWORD dwButtonModes,
+ DWORD dwButtonStates
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Hdphone,
+ Dword,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) hdPhone,
+ (DWORD) dwPhoneStates,
+ (DWORD) dwButtonModes,
+ (DWORD) dwButtonStates
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetStatusMessages"));
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetVolume(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwVolume
+ )
+{
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ Hdphone,
+ Dword,
+ Dword
+ };
+ DWORD args[] =
+ {
+ (DWORD) dwRequestID,
+ (DWORD) hdPhone,
+ (DWORD) dwHookSwitchDev,
+ (DWORD) dwVolume
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 4, pSetVolume),
+ args,
+ argTypes
+ };
+
+
+ return (REMOTEDOFUNC (&funcArgs, "phoneSetVolume"));
+}
+
+
+
+//
+// ------------------------- TSPI_providerXxx funcs ---------------------------
+//
+
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // Although this func is never called by TAPI v2.0, we export
+ // it so that the Telephony Control Panel Applet knows that it
+ // can configure this provider via lineConfigProvider(),
+ // otherwise Telephon.cpl will not consider it configurable
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreateLineDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreatePhoneDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ return LINEERR_OPERATIONFAILED;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+{
+ char szProviderN[16];
+ char *pszServerName;
+ DWORD hClientInst, dwNumServers, i;
+ RPC_BINDING_HANDLE hBindingInst;
+
+ HKEY hTelephonyKey;
+ HKEY hProviderNKey;
+ DWORD dwDataSize;
+ DWORD dwDataType;
+
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hTelephonyKey
+ );
+
+
+ //
+ // BUGBUG The following is a cheesy hack to allow us access to net
+ // since tapisrv is currently running on LocalSystem
+ //
+ // Once the service acct stuff is worked out we can nuke this
+ // (still need the GetMachineName code tho')
+ //
+
+ {
+// char szProviders[] = "Providers";
+ char szUserName[32], szDomainName[32], szPassword[32];
+ HKEY hProvidersKey;
+ DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
+
+
+ RegOpenKeyEx(
+ hTelephonyKey,
+ "Providers",
+ 0,
+ KEY_ALL_ACCESS,
+ &hProvidersKey
+ );
+
+ dwDataSize = sizeof(szUserName);
+
+ RegQueryValueEx(
+ hProvidersKey,
+ "User",
+ 0,
+ &dwDataType,
+ (LPBYTE) szUserName,
+ &dwDataSize
+ );
+
+ szUserName[dwDataSize] = '\0';
+
+ dwDataSize = sizeof(szDomainName);
+
+ RegQueryValueEx(
+ hProvidersKey,
+ "Domain",
+ 0,
+ &dwDataType,
+ (LPBYTE) szDomainName,
+ &dwDataSize
+ );
+
+ szDomainName[dwDataSize] = '\0';
+
+ dwDataSize = sizeof(szPassword);
+
+ RegQueryValueEx(
+ hProvidersKey,
+ "Password",
+ 0,
+ &dwDataType,
+ (LPBYTE) szPassword,
+ &dwDataSize
+ );
+
+ szPassword[dwDataSize] = '\0';
+
+ RegCloseKey (hProvidersKey);
+
+ if (LogonUser(
+ szUserName,
+ szDomainName,
+ szPassword,
+ LOGON32_LOGON_SERVICE,
+ LOGON32_PROVIDER_DEFAULT,
+ &hToken
+ ))
+ {
+ DBGOUT((3, "LogonUser() succeeded"));
+
+ wsprintf (gszDomainUser, "%s\\%s", szDomainName, szUserName);
+
+ GetComputerNameW (gszMachineName, &dwSize);
+
+ DBGOUT((
+ 3,
+ "\tdomainUser='%s', machine='%ws'",
+ gszDomainUser,
+ gszMachineName
+ ));
+ }
+ else
+ {
+ hToken = NULL;
+
+ DBGOUT((1, ""));
+ DBGOUT((1, "LogonUser() failed, err=%d", GetLastError()));
+ DBGOUT((1, "\tuserName='%s'", szUserName));
+ DBGOUT((1, "\tdomainName='%s'", szDomainName));
+ DBGOUT((1, "\tpassword='%s'", szPassword));
+ DBGOUT((1, ""));
+
+ RegCloseKey (hTelephonyKey);
+
+ return LINEERR_OPERATIONFAILED;
+ }
+ }
+
+
+ //
+ // Init gEventHandlerThreadParams & start EventHandlerThread
+ //
+
+ gEventHandlerThreadParams.dwEventBufferTotalSize = 1024;
+ gEventHandlerThreadParams.dwEventBufferUsedSize = 0;
+
+ if (!(gEventHandlerThreadParams.pEventBuffer = DrvAlloc(
+ gEventHandlerThreadParams.dwEventBufferTotalSize
+ )))
+ {
+ }
+
+ gEventHandlerThreadParams.pDataIn =
+ gEventHandlerThreadParams.pDataOut =
+ gEventHandlerThreadParams.pEventBuffer;
+
+ gEventHandlerThreadParams.dwMsgSize = 512;
+
+ if (!(gEventHandlerThreadParams.pMsg = DrvAlloc(
+ gEventHandlerThreadParams.dwMsgSize
+ )))
+ {
+ }
+
+ if (!(gEventHandlerThreadParams.hEvent = CreateEvent(
+ (LPSECURITY_ATTRIBUTES) NULL, // no security attrs
+ TRUE, // manual reset
+ FALSE, // initially non-signaled
+ NULL // unnamed
+ )))
+ {
+ }
+
+ gEventHandlerThreadParams.bExit = FALSE;
+
+ {
+ DWORD dwTID;
+
+
+ if (!(gEventHandlerThreadParams.hThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES) NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE) EventHandlerThread,
+ NULL,
+ 0,
+ &dwTID
+ )))
+ {
+ DBGOUT((
+ 1,
+ "CreateThread('EventHandlerThread') failed, err=%d",
+ GetLastError()
+ ));
+
+ RegCloseKey (hTelephonyKey);
+
+ return LINEERR_OPERATIONFAILED;
+ }
+ }
+
+
+ //
+ // Register the Rpc interface (leverage tapisrv's rpc server thread)
+ //
+
+ {
+ RPC_STATUS status;
+ unsigned char * pszSecurity = NULL;
+ unsigned int cMaxCalls = 20;
+
+
+ status = RpcServerUseProtseqEp(
+ "ncacn_np",
+ cMaxCalls,
+ "\\pipe\\remotesp",
+ pszSecurity // Security descriptor
+ );
+
+ DBGOUT((3, "RpcServerUseProtseqEp(np) ret'd %d", status));
+
+ if (status)
+ {
+ }
+
+ status = RpcServerRegisterIf(
+ remotesp_ServerIfHandle, // interface to register
+ NULL, // MgrTypeUuid
+ NULL // MgrEpv; null means use default
+ );
+
+ DBGOUT((3, "RpcServerRegisterIf ret'd %d", status));
+
+ if (status)
+ {
+ }
+ }
+
+
+ //
+ // Init globals
+ //
+ // NOTE: tapi's xxxEvent & xxxCreate procs are currently one in the same
+ //
+
+ wsprintf (szProviderN, "Provider%d", dwPermanentProviderID);
+
+ gdwPermanentProviderID = dwPermanentProviderID;
+
+ gpfnLineEventProc = lpfnLineCreateProc;
+ gpfnPhoneEventProc = lpfnPhoneCreateProc;
+
+ gpServers = (PDRVSERVER) NULL;
+ gpLineLookup = (PDRVLINELOOKUP) NULL;
+ gpPhoneLookup = (PDRVPHONELOOKUP) NULL;
+
+ RegOpenKeyEx(
+ hTelephonyKey,
+ szProviderN,
+ 0,
+ KEY_ALL_ACCESS,
+ &hProviderNKey
+ );
+
+ dwDataSize = sizeof(dwNumServers);
+ dwNumServers = 0;
+
+ RegQueryValueEx(
+ hProviderNKey,
+ "NumServers",
+ 0,
+ &dwDataType,
+ (LPBYTE) &dwNumServers,
+ &dwDataSize
+ );
+
+ dwDataSize = sizeof(gdwRetryCount);
+ gdwRetryCount = 0;
+
+ RegQueryValueEx(
+ hProviderNKey,
+ "RetryCount",
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwRetryCount,
+ &dwDataSize
+ );
+
+ dwDataSize = sizeof(gdwRetryTimeout);
+ gdwRetryTimeout = 0;
+
+ RegQueryValueEx(
+ hProviderNKey,
+ "RetryTimeout",
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwRetryTimeout,
+ &dwDataSize
+ );
+
+ DBGOUT((
+ 4,
+ "TSPI_ProviderEnumDevices: pN='%s', numSrvs=%d",
+ szProviderN,
+ dwNumServers
+ ));
+
+
+ if (!ImpersonateLoggedOnUser (hToken)) // BUGBUG local system hack
+ {
+ DBGOUT((1, "ImpersonateLoggedOnUser failed, err=%d", GetLastError()));
+
+ RegCloseKey (hProviderNKey);
+ RegCloseKey (hTelephonyKey);
+
+ return LINEERR_OPERATIONFAILED;
+
+ }
+
+
+ //
+ // Initialize all the servers
+ //
+
+ for (i = 0; i < dwNumServers; i++)
+ {
+ char szServerN[32];
+ DWORD dwNumLineDevices, dwNumPhoneDevices;
+ HLINEAPP hLineApp;
+ HPHONEAPP hPhoneApp;
+ PCONTEXT_HANDLE_TYPE phContext = NULL;
+
+
+ wsprintf (szServerN, "Server%d", i);
+
+ pszServerName = DrvAlloc (64);
+
+ dwDataSize = 64;
+
+ RegQueryValueEx(
+ hProviderNKey,
+ szServerN,
+ 0,
+ &dwDataType,
+ (LPBYTE) pszServerName,
+ &dwDataSize
+ );
+
+ pszServerName[dwDataSize] = '\0';
+
+ DBGOUT((1, "init: srvNam='%s'", pszServerName));
+
+ if (!pszServerName[0])
+ {
+ continue;
+ }
+
+
+ //
+ // Init the RPC connection
+ //
+
+ gpServer = DrvAlloc (sizeof (DRVSERVER));
+
+ {
+ DWORD dwUsedSize, dwBufSize;
+ RPC_STATUS status;
+ TAPI32_MSG msg[2];
+ unsigned char * pszStringBinding = NULL;
+
+
+ status = RpcStringBindingCompose(
+ NULL, // uuid
+ "ncacn_np", // prot
+ pszServerName, // server name
+ "\\pipe\\tapsrv", // interface name
+ NULL, // options
+ &pszStringBinding
+ );
+
+ if (status)
+ {
+ DBGOUT((
+ 0,
+ "RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
+ status,
+ pszServerName
+ ));
+ }
+
+ status = RpcBindingFromStringBinding(
+ pszStringBinding,
+ &hTapSrv
+ );
+
+ if (status)
+ {
+ DBGOUT((
+ 0,
+ "RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
+ status,
+ pszStringBinding
+ ));
+ }
+
+ {
+ DWORD dwRetryCount = 0;
+
+
+ do
+ {
+ WCHAR szDomainUser[32];
+
+
+ MultiByteToWideChar(
+ CP_ACP,
+ MB_PRECOMPOSED,
+ (LPCSTR) gszDomainUser,
+ -1,
+ szDomainUser,
+ 32
+ );
+
+ RpcTryExcept
+ {
+ long lUnused;
+
+
+ ClientAttach(
+ (PCONTEXT_HANDLE_TYPE *) &phContext,
+ 0xffffffff, // dwProcessID, -1 implies remotesp
+ (long *) &lUnused,
+ szDomainUser,
+ gszMachineName
+ );
+
+ dwRetryCount = gdwRetryCount;
+ }
+ RpcExcept (1)
+ {
+ if (dwRetryCount++ < gdwRetryCount)
+ {
+ Sleep (gdwRetryTimeout);
+ }
+ else
+ {
+ // BUGBUG gracefully handle cliAttach except error
+ }
+ }
+ RpcEndExcept
+
+ } while (dwRetryCount < gdwRetryCount);
+ }
+
+ RpcBindingFree (&hTapSrv);
+
+ RpcStringFree (&pszStringBinding);
+
+
+ //
+ //
+ //
+
+ {
+ PLINEINITIALIZE_PARAMS pParams;
+ BOOL bExit = FALSE;
+
+
+ msg[0].u.Req_Func = lInitialize;
+
+ pParams = (PLINEINITIALIZE_PARAMS) msg;
+
+
+ //
+ // NOTE: we pass the pServer in place of the lpfnCallback
+ // so the we always know which server is sending us
+ // async events
+ //
+
+ pParams->hInstance = 0;
+ pParams->lpfnCallback = (LINECALLBACK) ((LPVOID) gpServer);
+ pParams->dwFriendlyNameOffset =
+ pParams->dwModuleNameOffset = 0;
+ pParams->dwAPIVersion = TAPI_VERSION_CURRENT;
+
+ lstrcpyW ((WCHAR *) (msg + 1), gszMachineName);
+
+ dwBufSize =
+ dwUsedSize = sizeof (TAPI32_MSG) +
+ (lstrlenW (gszMachineName) + 1) * sizeof (WCHAR);
+
+ {
+ DWORD dwRetryCount = 0;
+
+ do
+ {
+ RpcTryExcept
+ {
+ ClientRequest(
+ phContext,
+ (char *) &msg,
+ dwBufSize,
+ &dwUsedSize
+ );
+
+ dwRetryCount = gdwRetryCount;
+ }
+ RpcExcept (1)
+ {
+ DBGOUT((1, "init: xcpt in lInit"));
+
+ if (dwRetryCount++ < gdwRetryCount)
+ {
+ Sleep (gdwRetryTimeout);
+ }
+ else
+ {
+ // BUGBUG need graceful cleanup
+ bExit = TRUE;
+ }
+ }
+ RpcEndExcept
+
+ } while (dwRetryCount < gdwRetryCount);
+ }
+
+ if (bExit)
+ {
+ // BUGBUG check the result of lineInit
+ }
+
+ hLineApp = pParams->hLineApp;
+ dwNumLineDevices = pParams->dwNumDevs;
+ }
+
+
+ //
+ //
+ //
+
+ {
+ PPHONEINITIALIZE_PARAMS pParams;
+
+
+ msg[0].u.Req_Func = pInitialize;
+
+ pParams = (PPHONEINITIALIZE_PARAMS) msg;
+
+ //
+ // NOTE: we pass the pServer in place of the lpfnCallback
+ // so the we always know which server is sending us
+ // async events
+ //
+
+ pParams->hInstance = 0;
+ pParams->lpfnCallback = (PHONECALLBACK) ((LPVOID) gpServer);
+ pParams->dwFriendlyNameOffset =
+ pParams->dwModuleNameOffset = 0;
+ pParams->dwAPIVersion = TAPI_VERSION_CURRENT;
+
+ lstrcpyW ((WCHAR *) (msg + 1), gszMachineName);
+
+ dwBufSize =
+ dwUsedSize = sizeof (TAPI32_MSG) +
+ (lstrlenW (gszMachineName) + 1) * sizeof (WCHAR);
+
+ {
+ DWORD dwRetryCount = 0;
+
+
+ do
+ {
+ RpcTryExcept
+ {
+ ClientRequest(
+ phContext,
+ (char *) &msg,
+ dwBufSize,
+ &dwUsedSize
+ );
+
+ dwRetryCount = gdwRetryCount;
+ }
+ RpcExcept (1)
+ {
+ if (dwRetryCount++ < gdwRetryCount)
+ {
+ Sleep (gdwRetryTimeout);
+ }
+ else
+ {
+ // BUGBUG gracefully handle phoneInit except error
+ }
+ }
+ RpcEndExcept
+
+ } while (dwRetryCount < gdwRetryCount);
+ }
+
+ // BUGBUG check the result of phoneInit
+
+ hPhoneApp = pParams->hPhoneApp;
+ dwNumPhoneDevices = pParams->dwNumDevs;
+ }
+ }
+
+ //
+ //
+ //
+
+ DBGOUT((
+ 1,
+ "TSPI_providerEnumDevices: srv='%s', lines=%d, phones=%d",
+ pszServerName,
+ dwNumLineDevices,
+ dwNumPhoneDevices
+ ));
+
+ {
+ DWORD j;
+
+
+ gpServer->pServerName = pszServerName;
+ gpServer->phContext = phContext;
+ gpServer->hLineApp = hLineApp;
+ gpServer->hPhoneApp = hPhoneApp;
+ gpServer->pNext = gpServers;
+
+ gpServers = gpServer;
+
+ for (j = 0; j < dwNumLineDevices; j++)
+ {
+ AddLine (gpServer, j, j, TRUE);
+ }
+
+ for (j = 0; j < dwNumPhoneDevices; j++)
+ {
+ AddPhone (gpServer, j, j, TRUE);
+ }
+ }
+
+ } // for (i = 0; i < iNumServers; i++)
+
+ RevertToSelf(); // BUGBUG LocalSystem hack
+
+ gdwInitialNumLineDevices =
+ *lpdwNumLines = (gpLineLookup ? gpLineLookup->dwUsedEntries : 0);
+
+ gdwInitialNumPhoneDevices =
+ *lpdwNumPhones = (gpPhoneLookup ? gpPhoneLookup->dwUsedEntries : 0);
+
+ // BUGBUG TSPI_provEnumDev: we ought really do alot of error clean up here
+
+ RegCloseKey (hProviderNKey);
+ RegCloseKey (hTelephonyKey);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerFreeDialogInstance(
+ HDRVDIALOGINSTANCE hdDlgInst
+ )
+{
+ // BUGBUG TSPI_providerFreeDialogInstance: implement
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerGenericDialogData(
+ DWORD dwObjectID,
+ DWORD dwObjectType,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ // BUGBUG TSPI_providerGenericDialogData: implement
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc,
+ LPDWORD lpdwTSPIOptions
+ )
+{
+ if (!hToken)
+ {
+ return LINEERR_OPERATIONFAILED;
+ }
+
+ gdwLineDeviceIDBase = dwLineDeviceIDBase;
+ gdwPhoneDeviceIDBase = dwPhoneDeviceIDBase;
+
+ gpfnCompletionProc = lpfnCompletionProc;
+
+ *lpdwTSPIOptions = 0;
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // Although this func is never called by TAPI v2.0, we export
+ // it so that the Telephony Control Panel Applet knows that it
+ // can add this provider via lineAddProvider(), otherwise
+ // Telephon.cpl will not consider it installable
+ //
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ //
+ // Although this func is never called by TAPI v2.0, we export
+ // it so that the Telephony Control Panel Applet knows that it
+ // can remove this provider via lineRemoveProvider(), otherwise
+ // Telephon.cpl will not consider it removable
+ //
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID
+ )
+{
+ PDRVSERVER pServer;
+ RPC_STATUS status;
+
+
+ //
+ // Set the flag instructing the EventHandlerThread to terminate
+ //
+
+ gEventHandlerThreadParams.bExit = TRUE;
+
+
+ //
+ // Send detach to each server, then wait for the async event threads
+ // to terminate and free the resources
+ //
+
+ if (!ImpersonateLoggedOnUser (hToken)) // BUGBUG LocalSystem hack
+ {
+ DBGOUT((1, "ImpersonateLoggedOnUser failed, err=%d", GetLastError()));
+
+ // fall thru
+ }
+
+ pServer = gpServers;
+
+ while (pServer)
+ {
+ DWORD dwRetryCount = 0;
+ PDRVSERVER pNextServer = pServer->pNext;
+
+
+ do
+ {
+ RpcTryExcept
+ {
+ ClientDetach (&pServer->phContext);
+
+ dwRetryCount = gdwRetryCount;
+ }
+ RpcExcept (1)
+ {
+ if (dwRetryCount++ < gdwRetryCount)
+ {
+ Sleep (gdwRetryTimeout);
+ }
+ }
+ RpcEndExcept
+
+ } while (dwRetryCount < gdwRetryCount);
+
+ DrvFree (pServer->pServerName);
+ DrvFree (pServer);
+
+ pServer = pNextServer;
+ }
+
+ RevertToSelf(); // BUGBUG LocalSystem hack
+
+ CloseHandle (hToken);
+
+
+ //
+ // Unregister out rpc server interface
+ //
+
+ status = RpcServerUnregisterIf(
+ remotesp_ServerIfHandle, // interface to register
+ NULL, // MgrTypeUuid
+ 0 // wait for calls to complete
+ );
+
+ DBGOUT((3, "RpcServerUntegisterIf ret'd %d", status));
+
+
+ //
+ // Wait for the EventHandlerThread to terminate, then clean up
+ // the related resources
+ //
+
+ while (WaitForSingleObject (gEventHandlerThreadParams.hThread, 0) !=
+ WAIT_OBJECT_0)
+ {
+ SetEvent (gEventHandlerThreadParams.hEvent);
+ Sleep (0);
+ }
+
+ CloseHandle (gEventHandlerThreadParams.hThread);
+ CloseHandle (gEventHandlerThreadParams.hEvent);
+ DrvFree (gEventHandlerThreadParams.pEventBuffer);
+ DrvFree (gEventHandlerThreadParams.pMsg);
+
+
+ //
+ // Free the lookup tables
+ //
+
+ while (gpLineLookup)
+ {
+ PDRVLINELOOKUP pNextLineLookup = gpLineLookup->pNext;
+
+
+ DrvFree (gpLineLookup);
+
+ gpLineLookup = pNextLineLookup;
+ }
+
+ while (gpPhoneLookup)
+ {
+ PDRVPHONELOOKUP pNextPhoneLookup = gpPhoneLookup->pNext;
+
+
+ DrvFree (gpPhoneLookup);
+
+ gpPhoneLookup = pNextPhoneLookup;
+ }
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerUIIdentify(
+ LPWSTR lpszUIDLLName
+ )
+{
+ wcscpy (lpszUIDLLName, L"remotesp.tsp");
+
+ return 0;
+}
+
+
+//
+// ---------------------------- TUISPI_xxx funcs ------------------------------
+//
+
+LONG
+TSPIAPI
+TUISPI_lineConfigDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ char buf[128];
+
+
+ wsprintf (buf, "devID=%d, devClass='%ws'", dwDeviceID, lpszDeviceClass);
+
+ MessageBox (hwndOwner, buf, "REMOTESP: TUISPI_lineConfigDialog", MB_OK);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_lineConfigDialogEdit(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass,
+ LPVOID const lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ )
+{
+ char buf[128];
+
+
+ wsprintf (buf, "devID=%d, devClass='%ws'", dwDeviceID, lpszDeviceClass);
+
+ MessageBox (hwndOwner, buf, "REMOTESP: TUISPI_lineConfigDialogEdit",MB_OK);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_phoneConfigDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ char buf[128];
+
+
+ wsprintf (buf, "devID=%d, devClass='%ws'", dwDeviceID, lpszDeviceClass);
+
+ MessageBox (hwndOwner, buf, "REMOTESP: TUISPI_phoneConfigDialog", MB_OK);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerConfig(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ DialogBoxParam(
+ ghInst,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) ConfigDlgProc,
+ (LPARAM) dwPermanentProviderID
+ );
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerGenericDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HTAPIDIALOGINSTANCE htDlgInst,
+ LPVOID lpParams,
+ DWORD dwSize,
+ HANDLE hEvent
+ )
+{
+ char buf[128];
+
+
+ SetEvent (hEvent);
+
+ wsprintf (buf, "htDlgInst=x%x", htDlgInst);
+
+ MessageBox (NULL, buf,"REMOTESP: TUISPI_providerGenericDialog",MB_OK);
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerGenericDialogData(
+ HTAPIDIALOGINSTANCE htDlgInst,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ DBGOUT((
+ 3,
+ "TUISPI_providerGenericDialogData: enter (lpParams=x%x, dwSize=x%x)",
+ lpParams,
+ dwSize
+ ));
+
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerInstall(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ char buf[32];
+ LONG lResult = LINEERR_OPERATIONFAILED;
+ HKEY hTelephonyKey, hProviderNKey;
+ DWORD dwDataType, dwDataSize, dwTemp, dwDisposition;
+
+
+ if (ProviderInstall ("remotesp.tsp", TRUE) == 0)
+ {
+ //
+ // Initialize our ProviderN section
+ //
+
+ wsprintf (buf, "Provider%d", dwPermanentProviderID);
+
+ if (RegCreateKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ &hTelephonyKey,
+ &dwDisposition
+
+ ) == ERROR_SUCCESS)
+ {
+ if (RegCreateKeyEx(
+ hTelephonyKey,
+ buf,
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ &hProviderNKey,
+ &dwDisposition
+
+ ) == ERROR_SUCCESS)
+ {
+ dwTemp = 0;
+
+ RegSetValueEx(
+ hProviderNKey,
+ gszNumServers,
+ 0,
+ REG_DWORD,
+ (LPBYTE) &dwTemp,
+ sizeof(dwTemp)
+ );
+
+ RegCloseKey (hProviderNKey);
+ RegCloseKey (hTelephonyKey);
+
+ DialogBoxParam(
+ ghInst,
+ MAKEINTRESOURCE(100),
+ hwndOwner,
+ (DLGPROC) ConfigDlgProc,
+ (LPARAM) dwPermanentProviderID
+ );
+
+ lResult = 0;
+ }
+ else
+ {
+ RegCloseKey (hTelephonyKey);
+ }
+ }
+ }
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TUISPI_providerRemove(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ char buf[32];
+ LONG lResult;
+ HKEY hTelephonyKey;
+
+
+ //
+ // Clean up our ProviderN section
+ //
+
+ wsprintf (buf, "Provider%d", dwPermanentProviderID);
+
+ if (RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hTelephonyKey
+
+ ) == ERROR_SUCCESS)
+ {
+ RegDeleteKey (hTelephonyKey, buf);
+ RegCloseKey (hTelephonyKey);
+ lResult = 0;
+ }
+ else
+ {
+ lResult = LINEERR_OPERATIONFAILED;
+ }
+
+ return lResult;
+}
+
+
+//
+// ------------------------ Private support routines --------------------------
+//
+
+#if DBG
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+{
+ if (dwDbgLevel <= gdwDebugLevel)
+ {
+ char buf[128] = "REMOTESP: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+ wvsprintf (&buf[10], lpszFormat, ap);
+ lstrcatA (buf, "\n");
+ OutputDebugStringA (buf);
+ va_end(ap);
+ }
+}
+#endif
+
+
+LONG
+AddLine(
+ PDRVSERVER pServer,
+ DWORD dwDeviceIDLocal,
+ DWORD dwDeviceIDServer,
+ BOOL bInit
+ )
+{
+ PDRVLINE pLine;
+ PDRVLINELOOKUP pLineLookup;
+
+
+ if (!gpLineLookup)
+ {
+ if (!(gpLineLookup = DrvAlloc(
+ sizeof(DRVLINELOOKUP) +
+ (DEF_NUM_LINE_ENTRIES-1) * sizeof (DRVLINE)
+ )))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ gpLineLookup->dwTotalEntries = DEF_NUM_LINE_ENTRIES;
+ }
+
+ pLineLookup = gpLineLookup;
+
+ while (pLineLookup->pNext)
+ {
+ pLineLookup = pLineLookup->pNext;
+ }
+
+ if (pLineLookup->dwUsedEntries == pLineLookup->dwTotalEntries)
+ {
+ PDRVLINELOOKUP pNewLineLookup;
+
+
+ if (!(pNewLineLookup = DrvAlloc(
+ sizeof(DRVLINELOOKUP) +
+ (2 * pLineLookup->dwTotalEntries - 1) * sizeof(DRVLINE)
+ )))
+ {
+ return LINEERR_NOMEM;
+ }
+
+ pNewLineLookup->dwTotalEntries = 2 * pLineLookup->dwTotalEntries;
+
+ if (bInit)
+ {
+ pNewLineLookup->dwUsedEntries = pLineLookup->dwTotalEntries;
+
+ CopyMemory(
+ pNewLineLookup->aEntries,
+ pLineLookup->aEntries,
+ pLineLookup->dwTotalEntries * sizeof (DRVLINE)
+ );
+
+ DrvFree (pLineLookup);
+
+ gpLineLookup = pNewLineLookup;
+
+ }
+
+ pLineLookup = pNewLineLookup;
+ }
+
+ pLine = pLineLookup->aEntries + pLineLookup->dwUsedEntries;
+
+ pLine->pServer = pServer;
+ pLine->dwDeviceIDLocal = dwDeviceIDLocal;
+ pLine->dwDeviceIDServer = dwDeviceIDServer;
+
+ pLineLookup->dwUsedEntries++;
+
+
+ //
+ // Negotiate the API/SPI version
+ //
+
+ {
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ LineID,
+ Dword,
+ Dword,
+ lpDword,
+ lpGet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) pServer->hLineApp,
+ (DWORD) dwDeviceIDLocal,
+ (DWORD) TAPI_VERSION1_0,
+ (DWORD) TAPI_VERSION_CURRENT,
+ (DWORD) &pLine->dwXPIVersion,
+ (DWORD) &pLine->ExtensionID,
+ (DWORD) sizeof (LINEEXTENSIONID),
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 7, lNegotiateAPIVersion),
+ args,
+ argTypes
+ };
+
+
+ REMOTEDOFUNC (&funcArgs, "lineNegotiateAPIVersion");
+ }
+
+ return 0;
+}
+
+
+LONG
+AddPhone(
+ PDRVSERVER pServer,
+ DWORD dwDeviceIDLocal,
+ DWORD dwDeviceIDServer,
+ BOOL bInit
+ )
+{
+ PDRVPHONE pPhone;
+ PDRVPHONELOOKUP pPhoneLookup;
+
+
+ if (!gpPhoneLookup)
+ {
+ if (!(gpPhoneLookup = DrvAlloc(
+ sizeof(DRVPHONELOOKUP) +
+ (DEF_NUM_PHONE_ENTRIES-1) * sizeof (DRVPHONE)
+ )))
+ {
+ return (bInit ? LINEERR_NOMEM : PHONEERR_NOMEM);
+ }
+
+ gpPhoneLookup->dwTotalEntries = DEF_NUM_PHONE_ENTRIES;
+ }
+
+ pPhoneLookup = gpPhoneLookup;
+
+ while (pPhoneLookup->pNext)
+ {
+ pPhoneLookup = pPhoneLookup->pNext;
+ }
+
+ if (pPhoneLookup->dwUsedEntries == pPhoneLookup->dwTotalEntries)
+ {
+ PDRVPHONELOOKUP pNewPhoneLookup;
+
+
+ if (!(pNewPhoneLookup = DrvAlloc(
+ sizeof(DRVPHONELOOKUP) +
+ (2 * pPhoneLookup->dwTotalEntries - 1) * sizeof(DRVPHONE)
+ )))
+ {
+ return (bInit ? LINEERR_NOMEM : PHONEERR_NOMEM);
+ }
+
+ pNewPhoneLookup->dwTotalEntries = 2 * pPhoneLookup->dwTotalEntries;
+
+ if (bInit)
+ {
+ pNewPhoneLookup->dwUsedEntries = pPhoneLookup->dwTotalEntries;
+
+ CopyMemory(
+ pNewPhoneLookup->aEntries,
+ pPhoneLookup->aEntries,
+ pPhoneLookup->dwTotalEntries * sizeof (DRVPHONE)
+ );
+
+ DrvFree (pPhoneLookup);
+
+ gpPhoneLookup = pNewPhoneLookup;
+ }
+
+ pPhoneLookup = pNewPhoneLookup;
+ }
+
+ pPhone = pPhoneLookup->aEntries + pPhoneLookup->dwUsedEntries;
+
+ pPhone->pServer = pServer;
+ pPhone->dwDeviceIDLocal = dwDeviceIDLocal;
+ pPhone->dwDeviceIDServer = dwDeviceIDServer;
+
+ pPhoneLookup->dwUsedEntries++;
+
+
+ //
+ // Negotiate the API/SPI version
+ //
+
+ {
+ static REMOTE_ARG_TYPES argTypes[] =
+ {
+ Dword,
+ PhoneID,
+ Dword,
+ Dword,
+ lpDword,
+ lpGet_SizeToFollow,
+ Size
+ };
+ DWORD args[] =
+ {
+ (DWORD) pServer->hPhoneApp,
+ (DWORD) dwDeviceIDLocal,
+ (DWORD) TAPI_VERSION1_0,
+ (DWORD) TAPI_VERSION_CURRENT,
+ (DWORD) &pPhone->dwXPIVersion,
+ (DWORD) &pPhone->ExtensionID,
+ (DWORD) sizeof (PHONEEXTENSIONID),
+ };
+ REMOTE_FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 7, pNegotiateAPIVersion),
+ args,
+ argTypes
+ };
+
+
+ REMOTEDOFUNC (&funcArgs, "phoneNegotiateAPIVersion");
+ }
+
+ return 0;
+}
+
+
+LPVOID
+DrvAlloc(
+ DWORD dwSize
+ )
+{
+ return (LocalAlloc (LPTR, dwSize));
+}
+
+
+void
+DrvFree(
+ LPVOID p
+ )
+{
+ LocalFree (p);
+}
+
+
+void
+__RPC_FAR *
+__RPC_API
+midl_user_allocate(
+ size_t len
+ )
+{
+ return (DrvAlloc (len));
+}
+
+
+void
+__RPC_API
+midl_user_free(
+ void __RPC_FAR * ptr
+ )
+{
+ DrvFree (ptr);
+}
+
+
+LONG
+RemoteSPAttach(
+ PCONTEXT_HANDLE_TYPE2 *pphContext
+ )
+{
+ //
+ // This func is called by TapiSrv.exe on a remote machine as a
+ // result of the call to ClientAttach in TSPI_providerEnumDevices.
+ // The gpServer variable contains a pointer to the DRVSERVER
+ // structure we are currently initializing for this tapi server,
+ // so we'll use this as the context value.
+ //
+
+ DBGOUT((3, "RemoteSPAttach: enter"));
+
+ *pphContext = (PCONTEXT_HANDLE_TYPE) gpServer;
+
+ return 0;
+}
+
+
+void
+RemoteSPEventProc(
+ PCONTEXT_HANDLE_TYPE2 phContext,
+ unsigned char *pBuffer,
+ long lSize
+ )
+{
+ //
+ // This func is called by tapisrv on a remote machine. We want to do
+ // things as quickly as possible here and return so we don't block the
+ // calling server thread.
+ //
+
+ DWORD dwMoveSize = (DWORD) lSize, dwMoveSizeWrapped = 0;
+
+
+ //
+ // Enter the critical section to sync access to gEventHandlerThreadParams
+ //
+
+ EnterCriticalSection (&gEventBufferCriticalSection);
+
+
+ //
+ // Check to see if there's enough room for this msg in the event buffer.
+ // If not, then alloc a new event buffer, copy contents of existing buffer
+ // to new buffer (careful to preserve ordering of valid data), free the
+ // existing buffer, and reset the pointers.
+ //
+
+ if ((gEventHandlerThreadParams.dwEventBufferUsedSize + lSize) >
+ gEventHandlerThreadParams.dwEventBufferTotalSize)
+ {
+ DWORD dwMoveSize2, dwMoveSizeWrapped2, dwNewEventBufferTotalSize;
+ LPBYTE pNewEventBuffer;
+
+
+ //
+ // Alloc a few more bytes than actually needed in the hope that we
+ // won't have to do this again soon (we don't want to go overboard
+ // & alloc a whole bunch since we don't currently free the buffer
+ // until provider shutdown)
+ //
+
+ dwNewEventBufferTotalSize =
+ gEventHandlerThreadParams.dwEventBufferUsedSize + lSize + 512;
+
+ if (!(pNewEventBuffer = DrvAlloc (dwNewEventBufferTotalSize)))
+ {
+ // BUGBUG we're hosed, blow off the msg (send a REINIT?)
+
+ LeaveCriticalSection (&gEventBufferCriticalSection);
+
+ return;
+ }
+
+ if (gEventHandlerThreadParams.dwEventBufferUsedSize != 0)
+ {
+ if (gEventHandlerThreadParams.pDataIn >
+ gEventHandlerThreadParams.pDataOut)
+ {
+ dwMoveSize2 = (DWORD) (gEventHandlerThreadParams.pDataIn -
+ gEventHandlerThreadParams.pDataOut);
+
+ dwMoveSizeWrapped2 = 0;
+ }
+ else
+ {
+ dwMoveSize2 = (DWORD) ((gEventHandlerThreadParams.pEventBuffer
+ + gEventHandlerThreadParams.dwEventBufferTotalSize)
+ - gEventHandlerThreadParams.pDataOut);
+
+ dwMoveSizeWrapped2 = (DWORD) (gEventHandlerThreadParams.pDataIn
+ - gEventHandlerThreadParams.pEventBuffer);
+ }
+
+ CopyMemory(
+ pNewEventBuffer,
+ gEventHandlerThreadParams.pDataOut,
+ dwMoveSize2
+ );
+
+ if (dwMoveSizeWrapped2)
+ {
+ CopyMemory(
+ pNewEventBuffer + dwMoveSize2,
+ gEventHandlerThreadParams.pEventBuffer,
+ dwMoveSizeWrapped2
+ );
+ }
+
+ DrvFree (gEventHandlerThreadParams.pEventBuffer);
+
+ gEventHandlerThreadParams.pDataIn = pNewEventBuffer + dwMoveSize2 +
+ dwMoveSizeWrapped2;
+ }
+ else
+ {
+ gEventHandlerThreadParams.pDataIn = pNewEventBuffer;
+ }
+
+ gEventHandlerThreadParams.pDataOut =
+ gEventHandlerThreadParams.pEventBuffer = pNewEventBuffer;
+
+ gEventHandlerThreadParams.dwEventBufferTotalSize =
+ dwNewEventBufferTotalSize;
+ }
+
+
+ //
+ // Write the msg data to the buffer
+ //
+
+ if (gEventHandlerThreadParams.pDataIn >=
+ gEventHandlerThreadParams.pDataOut)
+ {
+ DWORD dwFreeSize;
+
+
+ dwFreeSize = gEventHandlerThreadParams.dwEventBufferTotalSize -
+ (gEventHandlerThreadParams.pDataIn -
+ gEventHandlerThreadParams.pEventBuffer);
+
+ if (dwMoveSize > dwFreeSize)
+ {
+ dwMoveSizeWrapped = dwMoveSize - dwFreeSize;
+
+ dwMoveSize = dwFreeSize;
+ }
+ }
+
+ CopyMemory (gEventHandlerThreadParams.pDataIn, pBuffer, dwMoveSize);
+
+ if (dwMoveSizeWrapped != 0)
+ {
+ CopyMemory(
+ gEventHandlerThreadParams.pEventBuffer,
+ pBuffer + dwMoveSize,
+ dwMoveSizeWrapped
+ );
+
+ gEventHandlerThreadParams.pDataIn =
+ gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
+ }
+ else
+ {
+ gEventHandlerThreadParams.pDataIn += dwMoveSize;
+ }
+
+ gEventHandlerThreadParams.dwEventBufferUsedSize += (DWORD) lSize;
+
+
+ //
+ // Tell the EventHandlerThread there's another event to handle by
+ // signaling the event
+ //
+
+ SetEvent (gEventHandlerThreadParams.hEvent);
+
+
+ //
+ // We're done...
+ //
+
+ LeaveCriticalSection (&gEventBufferCriticalSection);
+
+
+ DBGOUT((3, "WriteEventBuffer: bytesWritten=x%x", lSize));
+}
+
+
+void
+__RPC_USER
+PCONTEXT_HANDLE_TYPE2_rundown(
+ PCONTEXT_HANDLE_TYPE2 phContext
+ )
+{
+ //
+ // This func is called when a server dies. We need to close any open
+ // lines/phones associated with the server, complete pending reqs, and...
+ //
+ // BUGBUG PCONTEXT_HANDLE_TYPE2_rundown
+ //
+}
+
+
+void
+RemoteSPDetach(
+ PCONTEXT_HANDLE_TYPE2 *pphContext
+ )
+{
+ DBGOUT((3, "RemoteSPDetach: enter"));
+
+ PCONTEXT_HANDLE_TYPE2_rundown (*pphContext);
+
+ *pphContext = (PCONTEXT_HANDLE_TYPE) NULL;
+
+ DBGOUT((3, "RemoteSPDetach: exit"));
+}
+
+
+LONG
+AddCallToList(
+ PDRVLINE pLine,
+ PDRVCALL pCall
+ )
+{
+ //
+ // Initialize some common fields in the call
+ //
+
+ pCall->pServer = pLine->pServer;
+ pCall->pLine = pLine;
+
+
+ //
+ // Safely add the call to the line's list
+ //
+
+ EnterCriticalSection (&gCallListCriticalSection);
+
+ if ((pCall->pNext = (PDRVCALL) pLine->pCalls))
+ {
+ pCall->pNext->pPrev = pCall;
+ }
+
+ pLine->pCalls = pCall;
+
+ LeaveCriticalSection (&gCallListCriticalSection);
+
+ return 0;
+}
+
+
+LONG
+RemoveCallFromList(
+ PDRVCALL pCall
+ )
+{
+ //
+ // Safely remove the call from the line's list
+ //
+
+ EnterCriticalSection (&gCallListCriticalSection);
+
+ if (pCall->pNext)
+ {
+ pCall->pNext->pPrev = pCall->pPrev;
+ }
+
+ if (pCall->pPrev)
+ {
+ pCall->pPrev->pNext = pCall->pNext;
+ }
+ else
+ {
+ pCall->pLine->pCalls = pCall->pNext;
+ }
+
+ LeaveCriticalSection (&gCallListCriticalSection);
+
+ return 0;
+}
+
+
+void
+Shutdown(
+ PDRVSERVER pServer
+ )
+{
+ //
+ // Do a lineShutdown
+ //
+
+ {
+ DWORD dwSize;
+ TAPI32_MSG msg;
+ PLINESHUTDOWN_PARAMS pParams;
+
+
+ msg.u.Req_Func = lShutdown;
+
+ pParams = (PLINESHUTDOWN_PARAMS) &msg;
+
+ pParams->hLineApp = pServer->hLineApp;
+
+ dwSize = sizeof (TAPI32_MSG);
+
+ {
+ DWORD dwRetryCount = 0;
+
+
+ do
+ {
+ RpcTryExcept
+ {
+ ClientRequest(
+ pServer->phContext,
+ (char *) &msg,
+ dwSize,
+ &dwSize
+ );
+
+ dwRetryCount = gdwRetryCount;
+ }
+ RpcExcept (1)
+ {
+ // TODO may want to increase the retry count here since we
+ // have to do this, & a million other clients may be
+ // trying to do the same thing at the same time
+
+ if (dwRetryCount++ < gdwRetryCount)
+ {
+ Sleep (gdwRetryTimeout);
+ }
+ }
+ RpcEndExcept
+
+ } while (dwRetryCount < gdwRetryCount);
+ }
+ }
+
+
+ //
+ // Do a phoneShutdown
+ //
+
+ {
+ DWORD dwSize;
+ TAPI32_MSG msg;
+ PPHONESHUTDOWN_PARAMS pParams;
+
+
+ msg.u.Req_Func = pShutdown;
+
+ pParams = (PPHONESHUTDOWN_PARAMS) &msg;
+
+ pParams->hPhoneApp = pServer->hPhoneApp;
+
+ dwSize = sizeof (TAPI32_MSG);
+
+ {
+ DWORD dwRetryCount = 0;
+
+
+ do
+ {
+ RpcTryExcept
+ {
+ ClientRequest(
+ pServer->phContext,
+ (char *) &msg,
+ dwSize,
+ &dwSize
+ );
+
+ dwRetryCount = gdwRetryCount;
+ }
+ RpcExcept (1)
+ {
+ // TODO may want to increase the retry count here since we
+ // have to do this, & a million other clients may be
+ // trying to do the same thing at the same time
+
+ if (dwRetryCount++ < gdwRetryCount)
+ {
+ Sleep (gdwRetryTimeout);
+ }
+ }
+ RpcEndExcept
+
+ } while (dwRetryCount < gdwRetryCount);
+ }
+ }
+
+
+ //
+ // Mark the server as disconnected (so no more requests will be sent)
+ //
+
+ pServer->bDisconnected = TRUE;
+
+
+ //
+ // Walk the line lookup tables & send a CLOSE msg for each open line
+ // associated with the server
+ //
+
+ {
+ PDRVLINELOOKUP pLookup = gpLineLookup;
+
+
+ while (pLookup)
+ {
+ DWORD i;
+ PDRVLINE pLine;
+
+
+ for(
+ i = 0, pLine = pLookup->aEntries;
+ i < pLookup->dwUsedEntries;
+ i++, pLine++
+ )
+ {
+ if (pLine->pServer == pServer)
+ {
+ pLine->pServer = NULL;
+
+ if (pLine->htLine)
+ {
+ PDRVCALL pCall;
+
+
+ pLine->hLine = NULL;
+
+ EnterCriticalSection (&gCallListCriticalSection);
+
+ pCall = pLine->pCalls;
+
+ while (pCall)
+ {
+ pCall->hCall = NULL;
+
+ pCall = pCall->pNext;
+ }
+
+ LeaveCriticalSection (&gCallListCriticalSection);
+
+ (*gpfnLineEventProc)(
+ pLine->htLine,
+ NULL,
+ LINE_CLOSE,
+ 0,
+ 0,
+ 0
+ );
+ }
+ }
+ }
+
+ pLookup = pLookup->pNext;
+ }
+ }
+
+
+ //
+ // Walk the phone lookup tables & send a CLOSE msg for each open phone
+ // associated with the server
+ //
+
+ {
+ PDRVPHONELOOKUP pLookup = gpPhoneLookup;
+
+
+ while (pLookup)
+ {
+ DWORD i;
+ PDRVPHONE pPhone;
+
+
+ for(
+ i = 0, pPhone = pLookup->aEntries;
+ i < pLookup->dwUsedEntries;
+ i++, pPhone++
+ )
+ {
+ if (pPhone->pServer == pServer)
+ {
+ pPhone->pServer = NULL;
+
+ if (pPhone->htPhone)
+ {
+ pPhone->hPhone = NULL;
+
+ (*gpfnPhoneEventProc)(
+ pPhone->htPhone,
+ PHONE_CLOSE,
+ 0,
+ 0,
+ 0
+ );
+ }
+ }
+ }
+
+ pLookup = pLookup->pNext;
+ }
+ }
+}
+
+
+BOOL
+CALLBACK
+ConfigDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ static HKEY hTelephonyKey, hProviderNKey;
+
+ DWORD dwDataType, dwDataSize;
+
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ char buf[32], szProviderN[16], szServerN[16];
+ BOOL bReadOnly;
+ DWORD i, iNumServers;
+ DWORD dwPermanentProviderID = (DWORD) lParam;
+
+
+ //
+ // First try to open the Telephony key with read/write access.
+ // If that fails, disable any controls that could cause a chg
+ // in config & try opening again with read only access.
+ //
+
+ if (RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hTelephonyKey
+
+ ) != ERROR_SUCCESS)
+ {
+ EnableWindow (GetDlgItem (hwnd, IDC_ADD), FALSE);
+ EnableWindow (GetDlgItem (hwnd, IDC_REMOVE), FALSE);
+ EnableWindow (GetDlgItem (hwnd, IDOK), FALSE);
+
+ if (RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ KEY_READ,
+ &hTelephonyKey
+
+ ) != ERROR_SUCCESS)
+ {
+ EndDialog (hwnd, 0);
+ return FALSE;
+ }
+
+ bReadOnly = TRUE;
+ }
+ else
+ {
+ bReadOnly = FALSE;
+ }
+
+ wsprintf (szProviderN, "%s%d", gszProvider, dwPermanentProviderID);
+
+ RegOpenKeyEx(
+ hTelephonyKey,
+ szProviderN,
+ 0,
+ (bReadOnly ? KEY_READ : KEY_ALL_ACCESS),
+ &hProviderNKey
+ );
+
+ dwDataSize = sizeof(iNumServers);
+
+ RegQueryValueEx(
+ hProviderNKey,
+ gszNumServers,
+ 0,
+ &dwDataType,
+ (LPBYTE) &iNumServers,
+ &dwDataSize
+ );
+
+ for (i = 0; i < iNumServers; i++)
+ {
+ wsprintf (szServerN, "%s%d", gszServer, i);
+
+ dwDataSize = sizeof(buf);
+
+ RegQueryValueEx(
+ hProviderNKey,
+ szServerN,
+ 0,
+ &dwDataType,
+ (LPBYTE) buf,
+ &dwDataSize
+ );
+
+ buf[dwDataSize] = '\0';
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) buf
+ );
+ }
+
+ SetWindowLong (hwnd, GWL_USERDATA, dwPermanentProviderID);
+
+ break;
+ }
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_ADD:
+ {
+ char buf[32];
+
+
+ GetDlgItemText (hwnd, IDC_EDIT1, buf, 31);
+
+ if (buf[0])
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM) buf
+ );
+ }
+
+ SetDlgItemText (hwnd, IDC_EDIT1, "");
+
+ break;
+ }
+ case IDC_REMOVE:
+ {
+ char buf[32];
+ LONG lSel;
+
+
+ if ((lSel = SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_GETCURSEL,
+ 0,
+ 0
+
+ )) != LB_ERR)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_GETTEXT,
+ lSel,
+ (LPARAM) buf
+ );
+
+ SendDlgItemMessage (hwnd, IDC_LIST1, LB_DELETESTRING, lSel, 0);
+
+ SetDlgItemText (hwnd, IDC_EDIT1, buf);
+ }
+
+ break;
+ }
+ case IDOK:
+ {
+ char buf[32], szServerN[16], szProviderN[16];
+ DWORD i, lCount;
+
+
+ wsprintf(
+ szProviderN,
+ "%s%d",
+ gszProvider,
+ GetWindowLong (hwnd, GWL_USERDATA)
+ );
+
+ lCount = SendDlgItemMessage (hwnd, IDC_LIST1, LB_GETCOUNT, 0, 0);
+
+ RegSetValueEx(
+ hProviderNKey,
+ gszNumServers,
+ 0,
+ REG_DWORD,
+ (LPBYTE) &lCount,
+ sizeof(lCount)
+ );
+
+ for (i = 0; i < lCount; i++)
+ {
+ SendDlgItemMessage(
+ hwnd,
+ IDC_LIST1,
+ LB_GETTEXT,
+ i,
+ (LPARAM) buf
+ );
+
+ wsprintf (szServerN, "%s%d", gszServer, i);
+
+ RegSetValueEx(
+ hProviderNKey,
+ szServerN,
+ 0,
+ REG_SZ,
+ (LPBYTE) buf,
+ lstrlenA (buf) + 1
+ );
+ }
+
+ // fall thru to below
+ }
+ case IDCANCEL:
+
+ RegCloseKey (hProviderNKey);
+ RegCloseKey (hTelephonyKey);
+ EndDialog (hwnd, 0);
+ break;
+
+ } // switch (LOWORD(wParam))
+
+ break;
+
+/* don't want to bring in another lib just yet
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint (hwnd, &ps);
+ FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
+ EndPaint (hwnd, &ps);
+
+ break;
+ } */
+ } // switch (msg)
+
+ return FALSE;
+}
+
+
+LONG
+PASCAL
+ProviderInstall(
+ char *pszProviderName,
+ BOOL bNoMultipleInstance
+ )
+{
+ LONG lResult;
+
+
+ //
+ // If only one installation instance of this provider is
+ // allowed then we want to check the provider list to see
+ // if the provider is already installed
+ //
+
+ if (bNoMultipleInstance)
+ {
+ LONG (WINAPI *pfnGetProviderList)();
+ DWORD dwTotalSize, i;
+ HINSTANCE hTapi32;
+ LPLINEPROVIDERLIST pProviderList;
+ LPLINEPROVIDERENTRY pProviderEntry;
+
+
+ //
+ // Load Tapi32.dll & get a pointer to the lineGetProviderList
+ // func. We don't want to statically link because this module
+ // plays the part of both core SP & UI DLL, and we don't want
+ // to incur the performance hit of automatically loading
+ // Tapi32.dll when running as a core SP within Tapisrv.exe's
+ // context.
+ //
+
+ if (!(hTapi32 = LoadLibrary ("tapi32.dll")))
+ {
+ DBGOUT((
+ 1,
+ "LoadLibrary(tapi32.dll) failed, err=%d",
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+ goto ProviderInstall_return;
+ }
+
+ if (!((FARPROC) pfnGetProviderList = GetProcAddress(
+ hTapi32,
+ (LPCSTR) "lineGetProviderList"
+ )))
+ {
+ DBGOUT((
+ 1,
+ "GetProcAddr(lineGetProviderList) failed, err=%d",
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+ goto ProviderInstall_unloadTapi32;
+ }
+
+
+ //
+ // Loop until we get the full provider list
+ //
+
+ dwTotalSize = sizeof (LINEPROVIDERLIST);
+
+ goto ProviderInstall_allocProviderList;
+
+ProviderInstall_getProviderList:
+
+ if ((lResult = (*pfnGetProviderList)(0x00020000, pProviderList)) != 0)
+ {
+ goto ProviderInstall_freeProviderList;
+ }
+
+ if (pProviderList->dwNeededSize > pProviderList->dwTotalSize)
+ {
+ dwTotalSize = pProviderList->dwNeededSize;
+
+ LocalFree (pProviderList);
+
+ProviderInstall_allocProviderList:
+
+ if (!(pProviderList = LocalAlloc (LPTR, dwTotalSize)))
+ {
+ lResult = LINEERR_NOMEM;
+ goto ProviderInstall_unloadTapi32;
+ }
+
+ pProviderList->dwTotalSize = dwTotalSize;
+
+ goto ProviderInstall_getProviderList;
+ }
+
+
+ //
+ // Inspect the provider list entries to see if this provider
+ // is already installed
+ //
+
+ pProviderEntry = (LPLINEPROVIDERENTRY) (((LPBYTE) pProviderList) +
+ pProviderList->dwProviderListOffset);
+
+ for (i = 0; i < pProviderList->dwNumProviders; i++)
+ {
+ char *pszInstalledProviderName = ((char *) pProviderList) +
+ pProviderEntry->dwProviderFilenameOffset,
+ *p;
+
+
+ //
+ // Make sure pszInstalledProviderName points at <filename>
+ // and not <path>\filename by walking backeards thru the
+ // string searching for last '\\'
+ //
+
+ p = pszInstalledProviderName +
+ lstrlen (pszInstalledProviderName) - 1;
+
+ for (; *p != '\\' && p != pszInstalledProviderName; p--);
+
+ pszInstalledProviderName =
+ (p == pszInstalledProviderName ? p : p + 1);
+
+ if (lstrcmpiA (pszInstalledProviderName, pszProviderName) == 0)
+ {
+ lResult = LINEERR_NOMULTIPLEINSTANCE;
+ goto ProviderInstall_freeProviderList;
+ }
+
+ pProviderEntry++;
+ }
+
+
+ //
+ // If here then the provider isn't currently installed,
+ // so do whatever configuration stuff is necessary and
+ // indicate SUCCESS
+ //
+
+ lResult = 0;
+
+
+ProviderInstall_freeProviderList:
+
+ LocalFree (pProviderList);
+
+ProviderInstall_unloadTapi32:
+
+ FreeLibrary (hTapi32);
+ }
+ else
+ {
+ //
+ // Do whatever configuration stuff is necessary and return SUCCESS
+ //
+
+ lResult = 0;
+ }
+
+ProviderInstall_return:
+
+ return lResult;
+}
diff --git a/private/tapi/dev/sp/remotesp/remotesp.def b/private/tapi/dev/sp/remotesp/remotesp.def
new file mode 100644
index 000000000..f962cad77
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/remotesp.def
@@ -0,0 +1,126 @@
+LIBRARY REMOTESP
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept
+ TSPI_lineAddToConference
+ TSPI_lineAnswer
+ TSPI_lineBlindTransfer
+ TSPI_lineClose
+ TSPI_lineCloseCall
+ TSPI_lineCompleteCall
+ TSPI_lineCompleteTransfer
+ TSPI_lineConditionalMediaDetection
+ TSPI_lineDevSpecific
+ TSPI_lineDevSpecificFeature
+ TSPI_lineDial
+ TSPI_lineDrop
+ TSPI_lineForward
+ TSPI_lineGatherDigits
+ TSPI_lineGenerateDigits
+ TSPI_lineGenerateTone
+ TSPI_lineGetAddressCaps
+ TSPI_lineGetAddressID
+ TSPI_lineGetAddressStatus
+ TSPI_lineGetCallAddressID
+ TSPI_lineGetCallInfo
+ TSPI_lineGetCallStatus
+ TSPI_lineGetDevCaps
+ TSPI_lineGetDevConfig
+ TSPI_lineGetExtensionID
+ TSPI_lineGetIcon
+ TSPI_lineGetID
+ TSPI_lineGetLineDevStatus
+ TSPI_lineGetNumAddressIDs
+ TSPI_lineHold
+ TSPI_lineMakeCall
+ TSPI_lineMonitorDigits
+ TSPI_lineMonitorMedia
+ TSPI_lineMonitorTones
+ TSPI_lineNegotiateExtVersion
+ TSPI_lineNegotiateTSPIVersion
+ TSPI_lineOpen
+ TSPI_linePark
+ TSPI_linePickup
+ TSPI_linePrepareAddToConference
+ TSPI_lineRedirect
+ TSPI_lineRemoveFromConference
+ TSPI_lineSecureCall
+ TSPI_lineSelectExtVersion
+ TSPI_lineSendUserUserInfo
+ TSPI_lineSetAppSpecific
+ TSPI_lineSetCallParams
+ TSPI_lineSetDefaultMediaDetection
+ TSPI_lineSetDevConfig
+ TSPI_lineSetMediaControl
+ TSPI_lineSetMediaMode
+ TSPI_lineSetStatusMessages
+ TSPI_lineSetTerminal
+ TSPI_lineSetupConference
+ TSPI_lineSetupTransfer
+ TSPI_lineSwapHold
+ TSPI_lineUncompleteCall
+ TSPI_lineUnhold
+ TSPI_lineUnpark
+
+ TSPI_phoneClose
+ TSPI_phoneDevSpecific
+ TSPI_phoneGetButtonInfo
+ TSPI_phoneGetData
+ TSPI_phoneGetDevCaps
+ TSPI_phoneGetDisplay
+ TSPI_phoneGetExtensionID
+ TSPI_phoneGetGain
+ TSPI_phoneGetHookSwitch
+ TSPI_phoneGetIcon
+ TSPI_phoneGetID
+ TSPI_phoneGetLamp
+ TSPI_phoneGetRing
+ TSPI_phoneGetStatus
+ TSPI_phoneGetVolume
+ TSPI_phoneNegotiateExtVersion
+ TSPI_phoneNegotiateTSPIVersion
+ TSPI_phoneOpen
+ TSPI_phoneSelectExtVersion
+ TSPI_phoneSetButtonInfo
+ TSPI_phoneSetData
+ TSPI_phoneSetDisplay
+ TSPI_phoneSetGain
+ TSPI_phoneSetHookSwitch
+ TSPI_phoneSetLamp
+ TSPI_phoneSetRing
+ TSPI_phoneSetStatusMessages
+ TSPI_phoneSetVolume
+
+ TSPI_providerConfig
+ TSPI_providerInit
+ TSPI_providerInstall
+ TSPI_providerRemove
+ TSPI_providerShutdown
+
+ TSPI_providerEnumDevices
+ TSPI_providerCreateLineDevice
+ TSPI_providerCreatePhoneDevice
+ TSPI_lineSetCurrentLocation
+ TSPI_lineReleaseUserUserInfo
+
+ TSPI_lineSetCallData
+ TSPI_lineSetCallQualityOfService
+ TSPI_lineSetCallTreatment
+ TSPI_lineSetLineDevStatus
+ TSPI_providerFreeDialogInstance
+ TSPI_providerGenericDialogData
+ TSPI_providerUIIdentify
+
+ TUISPI_lineConfigDialog
+ TUISPI_lineConfigDialogEdit
+ TUISPI_phoneConfigDialog
+ TUISPI_providerConfig
+ TUISPI_providerGenericDialog
+ TUISPI_providerGenericDialogData
+ TUISPI_providerInstall
+ TUISPI_providerRemove
+
+ ConfigDlgProc
diff --git a/private/tapi/dev/sp/remotesp/remotesp.h b/private/tapi/dev/sp/remotesp/remotesp.h
new file mode 100644
index 000000000..31394788d
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/remotesp.h
@@ -0,0 +1,388 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ remotesp.h
+
+Abstract:
+
+ This module contains
+
+Author:
+
+ Dan Knudson (DanKn) dd-Mmm-1995
+
+Revision History:
+
+--*/
+
+#include "windows.h"
+#include "stddef.h"
+#include "stdarg.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "malloc.h"
+#include "string.h"
+#include "tapi.h"
+#include "tspi.h"
+#include "client.h"
+#include "server.h"
+#include "line.h"
+#undef DEVICE_ID
+#include "phone.h"
+#include "tapsrv.h"
+#include "tapi.h"
+#include "tspi.h"
+#include "resource.h"
+
+
+#define NO_DATA 0xffffffff
+
+#define DEF_NUM_LINE_ENTRIES 16
+#define DEF_NUM_PHONE_ENTRIES 16
+
+#define IDI_ICON1 101
+#define IDI_ICON2 102
+#define IDI_ICON3 103
+
+#define DRVLINE_KEY ((DWORD) 'DRVL')
+#define DRVCALL_KEY ((DWORD) 'DRVC')
+#define DRVPHONE_KEY ((DWORD) 'DRVP')
+
+
+typedef struct _DRVSERVER
+{
+ char *pServerName;
+
+ PCONTEXT_HANDLE_TYPE phContext;
+
+ HLINEAPP hLineApp;
+
+ HPHONEAPP hPhoneApp;
+
+ BOOL bDisconnected;
+
+ struct _DRVSERVER *pNext;
+
+} DRVSERVER, *PDRVSERVER;
+
+
+typedef struct _DRVLINE
+{
+ DWORD dwKey;
+
+ PDRVSERVER pServer;
+
+ DWORD dwDeviceIDLocal;
+
+ DWORD dwDeviceIDServer;
+
+ DWORD dwXPIVersion;
+
+ LINEEXTENSIONID ExtensionID;
+
+ HLINE hLine;
+
+ HTAPILINE htLine;
+
+ LPVOID pCalls;
+
+} DRVLINE, *PDRVLINE;
+
+
+typedef struct _DRVCALL
+{
+ DWORD dwKey;
+
+ PDRVSERVER pServer;
+
+ PDRVLINE pLine;
+
+ DWORD dwAddressID;
+
+ HCALL hCall;
+
+ HTAPICALL htCall;
+
+ struct _DRVCALL *pPrev;
+
+ struct _DRVCALL *pNext;
+
+} DRVCALL, *PDRVCALL;
+
+
+typedef struct _DRVPHONE
+{
+ DWORD dwKey;
+
+ PDRVSERVER pServer;
+
+ DWORD dwDeviceIDLocal;
+
+ DWORD dwDeviceIDServer;
+
+ DWORD dwXPIVersion;
+
+ PHONEEXTENSIONID ExtensionID;
+
+ HPHONE hPhone;
+
+ HTAPIPHONE htPhone;
+
+} DRVPHONE, *PDRVPHONE;
+
+
+typedef struct _DRVLINELOOKUP
+{
+ DWORD dwTotalEntries;
+
+ DWORD dwUsedEntries;
+
+ struct _DRVLINELOOKUP *pNext;
+
+ DRVLINE aEntries[1];
+
+} DRVLINELOOKUP, *PDRVLINELOOKUP;
+
+
+typedef struct _DRVPHONELOOKUP
+{
+ DWORD dwTotalEntries;
+
+ DWORD dwUsedEntries;
+
+ struct _DRVPHONELOOKUP *pNext;
+
+ DRVPHONE aEntries[1];
+
+} DRVPHONELOOKUP, *PDRVPHONELOOKUP;
+
+
+typedef enum
+{
+ Dword,
+ LineID,
+ PhoneID,
+ Hdcall,
+ Hdline,
+ Hdphone,
+ lpDword,
+ lpsz,
+ lpGet_SizeToFollow,
+ lpSet_SizeToFollow,
+ lpSet_Struct,
+ lpGet_Struct,
+ Size
+
+} REMOTE_ARG_TYPES, *PREMOTE_ARG_TYPES;
+
+
+typedef struct _REMOTE_FUNC_ARGS
+{
+ DWORD Flags;
+
+ LPDWORD Args;
+
+ PREMOTE_ARG_TYPES ArgTypes;
+
+} REMOTE_FUNC_ARGS, *PREMOTE_FUNC_ARGS;
+
+
+HANDLE ghInst;
+
+char gszServer[] = "Server",
+ gszProvider[] = "Provider",
+ gszNumServers[] = "NumServers",
+ gszTelephonIni[] = "Telephon.ini";
+
+WCHAR gszMachineName[MAX_COMPUTERNAME_LENGTH + 1];
+char gszDomainUser[64];
+
+DWORD gdwLineDeviceIDBase,
+ gdwPhoneDeviceIDBase,
+ gdwInitialNumLineDevices,
+ gdwInitialNumPhoneDevices,
+ gdwTlsIndex,
+ gdwPermanentProviderID,
+ gdwRetryCount,
+ gdwRetryTimeout;
+
+HICON ghLineIcon,
+ ghPhoneIcon;
+
+HANDLE hToken,
+ ghRpcServerThread;
+
+LINEEVENT gpfnLineEventProc;
+PHONEEVENT gpfnPhoneEventProc;
+PDRVSERVER gpServer,
+ gpServers;
+PDRVLINELOOKUP gpLineLookup;
+PDRVPHONELOOKUP gpPhoneLookup;
+
+ASYNC_COMPLETION gpfnCompletionProc;
+
+CRITICAL_SECTION gEventBufferCriticalSection,
+ gCallListCriticalSection;
+
+LONG gaNoMemErrors[3] =
+{
+ 0,
+ LINEERR_NOMEM,
+ PHONEERR_NOMEM
+};
+
+LONG gaOpFailedErrors[3] =
+{
+ 0,
+ LINEERR_OPERATIONFAILED,
+ PHONEERR_OPERATIONFAILED
+};
+
+
+LONG gaServerDisconnectedErrors[3] =
+{
+ 0,
+ LINEERR_NODRIVER,
+ PHONEERR_NODRIVER
+};
+
+struct
+{
+ HANDLE hThread;
+
+ DWORD dwEventBufferTotalSize;
+
+ DWORD dwEventBufferUsedSize;
+
+ LPBYTE pEventBuffer;
+
+ LPBYTE pDataIn;
+
+ LPBYTE pDataOut;
+
+ PASYNCEVENTMSG pMsg;
+
+ DWORD dwMsgSize;
+
+ HANDLE hEvent;
+
+ BOOL bExit;
+
+} gEventHandlerThreadParams;
+
+
+
+
+
+#if DBG
+
+LONG
+WINAPI
+RemoteDoFunc(
+ PREMOTE_FUNC_ARGS pFuncArgs,
+ char *pszFuncName
+ );
+
+#define REMOTEDOFUNC(arg1,arg2) RemoteDoFunc(arg1,arg2)
+
+DWORD gdwDebugLevel = 0;
+
+#define DBGOUT(arg) DbgPrt arg
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+#else
+
+LONG
+WINAPI
+RemoteDoFunc(
+ PREMOTE_FUNC_ARGS pFuncArgs
+ );
+
+#define REMOTEDOFUNC(arg1,arg2) RemoteDoFunc(arg1)
+
+#define DBGOUT(arg)
+
+#endif
+
+
+BOOL
+WINAPI
+_CRT_INIT(
+ HINSTANCE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ );
+
+void
+PASCAL
+TSPI_lineMakeCall_PostProcess(
+ PASYNCEVENTMSG pMsg
+ );
+
+LONG
+AddLine(
+ PDRVSERVER pServer,
+ DWORD dwDeviceIDLocal,
+ DWORD dwDeviceIDServer,
+ BOOL bInit
+ );
+
+LONG
+AddPhone(
+ PDRVSERVER pServer,
+ DWORD dwDeviceIDLocal,
+ DWORD dwDeviceIDServer,
+ BOOL bInit
+ );
+
+LPVOID
+DrvAlloc(
+ DWORD dwSize
+ );
+
+void
+DrvFree(
+ LPVOID p
+ );
+
+LONG
+AddCallToList(
+ PDRVLINE pLine,
+ PDRVCALL pCall
+ );
+
+LONG
+RemoveCallFromList(
+ PDRVCALL pCall
+ );
+
+void
+Shutdown(
+ PDRVSERVER pServer
+ );
+
+
+BOOL
+CALLBACK
+ConfigDlgProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+LONG
+PASCAL
+ProviderInstall(
+ char *pszProviderName,
+ BOOL bNoMultipleInstance
+ );
diff --git a/private/tapi/dev/sp/remotesp/remotesp.ico b/private/tapi/dev/sp/remotesp/remotesp.ico
new file mode 100644
index 000000000..516eb3f84
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/remotesp.ico
Binary files differ
diff --git a/private/tapi/dev/sp/remotesp/remotesp.rc b/private/tapi/dev/sp/remotesp/remotesp.rc
new file mode 100644
index 000000000..d6728ec08
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/remotesp.rc
@@ -0,0 +1,23 @@
+#include "windows.h"
+#include "resource.h"
+#include "dialogs.dlg"
+
+IDI_ICON1 ICON DISCARDABLE "REMOTESP.ICO"
+IDI_ICON2 ICON DISCARDABLE "PHONE.ICO"
+IDI_ICON3 ICON DISCARDABLE "LINE.ICO"
+
+#if TAPI_NT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Remote Service Provider"
+#define VER_INTERNALNAME_STR "remotesp"
+#define VER_ORIGINALFILENAME_STR "REMOTESP.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/remotesp/resource.h b/private/tapi/dev/sp/remotesp/resource.h
new file mode 100644
index 000000000..176b4c1e0
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/resource.h
@@ -0,0 +1,7 @@
+#define IDI_ICON1 101
+#define IDI_ICON2 102
+#define IDI_ICON3 103
+#define IDC_EDIT1 201
+#define IDC_ADD 202
+#define IDC_REMOVE 203
+#define IDC_LIST1 204
diff --git a/private/tapi/dev/sp/remotesp/sources b/private/tapi/dev/sp/remotesp/sources
new file mode 100644
index 000000000..1b0200380
--- /dev/null
+++ b/private/tapi/dev/sp/remotesp/sources
@@ -0,0 +1,58 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=remotesp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=tsp
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib
+
+
+DLLBASE=0x60000000
+
+INCLUDES=.;..\..\client;..\..\server;$(BASEDIR)\public\sdk\inc
+
+SOURCES=remotesp.c \
+ tapsrv_c.c \
+ rmotsp_s.c \
+ remotesp.rc
+
+C_DEFINES=-DTAPI_NT=1
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/repeater/app/makefile b/private/tapi/dev/sp/repeater/app/makefile
new file mode 100644
index 000000000..f1084966b
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/app/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# Dialer.exe Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/repeater/app/repapp.c b/private/tapi/dev/sp/repeater/app/repapp.c
new file mode 100644
index 000000000..0c8f7a862
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/app/repapp.c
@@ -0,0 +1,1093 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <windows.h>
+#include <stdio.h>
+#include <commdlg.h>
+#include "resource.h"
+#include "..\new\logger.h"
+//////////////////////////////////////////////////////////////////////////////
+// PROTOTYPES
+//////////////////////////////////////////////////////////////////////////////
+static BOOL CreateMainWindow (int nCmdShow);
+
+static LRESULT CALLBACK MainWndProc (HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+BOOL LogFileNameProc();
+BOOL DoStructKey();
+BOOL DoPostKey();
+BOOL DoPreKey();
+void WriteToListBox(LPSTR lpszText, ...);
+BOOL ReadInLogFile();
+BOOL OpenLogFile();
+BOOL ReadKey(LPDWORD lpdwKey);
+
+//////////////////////////////////////////////////////////////////////////////
+// GLOBALS
+//////////////////////////////////////////////////////////////////////////////
+HINSTANCE ghInstance;
+HWND ghMainWnd;
+HWND ghListWnd;
+char gszLogFileName[MAX_PATH];
+HANDLE ghLogFile;
+
+LPSTR glpszFunctions[] =
+{
+ "TSPI_lineAccept",
+ "TSPI_lineAddToConference",
+ "TSPI_lineAgentSpecific",
+ "TSPI_lineAnswer",
+ "TSPI_lineBlindTransfer",
+ "TSPI_lineClose",
+ "TSPI_lineCloseCall",
+ "TSPI_lineCompleteCall",
+ "TSPI_lineCompleteTransfer",
+ "TSPI_lineConditionalMediaDetection",
+ "TSPI_lineDevSpecific",
+ "TSPI_lineDevSpecificFeature",
+ "TSPI_lineDial",
+ "TSPI_lineDrop",
+ "TSPI_lineForward",
+ "TSPI_lineGatherDigits",
+ "TSPI_lineGenerateDigits",
+ "TSPI_lineGenerateTone",
+ "TSPI_lineGetAddressCaps",
+ "TSPI_lineGetAddressID",
+ "TSPI_lineGetAddressStatus",
+ "TSPI_lineGetAgentActivityList",
+ "TSPI_lineGetAgentCaps",
+ "TSPI_lineGetAgentGroupList",
+ "TSPI_lineGetAgentStatus",
+ "TSPI_lineGetCallAddressID",
+ "TSPI_lineGetCallInfo",
+ "TSPI_lineGetCallStatus",
+ "TSPI_lineGetDevCaps",
+ "TSPI_lineGetDevConfig",
+ "TSPI_lineGetExtensionID",
+ "TSPI_lineGetIcon",
+ "TSPI_lineGetID",
+ "TSPI_lineGetLineDevStatus",
+ "TSPI_lineGetNumAddressIDs",
+ "TSPI_lineHold",
+ "TSPI_lineMakeCall",
+ "TSPI_lineMonitorDigits",
+ "TSPI_lineMonitorMedia",
+ "TSPI_lineMonitorTones",
+ "TSPI_lineNegotiateExtVersion",
+ "TSPI_lineNegotiateTSPIVersion",
+ "TSPI_lineOpen",
+ "TSPI_linePark",
+ "TSPI_linePickup",
+ "TSPI_linePrepareAddToConference",
+ "TSPI_lineRedirect",
+ "TSPI_lineReleaseUserUserInfo",
+ "TSPI_lineRemoveFromConference",
+ "TSPI_lineSecureCall",
+ "TSPI_lineSelectExtVersion",
+ "TSPI_lineSendUserUserInfo",
+ "TSPI_lineSetAgentActivity",
+ "TSPI_lineSetAgentGroup",
+ "TSPI_lineSetAgentState",
+ "TSPI_lineSetAppSpecific",
+ "TSPI_lineSetCallData",
+ "TSPI_lineSetCallParams",
+ "TSPI_lineSetCallQualityOfService",
+ "TSPI_lineSetCallTreatment",
+ "TSPI_lineSetCurrentLocation",
+ "TSPI_lineSetDefaultMediaDetection",
+ "TSPI_lineSetDevConfig",
+ "TSPI_lineSetLineDevStatus",
+ "TSPI_lineSetMediaControl",
+ "TSPI_lineSetMediaMode",
+ "TSPI_lineSetStatusMessages",
+ "TSPI_lineSetTerminal",
+ "TSPI_lineSetupConference",
+ "TSPI_lineSetupTransfer",
+ "TSPI_lineSwapHold",
+ "TSPI_lineUncompleteCall",
+ "TSPI_lineUnhold",
+ "TSPI_lineUnpark",
+ "TSPI_phoneClose",
+ "TSPI_phoneDevSpecific",
+ "TSPI_phoneGetButtonInfo",
+ "TSPI_phoneGetData",
+ "TSPI_phoneGetDevCaps",
+ "TSPI_phoneGetDisplay",
+ "TSPI_phoneGetExtensionID",
+ "TSPI_phoneGetGain",
+ "TSPI_phoneGetHookSwitch",
+ "TSPI_phoneGetIcon",
+ "TSPI_phoneGetID",
+ "TSPI_phoneGetLamp",
+ "TSPI_phoneGetRing",
+ "TSPI_phoneGetStatus",
+ "TSPI_phoneGetVolume",
+ "TSPI_phoneNegotiateExtVersion",
+ "TSPI_phoneNegotiateTSPIVersion",
+ "TSPI_phoneOpen",
+ "TSPI_phoneSelectExtVersion",
+ "TSPI_phoneSetButtonInfo",
+ "TSPI_phoneSetData",
+ "TSPI_phoneSetDisplay",
+ "TSPI_phoneSetGain",
+ "TSPI_phoneSetHookSwitch",
+ "TSPI_phoneSetLamp",
+ "TSPI_phoneSetRing",
+ "TSPI_phoneSetStatusMessages",
+ "TSPI_phoneSetVolume",
+ "TSPI_providerCreateLineDevice",
+ "TSPI_providerCreatePhoneDevice",
+ "TSPI_providerEnumDevices",
+ "TSPI_providerFreeDialogInstance",
+ "TSPI_providerGenericDialogData",
+ "TSPI_providerInit",
+ "TSPI_providerShutdown",
+ "TSPI_providerUIIdentify",
+ NULL
+};
+
+LPSTR glpszMessages[] =
+{
+ "LINE_ADDRESSSTATE",
+ "LINE_CALLINFO",
+ "LINE_CALLSTATE",
+ "LINE_CLOSE",
+ "LINE_DEVSPECIFIC",
+ "LINE_DEVSPECIFICFEATURE",
+ "LINE_GATHERDIGITS",
+ "LINE_GENERATE",
+ "LINE_LINEDEVSTATE",
+ "LINE_MONITORDIGITS",
+ "LINE_MONITORMEDIA",
+ "LINE_MONITORTONE",
+ "LINE_REPLY",
+ "LINE_REQUEST",
+ "PHONE_BUTTON",
+ "PHONE_CLOSE",
+ "PHONE_DEVSPECIFIC",
+ "PHONE_REPLY",
+ "PHONE_STATE",
+ "LINE_CREATE",
+ "PHONE_CREATE",
+ "LINE_AGENTSPECIFIC",
+ "LINE_AGENTSTATUS",
+ "LINE_APPNEWCALL",
+ "LINE_PROXYREQUEST",
+ "LINE_REMOVE",
+ "PHONE_REMOVE"
+};
+
+LPSTR glpszMessages500[] =
+{
+ "LINE_NEWCALL",
+ "LINE_CALLDEVSPECIFIC",
+ "LINE_CALLDEVSPECIFICFEATURE",
+ "LINE_CREATEDIALOGINSTANCE",
+ "LINE_SENDDIALOGINSTANCEDATA"
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// WinMain()
+//
+//////////////////////////////////////////////////////////////////////////////
+
+int WINAPI WinMain (HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine,
+ int nCmdShow)
+{
+ MSG msg;
+
+ ghInstance = hInstance;
+
+ if (!CreateMainWindow(nCmdShow))
+ {
+ return 0;
+ }
+
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return 1;
+}
+
+
+//*****************************************************************************
+// CreateMainWindow()
+//*****************************************************************************
+
+BOOL CreateMainWindow (int nCmdShow)
+{
+ WNDCLASS wc;
+ static char szClassName[] = "TapiClientWndClass";
+
+ wc.style = 0;
+ wc.lpfnWndProc = MainWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = ghInstance;
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wc.lpszMenuName = MAKEINTRESOURCE(IDR_REPAPPMENU);
+ wc.lpszClassName = szClassName;
+
+
+ if (!RegisterClass(&wc))
+ {
+ return FALSE;
+ }
+
+ ghMainWnd = CreateWindow(szClassName,
+ "Repeater Log App",
+ WS_OVERLAPPEDWINDOW,
+ 0,
+ 0,
+ GetSystemMetrics(SM_CXSCREEN)/2,
+ GetSystemMetrics(SM_CYSCREEN)/2,
+ NULL,
+ NULL,
+ ghInstance,
+ NULL);
+
+ ghListWnd = CreateWindow("LISTBOX",
+ NULL,
+ WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_USETABSTOPS,
+ 0,
+ 0,
+ 0,
+ 0,
+ ghMainWnd,
+ NULL,
+ ghInstance,
+ NULL);
+
+ if (ghListWnd == NULL)
+ {
+ return FALSE;
+ }
+
+
+ if (ghMainWnd == NULL)
+ {
+ return FALSE;
+ }
+
+ ShowWindow(ghMainWnd, nCmdShow);
+ UpdateWindow(ghMainWnd);
+ return TRUE;
+}
+
+
+//*****************************************************************************
+// MainWndProc()
+//*****************************************************************************
+
+LRESULT CALLBACK MainWndProc (HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_SIZE:
+ {
+ RECT rc;
+
+ GetClientRect(hwnd,
+ &rc);
+
+ MoveWindow(ghListWnd,
+ 0, 0,
+ rc.right,
+ rc.bottom,
+ TRUE);
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ if (LOWORD(wParam) == ID_FILE_EXIT)
+ {
+ DestroyWindow(hwnd);
+ break;
+ }
+
+ if (LOWORD(wParam) == ID_FILE_LOGFILENAME)
+ {
+ if (LogFileNameProc())
+ {
+ SendMessage(ghListWnd,
+ LB_RESETCONTENT,
+ 0,
+ 0);
+
+ ReadInLogFile();
+ }
+
+ break;
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+ default:
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+ return 0;
+}
+
+BOOL LogFileNameProc()
+{
+ OPENFILENAME ofn;
+ BOOL bReturn;
+
+ gszLogFileName[0] = '\0';
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = ghMainWnd;
+ ofn.hInstance = ghInstance;
+ ofn.lpstrFilter = "Log Files\0*.log\0\0";
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = gszLogFileName;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrTitle =NULL;
+ ofn.Flags = OFN_FILEMUSTEXIST;
+ ofn.nFileOffset = 0;
+ ofn.nFileExtension = 0;
+ ofn.lpstrDefExt = "LOG";
+ ofn.lCustData = 0;
+ ofn.lpfnHook = NULL;
+ ofn.lpTemplateName = NULL;
+
+ bReturn = GetOpenFileName(&ofn);
+
+ return bReturn;
+}
+
+BOOL ReadInLogFile()
+{
+ DWORD dwKey;
+
+ if (!OpenLogFile())
+ {
+ MessageBox(NULL,
+ "Couldn't open file",
+ NULL,
+ MB_OK);
+
+ return FALSE;
+ }
+
+ while (TRUE)
+ {
+ if (!ReadKey(&dwKey))
+ {
+// MessageBox(NULL,
+// "Couldn't readkey",
+// NULL,
+// MB_OK);
+ break;
+ }
+
+ else if (dwKey == DWPREKEY)
+ {
+ if (!DoPreKey())
+ {
+// MessageBox(NULL,
+// "Couldn't do pre key",
+// NULL,
+// MB_OK);
+
+ break;
+ }
+ }
+
+ else if (dwKey == DWPOSTKEY)
+ {
+ if (!DoPostKey())
+ {
+// MessageBox(NULL,
+// "Couldn't do post key",
+// NULL,
+// MB_OK);
+
+ break;
+ }
+ }
+
+ else if (dwKey == DWSTRCKEY)
+ {
+ if (!DoStructKey())
+ {
+// MessageBox(NULL,
+// "Couldn't do struct key",
+// NULL,
+// MB_OK);
+
+ break;
+ }
+ }
+
+ else
+ {
+ MessageBox(NULL,
+ "Error reading in log file",
+ NULL,
+ MB_OK);
+ break;
+ }
+ } // while
+
+ return TRUE;
+}
+
+BOOL OpenLogFile()
+{
+ ghLogFile = CreateFile(gszLogFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ, //0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (ghLogFile == INVALID_HANDLE_VALUE)
+ {
+ return FALSE;
+ }
+
+ SetFilePointer(ghLogFile,
+ 0,
+ NULL,
+ FILE_BEGIN);
+
+ return TRUE;
+}
+
+BOOL ReadKey(LPDWORD lpdwKey)
+{
+ DWORD dwSize;
+
+ if (!ReadFile(ghLogFile,
+ lpdwKey,
+ sizeof(DWORD),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ SetFilePointer(ghLogFile,
+ 0-dwSize,
+ NULL,
+ FILE_CURRENT);
+
+ return TRUE;
+}
+
+BOOL DoPreKey()
+{
+ PREHEADER PreHeader;
+ DWORD dwSize;
+
+ if (!ReadFile(ghLogFile,
+ &PreHeader,
+ sizeof(PreHeader),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+
+ if (dwSize != sizeof(PreHeader))
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("PreHeader - Time: %lu Type: %lu",
+ PreHeader.dwTime,
+ PreHeader.dwType);
+
+ switch(PreHeader.dwType)
+ {
+ case LINEMSG:
+ {
+ LINEMSGSTRUCT LineMsg;
+ LPSTR lpszMsg;
+
+ if (!ReadFile(ghLogFile,
+ &LineMsg,
+ sizeof(LineMsg),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ if (LineMsg.dwMsg < 500)
+ {
+ lpszMsg = glpszMessages[LineMsg.dwMsg];
+ }
+ else
+ {
+ lpszMsg = glpszMessages500[LineMsg.dwMsg-500];
+ }
+
+ WriteToListBox("\tLine Message: %s",
+ lpszMsg);
+ WriteToListBox("\t\thtLine: %lx, htCall: %lx",
+ LineMsg.htLine,
+ LineMsg.htCall);
+ WriteToListBox("\t\tdwParam1: %lx, dwParam2: %lx, dwParam3: %lx",
+ LineMsg.dw1,
+ LineMsg.dw2,
+ LineMsg.dw3);
+
+ break;
+ }
+
+ case PHONEMSG:
+ {
+ PHONEMSGSTRUCT PhoneMsg;
+ LPSTR lpszMsg;
+
+ if (!ReadFile(ghLogFile,
+ &PhoneMsg,
+ sizeof(PhoneMsg),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+
+ if (PhoneMsg.dwMsg < 500)
+ {
+ lpszMsg = glpszMessages[PhoneMsg.dwMsg];
+ }
+ else
+ {
+ lpszMsg = glpszMessages500[PhoneMsg.dwMsg-500];
+ }
+
+
+ WriteToListBox("\tPhone Message: %s",
+ lpszMsg);
+ WriteToListBox("\t\thtPhone: %lx",
+ PhoneMsg.htPhone);
+ WriteToListBox("\t\tdwParam1: %lx, dwParam2: %lx, dwParam3: %lx",
+ PhoneMsg.dw1,
+ PhoneMsg.dw2,
+ PhoneMsg.dw3);
+
+ break;
+ }
+
+ case ASYNCMSG:
+ {
+ ASYNCSTRUCT AsyncMsg;
+
+ if (!ReadFile(ghLogFile,
+ &AsyncMsg,
+ sizeof(AsyncMsg),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+
+ WriteToListBox("\tAsync Message - dwRequestID: %lx, lResult: %lx",
+ AsyncMsg.dwRequestID,
+ AsyncMsg.lResult);
+
+ break;
+ }
+
+ case SPFUNC1:
+ {
+ LOGSPFUNC1 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ break;
+ }
+
+ case SPFUNC2:
+ {
+ LOGSPFUNC2 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+
+ break;
+ }
+ case SPFUNC3:
+ {
+ LOGSPFUNC3 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+
+ break;
+ }
+
+ case SPFUNC4:
+ {
+ LOGSPFUNC4 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+ WriteToListBox("\tParam4: %lx",
+ LogStruct.dwParam4);
+
+ break;
+ }
+
+ case SPFUNC5:
+ {
+ LOGSPFUNC5 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+ WriteToListBox("\tParam4: %lx",
+ LogStruct.dwParam4);
+ WriteToListBox("\tParam5: %lx",
+ LogStruct.dwParam5);
+
+ break;
+ }
+
+ case SPFUNC6:
+ {
+ LOGSPFUNC6 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+ WriteToListBox("\tParam4: %lx",
+ LogStruct.dwParam4);
+ WriteToListBox("\tParam5: %lx",
+ LogStruct.dwParam5);
+ WriteToListBox("\tParam6: %lx",
+ LogStruct.dwParam6);
+
+ break;
+ }
+
+ case SPFUNC7:
+ {
+ LOGSPFUNC7 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+ WriteToListBox("\tParam4: %lx",
+ LogStruct.dwParam4);
+ WriteToListBox("\tParam5: %lx",
+ LogStruct.dwParam5);
+ WriteToListBox("\tParam6: %lx",
+ LogStruct.dwParam6);
+ WriteToListBox("\tParam7: %lx",
+ LogStruct.dwParam7);
+
+ break;
+ }
+
+ case SPFUNC8:
+ {
+ LOGSPFUNC8 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+ WriteToListBox("\tParam4: %lx",
+ LogStruct.dwParam4);
+ WriteToListBox("\tParam5: %lx",
+ LogStruct.dwParam5);
+ WriteToListBox("\tParam6: %lx",
+ LogStruct.dwParam6);
+ WriteToListBox("\tParam7: %lx",
+ LogStruct.dwParam7);
+ WriteToListBox("\tParam8: %lx",
+ LogStruct.dwParam8);
+
+ break;
+ }
+
+ case SPFUNC9:
+ {
+ LOGSPFUNC9 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+ WriteToListBox("\tParam4: %lx",
+ LogStruct.dwParam4);
+ WriteToListBox("\tParam5: %lx",
+ LogStruct.dwParam5);
+ WriteToListBox("\tParam6: %lx",
+ LogStruct.dwParam6);
+ WriteToListBox("\tParam7: %lx",
+ LogStruct.dwParam7);
+ WriteToListBox("\tParam8: %lx",
+ LogStruct.dwParam8);
+ WriteToListBox("\tParam9: %lx",
+ LogStruct.dwParam9);
+
+ break;
+ }
+
+ case SPFUNC12:
+ {
+ LOGSPFUNC12 LogStruct;
+
+ if (!ReadFile(ghLogFile,
+ &LogStruct,
+ sizeof(LogStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+
+ WriteToListBox("\tFunction: %s",
+ glpszFunctions[LogStruct.dwSPFUNC]);
+ WriteToListBox("\tParam1: %lx",
+ LogStruct.dwParam1);
+ WriteToListBox("\tParam2: %lx",
+ LogStruct.dwParam2);
+ WriteToListBox("\tParam3: %lx",
+ LogStruct.dwParam3);
+ WriteToListBox("\tParam4: %lx",
+ LogStruct.dwParam4);
+ WriteToListBox("\tParam5: %lx",
+ LogStruct.dwParam5);
+ WriteToListBox("\tParam6: %lx",
+ LogStruct.dwParam6);
+ WriteToListBox("\tParam7: %lx",
+ LogStruct.dwParam7);
+ WriteToListBox("\tParam8: %lx",
+ LogStruct.dwParam8);
+ WriteToListBox("\tParam9: %lx",
+ LogStruct.dwParam9);
+ WriteToListBox("\tParam11: %lx",
+ LogStruct.dwParam10);
+ WriteToListBox("\tParam11: %lx",
+ LogStruct.dwParam11);
+ WriteToListBox("\tParam12: %lx",
+ LogStruct.dwParam12);
+
+ break;
+ }
+
+ } // switch
+
+ return TRUE;
+
+}
+
+BOOL DoPostKey()
+{
+ POSTSTRUCT PostStruct;
+ DWORD dwSize;
+
+ if (!ReadFile(ghLogFile,
+ &PostStruct,
+ sizeof(PostStruct),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ WriteToListBox("Post Struct - dwTime: %lu, lReturn: %lx",
+ PostStruct.dwTime,
+ PostStruct.lReturn);
+
+ return TRUE;
+}
+
+BOOL DoStructKey()
+{
+ STRUCTHEADER StructHeader;
+ DWORD dwSize;
+ LPVOID pBuffer;
+
+ if (!ReadFile(ghLogFile,
+ &StructHeader,
+ sizeof(StructHeader),
+ &dwSize,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+
+ WriteToListBox("Struct Header - dwSize: %lu, dwID: %lx",
+ StructHeader.dwSize,
+ StructHeader.dwID);
+
+ if (StructHeader.dwSize == 0)
+ {
+ return TRUE;
+ }
+
+ pBuffer = GlobalAlloc(GPTR, StructHeader.dwSize);
+
+ // read in structure, but don't do anything with it for now
+ if (!ReadFile(ghLogFile,
+ pBuffer,
+ StructHeader.dwSize,
+ &dwSize,
+ NULL))
+ {
+ GlobalFree(pBuffer);
+ return FALSE;
+ }
+ if (dwSize == 0)
+ {
+ return FALSE;
+ }
+
+ GlobalFree(pBuffer);
+
+ return TRUE;
+}
+
+void WriteToListBox(LPSTR lpszText, ...)
+{
+ char szBuffer[1024];
+ va_list list;
+
+ va_start(list,lpszText);
+
+ vsprintf(szBuffer,lpszText,list);
+
+ SendMessage(ghListWnd,
+ LB_ADDSTRING,
+ 0,
+ (LPARAM)szBuffer);
+}
+
diff --git a/private/tapi/dev/sp/repeater/app/repapp.rc b/private/tapi/dev/sp/repeater/app/repapp.rc
new file mode 100644
index 000000000..25619c74a
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/app/repapp.rc
@@ -0,0 +1,37 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_REPAPPMENU MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Log File Name", ID_FILE_LOGFILENAME
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_FILE_EXIT
+ END
+END
+
+
+
+#if WINNT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Telephony API Repeater Log File Reader"
+#define VER_INTERNALNAME_STR "REPAPP"
+#define VER_ORIGINALFILENAME_STR "REPAPP.EXE"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1996. All Rights Reserved."
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/repeater/app/resource.h b/private/tapi/dev/sp/repeater/app/resource.h
new file mode 100644
index 000000000..7bd879f3b
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/app/resource.h
@@ -0,0 +1,22 @@
+#include <windows.h>
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by repapp.rc
+//
+#define IDD_LOGFILENAME 101
+#define IDR_REPAPPMENU 102
+#define IDC_LOGFILENAME 1000
+#define ID_FILE_LOGFILENAME 40001
+#define ID_FILE_EXIT 40002
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40003
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/private/tapi/dev/sp/repeater/app/sources b/private/tapi/dev/sp/repeater/app/sources
new file mode 100644
index 000000000..24be8c8f2
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/app/sources
@@ -0,0 +1,56 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+Notes:
+
+ Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=repapp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=PROGRAM
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\tapi32l.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+USE_CRTDLL=1
+
+SOURCES=repapp.rc \
+ repapp.c
+
+C_DEFINES=-DWINVER=0x0400
+
+UMTYPE=windows
+
+UMENTRY=winmain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/repeater/dirs b/private/tapi/dev/sp/repeater/dirs
new file mode 100644
index 000000000..57bb36ac0
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/dirs
@@ -0,0 +1,4 @@
+DIRS=\
+ new \
+ app \
+ setup
diff --git a/private/tapi/dev/sp/repeater/new/debug.c b/private/tapi/dev/sp/repeater/new/debug.c
new file mode 100644
index 000000000..a5fc2c9b9
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/debug.c
@@ -0,0 +1,180 @@
+//
+//
+
+#if DBG
+
+
+#include <windows.h>
+#include <windowsx.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <tapi.h>
+#include "debug.h"
+
+
+
+extern const char far szINIfilename[];
+
+DWORD gdwDebugLevel;
+
+
+static char szNewBuff[256];
+
+
+DWORD RepeaterDebugLevel = 0;
+static fRepeaterDebugLevelValid = FALSE;
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+
+{
+ static char buf[128] = "Repeater: ";
+
+
+ if (!fRepeaterDebugLevelValid)
+ {
+RepeaterDebugLevel = 0;
+/*
+ RepeaterDebugLevel = GetPrivateProfileInt( "Debug",
+ "RepeaterDebugLevel",
+ 0,
+ szINIfilename );
+*/
+ RepeaterDebugLevel = 99;
+
+ if ( RepeaterDebugLevel > 0 )
+ {
+ wsprintf(
+ &buf[10],
+ "RepeaterDebugLevel= %d\n\r",
+ RepeaterDebugLevel);
+
+ OutputDebugString((LPSTR)buf);
+
+
+ fRepeaterDebugLevelValid = TRUE;
+ }
+
+ }
+
+
+ //
+ // Is the message otherwise "low" enough to display?
+ //
+ if (dwDbgLevel <= RepeaterDebugLevel)
+ {
+ char buf[128] = "Repeater: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ wvsprintf (&buf[10],
+ lpszFormat,
+ ap
+ );
+
+ lstrcat (buf, "\n");
+
+ OutputDebugString(buf);
+
+ va_end(ap);
+ }
+
+ return;
+}
+
+
+
+
+
+
+//VOID
+//DbgPrt(
+// IN DWORD dwDbgLevel,
+// IN PUCHAR lpszFormat,
+// IN ...
+// )
+///*++
+//
+//Routine Description:
+//
+// Formats the incoming debug message & calls DbgPrint
+//
+//Arguments:
+//
+// DbgLevel - level of message verboseness
+//
+// DbgMessage - printf-style format string, followed by appropriate
+// list of arguments
+//
+//Return Value:
+//
+//
+//--*/
+//{
+//
+// static BOOL fAlreadyGotIt = FALSE;
+// static char buf[128] = "TAPI CPL: ";
+//#define TEXT_START 10
+//
+// if (!fAlreadyGotIt)
+// {
+//
+// gdwDebugLevel = (DWORD) GetPrivateProfileInt(
+// "Debug",
+// "Repeater32DebugLevel",
+// 0x0,
+// "Telephon.ini"
+// );
+//
+// fAlreadyGotIt = TRUE;
+//
+// wsprintf(&buf[TEXT_START], "Repeater32DebugLevel=%d \r\n", gdwDebugLevel);
+// OutputDebugStringA(buf);
+// }
+//
+//
+// if (dwDbgLevel <= gdwDebugLevel)
+// {
+// va_list ap;
+//
+//
+// va_start(ap, lpszFormat);
+//
+// vsprintf (&buf[TEXT_START],
+// lpszFormat,
+// ap
+// );
+//
+// lstrcat (buf, "\n");
+//
+// OutputDebugStringA (buf);
+//
+// va_end(ap);
+// }
+//}
+//
+
+#endif
diff --git a/private/tapi/dev/sp/repeater/new/debug.h b/private/tapi/dev/sp/repeater/new/debug.h
new file mode 100644
index 000000000..11abf22ec
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/debug.h
@@ -0,0 +1,25 @@
+#if DBG
+
+
+#if !WIN32
+#define IN
+#define PUCHAR char *
+#endif
+
+
+
+#define DBGOUT(arg) DbgPrt arg
+
+extern VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
diff --git a/private/tapi/dev/sp/repeater/new/depend.mk b/private/tapi/dev/sp/repeater/new/depend.mk
new file mode 100644
index 000000000..7f4b4291c
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/depend.mk
@@ -0,0 +1,7 @@
+.\logger.obj: ..\logger.c ..\logger.h ..\debug.h
+
+.\Repeater.obj: ..\Repeater.c ..\Repeater.h ..\debug.h
+
+.\debug.obj: ..\debug.c ..\debug.h
+
+.\Repeater.res: ..\Repeater.rc
diff --git a/private/tapi/dev/sp/repeater/new/logger.c b/private/tapi/dev/sp/repeater/new/logger.c
new file mode 100644
index 000000000..1f145c143
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/logger.c
@@ -0,0 +1,945 @@
+#define STRICT
+
+#include <windows.h>
+#include <windowsx.h>
+#include <tspi.h>
+#ifndef WIN32
+#include <memory.h>
+#endif
+#include "logger.h"
+#include "debug.h"
+
+#ifndef TCHAR
+#define TCHAR char
+#endif
+
+#if ! defined(TEXT)
+#define TEXT(string) string
+#endif
+
+#ifndef LPCWSTR
+#define LPCWSTR LPCSTR
+#endif
+
+extern BOOL gfTerminateNow;
+DWORD gdwTotalBlocks;
+DWORD gdwID = 0;
+CHUNK gChunks[MAXCHUNKS];
+
+typedef struct tagLOGSTRUCT
+{
+ int iSize;
+ struct tagLOGSTRUCT* pNext;
+
+} LOGSTRUCT, * PLOGSTRUCT;
+
+
+#ifdef WIN32
+PLOGSTRUCT gpBegin = NULL, gpEnd = NULL;
+CRITICAL_SECTION gcsLogging;
+CRITICAL_SECTION gcsID;
+#endif
+
+#ifdef WIN32
+HANDLE ghLogFile = NULL;
+#else
+HFILE ghLogFile = NULL;
+#endif
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+#ifndef WIN32
+char gszFileName[MAX_PATH];
+#endif
+
+BOOL InitLogging();
+void WriteData();
+BOOL CopyIDToList(int iCount, LPVOID pBuffer);
+
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+#ifdef WIN32
+
+DWORD WINAPI LoggingThread( LPVOID pThreadParm )
+{
+
+ DBGOUT((3, "Entering LoggingThread"));
+
+ while ( !gfTerminateNow )
+ {
+
+ if (NULL != gpBegin)
+ {
+ WriteData();
+ }
+
+ Sleep(0);
+
+ }
+
+ DBGOUT((3, "Closing File Handle"));
+
+ CloseHandle(ghLogFile);
+
+ DBGOUT((3, "Exiting thread"));
+
+ ExitThread(0);
+ return 0;
+}
+#endif //WIN32
+
+#if 0
+#ifdef WIN32
+void CopyData(LPVOID pBuffer, int iCount)
+{
+ PLOGSTRUCT pNew;
+
+ // if we have a lot of stuff to write, hold up here and
+ // wait until we've written a bunch
+ if (gdwTotalBlocks > MAXCHUNKS)
+ {
+ while (gdwTotalBlocks > MINCHUNKS)
+ {
+ Sleep(0);
+ }
+ }
+
+ pNew = (PLOGSTRUCT)GlobalAlloc(GPTR, iCount+sizeof(LOGSTRUCT));
+
+ pNew->pNext = NULL;
+ pNew->iSize = iCount;
+
+ memcpy(pNew+1, pBuffer, iCount);
+
+ EnterCriticalSection(&gcsLogging);
+ if (gpBegin == NULL)
+ {
+ gpBegin = pNew;
+ }
+ else
+ {
+ gpEnd->pNext = pNew;
+ }
+
+ gpEnd = pNew;
+ LeaveCriticalSection(&gcsLogging);
+
+ gdwTotalBlocks++;
+
+}
+
+#else
+void CopyData(LPVOID pBuffer, int iCount)
+{
+ OFSTRUCT ofstruct;
+
+ ofstruct.cBytes = sizeof(ofstruct);
+
+ ghLogFile = OpenFile(gszFileName,
+ &ofstruct,
+ OF_READWRITE);
+
+ if (ghLogFile == HFILE_ERROR)
+ {
+ DBGOUT((3,"OpenFile failed"));
+ return;
+ }
+
+ _llseek(ghLogFile,
+ 0,
+ 2);
+
+ if (_lwrite(ghLogFile,
+ pBuffer,
+ iCount) == HFILE_ERROR)
+ {
+ char szbuf[128];
+
+ wsprintf(szbuf, "icount %d", iCount);
+ MessageBox(NULL, szbuf, NULL, MB_OK);
+ MessageBox(NULL, "writefile error", NULL, MB_OK);
+ }
+
+ _lclose(ghLogFile);
+}
+#endif
+
+#endif // 0
+
+#ifdef WIN32
+void WriteData()
+{
+ PLOGSTRUCT pHold;
+ DWORD dwNumBytes;
+
+ while (gpBegin != NULL)
+ {
+ WriteFile(ghLogFile,
+ (LPCVOID)(gpBegin+1),
+ gpBegin->iSize,
+ &dwNumBytes,
+ NULL);
+
+ if (dwNumBytes != (DWORD)(gpBegin->iSize))
+ {
+ //bugbug do something
+ }
+
+ EnterCriticalSection(&gcsLogging);
+
+ pHold = gpBegin;
+
+ gpBegin = gpBegin->pNext;
+
+ LeaveCriticalSection(&gcsLogging);
+
+ GlobalFree(pHold);
+
+ gdwTotalBlocks--;
+ }
+
+}
+#endif
+#define SZFILEBASE "rep"
+#define SZFILEEXT ".log"
+#define SZREPEATERKEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Repeater"
+#define SZLOGFILE "LogFileDirectory"
+#define SZREPEATER "Repeater"
+#define SZTELEPHONINI "telephon.ini"
+
+BOOL InitLogging()
+{
+ TCHAR szFileName[MAX_PATH];
+ TCHAR szFilePath[MAX_PATH];
+ int i = 0;
+#ifdef WIN32
+ HKEY hRepeaterKey;
+ DWORD dwSize;
+#else
+ OFSTRUCT ofstruct;
+#endif
+
+ DBGOUT((3, "Entering InitLogging"));
+
+#ifdef WIN32
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ SZREPEATERKEY,
+ 0,
+ KEY_ALL_ACCESS,
+ &hRepeaterKey);
+
+ dwSize = MAX_PATH;
+ RegQueryValueEx(hRepeaterKey,
+ SZLOGFILE,
+ NULL,
+ NULL,
+ szFilePath,
+ &dwSize);
+
+ RegCloseKey(hRepeaterKey);
+#else
+ GetPrivateProfileString(SZREPEATER,
+ SZLOGFILE,
+ "",
+ szFilePath,
+ MAX_PATH,
+ SZTELEPHONINI);
+#endif
+
+
+ gdwTotalBlocks = 0;
+
+ while (TRUE)
+ {
+#ifdef WIN32
+ HANDLE hFile;
+ WIN32_FIND_DATA FindData;
+
+ wsprintf(szFileName,
+ "%s%s%d%s",
+ szFilePath,
+ SZFILEBASE,
+ i,
+ SZFILEEXT);
+
+ /*
+ ghLogFile = CreateFile(szFileName,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (ghLogFile == INVALID_HANDLE_VALUE)
+ {
+ break;
+ }
+
+ CloseHandle(ghLogFile);*/
+
+ hFile = FindFirstFile(szFileName,
+ &FindData);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ break;
+ }
+
+ FindClose(hFile);
+
+// CloseHandle(hFile);
+
+#else
+ ofstruct.cBytes = sizeof(ofstruct);
+
+ ghLogFile = OpenFile(szFileName,
+ &ofstruct,
+ OF_EXIST);
+
+ if (ghLogFile == HFILE_ERROR)
+ {
+ break;
+ }
+
+ _lclose(ghLogFile);
+#endif
+
+ i++;
+ }
+
+#ifdef WIN32
+
+ DBGOUT((3, "log file name is %s", szFileName));
+ ghLogFile = CreateFile(szFileName,
+ GENERIC_WRITE,
+ FILE_SHARE_READ, //0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (ghLogFile == INVALID_HANDLE_VALUE)
+ {
+ DBGOUT((3, "InitLogging failed CreateFile"));
+ return FALSE;
+ }
+
+#else
+
+ lstrcpy(gszFileName, szFileName);
+
+ ofstruct.cBytes = sizeof(ofstruct);
+
+ ghLogFile = OpenFile(gszFileName,
+ &ofstruct,
+ OF_CREATE);
+
+ _lclose(ghLogFile);
+/*
+ ofstruct.cBytes = sizeof(ofstruct);
+
+ DBGOUT((3, szFileName));
+
+ ghLogFile = OpenFile(szFileName,
+ &ofstruct,
+ OF_CREATE | OF_READWRITE);
+
+ if (ghLogFile == HFILE_ERROR)
+ {
+ DBGOUT((3, "InitLogging failed OpenFile"));
+ return FALSE;
+ }*/
+#endif
+
+#ifdef WIN32
+ InitializeCriticalSection(&gcsLogging);
+ InitializeCriticalSection(&gcsID);
+
+ gpBegin = NULL;
+ gpEnd = NULL;
+#endif
+
+ DBGOUT((3, "Exiting InitLogging"));
+ return TRUE;
+}
+
+
+
+void WritePreHeader(DWORD dwID, DWORD dwType)
+{
+ return;
+/*
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = dwType;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+ */
+}
+
+void WriteStruct(DWORD dwID,
+ DWORD dwSize,
+ LPVOID lpBuf)
+{
+ STRUCTHEADER StructHeader;
+
+ if (!lpBuf)
+ {
+ return;
+ }
+
+
+ StructHeader.dwKey = DWSTRCKEY;
+ StructHeader.dwSize = dwSize;
+ StructHeader.dwID = (DWORD)lpBuf;
+
+ CopyData(dwID, (LPVOID)&StructHeader, sizeof(StructHeader));
+ CopyData(dwID, lpBuf, (int)dwSize);
+}
+
+void WritePostStruct(DWORD dwID,
+ LONG lResult)
+{
+ POSTSTRUCT PostStruct;
+
+ PostStruct.dwKey = DWPOSTKEY;
+ PostStruct.dwTime = GetTickCount();
+ PostStruct.lReturn = lResult;
+
+ CopyData(dwID, (LPVOID)&PostStruct, sizeof(PostStruct));
+}
+
+void WriteLineMsgStruct(DWORD dwID,
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dw1,
+ DWORD dw2,
+ DWORD dw3)
+{
+ LINEMSGSTRUCT LineMsgStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = LINEMSG;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LineMsgStruct.dwMsg = dwMsg;
+ LineMsgStruct.htLine = htLine;
+ LineMsgStruct.htCall = htCall;
+ LineMsgStruct.dw1 = dw1;
+ LineMsgStruct.dw2 = dw2;
+ LineMsgStruct.dw3 = dw3;
+
+ CopyData(dwID, (LPVOID)&LineMsgStruct, sizeof(LineMsgStruct));
+}
+
+void WritePhoneMsgStruct(DWORD dwID,
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dw1,
+ DWORD dw2,
+ DWORD dw3)
+{
+ PHONEMSGSTRUCT PhoneMsgStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = PHONEMSG;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ PhoneMsgStruct.dwMsg = dwMsg;
+ PhoneMsgStruct.htPhone = htPhone;
+ PhoneMsgStruct.dw1 = dw1;
+ PhoneMsgStruct.dw2 = dw2;
+ PhoneMsgStruct.dw3 = dw3;
+
+ CopyData(dwID, (LPVOID)&PhoneMsgStruct, sizeof(PhoneMsgStruct));
+}
+
+void WriteAsyncStruct(DWORD dwID,
+ DWORD dwRequestID,
+ LONG lResult)
+{
+ ASYNCSTRUCT AsyncStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = ASYNCMSG;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ AsyncStruct.dwRequestID = dwRequestID;
+ AsyncStruct.lResult = lResult;
+
+
+ CopyData(dwID, (LPVOID)&AsyncStruct, sizeof(AsyncStruct));
+}
+void WriteLogStruct1(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1)
+{
+ LOGSPFUNC1 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC1;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+void WriteLogStruct2(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2)
+{
+ LOGSPFUNC2 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC2;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+void WriteLogStruct3(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3)
+{
+ LOGSPFUNC3 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC3;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+
+void WriteLogStruct4(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4)
+{
+ LOGSPFUNC4 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC4;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+ LogStruct.dwParam4 = dwParam4;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+void WriteLogStruct5(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5)
+{
+ LOGSPFUNC5 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC5;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+ LogStruct.dwParam4 = dwParam4;
+ LogStruct.dwParam5 = dwParam5;
+
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+void WriteLogStruct6(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6)
+{
+ LOGSPFUNC6 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC6;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+ LogStruct.dwParam4 = dwParam4;
+ LogStruct.dwParam5 = dwParam5;
+ LogStruct.dwParam6 = dwParam6;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+void WriteLogStruct7(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7)
+{
+ LOGSPFUNC7 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC7;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+ LogStruct.dwParam4 = dwParam4;
+ LogStruct.dwParam5 = dwParam5;
+ LogStruct.dwParam6 = dwParam6;
+ LogStruct.dwParam7 = dwParam7;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+
+void WriteLogStruct8(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7,
+ DWORD dwParam8)
+{
+ LOGSPFUNC8 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC8;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+ LogStruct.dwParam4 = dwParam4;
+ LogStruct.dwParam5 = dwParam5;
+ LogStruct.dwParam6 = dwParam6;
+ LogStruct.dwParam7 = dwParam7;
+ LogStruct.dwParam8 = dwParam8;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+
+void WriteLogStruct9(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7,
+ DWORD dwParam8,
+ DWORD dwParam9)
+{
+ LOGSPFUNC9 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC9;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+ LogStruct.dwParam4 = dwParam4;
+ LogStruct.dwParam5 = dwParam5;
+ LogStruct.dwParam6 = dwParam6;
+ LogStruct.dwParam7 = dwParam7;
+ LogStruct.dwParam8 = dwParam8;
+ LogStruct.dwParam9 = dwParam9;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+void WriteLogStruct12(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7,
+ DWORD dwParam8,
+ DWORD dwParam9,
+ DWORD dwParam10,
+ DWORD dwParam11,
+ DWORD dwParam12)
+{
+ LOGSPFUNC12 LogStruct;
+ PREHEADER PreHeader;
+
+ PreHeader.dwKey = DWPREKEY;
+ PreHeader.dwTime = GetTickCount();
+ PreHeader.dwType = SPFUNC12;
+
+ CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
+
+ LogStruct.dwSPFUNC = dwSPFUNC;
+ LogStruct.dwParam1 = dwParam1;
+ LogStruct.dwParam2 = dwParam2;
+ LogStruct.dwParam3 = dwParam3;
+ LogStruct.dwParam4 = dwParam4;
+ LogStruct.dwParam5 = dwParam5;
+ LogStruct.dwParam6 = dwParam6;
+ LogStruct.dwParam7 = dwParam7;
+ LogStruct.dwParam8 = dwParam8;
+ LogStruct.dwParam9 = dwParam9;
+ LogStruct.dwParam10 = dwParam10;
+ LogStruct.dwParam11 = dwParam11;
+ LogStruct.dwParam12 = dwParam12;
+
+ CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
+}
+
+void CopyData(DWORD dwID, LPVOID lpBuf, int dwSize)
+{
+ memcpy((LPBYTE)gChunks[dwID].pBuffer + gChunks[dwID].iStart,
+ lpBuf,
+ dwSize);
+
+ gChunks[dwID].iStart += dwSize;
+}
+
+BOOL GetChunkID(LPDWORD lpdwID)
+{
+#ifdef WIN32
+ EnterCriticalSection(&gcsID);
+#endif
+ while (TRUE)
+ {
+ while (gdwID < MAXCHUNKS)
+ {
+ if (!gChunks[gdwID].bInUse)
+ {
+ goto gotid;
+ }
+
+ gdwID++;
+ }
+
+ gdwID = 0;
+#ifdef WIN32
+ Sleep(0);
+#endif
+ }
+
+gotid:
+
+ *lpdwID = gdwID;
+ gChunks[gdwID].bInUse = TRUE;
+
+#ifdef WIN32
+ LeaveCriticalSection(&gcsID);
+#endif
+ return TRUE;
+}
+
+BOOL ReleaseID(DWORD dwID)
+{
+ CopyIDToList(gChunks[dwID].iStart,
+ gChunks[dwID].pBuffer);
+
+#ifdef WIN32
+ GlobalFree(gChunks[dwID].pBuffer);
+#else
+ GlobalFreePtr(gChunks[dwID].pBuffer);
+#endif
+ gChunks[dwID].iStart = 0;
+ gChunks[dwID].pBuffer = NULL;
+ gChunks[dwID].bInUse = FALSE;
+
+ return TRUE;
+}
+
+#ifdef WIN32
+BOOL CopyIDToList(int iCount, LPVOID pBuffer)
+{
+ PLOGSTRUCT pNew;
+
+ // if we have a lot of stuff to write, hold up here and
+ // wait until we've written a bunch
+ if (gdwTotalBlocks > MAXCHUNKS)
+ {
+ while (gdwTotalBlocks > MINCHUNKS)
+ {
+ Sleep(0);
+ }
+ }
+
+ pNew = (PLOGSTRUCT)GlobalAlloc(GPTR, iCount+sizeof(LOGSTRUCT));
+
+ pNew->pNext = NULL;
+ pNew->iSize = iCount;
+
+ memcpy(pNew+1, pBuffer, iCount);
+
+ EnterCriticalSection(&gcsLogging);
+ if (gpBegin == NULL)
+ {
+ gpBegin = pNew;
+ }
+ else
+ {
+ gpEnd->pNext = pNew;
+ }
+
+ gpEnd = pNew;
+ LeaveCriticalSection(&gcsLogging);
+
+ gdwTotalBlocks++;
+
+ return TRUE;
+}
+#else
+BOOL CopyIDToList(int iCount, LPVOID pBuffer)
+{
+ OFSTRUCT ofstruct;
+
+ ofstruct.cBytes = sizeof(ofstruct);
+
+ ghLogFile = OpenFile(gszFileName,
+ &ofstruct,
+ OF_READWRITE);
+
+ if (ghLogFile == HFILE_ERROR)
+ {
+ DBGOUT((3,"OpenFile failed"));
+ return FALSE;
+ }
+
+ _llseek(ghLogFile,
+ 0,
+ 2);
+
+ if (_lwrite(ghLogFile,
+ pBuffer,
+ iCount) == HFILE_ERROR)
+ {
+ DBGOUT((3, "_lwrite failed"));
+ }
+
+ _lclose(ghLogFile);
+
+ return TRUE;
+}
+#endif
+
+BOOL AllocChunk(DWORD dwID, DWORD dwSize)
+{
+ LPVOID pbuf;
+
+ // ok, i messed up and forgot to alloc for structheader.
+ // so i'll just add the size of 4 struct headers to each
+ // alloc. what a hack - o - rama
+ dwSize += 4*sizeof(STRUCTHEADER);
+
+#ifdef WIN32
+ pbuf = (LPVOID)GlobalAlloc(GPTR, dwSize);
+#else
+ pbuf = (LPVOID)GlobalAllocPtr(GPTR, dwSize);
+#endif
+
+ if (!pbuf)
+ {
+ gChunks[dwID].pBuffer = NULL;
+ return FALSE;
+ }
+
+#ifdef WIN32
+ memset(pbuf, 0, dwSize);
+#else
+ memset(pbuf, 0, (int)dwSize);
+#endif
+ gChunks[dwID].pBuffer = pbuf;
+ gChunks[dwID].bInUse = TRUE;
+ gChunks[dwID].iStart = 0;
+
+ return TRUE;
+}
+
diff --git a/private/tapi/dev/sp/repeater/new/logger.h b/private/tapi/dev/sp/repeater/new/logger.h
new file mode 100644
index 000000000..60b8c850b
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/logger.h
@@ -0,0 +1,317 @@
+#include <windows.h>
+#include <tspi.h>
+
+DWORD WINAPI LoggingThread( LPVOID pThreadParm );
+// void CopyData(LPVOID pBuffer, int iCount);
+void CopyData(DWORD dwID, LPVOID lpBuf, int dwSize);
+
+
+#define MAXCHUNKS 5000
+#define MINCHUNKS 1000
+
+// these are the preheader types
+
+#define LINEMSG 1
+#define PHONEMSG 2
+#define ASYNCMSG 3
+#define SPFUNC1 4
+#define SPFUNC2 5
+#define SPFUNC3 6
+#define SPFUNC4 7
+#define SPFUNC5 8
+#define SPFUNC6 9
+#define SPFUNC7 10
+#define SPFUNC8 11
+#define SPFUNC9 12
+#define SPFUNC12 13
+
+#define MYFOURCC( ch0, ch1, ch2, ch3 ) \
+ ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) | \
+ ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
+
+#define DWPREKEY MYFOURCC('P','R','E',' ')
+#define DWPOSTKEY MYFOURCC('P','O','S','T')
+#define DWSTRCKEY MYFOURCC('S','T','R','C')
+
+typedef struct tagCHUNK
+{
+ int iStart;
+ LPVOID pBuffer;
+ BOOL bInUse;
+} CHUNK, * PCHUNK;
+
+typedef struct tagPREHEADER
+{
+ DWORD dwKey; // 'PRE '
+ DWORD dwTime;
+ DWORD dwType;
+} PREHEADER, * PPREHEADER;
+
+typedef struct tagPOSTSTRUCT
+{
+ DWORD dwKey; // 'POST'
+ DWORD dwTime;
+ LONG lReturn;
+} POSTSTRUCT, * PPOSTSTRUCT;
+
+typedef struct tagSTRUCTHEADER
+{
+ DWORD dwKey; // 'STRC'
+ DWORD dwSize;
+ DWORD dwID;
+} STRUCTHEADER, * PSTRUCTHEADER;
+
+typedef struct tagLINEMSGSTRUCT
+{
+ DWORD dwMsg;
+ HTAPILINE htLine;
+ HTAPICALL htCall;
+ DWORD dw1;
+ DWORD dw2;
+ DWORD dw3;
+
+} LINEMSGSTRUCT, * PLINEMSGSTRUCT;
+
+
+typedef struct tagPHONEMSGSTRUCT
+{
+ DWORD dwMsg;
+ HTAPIPHONE htPhone;
+ DWORD dw1;
+ DWORD dw2;
+ DWORD dw3;
+
+} PHONEMSGSTRUCT, * PPHONEMSGSTRUCT;
+
+
+typedef struct tagASYNCSTRUCT
+{
+ DWORD dwRequestID;
+ LONG lResult;
+
+} ASYNCSTRUCT, * PASYNCSTRUCT;
+
+typedef struct tagLOGSPFUNC1
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+
+} LOGSPFUNC1, * PLOGSPFUNC1;
+
+typedef struct tagLOGSPFUNC2
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+
+} LOGSPFUNC2, * PLOGSPFUNC2;
+
+typedef struct tagLOGSPFUNC3
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+
+} LOGSPFUNC3, * PLOGSPFUNC3;
+
+typedef struct tagLOGSPFUNC4
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+
+} LOGSPFUNC4, * PLOGSPFUNC4;
+
+
+typedef struct tagLOGSPFUNC5
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+ DWORD dwParam5;
+
+} LOGSPFUNC5, * PLOGSPFUNC5;
+
+
+typedef struct tagLOGSPFUNC6
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+ DWORD dwParam5;
+ DWORD dwParam6;
+
+} LOGSPFUNC6, * PLOGSPFUNC6;
+
+
+typedef struct tagLOGSPFUNC7
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+ DWORD dwParam5;
+ DWORD dwParam6;
+ DWORD dwParam7;
+
+} LOGSPFUNC7, * PLOGSPFUNC7;
+
+
+typedef struct tagLOGSPFUNC8
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+ DWORD dwParam5;
+ DWORD dwParam6;
+ DWORD dwParam7;
+ DWORD dwParam8;
+
+} LOGSPFUNC8, * PLOGSPFUNC8;
+
+typedef struct tagLOGSPFUNC9
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+ DWORD dwParam5;
+ DWORD dwParam6;
+ DWORD dwParam7;
+ DWORD dwParam8;
+ DWORD dwParam9;
+
+} LOGSPFUNC9, * PLOGSPFUNC9;
+
+typedef struct tagLOGSPFUNC12
+{
+ DWORD dwSPFUNC;
+ DWORD dwParam1;
+ DWORD dwParam2;
+ DWORD dwParam3;
+ DWORD dwParam4;
+ DWORD dwParam5;
+ DWORD dwParam6;
+ DWORD dwParam7;
+ DWORD dwParam8;
+ DWORD dwParam9;
+ DWORD dwParam10;
+ DWORD dwParam11;
+ DWORD dwParam12;
+
+} LOGSPFUNC12, * PLOGSPFUNC12;
+
+void WritePreHeader(DWORD dwID, DWORD dwType);
+void WriteStruct(DWORD dwID,
+ DWORD dwSize,
+ LPVOID lpBuf);
+void WritePostStruct(DWORD dwID,
+ LONG lReturn);
+void WriteLineMsgStruct(DWORD dwID,
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dw1,
+ DWORD dw2,
+ DWORD dw3);
+void WritePhoneMsgStruct(DWORD dwID,
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dw1,
+ DWORD dw2,
+ DWORD dw3);
+void WriteAsyncStruct(DWORD dwID,
+ DWORD,
+ LONG);
+void WriteLogStruct1(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1);
+void WriteLogStruct2(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2);
+void WriteLogStruct3(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3);
+void WriteLogStruct4(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4);
+void WriteLogStruct5(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5);
+void WriteLogStruct6(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6);
+void WriteLogStruct7(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7);
+void WriteLogStruct8(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7,
+ DWORD dwParam8);
+void WriteLogStruct9(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7,
+ DWORD dwParam8,
+ DWORD dwParam9);
+void WriteLogStruct12(DWORD dwID,
+ DWORD dwSPFUNC,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwParam4,
+ DWORD dwParam5,
+ DWORD dwParam6,
+ DWORD dwParam7,
+ DWORD dwParam8,
+ DWORD dwParam9,
+ DWORD dwParam10,
+ DWORD dwParam11,
+ DWORD dwParam12);
+BOOL ReleaseID(DWORD dwID);
+BOOL GetChunkID(LPDWORD lpdwID);
+BOOL AllocChunk(DWORD dwID, DWORD dwSize);
+
diff --git a/private/tapi/dev/sp/repeater/new/makefile b/private/tapi/dev/sp/repeater/new/makefile
new file mode 100644
index 000000000..7cc5b6412
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# tsp3216s.dll Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/repeater/new/makefile.def b/private/tapi/dev/sp/repeater/new/makefile.def
new file mode 100644
index 000000000..403b6f324
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/makefile.def
@@ -0,0 +1,51 @@
+ROOT=..\..\..\..\..\..
+
+IS_OEM=1
+IS_32 = TRUE
+WANT_C932=1
+WIN32=1
+
+BUILDDLL=1
+DLLENTRY=DllMain
+
+
+
+DEPENDNAME=..\depend.mk
+
+DRVNAME=Repeater
+TARGETS=Repeater.tsp Repeater.sym
+
+
+SRCDIR=..
+
+SYMDIR=.
+
+
+BUILD_COFF=1
+
+
+
+L32EXE=Repeater.tsp # Name of exe.
+L32DEF=..\Repeater.def # Our def file.
+L32MAP=Repeater.map # Our map file.
+L32SYM=Repeater.sym # Our sym file.
+L32RES=Repeater.res # Resource file.
+L32OBJS= Repeater.obj logger.obj debug.obj
+L32LIBS= \
+ $(DEVROOT)\lib\user32.lib \
+ $(DEVROOT)\lib\kernel32.lib
+
+
+L32FLAGS=$(L32FLAGS) -MAP -DEF:..\REPEATER.DEF
+
+!include $(ROOT)\dev\master.mk
+
+
+INCLUDE=..\..\..\..\inc;$(ROOT)\win\thunk;$(ROOT)\win\core\inc;$(INCLUDE)
+
+#CFLAGS=$(CFLAGS) -DDONT_DECLARE_TSPI_FUNCTIONS=1
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
+
diff --git a/private/tapi/dev/sp/repeater/new/rep16.def b/private/tapi/dev/sp/repeater/new/rep16.def
new file mode 100644
index 000000000..d0ab25f46
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/rep16.def
@@ -0,0 +1,122 @@
+LIBRARY repeater
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept @500
+ TSPI_lineAddToConference @501
+ TSPI_lineAnswer @502
+ TSPI_lineBlindTransfer @503
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineCompleteCall @506
+ TSPI_lineCompleteTransfer @507
+ TSPI_lineConditionalMediaDetection @508
+ TSPI_lineConfigDialog @509
+ TSPI_lineDevSpecific @510
+ TSPI_lineDevSpecificFeature @511
+ TSPI_lineDial @512
+ TSPI_lineDrop @513
+ TSPI_lineForward @514
+ TSPI_lineGatherDigits @515
+ TSPI_lineGenerateDigits @516
+ TSPI_lineGenerateTone @517
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetDevConfig @525
+ TSPI_lineGetExtensionID @526
+ TSPI_lineGetIcon @527
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineHold @531
+ TSPI_lineMakeCall @532
+ TSPI_lineMonitorDigits @533
+ TSPI_lineMonitorMedia @534
+ TSPI_lineMonitorTones @535
+ TSPI_lineNegotiateExtVersion @536
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_lineOpen @538
+ TSPI_linePark @539
+ TSPI_linePickup @540
+ TSPI_linePrepareAddToConference @541
+ TSPI_lineRedirect @542
+ TSPI_lineRemoveFromConference @543
+ TSPI_lineSecureCall @544
+ TSPI_lineSelectExtVersion @545
+ TSPI_lineSendUserUserInfo @546
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetCallParams @548
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetDevConfig @550
+ TSPI_lineSetMediaControl @551
+ TSPI_lineSetMediaMode @552
+ TSPI_lineSetStatusMessages @553
+ TSPI_lineSetTerminal @554
+ TSPI_lineSetupConference @555
+ TSPI_lineSetupTransfer @556
+ TSPI_lineSwapHold @557
+ TSPI_lineUncompleteCall @558
+ TSPI_lineUnhold @559
+ TSPI_lineUnpark @560
+
+ TSPI_phoneClose @561
+ TSPI_phoneConfigDialog @562
+ TSPI_phoneDevSpecific @563
+ TSPI_phoneGetButtonInfo @564
+ TSPI_phoneGetData @565
+ TSPI_phoneGetDevCaps @566
+ TSPI_phoneGetDisplay @567
+ TSPI_phoneGetExtensionID @568
+ TSPI_phoneGetGain @569
+ TSPI_phoneGetHookSwitch @570
+ TSPI_phoneGetIcon @571
+ TSPI_phoneGetID @572
+ TSPI_phoneGetLamp @573
+ TSPI_phoneGetRing @574
+ TSPI_phoneGetStatus @575
+ TSPI_phoneGetVolume @576
+ TSPI_phoneNegotiateExtVersion @577
+ TSPI_phoneNegotiateTSPIVersion @578
+ TSPI_phoneOpen @579
+ TSPI_phoneSelectExtVersion @580
+ TSPI_phoneSetButtonInfo @581
+ TSPI_phoneSetData @582
+ TSPI_phoneSetDisplay @583
+ TSPI_phoneSetGain @584
+ TSPI_phoneSetHookSwitch @585
+ TSPI_phoneSetLamp @586
+ TSPI_phoneSetRing @587
+ TSPI_phoneSetStatusMessages @588
+ TSPI_phoneSetVolume @589
+
+ TSPI_providerConfig @590
+ TSPI_providerInit @591
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerShutdown @594
+
+ TSPI_providerEnumDevices @595
+ TSPI_lineDropOnClose @596
+ TSPI_lineDropNoOwner @597
+ TSPI_providerCreateLineDevice @598
+ TSPI_providerCreatePhoneDevice @599
+ TSPI_lineSetCurrentLocation @600
+ TSPI_lineConfigDialogEdit @601
+ TSPI_lineReleaseUserUserInfo @602
+
+; TSPI_lineSetCallData @603
+; TSPI_lineSetCallQualityOfService @604
+; TSPI_lineSetCallTreatment @605
+; TSPI_lineSetLineDevStatus @606
+; TSPI_providerFreeDialogInstance @607
+; TSPI_providerGenericDialogData @608
+; TSPI_providerUIIdentify @609
+
+
diff --git a/private/tapi/dev/sp/repeater/new/rep16.mak b/private/tapi/dev/sp/repeater/new/rep16.mak
new file mode 100644
index 000000000..ea96290a1
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/rep16.mak
@@ -0,0 +1,80 @@
+##### DLL Macros #####
+DLLNAME = repeater
+DLLSRCS = repeater.c logger.c debug.c
+DLLOBJS = repeater.obj logger.obj debug.obj
+
+##### DLL Library Macros #####
+DLLLIBS = libw ldllcew ver
+DLLMOD = -ALw -DDLL
+
+##### APP/DLL Include Macros #####
+DLLINCLS =
+
+##### APP/DLL Resource Macros #####
+APPRCFILES =
+DLLRCFILES =
+
+##### DEBUG Version Built #####
+DEBUG = 1
+
+##### Build Option Macros #####
+!if $(DEBUG)
+DDEF = -DDEBUG -DDBG
+CLOPT = -Zid -Od
+MOPT = -Zi
+LOPT = /CO /LI /MAP
+!else
+DDEF =
+CLOPT = -Os
+LOPT =
+!endif
+
+##### General Macros #####
+DEF =
+
+##### Tool Macros #####
+CC = cl -nologo -c $(DLLMOD) -G2sw -Zp -W3 $(CLOPT) $(DDEF) $(DEF)
+LINK = link /NOD /NOE $(LOPT)
+RC = rc $(DDEF) $(DEF)
+HC = hc
+
+##### Inference Rules #####
+.asm.obj:
+ $(ASM) $*.asm;
+
+.rc.res:
+ $(RC) -r $*.rc
+
+##### Main (default) Target #####
+goal: $(DLLNAME).tsp
+
+##### Dependents For Goal and Command Lines #####
+##### DLL Built Separately #####
+.c.obj :
+ $(CC) $(DLLSRCS)
+
+
+$(DLLNAME).tsp: $(DLLOBJS) rep16.def
+ $(LINK) @<<
+ $(DLLOBJS),
+ $(DLLNAME).tsp,
+ $(DLLNAME).map,
+ $(DLLLIBS),
+ rep16.def
+<<
+ implib $(DLLNAME).lib rep16.def
+
+# $(RC) -T $(DLLNAME).tsp
+#!if $(DEBUG)
+# cvpack -p $(DLLNAME).tsp
+#!endif
+
+##### Dependents #####
+$(DLLOBJS): $(DLLINCLS)
+
+##### Clean Directory #####
+clean:
+ -del *.obj
+ -del *.tsp
+ -del *.map
+ -del *.sym
diff --git a/private/tapi/dev/sp/repeater/new/repeater.c b/private/tapi/dev/sp/repeater/new/repeater.c
new file mode 100644
index 000000000..bf0d84dcd
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/repeater.c
@@ -0,0 +1,6251 @@
+#pragma warning(disable: 4087)
+
+#define STRICT
+#define UNICODE
+
+#include <windows.h>
+#include <windowsx.h>
+
+#ifndef WIN32
+#define TAPI_CURRENT_VERSION 0x00010004
+#endif
+
+#include <tapi.h>
+#include <tspi.h>
+
+#include "tsp3216.h"
+
+#include "Repeater.h"
+#include "logger.h"
+#include "debug.h"
+
+#ifndef WIN32
+#define TCHAR char
+#define TEXT(string) string
+#define LPCWSTR LPCSTR
+#endif
+
+#ifdef WIN32
+extern CRITICAL_SECTION gcsLogging;
+extern CRITICAL_SECTION gcsID;
+#endif
+
+#define TSPAPI PASCAL
+typedef LONG (TSPAPI* TSPAPIPROC)(void);
+
+#if DBG
+#define RepeaterDebugString(_x_) DbgPrt _x_
+#else
+#define RepeaterDebugString(_x_)
+#endif
+
+// globals
+
+HINSTANCE ghThisInst;
+BOOL gfTerminateNow = FALSE;
+BOOL gbStarted = FALSE;
+DWORD dwPermanentProvider;
+DWORD dwNumLines;
+DWORD dwNumPhones;
+
+#ifdef WIN32
+DWORD gdwLoggingThreadID;
+HANDLE ghLoggingThread;
+#endif
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+HDRVDIALOGINSTANCE gDlgInst;
+#endif
+
+//////////////////////////////////////////////////////
+HINSTANCE hProvider = NULL;
+TSPAPIPROC FAR * lpfnProcAddress = NULL;
+
+#ifdef WIN32
+#define MYALLOC(x,y) ((x) = GlobalAlloc(GPTR, (y)))
+#define MYFREE(x) GlobalFree(x)
+#else
+#define MYALLOC(x,y) ((x) = (LPVOID)MAKELONG(0, GlobalAlloc(GPTR, (y))))
+#define MYFREE(x) (GlobalFree((HGLOBAL)HIWORD(x)))
+
+#endif
+
+
+LINEEVENT glpLineEventProc32;
+PHONEEVENT glpPhoneEventProc32;
+
+ASYNC_COMPLETION glpAsyncCompletionProc32 = NULL;
+
+void InitLogging();
+
+#ifndef WIN32
+const char far szIniFile[] = "telephon.INI";
+#endif
+
+
+#define BOGUS_REQUEST_ID (0xfffffffd)
+
+#define NORMALCHUNK sizeof(PREHEADER) + sizeof(POSTSTRUCT)
+
+// all tspi function names
+// since all functions are exported by name
+char *gaszTSPIFuncNames[] =
+{
+ "TSPI_lineAccept",
+ "TSPI_lineAddToConference",
+ "TSPI_lineAgentSpecific",
+ "TSPI_lineAnswer",
+ "TSPI_lineBlindTransfer",
+ "TSPI_lineClose",
+ "TSPI_lineCloseCall",
+ "TSPI_lineCompleteCall",
+ "TSPI_lineCompleteTransfer",
+ "TSPI_lineConditionalMediaDetection",
+ "TSPI_lineDevSpecific",
+ "TSPI_lineDevSpecificFeature",
+ "TSPI_lineDial",
+ "TSPI_lineDrop",
+ "TSPI_lineForward",
+ "TSPI_lineGatherDigits",
+ "TSPI_lineGenerateDigits",
+ "TSPI_lineGenerateTone",
+ "TSPI_lineGetAddressCaps",
+ "TSPI_lineGetAddressID",
+ "TSPI_lineGetAddressStatus",
+ "TSPI_lineGetAgentActivityList",
+ "TSPI_lineGetAgentCaps",
+ "TSPI_lineGetAgentGroupList",
+ "TSPI_lineGetAgentStatus",
+ "TSPI_lineGetCallAddressID",
+ "TSPI_lineGetCallInfo",
+ "TSPI_lineGetCallStatus",
+ "TSPI_lineGetDevCaps",
+ "TSPI_lineGetDevConfig",
+ "TSPI_lineGetExtensionID",
+ "TSPI_lineGetIcon",
+ "TSPI_lineGetID",
+ "TSPI_lineGetLineDevStatus",
+ "TSPI_lineGetNumAddressIDs",
+ "TSPI_lineHold",
+ "TSPI_lineMakeCall",
+ "TSPI_lineMonitorDigits",
+ "TSPI_lineMonitorMedia",
+ "TSPI_lineMonitorTones",
+ "TSPI_lineNegotiateExtVersion",
+ "TSPI_lineNegotiateTSPIVersion",
+ "TSPI_lineOpen",
+ "TSPI_linePark",
+ "TSPI_linePickup",
+ "TSPI_linePrepareAddToConference",
+ "TSPI_lineRedirect",
+ "TSPI_lineReleaseUserUserInfo",
+ "TSPI_lineRemoveFromConference",
+ "TSPI_lineSecureCall",
+ "TSPI_lineSelectExtVersion",
+ "TSPI_lineSendUserUserInfo",
+ "TSPI_lineSetAgentActivity",
+ "TSPI_lineSetAgentGroup",
+ "TSPI_lineSetAgentState",
+ "TSPI_lineSetAppSpecific",
+ "TSPI_lineSetCallData",
+ "TSPI_lineSetCallParams",
+ "TSPI_lineSetCallQualityOfService",
+ "TSPI_lineSetCallTreatment",
+ "TSPI_lineSetCurrentLocation",
+ "TSPI_lineSetDefaultMediaDetection",
+ "TSPI_lineSetDevConfig",
+ "TSPI_lineSetLineDevStatus",
+ "TSPI_lineSetMediaControl",
+ "TSPI_lineSetMediaMode",
+ "TSPI_lineSetStatusMessages",
+ "TSPI_lineSetTerminal",
+ "TSPI_lineSetupConference",
+ "TSPI_lineSetupTransfer",
+ "TSPI_lineSwapHold",
+ "TSPI_lineUncompleteCall",
+ "TSPI_lineUnhold",
+ "TSPI_lineUnpark",
+ "TSPI_phoneClose",
+ "TSPI_phoneDevSpecific",
+ "TSPI_phoneGetButtonInfo",
+ "TSPI_phoneGetData",
+ "TSPI_phoneGetDevCaps",
+ "TSPI_phoneGetDisplay",
+ "TSPI_phoneGetExtensionID",
+ "TSPI_phoneGetGain",
+ "TSPI_phoneGetHookSwitch",
+ "TSPI_phoneGetIcon",
+ "TSPI_phoneGetID",
+ "TSPI_phoneGetLamp",
+ "TSPI_phoneGetRing",
+ "TSPI_phoneGetStatus",
+ "TSPI_phoneGetVolume",
+ "TSPI_phoneNegotiateExtVersion",
+ "TSPI_phoneNegotiateTSPIVersion",
+ "TSPI_phoneOpen",
+ "TSPI_phoneSelectExtVersion",
+ "TSPI_phoneSetButtonInfo",
+ "TSPI_phoneSetData",
+ "TSPI_phoneSetDisplay",
+ "TSPI_phoneSetGain",
+ "TSPI_phoneSetHookSwitch",
+ "TSPI_phoneSetLamp",
+ "TSPI_phoneSetRing",
+ "TSPI_phoneSetStatusMessages",
+ "TSPI_phoneSetVolume",
+ "TSPI_providerCreateLineDevice",
+ "TSPI_providerCreatePhoneDevice",
+ "TSPI_providerEnumDevices",
+ "TSPI_providerFreeDialogInstance",
+ "TSPI_providerGenericDialogData",
+ "TSPI_providerInit",
+ "TSPI_providerShutdown",
+ "TSPI_providerUIIdentify",
+ "TSPI_lineConfigDialog",
+ "TSPI_lineConfigDialogEdit",
+ "TSPI_phoneConfigDialog",
+ "TSPI_providerConfig"
+ "TSPI_lineDropOnClose",
+ "TSPI_lineDropNoOwner",
+ NULL
+};
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank1(
+ DWORD dwBlank1
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank1 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank2(
+ DWORD dwBlank1,
+ DWORD dwBlank2
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank2 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank3(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank3 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank4(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank4 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank5(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank5 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank6(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank6 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank7(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank7 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank8(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7,
+ DWORD dwBlank8
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank8 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank9(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7,
+ DWORD dwBlank8,
+ DWORD dwBlank9
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank9 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank10(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7,
+ DWORD dwBlank8,
+ DWORD dwBlank9,
+ DWORD dwBlank10
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank10 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank11(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7,
+ DWORD dwBlank8,
+ DWORD dwBlank9,
+ DWORD dwBlank10,
+ DWORD dwBlank11
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank11 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_LineBlank12(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7,
+ DWORD dwBlank8,
+ DWORD dwBlank9,
+ DWORD dwBlank10,
+ DWORD dwBlank11,
+ DWORD dwBlank12
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_LineBlank12 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank1(
+ DWORD dwBlank1
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank1 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank2(
+ DWORD dwBlank1,
+ DWORD dwBlank2
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank2 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank3(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank3 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank4(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank4 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank5(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank5 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank6(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank6 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank7(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank7 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank8(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7,
+ DWORD dwBlank8
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank8 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_PhoneBlank9(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7,
+ DWORD dwBlank8,
+ DWORD dwBlank9
+ )
+{
+ RepeaterDebugString((2, "Entering/leaving TSPI_PhoneBlank9 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+// function definitions
+
+#ifdef DEBUG
+VOID RepeaterOutputDebug(int level, LPSTR errString)
+ {
+ char outString[1024];
+
+ // if(level <= ???)
+ {
+ wsprintf(outString, "Repeater:(%d) %s\r\n", level, errString);
+ OutputDebugString(outString);
+ }
+ }
+#endif
+
+VOID
+ InitializeSPs(VOID);
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+void StartMeUp( void )
+{
+
+ gbStarted = TRUE;
+
+ MYALLOC(lpfnProcAddress, sizeof(gaszTSPIFuncNames)/sizeof(gaszTSPIFuncNames[0]) * sizeof(TSPAPIPROC));
+
+#ifdef WIN32
+ //
+ // Kick off the logging thread
+ //
+ InitLogging();
+
+ DBGOUT((3, "Entering StartMeUp"));
+
+ ghLoggingThread = CreateThread(
+ NULL,
+ 0,
+ LoggingThread,
+ NULL,
+ 0,
+ &gdwLoggingThreadID
+ );
+#else
+ InitLogging();
+#endif
+
+ InitializeSPs();
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+VOID
+ InitializeSPs(VOID)
+{
+ TCHAR LibFileName[MAXBUFSIZE];
+ TCHAR szBuffer[MAXBUFSIZE];
+#ifdef WIN32
+ HKEY hKey;
+ DWORD dwSize, dwType;
+#endif
+
+ // under the telephony key, there should be a repeater key,
+ // that is exactly like the providers key. the repeater key
+ // should list the provider to actually be used. the provider
+ // key should list repeater as the only sp.
+
+#ifdef WIN32
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Repeater"),
+ 0,
+ KEY_QUERY_VALUE,
+ &hKey);
+#endif
+
+#ifdef WIN32
+ dwSize = MAXBUFSIZE;
+ dwType = REG_SZ;
+ RegQueryValueEx(hKey,
+ TEXT("ProviderFilename0"),
+ NULL,
+ &dwType,
+ (LPBYTE)LibFileName,
+ &dwSize);
+#else
+ GetPrivateProfileString(TEXT("Repeater"),
+ TEXT("ProviderFilename0"),
+ TEXT(""),
+ LibFileName,
+ MAXBUFSIZE,
+ szIniFile);
+
+#endif
+
+ DBGOUT((1, "Loading provider"));
+
+ hProvider = LoadLibrary(LibFileName);
+
+ if ( hProvider )
+ {
+ DBGOUT((1, "LoadLibrary succeeded"));
+
+#ifdef WIN32
+
+ dwSize = sizeof(DWORD);
+ dwType = REG_DWORD;
+
+ RegQueryValueEx(hKey,
+ TEXT("ProviderID0"),
+ NULL,
+ &dwType,
+ (LPBYTE)&dwPermanentProvider,
+ &dwSize);
+#else
+ dwPermanentProvider=
+ GetPrivateProfileInt("Repeater",
+ TEXT("ProviderID0"),
+ 0,
+ szIniFile);
+
+ // try to read NumPhones and NumLines from telephon.ini
+ // if the sp implements enumdevices, these numbers
+ // will get overwritten anyway
+ dwNumLines = GetPrivateProfileInt("Provider0",
+ "NumLines",
+ 0,
+ szIniFile);
+
+ dwNumPhones = GetPrivateProfileInt("Provider0",
+ "NumPhones",
+ 0,
+ szIniFile);
+#endif
+ }
+
+ else
+ {
+ DBGOUT((1, " provider FAILED TO LOAD!"));
+ }
+
+
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+TSPAPIPROC GetProcAddressHashed(DWORD iFunction, UINT nNumParms)
+{
+
+ static TSPAPIPROC DefaultLineTable[] =
+ {
+ (TSPAPIPROC)TSPI_LineBlank1,
+ (TSPAPIPROC)TSPI_LineBlank2,
+ (TSPAPIPROC)TSPI_LineBlank3,
+ (TSPAPIPROC)TSPI_LineBlank4,
+ (TSPAPIPROC)TSPI_LineBlank5,
+ (TSPAPIPROC)TSPI_LineBlank6,
+ (TSPAPIPROC)TSPI_LineBlank7,
+ (TSPAPIPROC)TSPI_LineBlank8,
+ (TSPAPIPROC)TSPI_LineBlank9,
+ (TSPAPIPROC)TSPI_LineBlank10,
+ (TSPAPIPROC)TSPI_LineBlank11,
+ (TSPAPIPROC)TSPI_LineBlank12
+ };
+
+ static TSPAPIPROC DefaultPhoneTable[] =
+ {
+ (TSPAPIPROC)TSPI_PhoneBlank1,
+ (TSPAPIPROC)TSPI_PhoneBlank2,
+ (TSPAPIPROC)TSPI_PhoneBlank3,
+ (TSPAPIPROC)TSPI_PhoneBlank4,
+ (TSPAPIPROC)TSPI_PhoneBlank5,
+ (TSPAPIPROC)TSPI_PhoneBlank6,
+ (TSPAPIPROC)TSPI_PhoneBlank7,
+ (TSPAPIPROC)TSPI_PhoneBlank8,
+ (TSPAPIPROC)TSPI_PhoneBlank9,
+ };
+
+ TSPAPIPROC *pfn;
+ TSPAPIPROC *FunctionTable;
+
+
+ //
+ // Find out if it's a phone function or a line function
+ //
+ if (
+ (iFunction >= SP_PHONECLOSE)
+ &&
+ (iFunction <= SP_PHONESETVOLUME)
+ )
+ {
+ //
+ // It's a phone function
+ //
+ FunctionTable = DefaultPhoneTable;
+ }
+ else
+ {
+ //
+ // It's a line function
+ //
+ FunctionTable = DefaultLineTable;
+ }
+
+ if ( nNumParms > (sizeof(DefaultLineTable)/sizeof(TSPAPIPROC)) )
+ {
+ DBGOUT((1, ">Num funcs function was requested!"));
+ return 0;
+ }
+
+ // get the pointer to the function
+ pfn = &lpfnProcAddress[iFunction];
+
+ // have we already gotten the address?
+ if( NULL == *pfn )
+ {
+
+ // nope, call get proc address
+ DBGOUT((5, "%s address being gotten", gaszTSPIFuncNames[iFunction]));
+
+ *pfn = (TSPAPIPROC)GetProcAddress(hProvider,
+ gaszTSPIFuncNames[iFunction]);
+
+ //
+ // Did it fail?
+ //
+ if( NULL == *pfn )
+ {
+ DBGOUT((1, "Getting address failed"));
+ *pfn = FunctionTable[ nNumParms - 1 ];
+ }
+ }
+
+ DBGOUT((1, "leaving getprocess address *pfn %lx", *pfn));
+
+ return *pfn;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+#ifdef WIN32
+void PASCAL LineEventProc(
+#else
+void CALLBACK __export LineEventProc(
+#endif
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+
+ DWORD dwID;
+
+ DBGOUT((1, "Line event callback"));
+
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, sizeof(PREHEADER) + sizeof(LINEMSGSTRUCT));
+
+ switch (dwMsg)
+ {
+ case LINE_NEWCALL:
+ case LINE_CALLSTATE:
+ case LINE_CALLDEVSPECIFIC:
+ case LINE_CALLDEVSPECIFICFEATURE:
+ case LINE_CALLINFO:
+ case LINE_GATHERDIGITS:
+ case LINE_GENERATE:
+ case LINE_MONITORDIGITS:
+ case LINE_MONITORMEDIA:
+ case LINE_MONITORTONE:
+ case LINE_ADDRESSSTATE:
+ case LINE_CLOSE:
+ case LINE_DEVSPECIFIC:
+ case LINE_DEVSPECIFICFEATURE:
+ case LINE_LINEDEVSTATE:
+ case LINE_CREATE:
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ case LINE_CREATEDIALOGINSTANCE:
+ case LINE_REMOVE:
+#endif
+ break;
+
+ } // end of switch (dwMsg)
+
+ WritePreHeader(dwID,
+ LINEMSG);
+
+ WriteLineMsgStruct(dwID,
+ htLine,
+ htCall,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3);
+
+ ReleaseID(dwID);
+
+ (*glpLineEventProc32)(htLine,
+ htCall,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3);
+
+}
+
+#ifdef WIN32
+void PASCAL
+#else
+void CALLBACK __export
+#endif
+PhoneEventProc(
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+
+ DWORD dwID;
+
+ DBGOUT((1, "Phone event callback"));
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, sizeof(PREHEADER) + sizeof(PHONEMSGSTRUCT));
+
+ switch(dwMsg)
+ {
+ case PHONE_BUTTON:
+ case PHONE_CLOSE:
+ case PHONE_DEVSPECIFIC:
+ case PHONE_STATE:
+ case PHONE_CREATE:
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ case PHONE_REMOVE:
+#endif
+ break;
+ } // end of switch(dwMsg)
+
+ WritePreHeader(dwID,
+ PHONEMSG);
+
+ WritePhoneMsgStruct(dwID,
+ htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3);
+
+ ReleaseID(dwID);
+
+ (*glpPhoneEventProc32)(htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3);
+
+}
+
+
+#ifdef WIN32
+void CALLBACK //ASYNC_COMPLETION // PASCAL
+#else
+void CALLBACK __export
+#endif
+AsyncCompletionProc(DRV_REQUESTID dwRequestID,
+ LONG lResult)
+{
+
+ DWORD dwID;
+
+ DBGOUT((1, "Async completion callback"));
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, sizeof(PREHEADER) + sizeof(ASYNCSTRUCT));
+
+ WritePreHeader(dwID,
+ ASYNCMSG);
+
+ WriteAsyncStruct(dwID,
+ dwRequestID,
+ lResult);
+
+ ReleaseID(dwID);
+
+ (*glpAsyncCompletionProc32)( dwRequestID, lResult );
+
+}
+
+
+
+
+//
+// -------------------- TSPIAPI TSPI_line functions ---------------------------
+//
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineAccept(DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize)
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_lineAccept"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID,
+ SP_LINEACCEPT,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpsUserUserInfo,
+ (DWORD)dwSize);
+
+ WriteStruct(dwID,
+ dwSize,
+ (LPVOID)lpsUserUserInfo);
+
+ lReturn = (* GetProcAddressHashed(SP_LINEACCEPT, 4))(
+ dwRequestID,
+ hdCall,
+ lpsUserUserInfo,
+ dwSize);
+
+ WritePostStruct(dwID,
+ lReturn);
+
+ ReleaseID(dwID);
+
+ return lReturn;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HDRVCALL hdConsultCall
+ )
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3));
+
+ RepeaterDebugString((2, "Entering TSPI_lineAddToConference"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINEADDTOCONFERENCE,
+ dwRequestID,
+ (DWORD)hdConfCall,
+ (DWORD)hdConsultCall);
+
+ lReturn = (* GetProcAddressHashed(SP_LINEADDTOCONFERENCE,3))(
+ dwRequestID,
+ hdConfCall,
+ hdConsultCall);
+
+ WritePostStruct(dwID, lReturn);
+
+ ReleaseID(dwID);
+
+ return lReturn;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineAnswer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_lineAnswer"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINEACCEPT,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpsUserUserInfo,
+ (DWORD)dwSize);
+
+ WriteStruct(dwID, dwSize, (LPVOID)lpsUserUserInfo);
+
+ lReturn = (* GetProcAddressHashed(SP_LINEANSWER, 4))(
+ dwRequestID,
+ hdCall,
+ lpsUserUserInfo,
+ dwSize);
+
+ WritePostStruct(dwID, lReturn);
+
+ ReleaseID(dwID);
+
+ return lReturn;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineBlindTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode)
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + lstrlen(lpszDestAddress));
+
+ RepeaterDebugString((2, "Entering TSPI_lineBlindTransfer"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINEBLINDTRANSFER,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpszDestAddress,
+ dwCountryCode);
+
+ WriteStruct(dwID, lstrlen(lpszDestAddress), (LPVOID)lpszDestAddress);
+
+ lReturn = (* GetProcAddressHashed(SP_LINEBLINDTRANSFER, 4))(
+ dwRequestID,
+ hdCall,
+ lpszDestAddress,
+ dwCountryCode
+ );
+
+ WritePostStruct(dwID, lReturn);
+
+ ReleaseID(dwID);
+
+ return lReturn;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC1));
+
+ RepeaterDebugString((2, "Entering TSPI_lineClose"));
+
+ WritePreHeader(dwID, SPFUNC1);
+
+ WriteLogStruct1(dwID, SP_LINECLOSE,
+ (DWORD)hdLine);
+
+ lReturn = (* GetProcAddressHashed(SP_LINECLOSE, 1))(hdLine);
+
+ WritePostStruct(dwID, lReturn);
+
+ ReleaseID(dwID);
+
+ return lReturn;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC1));
+
+
+ RepeaterDebugString((2, "Entering TSPI_lineCloseCall"));
+
+ WritePreHeader(dwID, SPFUNC1);
+
+ WriteLogStruct1(dwID, SP_LINECLOSECALL,
+ (DWORD)hdCall);
+
+ lReturn = (* GetProcAddressHashed(SP_LINECLOSECALL, 1))(hdCall);
+
+ WritePostStruct(dwID, lReturn);
+
+ ReleaseID(dwID);
+
+ return lReturn;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineCompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPDWORD lpdwCompletionID,
+ DWORD dwCompletionMode,
+ DWORD dwMessageID
+ )
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + sizeof(DWORD));
+
+
+ RepeaterDebugString((2, "Entering TSPI_lineCompleteCall"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINECOMPLETECALL,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpdwCompletionID,
+ dwCompletionMode,
+ (DWORD)hdCall);
+
+ lReturn = (* GetProcAddressHashed(SP_LINECOMPLETECALL, 5))(
+ dwRequestID,
+ hdCall,
+ lpdwCompletionID,
+ dwCompletionMode,
+ hdCall
+ );
+
+ WritePostStruct(dwID, lReturn);
+
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwCompletionID);
+
+ ReleaseID(dwID);
+
+ return lReturn;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineCompleteTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVCALL hdConsultCall,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ DWORD dwTransferMode
+ )
+{
+ LONG lReturn;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC6) + sizeof(MYHDRVCALL));
+
+
+ RepeaterDebugString((2, "Entering TSPI_lineCompleteTransfer"));
+
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_LINECOMPLETETRANSFER,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)hdConsultCall,
+ (DWORD)htConfCall,
+ (DWORD)lphdConfCall,
+ dwTransferMode);
+
+ lReturn = (* GetProcAddressHashed(SP_LINECOMPLETETRANSFER, 6))(
+ dwRequestID,
+ hdCall,
+ hdConsultCall,
+ htConfCall,
+ lphdConfCall,
+ dwTransferMode
+ );
+
+ WritePostStruct(dwID, lReturn);
+
+ if (lReturn >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdConfCall);
+ }
+
+
+ ReleaseID(dwID);
+
+ return lReturn;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC3) +
+ (lpCallParams ? lpCallParams->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineConditionalMediaDetection"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINECONDITIONALMEDIADETECTION,
+ (DWORD)hdLine,
+ dwMediaModes,
+ (DWORD)lpCallParams);
+
+ if (lpCallParams)
+ {
+ WriteStruct(dwID, lpCallParams->dwTotalSize,
+ (LPVOID)lpCallParams);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINECONDITIONALMEDIADETECTION, 3))(
+ hdLine,
+ dwMediaModes,
+ lpCallParams);
+
+ WritePostStruct(dwID, lResult);
+
+ RepeaterDebugString((2, "Leaving TSPI_lineConditionalMediaDetection"));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+
+ LONG lResult = 0;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3) + lstrlen(lpszDeviceClass));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINECONFIGDIALOG,
+ dwDeviceID,
+#ifdef WIN32
+ (DWORD)hwndOwner,
+#else
+ MAKELONG(hwndOwner, 0),
+#endif
+ (DWORD)lpszDeviceClass);
+
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINECONFIGDIALOG, 3))(
+ dwDeviceID,
+ hwndOwner,
+ lpszDeviceClass
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineConfigDialogEdit(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass,
+ LPVOID const lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ RepeaterDebugString((2, "Entering TSPI_lineConfigDialogEdit"));
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC6) +
+ dwSize +
+ lstrlen(lpszDeviceClass) +
+ (lpDeviceConfigOut ? lpDeviceConfigOut->dwTotalSize : 0));
+
+
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_LINECONFIGDIALOGEDIT,
+ dwDeviceID,
+#ifdef WIN32
+ (DWORD)hwndOwner,
+#else
+ (DWORD)MAKELONG(hwndOwner, 0),
+#endif
+ (DWORD)lpszDeviceClass,
+ (DWORD)lpDeviceConfigIn,
+ dwSize,
+ (DWORD)lpDeviceConfigOut);
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+ if (lpDeviceConfigIn)
+ {
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpDeviceConfigIn);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINECONFIGDIALOGEDIT, 6))(
+ dwDeviceID,
+ hwndOwner,
+ lpszDeviceClass,
+ lpDeviceConfigIn,
+ dwSize,
+ lpDeviceConfigOut);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpDeviceConfigOut)
+ {
+ WriteStruct(dwID, lpDeviceConfigOut->dwTotalSize,
+ (LPVOID)lpDeviceConfigOut);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC6) + dwSize + dwSize);
+
+
+ RepeaterDebugString((2, "Entering TSPI_lineDevSpecific"));
+
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_LINEDEVSPECIFIC,
+ dwRequestID,
+ (DWORD)hdLine,
+ dwAddressID,
+ (DWORD)hdCall,
+ (DWORD)lpParams,
+ dwSize);
+
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpParams);
+
+
+ lResult = (* GetProcAddressHashed(SP_LINEDEVSPECIFIC, 6))(
+ dwRequestID,
+ hdLine,
+ dwAddressID,
+ hdCall,
+ lpParams,
+ dwSize);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpParams);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineDevSpecificFeature(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwFeature,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + dwSize + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_lineDevSpecificFeature"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINEDEVSPECIFICFEATURE,
+ dwRequestID,
+ (DWORD)hdLine,
+ dwFeature,
+ (DWORD)lpParams,
+ dwSize);
+
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpParams);
+
+ lResult = (* GetProcAddressHashed(SP_LINEDEVSPECIFICFEATURE, 5))(
+ dwRequestID,
+ hdLine,
+ dwFeature,
+ lpParams,
+ dwSize);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpParams);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineDial(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + lstrlen(lpszDestAddress));
+
+ RepeaterDebugString((2, "Entering TSPI_lineDial"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINEDIAL,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpszDestAddress,
+ dwCountryCode);
+
+ if (lpszDestAddress)
+ {
+ WriteStruct(dwID, lstrlen(lpszDestAddress),
+ (LPVOID)lpszDestAddress);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINEDIAL, 4))(
+ dwRequestID,
+ hdCall,
+ lpszDestAddress,
+ dwCountryCode
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_lineDrop"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINEDROP,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpsUserUserInfo,
+ dwSize);
+
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpsUserUserInfo);
+
+ lResult = (* GetProcAddressHashed(SP_LINEDROP, 4))(
+ dwRequestID,
+ hdCall,
+ lpsUserUserInfo,
+ dwSize
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineDropOnClose(
+ HDRVCALL hdCall
+ )
+{
+
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC1));
+
+ RepeaterDebugString((2, "Entering TSPI_lineDropOnClose"));
+
+ WritePreHeader(dwID, SPFUNC1);
+
+ WriteLogStruct1(dwID, SP_LINEDROPONCLOSE,
+ (DWORD)hdCall);
+
+ lResult = (* GetProcAddressHashed(SP_LINEDROPONCLOSE, 1))
+ (hdCall);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineDropNoOwner(
+ HDRVCALL hdCall
+ )
+{
+ TSPAPIPROC pfn;
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC1));
+
+
+ RepeaterDebugString((2, "Entering TSPI_lineDropNoOwner"));
+
+
+ WritePreHeader(dwID, SPFUNC1);
+
+ WriteLogStruct1(dwID, SP_LINEDROPNOOWNER,
+ (DWORD)hdCall);
+
+ pfn = (TSPAPIPROC)GetProcAddressHashed(SP_LINEDROPNOOWNER, 1);
+
+
+ if (pfn != (TSPAPIPROC)TSPI_LineBlank1)
+ {
+ lResult = (*pfn)(hdCall);
+ }
+ else
+ {
+ RepeaterDebugString((4, " This SP does not export DROPNOOWNER, so we'll call LINEDROP"));
+
+ lResult = (* GetProcAddressHashed(SP_LINEDROP, 4))(
+ (DWORD) BOGUS_REQUEST_ID,
+ (DWORD) hdCall,
+ (DWORD) NULL,
+ (DWORD) 0
+ );
+
+ //
+ // Did we get an error back sync?
+ //
+ if (
+ (lResult < 0)
+ &&
+ (lResult != BOGUS_REQUEST_ID)
+ )
+ {
+ //
+ // Yup. Return it.
+ //
+ }
+ else
+ {
+ //
+ // No, we got back the req id. Return success.
+ //
+ lResult = 0;
+ }
+ }
+
+ RepeaterDebugString((3, "Leaving TSPI_lineDropNoOwner, return code=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineForward(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD bAllAddresses,
+ DWORD dwAddressID,
+ LPLINEFORWARDLIST const lpForwardList,
+ DWORD dwNumRingsNoAnswer,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC9) +
+ (lpForwardList ? lpForwardList->dwTotalSize : 0) +
+ (lpCallParams ? lpCallParams->dwTotalSize : 0) +
+ sizeof(HDRVCALL));
+
+ RepeaterDebugString((2, "Entering TSPI_lineForward"));
+
+ WritePreHeader(dwID, SPFUNC9);
+
+ WriteLogStruct9(dwID, SP_LINEFORWARD,
+ dwRequestID,
+ (DWORD)hdLine,
+ (DWORD)bAllAddresses,
+ dwAddressID,
+ (DWORD)lpForwardList,
+ (DWORD)dwNumRingsNoAnswer,
+ (DWORD)htConsultCall,
+ (DWORD)lphdConsultCall,
+ (DWORD)lpCallParams);
+
+ if (lpForwardList)
+ {
+ WriteStruct(dwID, lpForwardList->dwTotalSize,
+ (LPVOID)lpForwardList);
+ }
+
+ if (lpCallParams)
+ {
+ WriteStruct(dwID, lpCallParams->dwTotalSize,
+ (LPVOID)lpCallParams);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINEFORWARD, 9))(
+ dwRequestID,
+ (HDRVLINE)hdLine,
+ bAllAddresses,
+ dwAddressID,
+ lpForwardList,
+ dwNumRingsNoAnswer,
+ htConsultCall,
+ lphdConsultCall,
+ lpCallParams
+ );
+
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdConsultCall);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGatherDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitModes,
+#ifdef WIN32
+ LPWSTR lpsDigits,
+#else
+ LPSTR lpsDigits,
+#endif
+ DWORD dwNumDigits,
+ LPCWSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC8) + lstrlen(lpszTerminationDigits));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGatherDigits"));
+
+ WritePreHeader(dwID, SPFUNC8);
+
+ WriteLogStruct8(dwID, SP_LINEGATHERDIGITS,
+ (DWORD)hdCall,
+ dwEndToEndID,
+ dwDigitModes,
+ (DWORD)lpsDigits,
+ dwNumDigits,
+ (DWORD)lpszTerminationDigits,
+ dwFirstDigitTimeout,
+ dwInterDigitTimeout);
+
+
+ // lpsDigits?
+
+ if (lpszTerminationDigits)
+ {
+ WriteStruct(dwID, lstrlen(lpszTerminationDigits),
+ (LPVOID)lpszTerminationDigits);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINEGATHERDIGITS, 8))(
+ hdCall,
+ dwEndToEndID,
+ dwDigitModes,
+ lpsDigits,
+ dwNumDigits,
+ lpszTerminationDigits,
+ dwFirstDigitTimeout,
+ dwInterDigitTimeout);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGenerateDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitMode,
+ LPCWSTR lpszDigits,
+ DWORD dwDuration
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + lstrlen(lpszDigits));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGenerateDigits"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINEGENERATEDIGITS,
+ (DWORD)hdCall,
+ dwEndToEndID,
+ dwDigitMode,
+ (DWORD)lpszDigits,
+ dwDuration);
+
+ if (lpszDigits)
+ {
+ WriteStruct(dwID, lstrlen(lpszDigits),
+ (LPVOID)lpszDigits);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINEGENERATEDIGITS, 5))(
+ hdCall,
+ dwEndToEndID,
+ dwDigitMode,
+ lpszDigits,
+ dwDuration );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGenerateTone(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwToneMode,
+ DWORD dwDuration,
+ DWORD dwNumTones,
+ LPLINEGENERATETONE const lpTones
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC6) + dwNumTones * sizeof(LINEGENERATETONE));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGenerateTone"));
+
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_LINEGENERATETONE,
+ (DWORD)hdCall,
+ dwEndToEndID,
+ dwToneMode,
+ dwDuration,
+ dwNumTones,
+ (DWORD)lpTones);
+
+ WriteStruct(dwID, dwNumTones * sizeof(LINEGENERATETONE),
+ (LPVOID)lpTones);
+
+ lResult = (* GetProcAddressHashed(SP_LINEGENERATETONE, 6))(
+ hdCall,
+ dwEndToEndID,
+ dwToneMode,
+ dwDuration,
+ dwNumTones,
+ lpTones );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC5) +
+ (lpAddressCaps ? lpAddressCaps->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetAddressCaps"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINEGETADDRESSCAPS,
+ dwDeviceID,
+ dwAddressID,
+ dwTSPIVersion,
+ dwExtVersion,
+ (DWORD)lpAddressCaps);
+
+ lResult = (* GetProcAddressHashed(SP_LINEGETADDRESSCAPS, 5))(
+ dwDeviceID,
+ dwAddressID,
+ dwTSPIVersion,
+ dwExtVersion,
+ lpAddressCaps
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpAddressCaps)
+ {
+ WriteStruct(dwID, lpAddressCaps->dwUsedSize,
+ (LPVOID)lpAddressCaps);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCWSTR lpsAddress,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + dwSize + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetAddressID"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINEGETADDRESSID,
+ (DWORD)hdLine,
+ (DWORD)lpdwAddressID,
+ dwAddressMode,
+ (DWORD)lpsAddress,
+ dwSize);
+
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpsAddress);
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINEGETADDRESSID, 5))(
+ hdLine,
+ lpdwAddressID,
+ dwAddressMode,
+ lpsAddress,
+ dwSize
+ );
+
+ RepeaterDebugString((2, "Leaving TSPI_lineGetAddressID"));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwAddressID);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC3) +
+ (lpAddressStatus ? lpAddressStatus->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetAddressStatus"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINEGETADDRESSSTATUS,
+ (DWORD)hdLine,
+ dwAddressID,
+ (DWORD)lpAddressStatus);
+
+ lResult = (* GetProcAddressHashed(SP_LINEGETADDRESSSTATUS, 3))(
+ hdLine,
+ dwAddressID,
+ lpAddressStatus);
+
+ RepeaterDebugString((2, "Leaving TSPI_lineGetAddressStatus"));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpAddressStatus)
+ {
+ WriteStruct(dwID, lpAddressStatus->dwUsedSize,
+ (LPVOID)lpAddressStatus);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetCallAddressID"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEGETCALLADDRESSID,
+ (DWORD)hdCall,
+ (DWORD)lpdwAddressID);
+
+ lResult = (* GetProcAddressHashed(SP_LINEGETCALLADDRESSID, 2))(
+ hdCall,
+ lpdwAddressID
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwAddressID);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC2) +
+ (lpCallInfo? lpCallInfo->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetCallInfo"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEGETCALLINFO,
+ (DWORD)hdCall,
+ (DWORD)lpCallInfo);
+
+ lResult = (* GetProcAddressHashed(SP_LINEGETCALLINFO, 2))(
+ hdCall,
+ lpCallInfo
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpCallInfo)
+ {
+ WriteStruct(dwID, lpCallInfo->dwUsedSize,
+ (LPVOID)lpCallInfo);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+{
+
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC2) +
+ (lpCallStatus ? lpCallStatus->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetCallStatus"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEGETCALLSTATUS,
+ (DWORD)hdCall,
+ (DWORD)lpCallStatus);
+
+
+ lResult = (* GetProcAddressHashed(SP_LINEGETCALLSTATUS, 2))(
+ hdCall,
+ lpCallStatus
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpCallStatus)
+ {
+ WriteStruct(dwID, lpCallStatus->dwUsedSize,
+ (LPVOID)lpCallStatus);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+ {
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC4) +
+ (lpLineDevCaps ? lpLineDevCaps->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetDevCaps"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINEGETDEVCAPS,
+ dwDeviceID,
+ dwTSPIVersion,
+ dwExtVersion,
+ (DWORD)lpLineDevCaps);
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINEGETDEVCAPS, 4))(
+ dwDeviceID,
+ dwTSPIVersion,
+ dwExtVersion,
+ lpLineDevCaps
+ );
+
+ DBGOUT((2, "Leaving TSPI_lineGetDevCaps retcode=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpLineDevCaps)
+ {
+ WriteStruct(dwID, lpLineDevCaps->dwUsedSize,
+ (LPVOID)lpLineDevCaps);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetDevConfig(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC3) +
+ (lpDeviceConfig ? lpDeviceConfig->dwTotalSize : 0) +
+ lstrlen(lpszDeviceClass));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetDevConfig"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINEGETDEVCONFIG,
+ dwDeviceID,
+ (DWORD)lpDeviceConfig,
+ (DWORD)lpszDeviceClass);
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINEGETDEVCONFIG, 3))(
+ dwDeviceID,
+ lpDeviceConfig,
+ lpszDeviceClass
+ );
+
+ DBGOUT((2, "Leaving TSPI_lineGetDevConfig retcode=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpDeviceConfig)
+ {
+ WriteStruct(dwID, lpDeviceConfig->dwUsedSize,
+ (LPVOID)lpDeviceConfig);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPLINEEXTENSIONID lpExtensionID
+ )
+{
+
+ LONG lResult = 0;
+ DWORD dwID;
+ TSPAPIPROC lpfn;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3) + sizeof(LINEEXTENSIONID));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetExtensionID"));
+
+ lpfn = (TSPAPIPROC)GetProcAddressHashed(SP_LINEGETEXTENSIONID, 3);
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINEGETEXTENSIONID,
+ dwDeviceID,
+ dwTSPIVersion,
+ (DWORD)lpExtensionID);
+
+ if (lpfn != (TSPAPIPROC)TSPI_LineBlank3)
+ {
+
+ lResult =
+ (* lpfn)(
+ dwDeviceID,
+ dwTSPIVersion,
+ lpExtensionID
+ );
+ }
+ else
+ {
+ RepeaterDebugString((2, " SP does not support TSPI_lineGetExtensionID. (We'll fill in zeros.)"));
+
+ lpExtensionID->dwExtensionID0 = 0;
+ lpExtensionID->dwExtensionID1 = 0;
+ lpExtensionID->dwExtensionID2 = 0;
+ lpExtensionID->dwExtensionID3 = 0;
+ }
+
+
+
+ RepeaterDebugString((2, "Leaving TSPI_lineGetExtensionID retcode=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(LINEEXTENSIONID),
+ (LPVOID)lpExtensionID);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetIcon(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC3) +
+ lstrlen(lpszDeviceClass) +
+ sizeof(HICON));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetIcon"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINEGETICON,
+ dwDeviceID,
+ (DWORD)lpszDeviceClass,
+ (DWORD)lphIcon);
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINEGETICON, 3))(
+ dwDeviceID,
+ lpszDeviceClass,
+ lphIcon
+ );
+
+ DBGOUT((2, "Leaving TSPI_lineGetIcon retcode=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HICON),
+ (LPVOID)lphIcon);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ ,
+ HANDLE hTargetProcess
+#endif
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC7) +
+ lstrlen(lpszDeviceClass) +
+ (lpDeviceID ? lpDeviceID->dwTotalSize : 0));
+
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetID"));
+
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+
+ WritePreHeader(dwID, SPFUNC7);
+
+ WriteLogStruct7(dwID, SP_LINEGETID,
+ (DWORD)hdLine,
+ (DWORD)dwAddressID,
+ (DWORD)hdCall,
+ (DWORD)dwSelect,
+ (DWORD)lpDeviceID,
+ (DWORD)lpszDeviceClass,
+ (DWORD)hTargetProcess);
+#else
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_LINEGETID,
+ (DWORD)hdLine,
+ (DWORD)dwAddressID,
+ (DWORD)hdCall,
+ (DWORD)dwSelect,
+ (DWORD)lpDeviceID,
+ (DWORD)lpszDeviceClass );
+#endif
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ lResult = (* GetProcAddressHashed(SP_LINEGETID, 7))(
+ hdLine,
+ dwAddressID,
+ hdCall,
+ dwSelect,
+ lpDeviceID,
+ lpszDeviceClass,
+ hTargetProcess);
+#else
+ lResult = (* GetProcAddressHashed(SP_LINEGETID, 6))(
+ hdLine,
+ dwAddressID,
+ hdCall,
+ dwSelect,
+ lpDeviceID,
+ lpszDeviceClass);
+#endif
+
+ RepeaterDebugString((2, "Leaving TSPI_lineGetID - lResult=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpDeviceID)
+ {
+ WriteStruct(dwID, lpDeviceID->dwUsedSize,
+ (LPVOID)lpDeviceID);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC2) +
+ (lpLineDevStatus ? lpLineDevStatus->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetLineDevStatus"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEGETLINEDEVSTATUS,
+ (DWORD)hdLine,
+ (DWORD)lpLineDevStatus);
+
+ lResult = (* GetProcAddressHashed(SP_LINEGETLINEDEVSTATUS, 2))(
+ hdLine,
+ lpLineDevStatus);
+
+ RepeaterDebugString((2, "Leaving TSPI_lineGetLineDevStatus"));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpLineDevStatus)
+ {
+ WriteStruct(dwID, lpLineDevStatus->dwUsedSize,
+ (LPVOID)lpLineDevStatus);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_lineGetNumAddressIDs"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEGETNUMADDRESSIDS,
+ (DWORD)hdLine,
+ (DWORD)lpdwNumAddressIDs);
+
+ lResult = (* GetProcAddressHashed(SP_LINEGETNUMADDRESSIDS, 2))(
+ hdLine,
+ lpdwNumAddressIDs );
+
+ RepeaterDebugString((2, "Leaving TSPI_lineGetNumAddressIDs - returning 0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwNumAddressIDs);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineHold"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEHOLD,
+ dwRequestID,
+ (DWORD)hdCall);
+
+ lResult = (* GetProcAddressHashed(SP_LINEHOLD, 2))(
+ dwRequestID,
+ hdCall
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC7) +
+ sizeof(HDRVCALL) +
+ lstrlen(lpszDestAddress) +
+ (lpCallParams?lpCallParams->dwTotalSize:0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineMakeCall"));
+
+ WritePreHeader(dwID, SPFUNC7);
+
+ WriteLogStruct7(dwID, SP_LINEMAKECALL,
+ dwRequestID,
+ (DWORD)hdLine,
+ (DWORD)htCall,
+ (DWORD)lphdCall,
+ (DWORD)lpszDestAddress,
+ dwCountryCode,
+ (DWORD)lpCallParams);
+
+ if (lpszDestAddress)
+ {
+ WriteStruct(dwID, lstrlen(lpszDestAddress),
+ (LPVOID)lpszDestAddress);
+ }
+
+ if (lpCallParams)
+ {
+ WriteStruct(dwID, lpCallParams->dwTotalSize,
+ (LPVOID)lpCallParams);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINEMAKECALL, 7))
+ (
+ dwRequestID,
+ hdLine,
+ htCall,
+ lphdCall,
+ lpszDestAddress,
+ dwCountryCode,
+ lpCallParams
+ );
+
+
+ RepeaterDebugString((2, "Leaving TSPI_lineMakeCall - returning 0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdCall);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineMonitorDigits(
+ HDRVCALL hdCall,
+ DWORD dwDigitModes
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineMonitorDigits"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEMONITORDIGITS,
+ (DWORD)hdCall,
+ dwDigitModes);
+
+ lResult = (* GetProcAddressHashed(SP_LINEMONITORDIGITS, 2))(
+ hdCall,
+ dwDigitModes
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineMonitorMedia(
+ HDRVCALL hdCall,
+ DWORD dwMediaModes
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineMonitorMedia"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEMONITORMEDIA,
+ (DWORD)hdCall,
+ dwMediaModes);
+
+ lResult = (* GetProcAddressHashed(SP_LINEMONITORMEDIA, 2))(
+ hdCall,
+ dwMediaModes
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineMonitorTones(
+ HDRVCALL hdCall,
+ DWORD dwToneListID,
+ LPLINEMONITORTONE const lpToneList,
+ DWORD dwNumEntries
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + dwNumEntries * sizeof(LINEMONITORTONE));
+
+ RepeaterDebugString((2, "Entering TSPI_lineMonitorTones"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINEMONITORTONES,
+ (DWORD)hdCall,
+ dwToneListID,
+ (DWORD)lpToneList,
+ dwNumEntries);
+
+ WriteStruct(dwID, sizeof(LINEMONITORTONE) * dwNumEntries,
+ (LPVOID)lpToneList);
+
+ lResult = (* GetProcAddressHashed(SP_LINEMONITORTONES, 4))(
+ hdCall,
+ dwToneListID,
+ lpToneList,
+ dwNumEntries
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_lineNegotiateExtVersion"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINENEGOTIATEEXTVERSION,
+ dwDeviceID,
+ dwTSPIVersion,
+ dwLowVersion,
+ dwHighVersion,
+ (DWORD)lpdwExtVersion);
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINENEGOTIATEEXTVERSION, 5))(
+ dwDeviceID,
+ dwTSPIVersion,
+ dwLowVersion,
+ dwHighVersion,
+ lpdwExtVersion
+ );
+
+
+ DBGOUT((2, "Leaving TSPI_lineNegotiateExeVersion retcode=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwExtVersion);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ LONG lResult = 0;
+ DWORD dwID;
+
+ if (!gbStarted)
+ {
+ StartMeUp();
+ }
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + sizeof(DWORD));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINENEGOTIATETSPIVERSION,
+ dwDeviceID,
+ dwLowVersion,
+ dwHighVersion,
+ (DWORD)lpdwTSPIVersion);
+
+ RepeaterDebugString((2, "Entering TSPI_lineNegotiateTSPIVersion"));
+
+ /// bugbugbug!! call the *(&(^$ function
+
+ lResult = (* GetProcAddressHashed(SP_LINENEGOTIATETSPIVERSION, 4))(
+ dwDeviceID,
+ dwLowVersion,
+ dwHighVersion,
+ lpdwTSPIVersion);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwTSPIVersion);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + sizeof(HDRVLINE));
+
+ RepeaterDebugString((2, "Entering TSPI_lineOpen"));
+
+ glpLineEventProc32 = lpfnEventProc;
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINEOPEN,
+ dwDeviceID,
+ (DWORD)htLine,
+ (DWORD)lphdLine,
+ dwTSPIVersion,
+ (DWORD)lpfnEventProc);
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINEOPEN, 5))(
+ dwDeviceID,
+ htLine,
+ lphdLine,
+ dwTSPIVersion,
+ LineEventProc
+ );
+
+ DBGOUT((2, "Leaving TSPI_lineOpen retcode=0x%08lx", lResult));
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVLINE),
+ (LPVOID)lphdLine);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_linePark(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwParkMode,
+ LPCWSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC5) +
+ lstrlen(lpszDirAddress) +
+ (lpNonDirAddress ? lpNonDirAddress->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_linePark"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINEPARK,
+ dwRequestID,
+ (DWORD)hdCall,
+ dwParkMode,
+ (DWORD)lpszDirAddress,
+ (DWORD)lpNonDirAddress);
+
+ if (dwParkMode & LINEPARKMODE_DIRECTED)
+ {
+ if (lpszDirAddress)
+ {
+ WriteStruct(dwID, lstrlen(lpszDirAddress),
+ (LPVOID)lpszDirAddress);
+ }
+ }
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINEPARK, 5))(
+ dwRequestID,
+ hdCall,
+ dwParkMode,
+ lpszDirAddress,
+ lpNonDirAddress);
+
+ WritePostStruct(dwID, lResult);
+
+ if ((lResult >= 0) && (dwParkMode & LINEPARKMODE_NONDIRECTED))
+ {
+ if (lpNonDirAddress)
+ {
+ WriteStruct(dwID, lpNonDirAddress->dwUsedSize,
+ (LPVOID)lpNonDirAddress);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_linePickup(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress,
+ LPCWSTR lpszGroupID
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC7) +
+ lstrlen(lpszDestAddress) +
+ lstrlen(lpszGroupID) +
+ sizeof(HDRVCALL));
+
+ RepeaterDebugString((2, "Entering TSPI_linePickup"));
+
+ WritePreHeader(dwID, SPFUNC7);
+
+ WriteLogStruct7(dwID, SP_LINEPICKUP,
+ dwRequestID,
+ (DWORD)hdLine,
+ (DWORD)dwAddressID,
+ (DWORD)htCall,
+ (DWORD)lphdCall,
+ (DWORD)lpszDestAddress,
+ (DWORD)lpszGroupID);
+
+ if (lpszDestAddress)
+ {
+ WriteStruct(dwID, lstrlen(lpszDestAddress),
+ (LPVOID)lpszDestAddress);
+ }
+
+ if (lpszGroupID)
+ {
+ WriteStruct(dwID, lstrlen(lpszGroupID),
+ (LPVOID)lpszGroupID);
+ }
+
+ lResult =
+ (* GetProcAddressHashed(SP_LINEPICKUP, 7))(
+ dwRequestID,
+ hdLine,
+ dwAddressID,
+ htCall,
+ lphdCall,
+ lpszDestAddress,
+ lpszGroupID);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdCall);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_linePrepareAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC5) +
+ (lpCallParams?lpCallParams->dwTotalSize:0) +
+ sizeof(HDRVCALL));
+
+ RepeaterDebugString((2, "Entering TSPI_linePrepareAddToConference"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINEPREPAREADDTOCONFERENCE,
+ dwRequestID,
+ (DWORD)hdConfCall,
+ (DWORD)htConsultCall,
+ (DWORD)lphdConsultCall,
+ (DWORD)lpCallParams);
+
+ if (lpCallParams)
+ {
+ WriteStruct(dwID, lpCallParams->dwTotalSize,
+ (LPVOID)lpCallParams);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINEPREPAREADDTOCONFERENCE,
+ 5))(
+ dwRequestID,
+ hdConfCall,
+ htConsultCall,
+ lphdConsultCall,
+ lpCallParams);
+
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdConsultCall);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineRedirect(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC4) +
+ lstrlen(lpszDestAddress));
+
+ RepeaterDebugString((2, "Entering TSPI_lineRedirect"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINEREDIRECT,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpszDestAddress,
+ dwCountryCode);
+
+ if (lpszDestAddress)
+ {
+ WriteStruct(dwID, lstrlen(lpszDestAddress),
+ (LPVOID)lpszDestAddress);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINEREDIRECT,
+ 4))(
+ dwRequestID,
+ hdCall,
+ lpszDestAddress,
+ dwCountryCode);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineRemoveFromConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineRemoveFromConference"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEREMOVEFROMCONFERENCE,
+ dwRequestID,
+ (DWORD)hdCall);
+
+ lResult = (* GetProcAddressHashed(SP_LINEREMOVEFROMCONFERENCE,
+ 2))(
+ dwRequestID,
+ hdCall);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSecureCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSecureCall"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINESECURECALL,
+ dwRequestID,
+ (DWORD)hdCall);
+
+ lResult = (* GetProcAddressHashed(SP_LINESECURECALL,
+ 2))(
+ dwRequestID,
+ hdCall);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSelectExtVersion(
+ HDRVLINE hdLine,
+ DWORD dwExtVersion
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSelectExtVersion"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINESELECTEXTVERSION,
+ (DWORD)hdLine,
+ (DWORD)dwExtVersion);
+
+ lResult = (* GetProcAddressHashed(SP_LINESELECTEXTVERSION,
+ 2))(
+ hdLine,
+ dwExtVersion);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSendUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_lineSendUserUserInfo"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINESENDUSERUSERINFO,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)lpsUserUserInfo,
+ dwSize);
+
+ if (lpsUserUserInfo)
+ {
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpsUserUserInfo);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINESENDUSERUSERINFO,
+ 4))(
+ dwRequestID,
+ hdCall,
+ lpsUserUserInfo,
+ dwSize);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetAppSpecific"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINESETAPPSPECIFIC,
+ (DWORD)hdCall,
+ dwAppSpecific);
+
+ lResult = (* GetProcAddressHashed(SP_LINESETAPPSPECIFIC, 2))(
+ hdCall,
+ dwAppSpecific
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetCallParams(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwBearerMode,
+ DWORD dwMinRate,
+ DWORD dwMaxRate,
+ LPLINEDIALPARAMS const lpDialParams
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC6) + sizeof(LINEDIALPARAMS));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetCallParams"));
+
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_LINESETCALLPARAMS,
+ dwRequestID,
+ (DWORD)hdCall,
+ dwBearerMode,
+ dwMinRate,
+ dwMaxRate,
+ (DWORD)lpDialParams);
+
+ if (lpDialParams)
+ {
+ WriteStruct(dwID, sizeof(LINEDIALPARAMS),
+ (LPVOID)lpDialParams);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINESETCALLPARAMS, 6))(
+ dwRequestID,
+ hdCall,
+ dwBearerMode,
+ dwMinRate,
+ dwMaxRate,
+ lpDialParams
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetCurrentLocation(
+ DWORD dwLocation
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC1));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetCurrentLocation"));
+
+ WritePreHeader(dwID, SPFUNC1);
+
+ WriteLogStruct1(dwID, SP_LINESETCURRENTLOCATION,
+ dwLocation);
+
+ lResult = (* GetProcAddressHashed(SP_LINESETCURRENTLOCATION, 1))
+ (dwLocation);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetDefaultMediaDetection"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINESETDEFAULTMEDIADETECTION,
+ (DWORD)hdLine,
+ dwMediaModes);
+
+ lResult = (* GetProcAddressHashed(
+ SP_LINESETDEFAULTMEDIADETECTION,
+ 2
+ ))(hdLine, dwMediaModes);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetDevConfig(
+ DWORD dwDeviceID,
+ LPVOID const lpDeviceConfig,
+ DWORD dwSize,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC4) +
+ dwSize +
+ lstrlen(lpszDeviceClass));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetDevConfig"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_LINESETDEVCONFIG,
+ (DWORD)dwDeviceID,
+ (DWORD)lpDeviceConfig,
+ dwSize,
+ (DWORD)lpszDeviceClass);
+
+ if (lpDeviceConfig)
+ {
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpDeviceConfig);
+ }
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINESETDEVCONFIG, 4))(
+ dwDeviceID,
+ lpDeviceConfig,
+ dwSize,
+ lpszDeviceClass
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetMediaControl(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPLINEMEDIACONTROLDIGIT const lpDigitList,
+ DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA const lpMediaList,
+ DWORD dwMediaNumEntries,
+ LPLINEMEDIACONTROLTONE const lpToneList,
+ DWORD dwToneNumEntries,
+ LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
+ DWORD dwCallStateNumEntries
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC12) +
+ sizeof(LINEMEDIACONTROLDIGIT) * dwDigitNumEntries +
+ sizeof(LINEMEDIACONTROLMEDIA) * dwMediaNumEntries +
+ sizeof(LINEMEDIACONTROLTONE) * dwToneNumEntries +
+ sizeof(LINEMEDIACONTROLCALLSTATE) * dwCallStateNumEntries);
+
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetMediaControl"));
+
+ WritePreHeader(dwID, SPFUNC12);
+
+ WriteLogStruct12(dwID, SP_LINESETMEDIACONTROL,
+ (DWORD)hdLine,
+ dwAddressID,
+ (DWORD)hdCall,
+ dwSelect,
+ (DWORD)lpDigitList,
+ dwDigitNumEntries,
+ (DWORD)lpMediaList,
+ dwMediaNumEntries,
+ (DWORD)lpToneList,
+ dwToneNumEntries,
+ (DWORD)lpCallStateList,
+ dwCallStateNumEntries);
+
+ if (lpDigitList)
+ {
+ WriteStruct(dwID, sizeof(LINEMEDIACONTROLDIGIT) * dwDigitNumEntries,
+ (LPVOID)lpDigitList);
+ }
+
+ if (lpMediaList)
+ {
+ WriteStruct(dwID, sizeof(LINEMEDIACONTROLMEDIA) * dwMediaNumEntries,
+ (LPVOID)lpMediaList);
+ }
+
+ if (lpToneList)
+ {
+ WriteStruct(dwID, sizeof(LINEMEDIACONTROLTONE) * dwToneNumEntries,
+ (LPVOID)lpToneList);
+ }
+
+ if (lpCallStateList)
+ {
+ WriteStruct(dwID, sizeof(LINEMEDIACONTROLCALLSTATE) * dwCallStateNumEntries,
+ (LPVOID)lpCallStateList);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINESETMEDIACONTROL,
+ 12))
+ (hdLine,
+ dwAddressID,
+ hdCall,
+ dwSelect,
+ lpDigitList,
+ dwDigitNumEntries,
+ lpMediaList,
+ dwMediaNumEntries,
+ lpToneList,
+ dwToneNumEntries,
+ lpCallStateList,
+ dwCallStateNumEntries);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetMediaMode"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINESETMEDIAMODE,
+ (DWORD)hdCall,
+ dwMediaMode);
+
+ lResult = (* GetProcAddressHashed(SP_LINESETMEDIAMODE, 2))(
+ hdCall,
+ dwMediaMode
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetStatusMessages(
+ HDRVLINE hdLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetStatusMessages"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINESETSTATUSMESSAGES,
+ (DWORD)hdLine,
+ dwLineStates,
+ dwAddressStates);
+
+ lResult = (* GetProcAddressHashed(SP_LINESETSTATUSMESSAGES, 3))(
+ hdLine,
+ dwLineStates,
+ dwAddressStates
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetTerminal(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ DWORD dwTerminalModes,
+ DWORD dwTerminalID,
+ DWORD bEnable
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC8));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetTerminal"));
+
+ WritePreHeader(dwID, SPFUNC8);
+
+ WriteLogStruct8(dwID, SP_LINESETTERMINAL,
+ dwRequestID,
+ (DWORD)hdLine,
+ dwAddressID,
+ (DWORD)hdCall,
+ dwSelect,
+ dwTerminalModes,
+ dwTerminalID,
+ bEnable);
+
+ lResult = (* GetProcAddressHashed(SP_LINESETTERMINAL,
+ 8))(
+ dwRequestID,
+ hdLine,
+ dwAddressID,
+ hdCall,
+ dwSelect,
+ dwTerminalModes,
+ dwTerminalID,
+ bEnable);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetupConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVLINE hdLine,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC9) +
+ sizeof(HDRVCALL) +
+ sizeof(HDRVCALL));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetupConference"));
+
+ WritePreHeader(dwID, SPFUNC9);
+
+ WriteLogStruct9(dwID, SP_LINESETUPCONFERENCE,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)hdLine,
+ (DWORD)htConfCall,
+ (DWORD)lphdConfCall,
+ (DWORD)htConsultCall,
+ (DWORD)lphdConsultCall,
+ dwNumParties,
+ (DWORD)lpCallParams);
+
+ lResult = (* GetProcAddressHashed(SP_LINESETUPCONFERENCE,
+ 9))(
+ dwRequestID,
+ hdCall,
+ hdLine,
+ htConfCall,
+ lphdConfCall,
+ htConsultCall,
+ lphdConsultCall,
+ dwNumParties,
+ lpCallParams);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdConfCall);
+
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdConsultCall);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSetupTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC5) +
+ sizeof(HDRVCALL) +
+ (lpCallParams ? lpCallParams->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSetupTransfer"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_LINESETUPTRANSFER,
+ dwRequestID,
+ (DWORD)hdCall,
+ (DWORD)htConsultCall,
+ (DWORD)lphdConsultCall,
+ (DWORD)lpCallParams);
+
+ if (lpCallParams)
+ {
+ WriteStruct(dwID, lpCallParams->dwTotalSize,
+ (LPVOID)lpCallParams);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_LINESETUPTRANSFER,
+ 5))(
+ dwRequestID,
+ hdCall,
+ htConsultCall,
+ lphdConsultCall,
+ lpCallParams);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdConsultCall);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineSwapHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdActiveCall,
+ HDRVCALL hdHeldCall
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3));
+
+ RepeaterDebugString((2, "Entering TSPI_lineSwapHold"));
+
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINESWAPHOLD,
+ dwRequestID,
+ (DWORD)hdActiveCall,
+ (DWORD)hdHeldCall);
+
+
+ lResult = (* GetProcAddressHashed(SP_LINESWAPHOLD,
+ 3))(
+ dwRequestID,
+ hdActiveCall,
+ hdHeldCall);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineUncompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwCompletionID
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3));
+
+ RepeaterDebugString((2, "Entering TSPI_lineUncompleteCall"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_LINEUNCOMPLETECALL,
+ dwRequestID,
+ (DWORD)hdLine,
+ dwCompletionID);
+
+ lResult = (* GetProcAddressHashed(SP_LINEUNCOMPLETECALL,
+ 3))(
+ dwRequestID,
+ hdLine,
+ dwCompletionID);
+
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineUnhold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineUnhold"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINEUNHOLD,
+ dwRequestID,
+ (DWORD)hdCall);
+
+ lResult = (* GetProcAddressHashed(SP_LINEUNHOLD,
+ 2))(
+ dwRequestID,
+ hdCall);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineUnpark(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCWSTR lpszDestAddress
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC6) +
+ lstrlen(lpszDestAddress) +
+ sizeof(HDRVCALL));
+
+ RepeaterDebugString((2, "Entering TSPI_lineUnpark"));
+
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_LINEUNPARK,
+ dwRequestID,
+ (DWORD)hdLine,
+ dwAddressID,
+ (DWORD)htCall,
+ (DWORD)lphdCall,
+ (DWORD)lpszDestAddress);
+
+ if (lpszDestAddress)
+ {
+ WriteStruct(dwID, lstrlen(lpszDestAddress),
+ (LPVOID)lpszDestAddress);
+ }
+
+ lResult= (* GetProcAddressHashed(SP_LINEUNPARK,
+ 6))(
+ dwRequestID,
+ hdLine,
+ dwAddressID,
+ htCall,
+ lphdCall,
+ lpszDestAddress);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HDRVCALL),
+ (LPVOID)lphdCall);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+LONG
+TSPIAPI
+TSPI_lineReleaseUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_lineReleaseUserUserInfo"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_LINERELEASEUSERUSERINFO,
+ (DWORD)dwRequestID,
+ (DWORD)hdCall);
+
+ lResult = (* GetProcAddressHashed(SP_LINERELEASEUSERUSERINFO,
+ 2))(
+ dwRequestID,
+ hdCall);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+
+//
+// ----------------------- TSPIAPI TSPI_phone functions -----------------------
+//
+
+LONG
+TSPIAPI
+TSPI_phoneClose(
+ HDRVPHONE hdPhone
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC1));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneClose"));
+
+ WritePreHeader(dwID, SPFUNC1);
+
+ WriteLogStruct1(dwID, SP_PHONECLOSE,
+ (DWORD)hdPhone);
+
+ lResult = (* GetProcAddressHashed(SP_PHONECLOSE, 1))(
+ hdPhone
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneClose - lResult=0x%08lx", lResult));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC3) +
+ lstrlen(lpszDeviceClass));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONECONFIGDIALOG,
+ dwDeviceID,
+#ifdef WIN32
+ (DWORD)hwndOwner,
+#else
+ (DWORD)MAKELONG(hwndOwner, 0),
+#endif
+ (DWORD)lpszDeviceClass);
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_PHONECONFIGDIALOG, 3))(
+ dwDeviceID,
+ hwndOwner,
+ lpszDeviceClass);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_phoneDevSpecific"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONEDEVSPECIFIC,
+ dwRequestID,
+ (DWORD)hdPhone,
+ (DWORD)lpParams,
+ (DWORD)dwSize);
+
+ if (lpParams)
+ {
+ WriteStruct(dwID, dwSize,
+ (LPVOID)lpParams);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_PHONEDEVSPECIFIC,
+ 4))(
+ dwRequestID,
+ hdPhone,
+ lpParams,
+ dwSize);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetButtonInfo(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO lpButtonInfo
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC3) +
+ (lpButtonInfo ? lpButtonInfo->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetButtonInfo"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETBUTTONINFO,
+ (DWORD)hdPhone,
+ dwButtonLampID,
+ (DWORD)lpButtonInfo);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETBUTTONINFO,
+ 3))(
+ hdPhone,
+ dwButtonLampID,
+ lpButtonInfo);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpButtonInfo)
+ {
+ WriteStruct(dwID, lpButtonInfo->dwUsedSize,
+ (LPVOID)lpButtonInfo);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetData(
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID lpData,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetData"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONEGETDATA,
+ (DWORD)hdPhone,
+ (DWORD)dwDataID,
+ (DWORD)lpData,
+ dwSize);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETDATA,
+ 4))(
+ hdPhone,
+ dwDataID,
+ lpData,
+ dwSize);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpData)
+ {
+ WriteStruct(dwID, dwSize,
+ lpData);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPPHONECAPS lpPhoneCaps
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC4) +
+ (lpPhoneCaps ? lpPhoneCaps->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetDevCaps"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONEGETDEVCAPS,
+ dwDeviceID,
+ dwTSPIVersion,
+ dwExtVersion,
+ (DWORD)lpPhoneCaps);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETDEVCAPS, 4))(
+ dwDeviceID,
+ dwTSPIVersion,
+ dwExtVersion,
+ lpPhoneCaps
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpPhoneCaps)
+ {
+ WriteStruct(dwID, lpPhoneCaps->dwUsedSize,
+ (LPVOID)lpPhoneCaps);
+ }
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetDevCaps"));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDisplay(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDisplay
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC2) +
+ (lpDisplay ? lpDisplay->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetDisplay"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_PHONEGETDISPLAY,
+ (DWORD)hdPhone,
+ (DWORD)lpDisplay);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETDISPLAY,
+ 2))(
+ hdPhone,
+ lpDisplay);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpDisplay)
+ {
+ WriteStruct(dwID, lpDisplay->dwUsedSize,
+ (LPVOID)lpDisplay);
+ }
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPPHONEEXTENSIONID lpExtensionID
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+ TSPAPIPROC lpfn;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3) + sizeof(PHONEEXTENSIONID));
+
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetExtensionID"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETEXTENSIONID,
+ dwDeviceID,
+ dwTSPIVersion,
+ (DWORD)lpExtensionID);
+
+
+ lpfn = GetProcAddressHashed(SP_PHONEGETEXTENSIONID, 3);
+
+ //
+ // Does this service provider export this function?
+ //
+ if (lpfn != (TSPAPIPROC)TSPI_PhoneBlank3)
+ {
+ lResult = (* lpfn)(
+ dwDeviceID,
+ dwTSPIVersion,
+ lpExtensionID
+ );
+ }
+ else
+ {
+ //
+ // Nope. Fill it fulla rocks.
+ //
+ RepeaterDebugString((2, " SP# does not support TSPI_phoneGetExtensionID. (We'll zero it)"));
+
+ lpExtensionID->dwExtensionID0 = 0;
+ lpExtensionID->dwExtensionID1 = 0;
+ lpExtensionID->dwExtensionID2 = 0;
+ lpExtensionID->dwExtensionID3 = 0;
+
+ lResult = 0;
+ }
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ if (lpExtensionID)
+ {
+ WriteStruct(dwID, sizeof(PHONEEXTENSIONID),
+ (LPVOID)lpExtensionID);
+ }
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetExtensionID - lResult=0x%08lx",lResult));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetGain(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwGain
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetGain"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETGAIN,
+ (DWORD)hdPhone,
+ dwHookSwitchDev,
+ (DWORD)lpdwGain);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETGAIN, 3))(
+ hdPhone,
+ dwHookSwitchDev,
+ lpdwGain
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwGain);
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetGain"));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetHookSwitch(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwHookSwitchDevs
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetHookSwitch"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_PHONEGETHOOKSWITCH,
+ (DWORD)hdPhone,
+ (DWORD)lpdwHookSwitchDevs);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETHOOKSWITCH, 2))(
+ hdPhone,
+ lpdwHookSwitchDevs
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwHookSwitchDevs);
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetHoosSwitch"));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetIcon(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC3) +
+ sizeof(HICON) +
+ lstrlen(lpszDeviceClass));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetIcon"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETICON,
+ dwDeviceID,
+ (DWORD)lpszDeviceClass,
+ (DWORD)lphIcon);
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETICON, 3))(
+ dwDeviceID,
+ lpszDeviceClass,
+ lphIcon
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >= 0)
+ {
+ WriteStruct(dwID, sizeof(HICON),
+ (LPVOID)lphIcon);
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetIcon"));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetID(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCWSTR lpszDeviceClass
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ ,
+ HANDLE hTargetProcess
+#endif
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC4) +
+ lstrlen(lpszDeviceClass) +
+ (lpDeviceID ? lpDeviceID->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetID"));
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONEGETID,
+ (DWORD)hdPhone,
+ (DWORD)lpDeviceID,
+ (DWORD)lpszDeviceClass,
+ (DWORD)hTargetProcess
+ );
+#else
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETID,
+ (DWORD)hdPhone,
+ (DWORD)lpDeviceID,
+ (DWORD)lpszDeviceClass
+ );
+#endif
+
+
+ if (lpszDeviceClass)
+ {
+ WriteStruct(dwID, lstrlen(lpszDeviceClass),
+ (LPVOID)lpszDeviceClass);
+ }
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ lResult = (* GetProcAddressHashed(SP_PHONEGETID, 4))(
+ hdPhone,
+ lpDeviceID,
+ lpszDeviceClass,
+ hTargetProcess
+ );
+#else
+ lResult = (* GetProcAddressHashed(SP_PHONEGETID, 3))(
+ hdPhone,
+ lpDeviceID,
+ lpszDeviceClass
+ );
+#endif
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ if (lpDeviceID)
+ {
+ WriteStruct(dwID, lpDeviceID->dwUsedSize,
+ (LPVOID)lpDeviceID);
+ }
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetID - lResult=0x%08lx",
+ lResult));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetLamp(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPDWORD lpdwLampMode
+ )
+{
+
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetLamp"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETLAMP,
+ (DWORD)hdPhone,
+ dwButtonLampID,
+ (DWORD)lpdwLampMode);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETLAMP,
+ 3))(
+ hdPhone,
+ dwButtonLampID,
+ lpdwLampMode);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwLampMode);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetRing(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwRingMode,
+ LPDWORD lpdwVolume
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3) + sizeof(DWORD) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetRing"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETRING,
+ (DWORD)hdPhone,
+ (DWORD)lpdwRingMode,
+ (DWORD)lpdwVolume);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETRING,
+ 3))(
+ hdPhone,
+ lpdwRingMode,
+ lpdwVolume);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwRingMode);
+
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwVolume);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetStatus(
+ HDRVPHONE hdPhone,
+ LPPHONESTATUS lpPhoneStatus
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK +
+ sizeof(LOGSPFUNC2) +
+ (lpPhoneStatus ? lpPhoneStatus->dwTotalSize : 0));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetStatus"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_PHONEGETSTATUS,
+ (DWORD)hdPhone,
+ (DWORD)lpPhoneStatus);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETSTATUS, 2))(
+ hdPhone,
+ lpPhoneStatus
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ if (lpPhoneStatus)
+ {
+ WriteStruct(dwID, lpPhoneStatus->dwUsedSize,
+ (LPVOID)lpPhoneStatus);
+ }
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetStatus - lResult=0x%08lx",
+ lResult));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetVolume(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwVolume
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC3) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneGetVolume"));
+
+ WritePreHeader(dwID, SPFUNC3);
+
+ WriteLogStruct3(dwID, SP_PHONEGETVOLUME,
+ (DWORD)hdPhone,
+ dwHookSwitchDev,
+ (DWORD)lpdwVolume);
+
+ lResult = (* GetProcAddressHashed(SP_PHONEGETVOLUME, 3))(
+ hdPhone,
+ dwHookSwitchDev,
+ lpdwVolume
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwVolume);
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneGetVolume - lResult=0x%08lx",
+ lResult));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+ TSPAPIPROC lpfn;
+
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneNegotiateExtVersion"));
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_PHONENEGOTIATEEXTVERSION,
+ dwDeviceID,
+ dwTSPIVersion,
+ dwLowVersion,
+ dwHighVersion,
+ (DWORD)lpdwExtVersion);
+
+ lpfn = GetProcAddressHashed(SP_PHONENEGOTIATEEXTVERSION,
+ 5);
+
+ if (lpfn)
+ {
+ lResult = (*lpfn)(
+ dwDeviceID,
+ dwTSPIVersion,
+ dwLowVersion,
+ dwHighVersion,
+ lpdwExtVersion);
+ }
+ else
+ {
+ lResult = PHONEERR_OPERATIONUNAVAIL;
+ }
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwExtVersion);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4) + sizeof(DWORD));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneNegotiateTSPIVersion"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONENEGOTIATETSPIVERSION,
+ dwDeviceID,
+ dwLowVersion,
+ dwHighVersion,
+ (DWORD)lpdwTSPIVersion);
+
+ lResult = (* GetProcAddressHashed(SP_PHONENEGOTIATETSPIVERSION, 4))(
+ dwDeviceID,
+ dwLowVersion,
+ dwHighVersion,
+ lpdwTSPIVersion);
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ WriteStruct(dwID, sizeof(DWORD),
+ (LPVOID)lpdwTSPIVersion);
+ }
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneOpen(
+ DWORD dwDeviceID,
+ HTAPIPHONE htPhone,
+ LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion,
+ PHONEEVENT lpfnEventProc
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + sizeof(HDRVPHONE));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneOpen"));
+
+ glpPhoneEventProc32 = lpfnEventProc;
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ WriteLogStruct5(dwID, SP_PHONEOPEN,
+ dwDeviceID,
+ (DWORD)htPhone,
+ (DWORD)lphdPhone,
+ dwTSPIVersion,
+ (DWORD)PhoneEventProc);
+ lResult =
+ (* GetProcAddressHashed(SP_PHONEOPEN, 5))(
+ dwDeviceID,
+ htPhone,
+ lphdPhone,
+ dwTSPIVersion,
+ PhoneEventProc
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ if (lResult >=0)
+ {
+ WriteStruct(dwID, sizeof(HDRVPHONE),
+ (LPVOID)lphdPhone);
+ }
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneOpen - lResult=0x%08lx", lResult));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSelectExtVersion(
+ HDRVPHONE hdPhone,
+ DWORD dwExtVersion
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC2));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSelectExtVersion"));
+
+ WritePreHeader(dwID, SPFUNC2);
+
+ WriteLogStruct2(dwID, SP_PHONESELECTEXTVERSION,
+ (DWORD)hdPhone,
+ dwExtVersion);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESELECTEXTVERSION,
+ 2))(
+ hdPhone,
+ dwExtVersion);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetButtonInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO const lpButtonInfo
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetButtonInfo"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONESETBUTTONINFO,
+ dwRequestID,
+ (DWORD)hdPhone,
+ dwButtonLampID,
+ (DWORD)lpButtonInfo);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETBUTTONINFO,
+ 4))(
+ dwRequestID,
+ hdPhone,
+ dwButtonLampID,
+ lpButtonInfo);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetData(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID const lpData,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC5) + dwSize);
+
+ WritePreHeader(dwID, SPFUNC5);
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetData"));
+
+ WriteLogStruct5(dwID, SP_PHONESETDATA,
+ dwRequestID,
+ (DWORD)hdPhone,
+ dwDataID,
+ (DWORD)lpData,
+ dwSize);
+
+ if (lpData)
+ {
+ WriteStruct(dwID,
+ dwSize,
+ (LPVOID)lpData);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETDATA,
+ 5))(
+ dwRequestID,
+ hdPhone,
+ dwDataID,
+ lpData,
+ dwSize);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetDisplay(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRow,
+ DWORD dwColumn,
+ LPCWSTR lpsDisplay,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC6) + dwSize);
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetDisplay"));
+
+ WritePreHeader(dwID, SPFUNC6);
+
+ WriteLogStruct6(dwID, SP_PHONESETDISPLAY,
+ dwRequestID,
+ (DWORD)hdPhone,
+ dwRow,
+ dwColumn,
+ (DWORD)lpsDisplay,
+ dwSize);
+
+ if (lpsDisplay)
+ {
+ WriteStruct(dwID,
+ dwSize,
+ (LPVOID)lpsDisplay);
+ }
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETDISPLAY,
+ 6))(
+ dwRequestID,
+ hdPhone,
+ dwRow,
+ dwColumn,
+ lpsDisplay,
+ dwSize);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetGain(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwGain
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetGain"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONESETGAIN,
+ dwRequestID,
+ (DWORD)hdPhone,
+ dwHookSwitchDev,
+ dwGain);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETGAIN, 4))(
+ dwRequestID,
+ hdPhone,
+ dwHookSwitchDev,
+ dwGain
+ );
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneSetGain - lResult=0x%08lx",
+ lResult));
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetHookSwitch(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDevs,
+ DWORD dwHookSwitchMode
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetHookSwitch"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONESETHOOKSWITCH,
+ dwRequestID,
+ (DWORD)hdPhone,
+ dwHookSwitchDevs,
+ dwHookSwitchMode);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETHOOKSWITCH, 4))(
+ dwRequestID,
+ hdPhone,
+ dwHookSwitchDevs,
+ dwHookSwitchMode
+ );
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneSetHookSwitch - lResult=0x%08lx",
+ lResult));
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetLamp(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ DWORD dwLampMode
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetLamp"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONESETLAMP,
+ dwRequestID,
+ (DWORD)hdPhone,
+ (DWORD)dwButtonLampID,
+ dwLampMode);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETLAMP,
+ 4))(
+ dwRequestID,
+ hdPhone,
+ dwButtonLampID,
+ dwLampMode);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetRing(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRingMode,
+ DWORD dwVolume
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetRing"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONESETRING,
+ dwRequestID,
+ (DWORD)hdPhone,
+ dwRingMode,
+ dwVolume);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETRING,
+ 4))(
+ dwRequestID,
+ hdPhone,
+ dwRingMode,
+ dwVolume);
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetStatusMessages(
+ HDRVPHONE hdPhone,
+ DWORD dwPhoneStates,
+ DWORD dwButtonModes,
+ DWORD dwButtonStates
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetStatusMessages"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONESETSTATUSMESSAGES,
+ (DWORD)hdPhone,
+ dwPhoneStates,
+ dwButtonModes,
+ dwButtonStates);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETSTATUSMESSAGES, 4))(
+ hdPhone,
+ dwPhoneStates,
+ dwButtonModes,
+ dwButtonStates
+ );
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneSetStatusMessages"));
+
+ WritePostStruct(dwID, lResult);
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetVolume(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwVolume
+ )
+{
+ LONG lResult;
+ DWORD dwID;
+
+ GetChunkID(&dwID);
+ AllocChunk(dwID, NORMALCHUNK + sizeof(LOGSPFUNC4));
+
+ RepeaterDebugString((2, "Entering TSPI_phoneSetVolume"));
+
+ WritePreHeader(dwID, SPFUNC4);
+
+ WriteLogStruct4(dwID, SP_PHONESETVOLUME,
+ dwRequestID,
+ (DWORD)hdPhone,
+ dwHookSwitchDev,
+ dwVolume);
+
+ lResult = (* GetProcAddressHashed(SP_PHONESETVOLUME, 4))(
+ dwRequestID,
+ hdPhone,
+ dwHookSwitchDev,
+ dwVolume
+ );
+
+ WritePostStruct(dwID, lResult);
+
+ RepeaterDebugString((2, "Leaving TSPI_phoneSetVolume - lResult=0x%08lx",
+ lResult));
+
+ ReleaseID(dwID);
+
+ return lResult;
+}
+
+
+
+
+//
+// ----------------------- TSPIAPI TSPI_provider functions --------------------
+//
+
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ LONG lResult;
+
+ lResult = (* GetProcAddressHashed(SP_PROVIDERCONFIG, 2))
+ (hwndOwner,
+ dwPermanentProviderID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ ,
+ LPDWORD lpdwTSPIOptions
+#endif
+ )
+{
+ LONG lResult;
+
+ if (!gbStarted)
+ {
+ StartMeUp();
+ }
+
+ RepeaterDebugString((2, "Entering TSPI_providerInit"));
+
+ glpAsyncCompletionProc32 = lpfnCompletionProc;
+
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ lResult = (* GetProcAddressHashed(SP_PROVIDERINIT, 8))
+ (
+ dwTSPIVersion,
+ dwPermanentProviderID,
+ dwLineDeviceIDBase,
+ dwPhoneDeviceIDBase,
+ dwNumLines,
+ dwNumPhones,
+ AsyncCompletionProc,
+ lpdwTSPIOptions
+ );
+#else
+ lResult = (* GetProcAddressHashed( SP_PROVIDERINIT, 7))
+ (
+ dwTSPIVersion,
+ dwPermanentProvider,
+ dwLineDeviceIDBase,
+ dwPhoneDeviceIDBase,
+ dwNumLines,
+ dwNumPhones,
+ AsyncCompletionProc
+ );
+#endif
+
+ DBGOUT((1, "leaving provider init"));
+
+ return lResult;
+}
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ return 0;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ ,
+ DWORD dwPermanentProviderID
+#endif
+ )
+{
+ RepeaterDebugString((2, "Entering TSPI_providerShutdown"));
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+ (* GetProcAddressHashed(SP_PROVIDERSHUTDOWN, 2))(
+ dwTSPIVersion,
+ dwPermanentProviderID
+ );
+#else
+ (* GetProcAddressHashed(SP_PROVIDERSHUTDOWN, 1))(
+ dwTSPIVersion
+ );
+#endif
+
+// FreeLibrary(hProvider);
+
+// MYFREE(lpfnProcAddress);
+
+ return(ERR_NONE);
+}
+
+LONG
+TSPIAPI
+TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+{
+ TSPAPIPROC lpfn;
+
+ if (!gbStarted)
+ {
+ StartMeUp();
+ }
+
+ RepeaterDebugString((2, "Entering TSPI_providerEnumDevices"));
+
+
+ glpLineEventProc32 = lpfnLineCreateProc;
+ glpPhoneEventProc32 = lpfnPhoneCreateProc;
+
+// InitializeSPs();
+
+ lpfn = GetProcAddressHashed(SP_PROVIDERENUMDEVICES, 6);
+
+ if (lpfn != (TSPAPIPROC)TSPI_LineBlank6)
+ {
+ DBGOUT((1, "calling providerenumdevices"));
+
+ (* lpfn)(
+ dwPermanentProvider,
+ &dwNumLines,
+ &dwNumPhones,
+ hProvider,
+ LineEventProc,
+ PhoneEventProc
+ );
+
+ *lpdwNumLines = dwNumLines;
+ *lpdwNumPhones = dwNumPhones;
+ }
+ else
+ {
+ DBGOUT((1, "failed to get entry"));
+ }
+
+ DBGOUT((2, " TSPI_providerEnumDevices: #lines= %d #phones= %d",
+ *lpdwNumLines,
+ *lpdwNumPhones));
+
+ return(ERR_NONE);
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreateLineDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ LONG lResult;
+
+ lResult = (* GetProcAddressHashed(SP_PROVIDERCREATELINEDEVICE, 2))(
+ dwTempID,
+ dwDeviceID);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerCreatePhoneDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+{
+ LONG lResult;
+
+ lResult = (* GetProcAddressHashed(SP_PROVIDERCREATEPHONEDEVICE, 2))(
+ dwTempID,
+ dwDeviceID);
+
+ return lResult;
+
+}
+
+#if (TAPI_CURRENT_VERSION >= 0x00020000)
+
+LONG
+TSPIAPI
+TSPI_providerFreeDialogInstance(
+ HDRVDIALOGINSTANCE hdDlgInst
+ )
+{
+ LONG lResult;
+
+ RepeaterDebugString((2, "Entering TSPI_providerFreeDialogInstance"));
+
+
+ lResult = (* GetProcAddressHashed(SP_PROVIDERFREEDIALOGINSTANCE,1))(
+ hdDlgInst);
+
+ return lResult;
+}
+
+
+
+LONG
+TSPIAPI
+TSPI_providerGenericDialogData(
+ DWORD dwObjectID,
+ DWORD dwObjectType,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ LONG lResult;
+
+ RepeaterDebugString((2, "Entering TSPI_providerGenericDialogData"));
+
+ lResult = (* GetProcAddressHashed(SP_PROVIDERGENERICDIALOGDATA, 4))(
+ dwObjectID,
+ dwObjectType,
+ lpParams,
+ dwSize);
+
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_providerUIIdentify(
+ LPWSTR lpszUIDLLName
+ )
+{
+ LONG lResult;
+
+ RepeaterDebugString((2, "Entering TSPI_providerUIIdentify"));
+
+ lResult = (* GetProcAddressHashed(SP_PROVIDERUIIDENTIFY, 1))(
+ lpszUIDLLName);
+
+ return lResult;
+}
+
+#endif // tapi 2.0
+
+#ifdef WIN32
+
+BOOL WINAPI DllMain(
+ HANDLE hModule,
+ DWORD dwReason,
+ DWORD dwReserved
+ )
+{
+
+ DBGOUT((1, "DllEntryPoint entered reason=%lx\r\n", dwReason));
+
+
+ if ( dwReason == 1 )
+ {
+// StartMeUp();
+ // don't do nothin'
+ }
+
+ if (dwReason == 0)
+ {
+ if (gbStarted)
+ {
+ gfTerminateNow = TRUE;
+
+ WaitForSingleObject(ghLoggingThread,
+ 2000);
+
+ CloseHandle(ghLoggingThread);
+ DeleteCriticalSection(&gcsLogging);
+ DeleteCriticalSection(&gcsID);
+ FreeLibrary(hProvider);
+
+ MYFREE(lpfnProcAddress);
+ }
+
+
+ }
+
+
+ return(1); // success
+}
+
+#else
+
+int
+FAR
+PASCAL
+LibMain(HANDLE hInstance,
+ WORD wDataSegment,
+ WORD wHeapSize,
+ LPSTR lpszCmdLine)
+{
+ StartMeUp();
+ return TRUE;
+}
+
+#endif
diff --git a/private/tapi/dev/sp/repeater/new/repeater.def b/private/tapi/dev/sp/repeater/new/repeater.def
new file mode 100644
index 000000000..01ec325c7
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/repeater.def
@@ -0,0 +1,122 @@
+LIBRARY repeater.tsp
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept @500
+ TSPI_lineAddToConference @501
+ TSPI_lineAnswer @502
+ TSPI_lineBlindTransfer @503
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineCompleteCall @506
+ TSPI_lineCompleteTransfer @507
+ TSPI_lineConditionalMediaDetection @508
+; TSPI_lineConfigDialog @509
+ TSPI_lineDevSpecific @510
+ TSPI_lineDevSpecificFeature @511
+ TSPI_lineDial @512
+ TSPI_lineDrop @513
+ TSPI_lineForward @514
+ TSPI_lineGatherDigits @515
+ TSPI_lineGenerateDigits @516
+ TSPI_lineGenerateTone @517
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetDevConfig @525
+ TSPI_lineGetExtensionID @526
+ TSPI_lineGetIcon @527
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineHold @531
+ TSPI_lineMakeCall @532
+ TSPI_lineMonitorDigits @533
+ TSPI_lineMonitorMedia @534
+ TSPI_lineMonitorTones @535
+ TSPI_lineNegotiateExtVersion @536
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_lineOpen @538
+ TSPI_linePark @539
+ TSPI_linePickup @540
+ TSPI_linePrepareAddToConference @541
+ TSPI_lineRedirect @542
+ TSPI_lineRemoveFromConference @543
+ TSPI_lineSecureCall @544
+ TSPI_lineSelectExtVersion @545
+ TSPI_lineSendUserUserInfo @546
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetCallParams @548
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetDevConfig @550
+ TSPI_lineSetMediaControl @551
+ TSPI_lineSetMediaMode @552
+ TSPI_lineSetStatusMessages @553
+ TSPI_lineSetTerminal @554
+ TSPI_lineSetupConference @555
+ TSPI_lineSetupTransfer @556
+ TSPI_lineSwapHold @557
+ TSPI_lineUncompleteCall @558
+ TSPI_lineUnhold @559
+ TSPI_lineUnpark @560
+
+ TSPI_phoneClose @561
+; TSPI_phoneConfigDialog @562
+ TSPI_phoneDevSpecific @563
+ TSPI_phoneGetButtonInfo @564
+ TSPI_phoneGetData @565
+ TSPI_phoneGetDevCaps @566
+ TSPI_phoneGetDisplay @567
+ TSPI_phoneGetExtensionID @568
+ TSPI_phoneGetGain @569
+ TSPI_phoneGetHookSwitch @570
+ TSPI_phoneGetIcon @571
+ TSPI_phoneGetID @572
+ TSPI_phoneGetLamp @573
+ TSPI_phoneGetRing @574
+ TSPI_phoneGetStatus @575
+ TSPI_phoneGetVolume @576
+ TSPI_phoneNegotiateExtVersion @577
+ TSPI_phoneNegotiateTSPIVersion @578
+ TSPI_phoneOpen @579
+ TSPI_phoneSelectExtVersion @580
+ TSPI_phoneSetButtonInfo @581
+ TSPI_phoneSetData @582
+ TSPI_phoneSetDisplay @583
+ TSPI_phoneSetGain @584
+ TSPI_phoneSetHookSwitch @585
+ TSPI_phoneSetLamp @586
+ TSPI_phoneSetRing @587
+ TSPI_phoneSetStatusMessages @588
+ TSPI_phoneSetVolume @589
+
+ TSPI_providerConfig @590
+ TSPI_providerInit @591
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerShutdown @594
+
+ TSPI_providerEnumDevices @595
+; TSPI_lineDropOnClose @596
+; TSPI_lineDropNoOwner @597
+ TSPI_providerCreateLineDevice @598
+ TSPI_providerCreatePhoneDevice @599
+ TSPI_lineSetCurrentLocation @600
+; TSPI_lineConfigDialogEdit @601
+ TSPI_lineReleaseUserUserInfo @602
+
+; TSPI_lineSetCallData @603
+; TSPI_lineSetCallQualityOfService @604
+; TSPI_lineSetCallTreatment @605
+; TSPI_lineSetLineDevStatus @606
+ TSPI_providerFreeDialogInstance @607
+ TSPI_providerGenericDialogData @608
+ TSPI_providerUIIdentify @609
+
+
diff --git a/private/tapi/dev/sp/repeater/new/repeater.h b/private/tapi/dev/sp/repeater/new/repeater.h
new file mode 100644
index 000000000..8157b9e2f
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/repeater.h
@@ -0,0 +1,177 @@
+/* TSP3216S.H
+ Copyright 1995 (C) Microsoft Corporation
+
+ 32-bit TAPI service provider to act as a cover for a system's 16-bit SPs
+
+ 16-bit part: TSP3216S.DLL
+ 32-bit part: TSP3216L.DLL
+
+ t-jereh 20-July-1995
+
+ TODO:
+ 1) allow debug levels
+ 2) if oom in InitializeSPs(), fail
+
+ */
+
+#define MAXBUFSIZE 256 /* maximum buffer size */
+
+#define ERR_NONE 0 /* success return value */
+
+#define TAPI_CUR_VER 0x00010004
+
+#define TSPI_PROC_LAST 118 /* there are TSPI functions from 500 to 617 */
+
+
+// structs
+
+typedef struct tagMYLINE
+ {
+ HDRVLINE hdLine;
+ int iProvider;
+ DWORD dwDeviceID;
+ LINEEVENT lpfnEventProc;
+ HTAPILINE htLine;
+ } MYLINE, FAR *LPMYLINE;
+
+
+typedef struct tagMYPHONE
+ {
+ HDRVPHONE hdPhone;
+ int iProvider;
+ DWORD dwDeviceID;
+ PHONEEVENT lpfnEventProc;
+ HTAPIPHONE htPhone;
+ } MYPHONE, FAR *LPMYPHONE;
+
+typedef struct tagMYHDRVCALL
+{
+ HTAPICALL htCall;
+ HDRVCALL hdCall;
+ int iProvider;
+ DWORD dwDeviceID;
+} MYHDRVCALL, FAR *LPMYHDRVCALL;
+
+typedef struct tagMYTEMPID
+{
+ int iProvider;
+ DWORD dwTempID;
+} MYTEMPID, FAR *LPMYTEMPID;
+
+#define SP_LINEACCEPT 0
+#define SP_LINEADDTOCONFERENCE 1
+#define SP_LINEAGENTSPECIFIC 2
+#define SP_LINEANSWER 3
+#define SP_LINEBLINDTRANSFER 4
+#define SP_LINECLOSE 5
+#define SP_LINECLOSECALL 6
+#define SP_LINECOMPLETECALL 7
+#define SP_LINECOMPLETETRANSFER 8
+#define SP_LINECONDITIONALMEDIADETECTION 9
+#define SP_LINEDEVSPECIFIC 10
+#define SP_LINEDEVSPECIFICFEATURE 11
+#define SP_LINEDIAL 12
+#define SP_LINEDROP 13
+#define SP_LINEFORWARD 14
+#define SP_LINEGATHERDIGITS 15
+#define SP_LINEGENERATEDIGITS 16
+#define SP_LINEGENERATETONE 17
+#define SP_LINEGETADDRESSCAPS 18
+#define SP_LINEGETADDRESSID 19
+#define SP_LINEGETADDRESSSTATUS 20
+#define SP_LINEGETAGENTACTIVITYLIST 21
+#define SP_LINEGETAGENTCAPS 22
+#define SP_LINEGETAGENTGROUPLIST 23
+#define SP_LINEGETAGENTSTATUS 24
+#define SP_LINEGETCALLADDRESSID 25
+#define SP_LINEGETCALLINFO 26
+#define SP_LINEGETCALLSTATUS 27
+#define SP_LINEGETDEVCAPS 28
+#define SP_LINEGETDEVCONFIG 29
+#define SP_LINEGETEXTENSIONID 30
+#define SP_LINEGETICON 31
+#define SP_LINEGETID 32
+#define SP_LINEGETLINEDEVSTATUS 33
+#define SP_LINEGETNUMADDRESSIDS 34
+#define SP_LINEHOLD 35
+#define SP_LINEMAKECALL 36
+#define SP_LINEMONITORDIGITS 37
+#define SP_LINEMONITORMEDIA 38
+#define SP_LINEMONITORTONES 39
+#define SP_LINENEGOTIATEEXTVERSION 40
+#define SP_LINENEGOTIATETSPIVERSION 41
+#define SP_LINEOPEN 42
+#define SP_LINEPARK 43
+#define SP_LINEPICKUP 44
+#define SP_LINEPREPAREADDTOCONFERENCE 45
+#define SP_LINEREDIRECT 46
+#define SP_LINERELEASEUSERUSERINFO 47
+#define SP_LINEREMOVEFROMCONFERENCE 48
+#define SP_LINESECURECALL 49
+#define SP_LINESELECTEXTVERSION 50
+#define SP_LINESENDUSERUSERINFO 51
+#define SP_LINESETAGENTACTIVITY 52
+#define SP_LINESETAGENTGROUP 53
+#define SP_LINESETAGENTSTATE 54
+#define SP_LINESETAPPSPECIFIC 55
+#define SP_LINESETCALLDATA 56
+#define SP_LINESETCALLPARAMS 57
+#define SP_LINESETCALLQUALITYOFSERVICE 58
+#define SP_LINESETCALLTREATMENT 59
+#define SP_LINESETCURRENTLOCATION 60
+#define SP_LINESETDEFAULTMEDIADETECTION 61
+#define SP_LINESETDEVCONFIG 62
+#define SP_LINESETLINEDEVSTATUS 63
+#define SP_LINESETMEDIACONTROL 64
+#define SP_LINESETMEDIAMODE 65
+#define SP_LINESETSTATUSMESSAGES 66
+#define SP_LINESETTERMINAL 67
+#define SP_LINESETUPCONFERENCE 68
+#define SP_LINESETUPTRANSFER 69
+#define SP_LINESWAPHOLD 70
+#define SP_LINEUNCOMPLETECALL 71
+#define SP_LINEUNHOLD 72
+#define SP_LINEUNPARK 73
+#define SP_PHONECLOSE 74
+#define SP_PHONEDEVSPECIFIC 75
+#define SP_PHONEGETBUTTONINFO 76
+#define SP_PHONEGETDATA 77
+#define SP_PHONEGETDEVCAPS 78
+#define SP_PHONEGETDISPLAY 79
+#define SP_PHONEGETEXTENSIONID 80
+#define SP_PHONEGETGAIN 81
+#define SP_PHONEGETHOOKSWITCH 82
+#define SP_PHONEGETICON 83
+#define SP_PHONEGETID 84
+#define SP_PHONEGETLAMP 85
+#define SP_PHONEGETRING 86
+#define SP_PHONEGETSTATUS 87
+#define SP_PHONEGETVOLUME 88
+#define SP_PHONENEGOTIATEEXTVERSION 89
+#define SP_PHONENEGOTIATETSPIVERSION 90
+#define SP_PHONEOPEN 91
+#define SP_PHONESELECTEXTVERSION 92
+#define SP_PHONESETBUTTONINFO 93
+#define SP_PHONESETDATA 94
+#define SP_PHONESETDISPLAY 95
+#define SP_PHONESETGAIN 96
+#define SP_PHONESETHOOKSWITCH 97
+#define SP_PHONESETLAMP 98
+#define SP_PHONESETRING 99
+#define SP_PHONESETSTATUSMESSAGES 100
+#define SP_PHONESETVOLUME 101
+#define SP_PROVIDERCREATELINEDEVICE 102
+#define SP_PROVIDERCREATEPHONEDEVICE 103
+#define SP_PROVIDERENUMDEVICES 104
+#define SP_PROVIDERFREEDIALOGINSTANCE 105
+#define SP_PROVIDERGENERICDIALOGDATA 106
+#define SP_PROVIDERINIT 107
+#define SP_PROVIDERSHUTDOWN 108
+#define SP_PROVIDERUIIDENTIFY 109
+#define SP_LINECONFIGDIALOG 110
+#define SP_LINECONFIGDIALOGEDIT 111
+#define SP_PHONECONFIGDIALOG 112
+#define SP_PROVIDERCONFIG 113
+#define SP_LINEDROPONCLOSE 114
+#define SP_LINEDROPNOOWNER 115
+#define SP_LASTPROCNUMBER (SP_LINEDROPNOOWNER + 1)
diff --git a/private/tapi/dev/sp/repeater/new/repeater.rc b/private/tapi/dev/sp/repeater/new/repeater.rc
new file mode 100644
index 000000000..cdd206da8
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/repeater.rc
@@ -0,0 +1,19 @@
+#include "windows.h"
+
+
+#if WINNT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Telephony API Repeater Service Provider"
+#define VER_INTERNALNAME_STR "REPEATER"
+#define VER_ORIGINALFILENAME_STR "REPEATER.TSP"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1996. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/repeater/new/repeater.txt b/private/tapi/dev/sp/repeater/new/repeater.txt
new file mode 100644
index 000000000..bff82259a
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/repeater.txt
@@ -0,0 +1,87 @@
+At install time:
+
+// If for record, list all providers and ask user which one to record
+// (Multiple at once? *Not at first.)
+
+// If for playback, install as a new provider(?)
+
+
+-----------------------------------------------------------------------------
+At record time:
+
+// Insert between TAPI & target SP (multiple SPs at once? *Not at first.)
+
+// Really cool to self-modify export table so that only functions exported
+// are those exported by the target SP (unlikely)
+
+// On startup, spin a thread that will take messages & write to a file
+
+// When a message comes up, all parms & timestamp will be added to a queue and the
+// other thread will be signaled to put messages to the queue
+
+// When a function call comes down, parms will be recorded for comparison
+// to parms sent down during playback (THIS DEFINITION NEEDS WORK!!)
+
+
+// !! Events going up should get TWO timestamps!!! One since startup and
+// !! one since last (non-status?) function going down.
+
+
+// After a function call, the return stuff (retcode, async buffer if any,
+// async retcode) and timestamp are recorded
+
+
+Features for recording:
+
+// At set times, or before/after passing functions down to target SP
+// and/or after/during messages up, call status functions on calls & lines
+// so that if, during playback, status is unexpectedly asked for (because
+// the ISV is trying something new) "correct" status is returned
+
+
+-----------------------------------------------------------------------------
+At playback:
+
+// Already installed. Separate app to kick off, log stuff, and maybe get
+// some user intervention (eg: have user manually kick off each event; have
+// user alter data going up/down; etc)
+
+// FileOpen common-dialog box to open Repeater file
+
+// Talk through sidedoor (NOT LINEDEVSPECIFIC - MUST NOT ALREADY init provider)
+// to get filename to Repeater
+
+// On startup, spin a thread that will log stuff?
+
+// When function calls come down, check them off the list if they are expected
+// If not expected, log it (maybe even log it if it was expected, LOGLEVEL)
+// If not expected, THEN WHAT? If a status call, return same status if this
+// call was reported previously for 2 calls then the same status that was
+// returned next. IE: A developer is working to fix a bug in an event stream
+// and sets a loop to check the status of a call before continuing. He should
+// receive a couple of "not done yet" statuses before the "ok, it's done"
+// status.
+
+// When completing async events, be sure to use the GOOD (current) asyncID!
+
+// If a function call does not happen by (SOME AMOUNT OF TIME - the next
+// status up message?), then log it.
+
+// Pass any events up at the time delta they happened. (Delta from func down?)
+
+// What about UI functions? Probably just put up a MessageBox that says
+// "Kilroy was here"
+
+
+Features for playback:
+
+// Have playback optionally ignore function down stuff. So that a PBX maker
+// can record events that are calls coming in and send that to ISVs. The
+// ISV can then test their apps against incoming calls on the PBX.
+
+// How valuable to be able to insert into a playback stream? EG: A PBX
+// stream has incoming calls, but to test IVR stuff, an ISV wants to simulate
+// DTMF pressed. EG2: An ISV realizes what he did wrong and wants to run
+// a simulation and so wants to change one of the status returned messages.
+// - changes a disconnect to dialing, then inserts a conntected then changes
+// the disconnect to happen a MINUTE later...
diff --git a/private/tapi/dev/sp/repeater/new/sources b/private/tapi/dev/sp/repeater/new/sources
new file mode 100644
index 000000000..52bde1c8c
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/sources
@@ -0,0 +1,53 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=repeater
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETEXT=TSP
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+DLLBASE=0x60000000
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+SOURCES=repeater.c \
+ logger.c \
+ debug.c \
+ repeater.rc
+
+UMTYPE=windows
+
+DLLENTRY=DllMain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/repeater/new/tsp3216.h b/private/tapi/dev/sp/repeater/new/tsp3216.h
new file mode 100644
index 000000000..4b4959868
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/new/tsp3216.h
@@ -0,0 +1,10 @@
+#define TSP3216L_MESSAGE (WM_USER+10)
+
+enum {CALLBACK_ASYNCCOMPLETION,
+ CALLBACK_LINEEVENT,
+ CALLBACK_PHONEEVENT,
+ CALLBACK_LINECREATE,
+ CALLBACK_PHONECREATE
+ } CALLBACK_TYPES;
+
+
diff --git a/private/tapi/dev/sp/repeater/setup/makefile b/private/tapi/dev/sp/repeater/setup/makefile
new file mode 100644
index 000000000..f1084966b
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/setup/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# Dialer.exe Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/repeater/setup/resource.h b/private/tapi/dev/sp/repeater/setup/resource.h
new file mode 100644
index 000000000..c20e295b0
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/setup/resource.h
@@ -0,0 +1,22 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Setup.rc
+//
+#define IDD_REPEATER 101
+#define IDC_FILEDIRECTORY 1000
+#define IDC_SPNAME 1001
+#define ID_UNINSTALL 1002
+#define ID_INSTALL 1003
+#define ID_MOREINFO 1004
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1005
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/private/tapi/dev/sp/repeater/setup/setup.cpp b/private/tapi/dev/sp/repeater/setup/setup.cpp
new file mode 100644
index 000000000..79169a1a1
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/setup/setup.cpp
@@ -0,0 +1,779 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <windows.h>
+#include <commdlg.h>
+#include "resource.h"
+
+//////////////////////////////////////////////////////////////////////////////
+// PROTOTYPES
+//////////////////////////////////////////////////////////////////////////////
+static BOOL CreateMainWindow (int nCmdShow);
+
+BOOL CALLBACK RepeaterDlgProc (HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+BOOL DoInstall(HWND);
+BOOL DoUninstall(HWND);
+BOOL DoMoreInfo();
+
+//////////////////////////////////////////////////////////////////////////////
+// GLOBALS
+//////////////////////////////////////////////////////////////////////////////
+HINSTANCE ghInstance;
+BOOL gbIsNT = FALSE;
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// WinMain()
+//
+//////////////////////////////////////////////////////////////////////////////
+
+int WINAPI WinMain (HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine,
+ int nCmdShow)
+{
+ ghInstance = GetModuleHandle(NULL);
+
+ if (GetVersion() < 0x80000000)
+ {
+ gbIsNT = TRUE;
+ }
+
+ DialogBox(ghInstance,
+ MAKEINTRESOURCE(IDD_REPEATER),
+ GetDesktopWindow(),
+ (DLGPROC)RepeaterDlgProc);
+ return 1;
+}
+
+
+//*****************************************************************************
+// MainWndProc()
+//*****************************************************************************
+
+BOOL CALLBACK RepeaterDlgProc (HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+
+ SetWindowPos(hwnd,
+ HWND_TOP,
+ GetSystemMetrics(SM_CXSCREEN)/4,
+ GetSystemMetrics(SM_CYSCREEN)/4,
+ 0,
+ 0,
+ SWP_NOSIZE);
+
+
+ SetFocus(GetDlgItem(hwnd,
+ IDC_SPNAME));
+
+ return 0;
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case ID_UNINSTALL:
+ if (DoUninstall(hwnd))
+ {
+ MessageBox(hwnd,
+ "Repeater successfully uninstalled.",
+ "Repeater Setup",
+ NULL);
+ EndDialog(hwnd, 1);
+ }
+ break;
+
+ case ID_INSTALL:
+ if (DoInstall(hwnd))
+ {
+ MessageBox(hwnd,
+ "Repeater successfully installed.",
+ "Repeater Setup",
+ NULL);
+ EndDialog(hwnd, 1);
+ }
+ break;
+
+ case ID_MOREINFO:
+ if (DoMoreInfo())
+ {
+ EndDialog(hwnd, 1);
+ }
+ break;
+
+ case IDCANCEL:
+ EndDialog(hwnd, 0);
+ break;
+ default:
+ return FALSE;
+ }
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#define SZTAPIKEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony"
+#define SZREPEATERSETUP "Repeater Setup"
+#define SZPROVIDERS "Providers"
+#define SZREPEATER "Repeater"
+#define SZNUMPROVIDERS "NumProviders"
+#define SZREPEATERFILENAME "Repeater.TSP"
+#define SZLOGDIR "LogFileDirectory"
+#define SZPROVIDERFILENAME "ProviderFilename"
+#define SZPROVIDER "Provider"
+#define SZPROVIDERID "ProviderID"
+#define SZTELEPHONINI "TELEPHON.INI"
+
+
+BOOL DoInstall(HWND hWnd)
+{
+ char szSPName[256];
+ char szLogFilePath[256];
+ char szTestName[256];
+ int i;
+ HANDLE hFileHandle;
+ DWORD dwSize;
+ DWORD dwHold, dwNumProviders;
+ HKEY hTapiKey, hProvidersKey, hRepeaterKey;
+ char szbuf[64], szfilebuf[256];
+ char sznum[16];
+
+
+
+ GetDlgItemText(hWnd,
+ IDC_SPNAME,
+ szSPName,
+ 256);
+
+ GetDlgItemText(hWnd,
+ IDC_FILEDIRECTORY,
+ szLogFilePath,
+ 256);
+
+ i = lstrlen(szLogFilePath);
+ if (szLogFilePath[i-1] != '\\')
+ {
+ szLogFilePath[i+1]=0;
+ szLogFilePath[i]='\\';
+ }
+
+ wsprintf(szTestName, "%s%s", szLogFilePath, "testme");
+ if ((hFileHandle = CreateFile(szTestName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL)) == INVALID_HANDLE_VALUE)
+ {
+ MessageBox(NULL, "Directory does not exist", NULL, MB_OK);
+ return FALSE;
+ }
+ else
+ {
+ CloseHandle(hFileHandle);
+ DeleteFile(szTestName);
+ }
+
+ if (gbIsNT)
+ {
+ // get tapi key
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ SZTAPIKEY,
+ 0,
+ KEY_ALL_ACCESS,
+ &hTapiKey);
+
+ // get providers key
+ RegOpenKeyEx(hTapiKey,
+ SZPROVIDERS,
+ 0,
+ KEY_ALL_ACCESS,
+ &hProvidersKey);
+
+ // create repeater key
+ RegCreateKeyEx(hTapiKey,
+ SZREPEATER,
+ 0,
+ "Repeater Type",
+ REG_OPTION_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hRepeaterKey,
+ &dwHold);
+
+ // get number of providers
+ dwSize = sizeof(DWORD);
+ RegQueryValueEx(hProvidersKey,
+ SZNUMPROVIDERS,
+ NULL,
+ NULL,
+ (LPBYTE)&dwNumProviders,
+ &dwSize);
+
+ // find the provider
+ for (i = 0; i < (int)dwNumProviders; i++)
+ {
+ wsprintf(szbuf, "%s%d",SZPROVIDERFILENAME, i);
+
+ dwSize = 256;
+ RegQueryValueEx(hProvidersKey,
+ szbuf,
+ NULL,
+ NULL,
+ (LPBYTE)szfilebuf,
+ &dwSize);
+
+ // if it's the same break
+ if (!lstrcmpi(szfilebuf, szSPName))
+ {
+ break;
+ }
+
+ }
+
+ // didn't find the provider
+ if (i == (int)dwNumProviders)
+ {
+ char szmessage[256];
+
+ wsprintf(szmessage,
+ "Provider %s is not installed\n",
+ szSPName);
+
+ MessageBox(hWnd,
+ szmessage,
+ SZREPEATERSETUP,
+ MB_OK);
+
+ // return false so they can reenter the name correctly
+ return FALSE;
+ }
+
+
+ }
+
+ else // win95
+ {
+ // get number of providers
+ dwNumProviders = GetPrivateProfileInt(SZPROVIDERS,
+ SZNUMPROVIDERS,
+ 0,
+ SZTELEPHONINI);
+
+ // find the provider
+ for (i = 0; i < (int)dwNumProviders; i++)
+ {
+ wsprintf(szbuf, "%s%d",SZPROVIDERFILENAME, i);
+
+ GetPrivateProfileString(SZPROVIDERS,
+ szbuf,
+ "",
+ szfilebuf,
+ 256,
+ SZTELEPHONINI);
+
+ // if it's the same break
+ if (!lstrcmpi(szfilebuf, szSPName))
+ {
+ break;
+ }
+
+ }
+
+ // didn't find the provider
+ if (i == (int)dwNumProviders)
+ {
+ char szmessage[256];
+
+ wsprintf(szmessage,
+ "Provider %s is not installed\n",
+ szSPName);
+
+ MessageBox(hWnd,
+ szmessage,
+ SZREPEATERSETUP,
+ MB_OK);
+
+ // return false so they can reenter the name correctly
+ return FALSE;
+ }
+
+ }
+
+ // ok now copy repeater
+
+ {
+ char szfile[MAX_PATH];
+ char sztarget[MAX_PATH];
+ char szdir[MAX_PATH];
+ int j;
+
+ GetModuleFileName(NULL,
+ szdir,
+ MAX_PATH);
+
+ j = lstrlen(szdir);
+ while (szdir[j] != '\\')
+ {
+ szdir[j] = 0;
+ j--;
+ }
+
+ // get rid of \ too
+ szdir[j] = 0;
+
+ wsprintf(szfile, "%s\\%s", szdir, SZREPEATERFILENAME);
+
+ GetSystemDirectory(szdir, MAX_PATH);
+
+ wsprintf(sztarget, "%s\\%s", szdir, SZREPEATERFILENAME);
+
+ if (!CopyFile(szfile,
+ sztarget,
+ FALSE))
+ {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ {
+ // ask them where the file is
+ OPENFILENAME ofn;
+ BOOL bReturn;
+
+ szfile[0] = '\0';
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hWnd;
+ ofn.hInstance = ghInstance;
+ ofn.lpstrFilter = "TSP Files\0*.tsp\0\0";
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = szfile;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrTitle ="Location of REPEATER.TSP";
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER;
+ ofn.nFileOffset = 0;
+ ofn.nFileExtension = 0;
+ ofn.lpstrDefExt = "TSP";
+ ofn.lCustData = 0;
+ ofn.lpfnHook = NULL;
+ ofn.lpTemplateName = NULL;
+
+ bReturn = GetOpenFileName(&ofn);
+
+ if (!bReturn)
+ {
+ return FALSE;
+ }
+
+ if (!CopyFile(szfile,
+ sztarget,
+ FALSE))
+ {
+ MessageBox(NULL, "Copy file failed", NULL, MB_OK);
+ return FALSE;
+ }
+
+ }
+ else
+ {
+ MessageBox(NULL, "CopyFile failed", NULL, MB_OK);
+ return FALSE;
+ }
+
+ }
+ }
+
+
+
+ if (gbIsNT)
+ {
+ // now i is the provider number, so put repeater there
+ // and move provider's info to repeater key
+
+ // set ProviderFilenameX=repeater.tsp
+ dwSize = lstrlen(SZREPEATERFILENAME) + 1;
+ RegSetValueEx(hProvidersKey,
+ szbuf,
+ 0,
+ REG_SZ,
+ (LPBYTE)SZREPEATERFILENAME,
+ dwSize);
+
+ // set providerfilename0 = szProviderName
+ dwSize = lstrlen(szSPName) + 1;
+ wsprintf(szfilebuf, "%s%d", SZPROVIDERFILENAME, 0);
+ RegSetValueEx(hRepeaterKey,
+ szfilebuf,
+ 0,
+ REG_SZ,
+ (LPBYTE)szSPName,
+ dwSize);
+
+ // get provider id
+
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, i);
+ dwSize = sizeof(DWORD);
+ RegQueryValueEx(hProvidersKey,
+ szbuf,
+ NULL,
+ NULL,
+ (LPBYTE)&dwHold,
+ &dwSize);
+
+ // write in as provider ID 0
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, 0);
+ dwSize = sizeof(DWORD);
+ RegSetValueEx(hRepeaterKey,
+ szbuf,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwHold,
+ dwSize);
+
+ // write num providers in repeater key (always 1)
+ dwHold = 1;
+ dwSize = sizeof(DWORD);
+ RegSetValueEx(hRepeaterKey,
+ SZNUMPROVIDERS,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwHold,
+ dwSize);
+
+ dwSize = lstrlen(szLogFilePath) + 1;
+ RegSetValueEx(hRepeaterKey,
+ SZLOGDIR,
+ 0,
+ REG_SZ,
+ (LPBYTE)szLogFilePath,
+ dwSize);
+
+ RegCloseKey(hRepeaterKey);
+ RegCloseKey(hProvidersKey);
+ RegCloseKey(hTapiKey);
+ }
+ else
+ {
+ // now i is the provider number, so put repeater there
+ // and move provider's info to repeater key
+
+ // set ProviderFilenameX=repeater.tsp
+ WritePrivateProfileString(SZPROVIDERS,
+ szbuf,
+ SZREPEATERFILENAME,
+ SZTELEPHONINI);
+ // set providerfilename0 = szProviderName
+ wsprintf(szfilebuf, "%s%d", SZPROVIDERFILENAME, 0);
+ WritePrivateProfileString(SZREPEATER,
+ szfilebuf,
+ szSPName,
+ SZTELEPHONINI);
+
+ // get provider id
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, i);
+ dwHold = GetPrivateProfileInt(SZPROVIDERS,
+ szbuf,
+ 0,
+ SZTELEPHONINI);
+
+ // write in as provider ID 0
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, 0);
+ wsprintf(sznum, "%d", dwHold);
+ WritePrivateProfileString(SZREPEATER,
+ szbuf,
+ sznum,
+ SZTELEPHONINI);
+
+ // write num providers in repeater key (always 1)
+ WritePrivateProfileString(SZREPEATER,
+ SZNUMPROVIDERS,
+ "1",
+ SZTELEPHONINI);
+
+ WritePrivateProfileString(SZREPEATER,
+ SZLOGDIR,
+ szLogFilePath,
+ SZTELEPHONINI);
+
+
+ }
+ return TRUE;
+}
+
+BOOL DoUninstall(HWND hWnd)
+{
+ if (gbIsNT)
+ {
+ DWORD dwSize, dwHold, dwNumProviders;
+ HKEY hTapiKey, hProvidersKey, hRepeaterKey;
+ char szbuf[64], szfilebuf[256];
+ int i;
+
+ // get tapi key
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ SZTAPIKEY,
+ 0,
+ KEY_ALL_ACCESS,
+ &hTapiKey);
+
+ // get providers key
+ RegOpenKeyEx(hTapiKey,
+ SZPROVIDERS,
+ 0,
+ KEY_ALL_ACCESS,
+ &hProvidersKey);
+
+ RegOpenKeyEx(hTapiKey,
+ SZREPEATER,
+ 0,
+ KEY_ALL_ACCESS,
+ &hRepeaterKey);
+
+ // get number of providers
+ dwSize = sizeof(DWORD);
+ RegQueryValueEx(hProvidersKey,
+ SZNUMPROVIDERS,
+ NULL,
+ NULL,
+ (LPBYTE)&dwNumProviders,
+ &dwSize);
+
+ // find the provider
+ for (i = 0; i < (int)dwNumProviders; i++)
+ {
+ wsprintf(szbuf, "%s%d",SZPROVIDERFILENAME, i);
+
+ dwSize = 256;
+ RegQueryValueEx(hProvidersKey,
+ szbuf,
+ NULL,
+ NULL,
+ (LPBYTE)szfilebuf,
+ &dwSize);
+
+ // if it's the same break
+ if (!lstrcmpi(szfilebuf, SZREPEATERFILENAME))
+ {
+ break;
+ }
+
+ }
+
+ // didn't find the repeater provider
+ if (i == (int)dwNumProviders)
+ {
+ MessageBox(hWnd,
+ "Repeater is not installed",
+ SZREPEATERSETUP,
+ MB_OK);
+
+ return TRUE;
+ }
+
+ // now i is the provider number, so put repeater there
+ // and move provider's info to repeater key
+
+ // get original sp's name
+ wsprintf(szbuf, "%s%d", SZPROVIDERFILENAME, 0);
+ dwSize = 256;
+ RegQueryValueEx(hRepeaterKey,
+ szbuf,
+ NULL,
+ NULL,
+ (LPBYTE)szfilebuf,
+ &dwSize);
+
+ // write name back into provider's key
+ wsprintf(szbuf, "%s%d", SZPROVIDERFILENAME, i);
+ dwSize = lstrlen(szfilebuf) + 1;
+ RegSetValueEx(hProvidersKey,
+ szbuf,
+ 0,
+ REG_SZ,
+ (LPBYTE)szfilebuf,
+ dwSize);
+
+ // get provider id
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, 0);
+ dwSize = sizeof(DWORD);
+ RegQueryValueEx(hRepeaterKey,
+ szbuf,
+ NULL,
+ NULL,
+ (LPBYTE)&dwHold,
+ &dwSize);
+
+ // write in as provider ID
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, i);
+ dwSize = sizeof(DWORD);
+ RegSetValueEx(hProvidersKey,
+ szbuf,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwHold,
+ dwSize);
+
+ RegCloseKey(hRepeaterKey);
+ RegCloseKey(hProvidersKey);
+ RegDeleteKey(hTapiKey,
+ SZREPEATER);
+ RegCloseKey(hTapiKey);
+
+ }
+
+ else // win95
+ {
+ DWORD dwHold, dwNumProviders;
+ char szbuf[64], szfilebuf[256];
+ int i;
+
+ // get number of providers
+ dwNumProviders = GetPrivateProfileInt(SZPROVIDERS,
+ SZNUMPROVIDERS,
+ 0,
+ SZTELEPHONINI);
+
+ // find the provider
+ for (i = 0; i < (int)dwNumProviders; i++)
+ {
+ wsprintf(szbuf, "%s%d",SZPROVIDERFILENAME, i);
+
+ GetPrivateProfileString(SZPROVIDERS,
+ szbuf,
+ "",
+ szfilebuf,
+ 256,
+ SZTELEPHONINI);
+ // if it's the same break
+ if (!lstrcmpi(szfilebuf, SZREPEATERFILENAME))
+ {
+ break;
+ }
+
+ }
+
+ // didn't find the repeater provider
+ if (i == (int)dwNumProviders)
+ {
+ MessageBox(hWnd,
+ "Repeater is not installed",
+ SZREPEATERSETUP,
+ MB_OK);
+
+ return TRUE;
+ }
+
+ // now i is the provider number, so put repeater there
+ // and move provider's info to repeater key
+
+ // get original sp's name
+ wsprintf(szbuf, "%s%d", SZPROVIDERFILENAME, 0);
+ GetPrivateProfileString(SZREPEATER,
+ szbuf,
+ "",
+ szfilebuf,
+ 256,
+ SZTELEPHONINI);
+
+ // write name back into provider's key
+ wsprintf(szbuf, "%s%d", SZPROVIDERFILENAME, i);
+ WritePrivateProfileString(SZPROVIDERS,
+ szbuf,
+ szfilebuf,
+ SZTELEPHONINI);
+
+ // get provider id
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, 0);
+ dwHold = GetPrivateProfileInt(SZREPEATER,
+ szbuf,
+ 0,
+ SZTELEPHONINI);
+
+ // write in as provider ID
+ wsprintf(szbuf, "%s%d", SZPROVIDERID, i);
+ wsprintf(szfilebuf, "%d", dwHold);
+ WritePrivateProfileString(SZPROVIDERS,
+ szbuf,
+ szfilebuf,
+ SZTELEPHONINI);
+
+ }
+
+ // ok now copy repeater
+
+ {
+ char szfile[MAX_PATH];
+ char szdir[MAX_PATH];
+
+ GetSystemDirectory(szdir, MAX_PATH);
+
+ wsprintf(szfile, "%s\\%s", szdir, SZREPEATERFILENAME);
+
+ if (!DeleteFile(szfile))
+ {
+ MessageBox(NULL, "DeleteFile failed", NULL, MB_OK);
+ return FALSE;
+ }
+ }
+
+
+ return TRUE;
+}
+
+
+BOOL DoMoreInfo()
+{
+ char szname[MAX_PATH], szbuf[MAX_PATH];
+ int i;
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+
+ FillMemory(&si,
+ sizeof(si),
+ 0);
+
+ si.cb = sizeof(si);
+
+ GetModuleFileName(NULL,
+ szname,
+ MAX_PATH);
+
+ i = lstrlen(szname);
+
+ while (szname[i] != '\\')
+ {
+ szname[i] = 0;
+ i--;
+ }
+
+ wsprintf(szbuf, "notepad.exe %srepeater.txt", szname);
+ CreateProcess(NULL,
+ szbuf,
+ NULL,
+ NULL,
+ FALSE,
+ NORMAL_PRIORITY_CLASS,
+ NULL,
+ NULL,
+ &si,
+ &pi);
+ return FALSE;
+}
diff --git a/private/tapi/dev/sp/repeater/setup/setup.rc b/private/tapi/dev/sp/repeater/setup/setup.rc
new file mode 100644
index 000000000..63272a2af
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/setup/setup.rc
@@ -0,0 +1,46 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include <windows.h>
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_REPEATER DIALOG DISCARDABLE 0, 0, 268, 159
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Repeater Setup"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "&Install",ID_INSTALL,211,7,50,14
+ PUSHBUTTON "&Uninstall",ID_UNINSTALL,211,24,50,14
+ PUSHBUTTON "&More Info",ID_MOREINFO,211,42,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,211,59,50,14
+ EDITTEXT IDC_SPNAME,7,98,229,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_FILEDIRECTORY,7,132,229,14,ES_AUTOHSCROLL
+ LTEXT "Full path to directory to hold log files:",IDC_STATIC,7,
+ 121,228,8
+ LTEXT "Name of service provider (the .TSP file) EX: repeater.tsp",
+ IDC_STATIC,7,86,226,8
+ LTEXT "This program will install or uninstall the Repeater service provider. The TAPI service provider that Repeater is collecting information about MUST be installed before this program can be run. ",
+ IDC_STATIC,11,11,186,35
+END
+
+
+#if WINNT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Telephony API Repeater Setup"
+#define VER_INTERNALNAME_STR "SETUP"
+#define VER_ORIGINALFILENAME_STR "SETUP.EXE"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1996. All Rights Reserved."
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/repeater/setup/sources b/private/tapi/dev/sp/repeater/setup/sources
new file mode 100644
index 000000000..f1ddd48a6
--- /dev/null
+++ b/private/tapi/dev/sp/repeater/setup/sources
@@ -0,0 +1,55 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+Notes:
+
+ Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=setup
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=PROGRAM
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib
+
+INCLUDES=.;$(BASEDIR)\public\sdk\inc
+
+USE_CRTDLL=1
+
+SOURCES=setup.rc \
+ setup.cpp
+
+C_DEFINES=-DWINVER=0x0400
+
+UMTYPE=windows
+
+UMENTRY=winmain
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/tsp1632/makefile b/private/tapi/dev/sp/tsp1632/makefile
new file mode 100644
index 000000000..5bcdbc56d
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/makefile
@@ -0,0 +1,25 @@
+!if "$(OS)" == "Windows_NT"
+
+!else
+
+##########################################################################
+#
+# Microsoft Confidential
+# Copyright (C) Microsoft Corporation 1995
+# All Rights Reserved.
+#
+##########################################################################
+
+
+ROOT = ..\..\..\..\..
+DIR = tsp1632
+
+IS_OEM=1
+
+DIRLIST = script tsp1632l tsp1632s
+
+!include $(ROOT)\root.mk
+
+NTMAKEENV=.
+
+!endif
diff --git a/private/tapi/dev/sp/tsp1632/script/makefile b/private/tapi/dev/sp/tsp1632/script/makefile
new file mode 100644
index 000000000..c23c3c66a
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/makefile
@@ -0,0 +1,16 @@
+# THUNK Make file
+#
+#
+# Build Environment
+
+ROOT=..\..\..\..\..\..
+IS_OEM=1
+
+VERSIONLIST=debug retail
+DEFAULTVERDIR=debug
+DIR=thunk
+
+COMMONMKFILE=subthk.mk
+
+!include $(ROOT)\root.mk
+
diff --git a/private/tapi/dev/sp/tsp1632/script/subthk.mk b/private/tapi/dev/sp/tsp1632/script/subthk.mk
new file mode 100644
index 000000000..1f14abff8
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/subthk.mk
@@ -0,0 +1,49 @@
+# THUNK Make file
+#
+#
+
+# Build Environment
+ROOT=..\..\..\..\..\..\..
+IS_OEM=1
+
+# international mode
+
+!ifdef DBCS
+FDTHK = FdThkDB
+!else
+FDTHK = FdThk
+!endif
+
+THKASM = TapiThk.asm Tapi32.asm TapiFThk.asm
+FTHKASM = TapiFThk.asm
+
+
+TARGETS= $(THKASM)
+
+
+#DEPENDNAME=..\depend.mk
+
+#!include $(ROOT)\win\core\core.mk
+
+INCLUDE =
+
+#WIN32DEV=..\..\..\..\dev
+#WINCORE=..\..
+
+THUNKCOM = $(ROOT)\dev\tools\binr\thunk.exe
+
+THUNK = $(THUNKCOM) $(THUNKOPT)
+
+!IF "$(VERDIR)" == "maxdebug" || "$(VERDIR)" == "debug"
+THUNKOPT =
+!ELSE
+THUNKOPT =
+!ENDIF
+
+
+$(THKASM) : $(THUNKCOM) ..\$(@B).thk
+ $(THUNK) -NC THUNK16B -o $(@B) ..\$(@B).thk
+
+
+TapiThk.asm TapiFThk.asm Tapi32.asm: ..\TapiThk.inc
+
diff --git a/private/tapi/dev/sp/tsp1632/script/tapi32.inc b/private/tapi/dev/sp/tsp1632/script/tapi32.inc
new file mode 100644
index 000000000..ceb07849a
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/tapi32.inc
@@ -0,0 +1,11 @@
+; Callback24 PROTO NEAR STDCALL :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
+;Callback24 PROTO NEAR STDCALL :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
+
+include thkrp.inc
+include cbcheck.inc
+include thkframe.inc
+include public.inc
+include thkmacro.inc
+
+externDef Callback24:far16
+
diff --git a/private/tapi/dev/sp/tsp1632/script/tapi32.thk b/private/tapi/dev/sp/tsp1632/script/tapi32.thk
new file mode 100644
index 000000000..127088392
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/tapi32.thk
@@ -0,0 +1,31 @@
+/*
+ * Lzexpand APIs thunks for Win32s
+ */
+//__foldwin32sstuff __foldwin32sstuff;
+//foldstyleinitialization = true;
+
+
+enablemapdirect3216 = true;
+//preload32=true;
+//flatthunks = true;
+
+#include "..\types.thk"
+
+typedef DWORD HTAPI;
+typedef HTAPI *LPHTAPI;
+typedef HTAPI HAPP;
+typedef HAPP HLINEAPP;
+
+
+// Thunk for callback
+BOOL _TapiCallbackThunk( HLINEAPP hDevice,
+ DWORD dwMessage,
+ DWORD dwInstance,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD cbProc32)
+{
+ target = Callback28;
+}
+
diff --git a/private/tapi/dev/sp/tsp1632/script/tapicbid.inc b/private/tapi/dev/sp/tsp1632/script/tapicbid.inc
new file mode 100644
index 000000000..06b100729
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/tapicbid.inc
@@ -0,0 +1,17 @@
+; Callback-type id's for TAPI callbacks. All callback-type id's are
+; 32-bits long and the upper 16-bits must be set to the module's
+; Callback Client id.
+;
+; WARNING -- WARNING -- WARNING
+;
+; Win32c.dll uses the lower 16 bits of CBID's to index directly into
+; the tables stored in GDI.EXE (gdicb16.asm) and GDI32.DLL (gdicb32.asm).
+; Those tables *must* match these id's or callbacks will fail miserably.
+; Do everyone a big favor and add new id's only at the end, and never
+; change an existing id.
+;
+
+ID_LINEINITIALIZE equ 0
+ID_PHONEINITIALIZE equ 1
+ID_LINESHUTDOWN equ 2
+ID_PHONESHUTDOWN equ 3
diff --git a/private/tapi/dev/sp/tsp1632/script/tapifthk.inc b/private/tapi/dev/sp/tsp1632/script/tapifthk.inc
new file mode 100644
index 000000000..e2099aa99
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/tapifthk.inc
@@ -0,0 +1 @@
+; empty file !
diff --git a/private/tapi/dev/sp/tsp1632/script/tapifthk.thk b/private/tapi/dev/sp/tsp1632/script/tapifthk.thk
new file mode 100644
index 000000000..ff6cc6fdd
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/tapifthk.thk
@@ -0,0 +1,587 @@
+/*
+ * Lzexpand APIs thunks for Win32s
+ */
+//__foldwin32sstuff __foldwin32sstuff;
+//foldstyleinitialization = true;
+
+enablemapdirect1632 = true;
+//preload32=true;
+//flatthunks = false;
+
+#include "..\types.thk"
+
+typedef DWORD HTAPI;
+typedef HTAPI *LPHTAPI;
+typedef HTAPI HAPP;
+typedef HAPP *LPHAPP;
+typedef HTAPI HLINEAPP;
+typedef HTAPI HPHONEAPP;
+typedef HTAPI HCALL;
+typedef HCALL *LPHCALL;
+typedef HTAPI HLINE;
+typedef HLINE *LPHLINE;
+typedef HTAPI HPHONE;
+typedef HPHONE *LPHPHONE;
+typedef HICON *LPHICON;
+typedef LPSTR LPCSTR;
+/* LPVOID in types.thk */
+typedef LPVOID LPLINETRANSLATEOUTPUT; /* LP to data structure */
+typedef LPVOID LPLINETRANSLATECAPS; /* LP to data structure */
+typedef LPVOID LPLINEFORWARDLIST;
+typedef LPVOID LPLINECALLPARAMS;
+typedef LPVOID LPLINEGENERATETONE;
+typedef LPVOID LPLINEADDRESSCAPS;
+typedef LPVOID LPLINEADDRESSSTATUS;
+typedef LPVOID LPLINECALLINFO;
+typedef LPVOID LPLINECALLSTATUS;
+typedef LPVOID LPLINECALLLIST;
+typedef LPVOID LPLINEDEVCAPS;
+typedef LPVOID LPLINEDEVSTATUS;
+typedef LPVOID LPLINEMONITORTONE;
+typedef LPVOID LPLINEEXTENSIONID;
+typedef LPVOID LPVARSTRING;
+typedef LPVOID LPLINEDIALPARAMS;
+typedef LPVOID LPLINEMEDIACONTROLDIGIT;
+typedef LPVOID LPLINEMEDIACONTROLMEDIA;
+typedef LPVOID LPLINEMEDIACONTROLTONE;
+typedef LPVOID LPLINEMEDIACONTROLCALLSTATE;
+typedef LPVOID LPPHONEBUTTONINFO;
+typedef LPVOID LPPHONECAPS;
+typedef LPVOID LPPHONESTATUS;
+typedef LPVOID LPPHONEEXTENSIONID;
+typedef LPVOID LPLINECOUNTRYLIST;
+typedef LPVOID LPLINEPROVIDERLIST;
+
+
+
+//
+//
+typedef DWORD DRV_REQUESTID;
+typedef DWORD HDRVLINE;
+typedef DWORD HDRVPHONE;
+typedef DWORD HTAPICALL;
+typedef DWORD HTAPILINE;
+typedef DWORD HDRVCALL;
+typedef HDRVCALL * LPHDRVCALL;
+typedef HDRVLINE * LPHDRVLINE;
+typedef HDRVPHONE * LPHDRVPHONE;
+
+typedef DWORD HTAPIPHONE;
+
+typedef DWORD LINEEVENT;
+typedef DWORD PHONEEVENT;
+
+typedef LPVOID ASYNC_COMPLETION;
+
+typedef DWORD HPROVIDER;
+//
+//
+
+
+
+
+
+
+//UINT GetTapiHInst(void) =
+//UINT GetTapiHInst(void)
+//{}
+
+
+UINT NewData(void) =
+UINT NewData(void)
+{}
+
+UINT NewData2(void) =
+UINT NewData2(void)
+{}
+
+
+
+/* Tapi Address Translation procedures */
+
+LONG TSPI_lineSetCurrentLocation (DWORD dwLocation) =
+LONG TSPI_lineSetCurrentLocation (DWORD dwLocation)
+{}
+
+//LONG lineSetTollList (HLINEAPP hLineApp, DWORD dwPermanentLineID, LPCSTR lpszAddressIn, DWORD dwTollListOption) =
+//LONG lineSetTollList (HLINEAPP hLineApp, DWORD dwPermanentLineID, LPCSTR lpszAddressIn, DWORD dwTollListOption)
+//{}
+
+//LONG lineTranslateAddress (HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, LPCSTR lpszAddressIn,
+// DWORD dwCard, DWORD dwTranslateOptions, LPLINETRANSLATEOUTPUT lpTranslateOutput) =
+//LONG lineTranslateAddress (HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, LPCSTR lpszAddressIn,
+// DWORD dwCard, DWORD dwTranslateOptions, LPLINETRANSLATEOUTPUT lpTranslateOutput)
+//{}
+
+//LONG lineGetTranslateCaps (HLINEAPP hLineApp, DWORD dwAPIVersion, LPLINETRANSLATECAPS lpTranslateCaps) =
+//LONG lineGetTranslateCaps (HLINEAPP hLineApp, DWORD dwAPIVersion, LPLINETRANSLATECAPS lpTranslateCaps)
+//{}
+
+
+/* Tapi function prototypes */
+
+LONG TSPI_lineAccept (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineAccept (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HDRVCALL hdConsultCall) =
+LONG TSPI_lineAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HDRVCALL hdConsultCall)
+{}
+
+LONG TSPI_lineAnswer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineAnswer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineBlindTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) =
+LONG TSPI_lineBlindTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
+{}
+
+LONG TSPI_lineClose (HDRVLINE hdLine) =
+LONG TSPI_lineClose (HDRVLINE hdLine)
+{}
+
+LONG TSPI_lineCloseCall(HDRVCALL hdCall) =
+LONG TSPI_lineCloseCall(HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineConditionalMediaDetection (HDRVLINE hdLine, DWORD dwMediaModes, LPLINECALLPARAMS lpLineCallParams) =
+LONG TSPI_lineConditionalMediaDetection (HDRVLINE hdLine, DWORD dwMediaModes, LPLINECALLPARAMS lpLineCallParams)
+{}
+
+LONG TSPI_lineConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass)
+{}
+
+//LONG lineDeallocateCall (HDRVCALL hdCall) =
+//LONG lineDeallocateCall (HDRVCALL hdCall)
+//{}
+
+LONG TSPI_lineDial (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) =
+LONG TSPI_lineDial (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
+{}
+
+LONG TSPI_lineDrop (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineDrop (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineDropNoOwner (HDRVCALL hdCall) =
+LONG TSPI_lineDropNoOwner (HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineDropOnClose (HDRVCALL hdCall) =
+LONG TSPI_lineDropOnClose (HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineGenerateDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitMode, LPCSTR lpszDigits, DWORD dwDuration) =
+LONG TSPI_lineGenerateDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitMode, LPCSTR lpszDigits, DWORD dwDuration)
+{}
+
+LONG TSPI_lineGenerateTone (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwToneMode, DWORD dwDuration, DWORD dwNumTones, LPLINEGENERATETONE lpTones) =
+LONG TSPI_lineGenerateTone (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwToneMode, DWORD dwDuration, DWORD dwNumTones, LPLINEGENERATETONE lpTones)
+{}
+
+LONG TSPI_lineGetAddressCaps (DWORD dwDeviceID, DWORD dwAddressID, DWORD dwAPIVersion,
+ DWORD dwExtVersion, LPLINEADDRESSCAPS lpAddressCaps) =
+LONG TSPI_lineGetAddressCaps (DWORD dwDeviceID, DWORD dwAddressID, DWORD dwAPIVersion,
+ DWORD dwExtVersion, LPLINEADDRESSCAPS lpAddressCaps)
+{}
+
+LONG TSPI_lineGetAddressID (HDRVLINE hdLine, LPDWORD lpdwAddressID, DWORD dwAddressMode, LPCSTR lpsAddress, DWORD dwSize) =
+LONG TSPI_lineGetAddressID (HDRVLINE hdLine, LPDWORD lpdwAddressID, DWORD dwAddressMode, LPCSTR lpsAddress, DWORD dwSize)
+{}
+
+LONG TSPI_lineGetAddressStatus (HDRVLINE hdLine, DWORD dwAddressID, LPLINEADDRESSSTATUS lpAddressStatus) =
+LONG TSPI_lineGetAddressStatus (HDRVLINE hdLine, DWORD dwAddressID, LPLINEADDRESSSTATUS lpAddressStatus)
+{}
+
+LONG TSPI_lineGetCallAddressID (HDRVCALL hdCall, LPDWORD lpdwAddressID) =
+LONG TSPI_lineGetCallAddressID (HDRVCALL hdCall, LPDWORD lpdwAddressID)
+{}
+
+LONG TSPI_lineGetCallInfo (HDRVCALL hdCall, LPLINECALLINFO lpCallInfo) =
+LONG TSPI_lineGetCallInfo (HDRVCALL hdCall, LPLINECALLINFO lpCallInfo)
+{}
+
+LONG TSPI_lineGetCallStatus (HDRVCALL hdCall, LPLINECALLSTATUS lpCallStatus) =
+LONG TSPI_lineGetCallStatus (HDRVCALL hdCall, LPLINECALLSTATUS lpCallStatus)
+{}
+
+//LONG lineGetConfRelatedCalls (HDRVCALL hdCall, LPLINECALLLIST lpCallList) =
+//LONG lineGetConfRelatedCalls (HDRVCALL hdCall, LPLINECALLLIST lpCallList)
+//{}
+
+LONG TSPI_lineGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPLINEDEVCAPS lpLineDevCaps) =
+LONG TSPI_lineGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPLINEDEVCAPS lpLineDevCaps)
+{}
+
+LONG TSPI_lineGetDevConfig (DWORD dwDeviceID, LPVARSTRING lpDeviceConfig, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineGetDevConfig (DWORD dwDeviceID, LPVARSTRING lpDeviceConfig, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_lineGetExtensionID (DWORD dwDeviceID, DWORD dwTSPIVersion, LPLINEEXTENSIONID lpExtensionID) =
+LONG TSPI_lineGetExtensionID (DWORD dwDeviceID, DWORD dwTSPIVersion, LPLINEEXTENSIONID lpExtensionID)
+{}
+
+//LONG lineGetNewCalls (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwSelect, LPLINECALLLIST lpCallList) =
+//LONG lineGetNewCalls (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwSelect, LPLINECALLLIST lpCallList)
+//{}
+
+LONG TSPI_lineGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon) =
+LONG TSPI_lineGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon)
+{}
+
+LONG TSPI_lineGetID (HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineGetID (HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_lineGetLineDevStatus (HDRVLINE hdLine, LPLINEDEVSTATUS lpLineDevStatus) =
+LONG TSPI_lineGetLineDevStatus (HDRVLINE hdLine, LPLINEDEVSTATUS lpLineDevStatus)
+{}
+
+LONG TSPI_lineGetNumAddressIDs (HDRVLINE hdLine, LPDWORD lpdwNumAddressIDS) =
+LONG TSPI_lineGetNumAddressIDs (HDRVLINE hdLine, LPDWORD lpdwNumAddressIDS)
+{}
+
+//LONG lineGetNumRings (HDRVLINE hdLine, DWORD dwAddressID, LPDWORD lpdwNumRings) =
+//LONG lineGetNumRings (HDRVLINE hdLine, DWORD dwAddressID, LPDWORD lpdwNumRings)
+//{}
+
+//LONG lineGetRequest (HDRVLINEAPP hdLineApp, DWORD dwRequestMode, LPVOID lpRequestBuffer) =
+//LONG lineGetRequest (HDRVLINEAPP hdLineApp, DWORD dwRequestMode, LPVOID lpRequestBuffer)
+//{}
+
+//LONG lineGetStatusMessages (HDRVLINE hdLine, LPDWORD lpdwLineStates, LPDWORD lpdwAddressStates) =
+//LONG lineGetStatusMessages (HDRVLINE hdLine, LPDWORD lpdwLineStates, LPDWORD lpdwAddressStates)
+//{}
+
+//LONG lineHandoff (HDRVCALL hdCall, LPCSTR lpszModuleName, DWORD dwMediaMode) =
+//LONG lineHandoff (HDRVCALL hdCall, LPCSTR lpszModuleName, DWORD dwMediaMode)
+//{}
+
+LONG TSPI_lineHold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineHold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineReleaseUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineReleaseUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineMonitorDigits (HDRVCALL hdCall, DWORD dwDigitModes) =
+LONG TSPI_lineMonitorDigits (HDRVCALL hdCall, DWORD dwDigitModes)
+{}
+
+LONG TSPI_lineMonitorMedia (HDRVCALL hdCall, DWORD dwMediaModes) =
+LONG TSPI_lineMonitorMedia (HDRVCALL hdCall, DWORD dwMediaModes)
+{}
+
+LONG TSPI_lineMonitorTones (HDRVCALL hdCall, DWORD dwToneListID, LPLINEMONITORTONE lpToneList, DWORD dwNumEntries) =
+LONG TSPI_lineMonitorTones (HDRVCALL hdCall, DWORD dwToneListID, LPLINEMONITORTONE lpToneList, DWORD dwNumEntries)
+{}
+
+LONG TSPI_lineNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion) =
+LONG TSPI_lineNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTsPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion)
+{}
+
+LONG TSPI_lineNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwLowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion) =
+LONG TSPI_lineNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwLowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion)
+{}
+
+LONG TSPI_lineOpen (DWORD dwDeviceID, HTAPILINE htLine, LPHDRVLINE lphdLine, DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc) =
+LONG TSPI_lineOpen (DWORD dwDeviceID, HTAPILINE htLine, LPHDRVLINE lphdLine, DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc)
+{}
+
+LONG TSPI_lineRedirect (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) =
+LONG TSPI_lineRedirect (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
+{}
+
+LONG TSPI_lineRemoveFromConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineRemoveFromConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineSecureCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineSecureCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineSelectExtVersion (HDRVLINE hdLine, DWORD dwExtVersion) =
+LONG TSPI_lineSelectExtVersion (HDRVLINE hdLine, DWORD dwExtVersion)
+{}
+
+LONG TSPI_lineSendUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineSendUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineSetAppSpecific (HDRVCALL hdCall, DWORD dwAppSpecific) =
+LONG TSPI_lineSetAppSpecific (HDRVCALL hdCall, DWORD dwAppSpecific)
+{}
+
+LONG TSPI_lineSetCallParams (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwBearerMode, DWORD dwMinRate, DWORD dwMaxRate, LPLINEDIALPARAMS lpDialParams) =
+LONG TSPI_lineSetCallParams (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwBearerMode, DWORD dwMinRate, DWORD dwMaxRate, LPLINEDIALPARAMS lpDialParams)
+{}
+
+//LONG lineSetCallPrivilege (HDRVCALL hdCall, DWORD dwCallPrivilege) =
+//LONG lineSetCallPrivilege (HDRVCALL hdCall, DWORD dwCallPrivilege)
+//{}
+
+LONG TSPI_lineSetDevConfig (DWORD dwDeviceID, LPVOID lpDeviceConfig, DWORD dwSize, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineSetDevConfig (DWORD dwDeviceID, LPVOID lpDeviceConfig, DWORD dwSize, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_lineSetMediaControl (HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPLINEMEDIACONTROLDIGIT lpDigitList, DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA lpMediaList, DWORD dwMediaNumEntries, LPLINEMEDIACONTROLTONE lpToneList, DWORD dwToneNumEntries, LPLINEMEDIACONTROLCALLSTATE lpCallStateList, DWORD dwCallStateNumEntries) =
+LONG TSPI_lineSetMediaControl (HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPLINEMEDIACONTROLDIGIT lpDigitList, DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA lpMediaList, DWORD dwMediaNumEntries, LPLINEMEDIACONTROLTONE lpToneList, DWORD dwToneNumEntries, LPLINEMEDIACONTROLCALLSTATE lpCallStateList, DWORD dwCallStateNumEntries)
+{}
+
+LONG TSPI_lineSetDefaultMediaDetection(HDRVLINE hdLine, DWORD dwMediaModes) =
+LONG TSPI_lineSetDefaultMediaDetection(HDRVLINE hdLine, DWORD dwMediaModes)
+{}
+
+LONG TSPI_lineSetMediaMode (HDRVCALL hdCall, DWORD dwMediaModes) =
+LONG TSPI_lineSetMediaMode (HDRVCALL hdCall, DWORD dwMediaModes)
+{}
+
+//LONG lineSetNumRings (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwNumRings) =
+//LONG lineSetNumRings (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwNumRings)
+//{}
+
+LONG TSPI_lineSetStatusMessages (HDRVLINE hdLine, DWORD dwLineStates, DWORD dwAddressStates) =
+LONG TSPI_lineSetStatusMessages (HDRVLINE hdLine, DWORD dwLineStates, DWORD dwAddressStates)
+{}
+
+LONG TSPI_lineSetTerminal (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect,
+ DWORD dwTerminalModes, DWORD dwTerminalID, DWORD bEnable) =
+LONG TSPI_lineSetTerminal (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect,
+ DWORD dwTerminalModes, DWORD dwTerminalID, DWORD bEnable)
+{}
+
+LONG TSPI_lineSwapHold (DRV_REQUESTID dwRequestID, HDRVCALL hdActiveCall, HDRVCALL hdHeldCall) =
+LONG TSPI_lineSwapHold (DRV_REQUESTID dwRequestID, HDRVCALL hdActiveCall, HDRVCALL hdHeldCall)
+{}
+
+LONG TSPI_lineUncompleteCall (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwCompletionID) =
+LONG TSPI_lineUncompleteCall (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwCompletionID)
+{}
+
+LONG TSPI_lineUnhold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineUnhold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_phoneClose (HDRVPHONE hdPhone) =
+LONG TSPI_phoneClose (HDRVPHONE hdPhone)
+{}
+
+LONG TSPI_phoneConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass) =
+LONG TSPI_phoneConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_phoneGetButtonInfo (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo) =
+LONG TSPI_phoneGetButtonInfo (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo)
+{}
+
+LONG TSPI_phoneGetData (HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize) =
+LONG TSPI_phoneGetData (HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize)
+{}
+
+LONG TSPI_phoneGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPPHONECAPS lpPhoneCaps) =
+LONG TSPI_phoneGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPPHONECAPS lpPhoneCaps)
+{}
+
+LONG TSPI_phoneGetDisplay (HDRVPHONE hdPhone, LPVARSTRING lpDisplay) =
+LONG TSPI_phoneGetDisplay (HDRVPHONE hdPhone, LPVARSTRING lpDisplay)
+{}
+
+LONG TSPI_phoneGetExtensionID (DWORD dwDevice, DWORD dwTSPIVersion, LPPHONEEXTENSIONID lpExtensionID) =
+LONG TSPI_phoneGetExtensionID (DWORD dwDevice, DWORD dwTSPIVersion, LPPHONEEXTENSIONID lpExtensionID)
+{}
+
+LONG TSPI_phoneGetGain (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwGain) =
+LONG TSPI_phoneGetGain (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwGain)
+{}
+
+LONG TSPI_phoneGetHookSwitch (HDRVPHONE hdPhone, LPDWORD lpdwHookSwitchDevs) =
+LONG TSPI_phoneGetHookSwitch (HDRVPHONE hdPhone, LPDWORD lpdwHookSwitchDevs)
+{}
+
+LONG TSPI_phoneGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon) =
+LONG TSPI_phoneGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon)
+{}
+
+LONG TSPI_phoneGetID (HDRVPHONE hdPhone, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass) =
+LONG TSPI_phoneGetID (HDRVPHONE hdPhone, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_phoneGetLamp (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPDWORD lpdwLampMode) =
+LONG TSPI_phoneGetLamp (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPDWORD lpdwLampMode)
+{}
+
+LONG TSPI_phoneGetRing (HDRVPHONE hdPhone, LPDWORD lpdwRingMode, LPDWORD lpdwVolume) =
+LONG TSPI_phoneGetRing (HDRVPHONE hdPhone, LPDWORD lpdwRingMode, LPDWORD lpdwVolume)
+{}
+
+LONG TSPI_phoneGetStatus (HDRVPHONE hdPhone, LPPHONESTATUS lpPhoneStatus) =
+LONG TSPI_phoneGetStatus (HDRVPHONE hdPhone, LPPHONESTATUS lpPhoneStatus)
+{}
+
+//LONG phoneGetStatusMessages (HDRVPHONE hdPhone, LPDWORD lpdwPhoneStates, LPDWORD lpdwButtonModes, LPDWORD lpdwButtonStates) =
+//LONG phoneGetStatusMessages (HDRVPHONE hdPhone, LPDWORD lpdwPhoneStates, LPDWORD lpdwButtonModes, LPDWORD lpdwButtonStates)
+//{}
+
+LONG TSPI_phoneGetVolume (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwVolume) =
+LONG TSPI_phoneGetVolume (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwVolume)
+{}
+
+LONG TSPI_phoneNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion) =
+LONG TSPI_phoneNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion)
+{}
+
+LONG TSPI_phoneNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwTSPILowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion) =
+LONG TSPI_phoneNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwTSPILowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion)
+{}
+
+LONG TSPI_phoneOpen (DWORD dwDeviceID, HTAPIPHONE htPhone, LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion, PHONEEVENT lpfnEventProc) =
+LONG TSPI_phoneOpen (DWORD dwDeviceID, HTAPIPHONE htPhone, LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion, PHONEEVENT lpfnEventProc)
+{}
+
+LONG TSPI_phoneSelectExtVersion (HDRVPHONE hdPhone, DWORD dwExtVersion) =
+LONG TSPI_phoneSelectExtVersion (HDRVPHONE hdPhone, DWORD dwExtVersion)
+{}
+
+LONG TSPI_phoneSetButtonInfo (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo) =
+LONG TSPI_phoneSetButtonInfo (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo)
+{}
+
+LONG TSPI_phoneSetData (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize) =
+LONG TSPI_phoneSetData (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize)
+{}
+
+LONG TSPI_phoneSetDisplay (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRow, DWORD dwColumn, LPCSTR lpsDisplay, DWORD dwSize) =
+LONG TSPI_phoneSetDisplay (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRow, DWORD dwColumn, LPCSTR lpsDisplay, DWORD dwSize)
+{}
+
+LONG TSPI_phoneSetGain (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwGain) =
+LONG TSPI_phoneSetGain (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwGain)
+{}
+
+LONG TSPI_phoneSetHookSwitch (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDevs, DWORD dwHookSwitchMode) =
+LONG TSPI_phoneSetHookSwitch (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDevs, DWORD dwHookSwitchMode)
+{}
+
+LONG TSPI_phoneSetLamp (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, DWORD dwLampMode) =
+LONG TSPI_phoneSetLamp (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, DWORD dwLampMode)
+{}
+
+LONG TSPI_phoneSetRing (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRingMode, DWORD dwVolume) =
+LONG TSPI_phoneSetRing (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRingMode, DWORD dwVolume)
+{}
+
+LONG TSPI_phoneSetStatusMessages (HDRVPHONE hdPhone, DWORD dwPhoneStates, DWORD dwButtonModes, DWORD dwButtonStates) =
+LONG TSPI_phoneSetStatusMessages (HDRVPHONE hdPhone, DWORD dwPhoneStates, DWORD dwButtonModes, DWORD dwButtonStates)
+{}
+
+LONG TSPI_phoneSetVolume (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwVolume) =
+LONG TSPI_phoneSetVolume (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwVolume)
+{}
+
+
+/* TAPI 1.1 extensions */
+
+
+//LONG lineTranslateDialog (HDRVLINEAPP hdLineApp, DWORD dwDeviceId, DWORD dwAPIVersion, HWND hWnd, LPSTR lpszAddressIn) =
+//LONG lineTranslateDialog (HDRVLINEAPP hdLineApp, DWORD dwDeviceId, DWORD dwAPIVersion, HWND hWnd, LPSTR lpszAddressIn)
+//{}
+
+//LONG lineGetCountry (DWORD dwCountryID, DWORD dwAPIVersion, LPLINECOUNTRYLIST lpLineCountryList) =
+//LONG lineGetCountry (DWORD dwCountryID, DWORD dwAPIVersion, LPLINECOUNTRYLIST lpLineCountryList)
+//{}
+
+//LONG lineGetAppPriority (LPCSTR lpszAppName, DWORD dwMediaMode, LPLINEEXTENSIONID lpExtensionID, DWORD dwRequestMode, LPVARSTRING lpExtensionName, LPDWORD lpdwPriority) =
+//LONG lineGetAppPriority (LPCSTR lpszAppName, DWORD dwMediaMode, LPLINEEXTENSIONID lpExtensionID, DWORD dwRequestMode, LPVARSTRING lpExtensionName, LPDWORD lpdwPriority)
+//{}
+
+//LONG lineSetAppPriority (LPCSTR lpszAppName, DWORD dwMediaMode, LPLINEEXTENSIONID lpExtensionID, DWORD dwRequestMode, LPCSTR lpszExtensionName, DWORD dwPriority) =
+//LONG lineSetAppPriority (LPCSTR lpszAppName, DWORD dwMediaMode, LPLINEEXTENSIONID lpExtensionID, DWORD dwRequestMode, LPCSTR lpszExtensionName, DWORD dwPriority)
+//{}
+
+//LONG lineAddProvider (LPCSTR lpszProviderFilename, HWND hwndOwner, LPDWORD lpdwPermanentProviderID) =
+//LONG lineAddProvider (LPCSTR lpszProviderFilename, HWND hwndOwner, LPDWORD lpdwPermanentProviderID)
+//{}
+
+//LONG lineConfigProvider (HWND hwndOwner, DWORD dwPermanentProviderID) =
+//LONG lineConfigProvider (HWND hwndOwner, DWORD dwPermanentProviderID)
+//{}
+
+//LONG lineRemoveProvider (DWORD dwPermanentProviderID, HWND hwndOwner) =
+//LONG lineRemoveProvider (DWORD dwPermanentProviderID, HWND hwndOwner)
+//{}
+
+//LONG lineGetProviderList (DWORD dwAPIVersion, LPLINEPROVIDERLIST lpProviderList) =
+//LONG lineGetProviderList (DWORD dwAPIVersion, LPLINEPROVIDERLIST lpProviderList)
+//{}
+
+LONG TSPI_lineConfigDialogEdit(DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass, LPVOID lpDeviceConfigIn, DWORD dwSize, LPVARSTRING lpDeviceConfigOut) =
+LONG TSPI_lineConfigDialogEdit(DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass, LPVOID lpDeviceConfigIn, DWORD dwSize, LPVARSTRING lpDeviceConfigOut)
+{}
+
+
+
+
+LONG TSPI_providerConfig (HWND hwndOwner, DWORD dwPermanentProviderID) =
+LONG TSPI_providerConfig (HWND hwndOwner, DWORD dwPermanentProviderID)
+{}
+
+LONG TSPI_providerCreateLineDevice (DWORD dwTempID, DWORD dwDeviceID ) =
+LONG TSPI_providerCreateLineDevice (DWORD dwTempID, DWORD dwDeviceID )
+{}
+
+LONG TSPI_providerCreatePhoneDevice (DWORD dwTempID, DWORD dwDeviceID ) =
+LONG TSPI_providerCreatePhoneDevice (DWORD dwTempID, DWORD dwDeviceID )
+{}
+
+LONG TSPI_providerEnumDevices(DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines, LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider, LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc) =
+LONG TSPI_providerEnumDevices(DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines, LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider, LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc)
+{}
+
+LONG TSPI_providerInit (DWORD dwTSPIVersion, DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase, DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines, DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc) =
+LONG TSPI_providerInit (DWORD dwTSPIVersion, DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase, DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines, DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc)
+{}
+
+LONG TSPI_providerInstall (HWND hwndOwner, DWORD dwPermanentProviderID) =
+LONG TSPI_providerInstall (HWND hwndOwner, DWORD dwPermanentProviderID)
+{}
+
+LONG TSPI_providerRemove (HWND hwndOwner, DWORD dwPermanentProviderID) =
+LONG TSPI_providerRemove (HWND hwndOwner, DWORD dwPermanentProviderID)
+{}
+
+LONG TSPI_providerShutdown (DWORD dwTSPIVersion) =
+LONG TSPI_providerShutdown (DWORD dwTSPIVersion)
+{}
+
+
+// // LONG DllEntryPoint(HANDLE hinstDLL, DWORD dwReason, LPVOID lpReserved) =
+// // LONG DllEntryPoint(HANDLE hinstDLL, DWORD dwReason, LPVOID lpReserved)
+// // {}
diff --git a/private/tapi/dev/sp/tsp1632/script/tapithk.inc b/private/tapi/dev/sp/tsp1632/script/tapithk.inc
new file mode 100644
index 000000000..63ad5baca
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/tapithk.inc
@@ -0,0 +1,1234 @@
+
+CodeData equ <THUNK16BCodeData>
+
+include thkrp.inc
+include cbcheck.inc
+include thkframe.inc
+include public.inc
+include thkmacro.inc
+;include struc.inc
+
+include cbcid.inc
+include tapicbid.inc
+
+;externDef IsBadCodePtr:far16
+externDef CALLBACK_BODY_16:far16
+externDef Escape:far16
+externDef AllocCallback:far16
+externDef MapLS:far16
+externDef UnmapLS:far16
+ifdef DEBUG
+externDef _wsprintf:far16
+externDef OutputDebugString:far16
+endif
+
+externDef FreeCallback:far16
+
+
+externDef lineInitialize:far16
+externDef phoneInitialize:far16
+externDef lineShutdown:far16
+externDef phoneShutdown:far16
+
+
+public addrCBLineInit ;Address of callback routine passed in lineInitialize
+public addrCBPhoneInit ;Address of callback routine passed in phoneInitialize
+public cbcidTapi ;Callback ID for client returned by RegisterCBClient
+_DATA SEGMENT
+addrCBLineInit dd 0
+addrCBPhoneInit dd 0
+cbcidTapi dd 0
+_DATA ENDS
+
+ifdef DEBUG
+;; Writes message to debug port.
+;;
+;; Usage:
+;; DPRINT "I'm feeling buggy."
+;;
+DPRINT macro string
+ local mes, skip_mes
+
+ jmp skip_mes
+mes db &string&,13,10,0
+skip_mes:
+ push eax ;Save all registers not preserved by PASCAL format.
+ push ebx
+ push ecx
+ push edx
+
+ push cs ;Arg: OutputDebugString(lpstr)
+ push offset mes
+ call OutputDebugString
+
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+endm ;DPRINT
+endif
+
+
+;-----------------------------------------------------------------------;
+; body_LINEINITIALIZE16
+;-----------------------------------------------------------------------;
+body_LINEINITIALIZE16 macro
+
+;LONG lineInitialize16 (LPHLINEAPP lphLineApp,
+; HINSTANCE hInstance,
+; LINECALLBACK lpfnCallback,
+; LPCSTR lpszAppName,
+; LPDWORD lpdwNumDevs)
+;
+bp_lphLineApp equ <bp_top>
+bp_hInstance equ <bp_top+4>
+bp_lpfnCallback equ <bp_top+8>
+bp_lpszAppName equ <bp_top+12>
+bp_lpdwNumDevs equ <bp_top+16>
+;
+
+bp_lpszAppNameTmp equ <dword ptr [bp-4]>
+bp_lpdwNumDevsTmp equ <dword ptr [bp-8]>
+bp_lphLineAppTmp equ <dword ptr [bp-12]>
+
+ ;
+ ; First order of business: check the code pointer. If it's
+ ; bogus, we leave.
+ ;
+
+; push dword ptr bp_lpfnCallback
+; call IsBadCodePtr
+; or eax, eax
+; jnz DoNothing
+
+ sub eax, eax
+ push eax ;bp_lpszAppNameTmp
+ push eax ;bp_lpdwNumDevsTmp
+ push eax ;bp_lphLineAppTmp
+
+ push dword ptr bp_lphLineApp
+ call MapLS
+ mov bp_lphLineAppTmp, eax
+ push eax
+
+ mov eax, dword ptr bp_hInstance ; Get the hInst
+ or eax, eax ; Is it NULL?
+ jz @f ; Yup, and that's ok.
+ MAP_NULL_HINST eax ; Needs to be mapped.
+ push ax
+
+; mov ax, seg addrCBLineInit
+; mov ds, ax
+; mov eax, dword ptr bp_lpfnCallback
+; mov addrCBLineInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_LINEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+
+ push dword ptr bp_lpfnCallback
+
+ push dword ptr bp_lpszAppName
+ call MapLS
+ mov bp_lpszAppNameTmp, eax
+ push eax
+
+ push dword ptr bp_lpdwNumDevs
+ call MapLS
+ mov bp_lpdwNumDevsTmp, eax
+ push eax
+
+
+ call lineInitialize
+
+
+ shl eax,16 ; Convert the 16bit retcode...
+ shrd eax,edx,16 ; to a 32bit retcode.
+
+ push eax ; Save the retcode for later.
+
+ push dword ptr bp_lpdwNumDevsTmp
+ call UnMapLS
+
+ push dword ptr bp_lpszAppNameTmp
+ call UnMapLS
+
+ push dword ptr bp_lphLineAppTmp
+ call UnMapLS
+
+ pop eax ; Get the retcode
+
+;DoNothing:
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_PHONEINITIALIZE
+;-----------------------------------------------------------------------;
+body_PHONEINITIALIZE16 macro
+
+;LONG phoneInitialize (LPHPHONEAPP lphPhoneApp,
+; HINSTANCE hInstance,
+; PHONECALLBACK lpfnCallback,
+; LPCSTR lpszAppName,
+; LPDWORD lpdwNumDevs)
+;
+bp_lphPhoneApp equ <bp_top>
+bp_hInstance equ <bp_top+4>
+bp_lpfnCallback equ <bp_top+8>
+bp_lpszAppName equ <bp_top+12>
+bp_lpdwNumDevs equ <bp_top+16>
+;
+
+bp_lpszAppNameTmp equ <dword ptr [bp-4]>
+bp_lpdwNumDevsTmp equ <dword ptr [bp-8]>
+bp_lphPhoneAppTmp equ <dword ptr [bp-12]>
+
+ sub eax, eax
+ push eax ;bp_lpszAppNameTmp
+ push eax ;bp_lpdwNumDevsTmp
+ push eax ;bp_lphPhoneAppTmp
+
+ push dword ptr bp_lphPhoneApp
+ call MapLS
+ mov bp_lphPhoneAppTmp, eax
+ push eax
+
+ mov eax, dword ptr bp_hInstance ; Get the hInst
+ or eax, eax ; Is it NULL?
+ jz @f ; Yup, and that's ok.
+ MAP_NULL_HINST eax ; Needs to be mapped.
+ push ax
+
+; mov ax, seg addrCBPhoneInit
+; mov ds, ax
+; mov eax, dword ptr bp_lpfnCallback
+; mov addrCBPhoneInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_PHONEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+ push dword ptr bp_lpfnCallback
+
+ push dword ptr bp_lpszAppName
+ call MapLS
+ mov bp_lpszAppNameTmp, eax
+ push eax
+
+ push dword ptr bp_lpdwNumDevs
+ call MapLS
+ mov bp_lpdwNumDevsTmp, eax
+ push eax
+
+
+ call phoneInitialize
+
+
+ shl eax,16 ; Convert the 16bit retcode...
+ shrd eax,edx,16 ; to a 32bit retcode.
+
+ push eax ; Save the retcode for later.
+
+ push dword ptr bp_lpdwNumDevsTmp
+ call UnMapLS
+
+ push dword ptr bp_lpszAppNameTmp
+ call UnMapLS
+
+ push dword ptr bp_lphPhoneAppTmp
+ call UnMapLS
+
+ pop eax ; Get the retcode
+
+endm
+
+
+;-----------------------------------------------------------------------;
+;-----------------------------------------------------------------------;
+;PUSH__LINEINITIALIZE_hInstance macro iOffset, iJunk
+; local Null_OK
+;
+; mov eax, [bp+iOffset] ;;Allow NULL to be passed here (for now)
+; or eax, eax
+; jz Null_OK
+; MAP_NULL_HINST eax
+;Null_OK:
+; push ax
+;
+;endm ;PUSH__LINEINITIALIZE_hInstance
+;
+;
+;-----------------------------------------------------------------------;
+;-----------------------------------------------------------------------;
+;PUSH__PHONEINITIALIZE_hInstance macro iOffset, iJunk
+; local Null_OK
+;
+; mov eax, [bp+iOffset] ;;Allow NULL to be passed here (for now)
+; or eax, eax
+; jz Null_OK
+; MAP_NULL_HINST eax
+;Null_OK:
+; push ax
+;
+;endm ;PUSH__PHONEINITIALIZE_hInstance
+;
+;
+;;-----------------------------------------------------------------------;
+;; PUSH__LINEINITIALIZE_lpfnCallback (similar to PUSH_SetAbortProc_pfnAbort)
+;;-----------------------------------------------------------------------;
+;PUSH__LINEINITIALIZE_lpfnCallback macro iOffset, iTempOffset
+;; assume ds:DATA16
+;
+; mov ax, seg addrCBLineInit
+; mov ds, ax
+;
+; mov eax, dword ptr [bp+iOffset]
+; mov addrCBLineInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_LINEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+;endm
+;
+;
+;-----------------------------------------------------------------------;
+; PUSH__PHONEINITIALIZE_lpfnCallback
+;-----------------------------------------------------------------------;
+;PUSH__PHONEINITIALIZE_lpfnCallback macro iOffset, iTempOffset
+; assume ds:DATA16
+; mov ax, seg addrCBPhoneInit
+; mov ds, ax
+;
+; mov eax, dword ptr [bp+iOffset]
+; mov addrCBPhoneInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_PHONEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+;endm
+
+
+;==============================================================================
+; local macro, free resources allocated for a call-back function
+; check if it is a NULL pointer before calling FreeCallBack.
+; eax contains the 32-bit address of the mapped call-back function
+; ecx contains the callback ID ((cbcidTapi << 16) + ID[PHONE/LINE]INITIALIZE)
+;==============================================================================
+;FREE_CALLBACK_TAPI macro
+; local done
+;
+; or eax,eax
+; jz done ;don't process NULL pointers
+;
+; push bx ;save BX
+; push es ;save ES
+;
+; push eax ;32-bit callback address
+; push ecx
+; call FreeCallback
+;
+; pop es ;restore ES
+; pop bx ;restore BX
+;done:
+;endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINESHUTDOWN
+; Use FREE_CALLBACK instead of directly calling FreeCallback so that we
+; check for NULL pointers.
+;-----------------------------------------------------------------------;
+body_LINESHUTDOWN16 macro
+bp_hLineApp equ <bp_top>
+; assume ds:DATA16
+ mov ax, seg addrCBLineInit
+ mov ds, ax
+
+ mov eax, dword ptr bp_hLineApp
+ push eax
+ifdef DEBUG
+ int 3
+endif
+ call lineShutdown
+
+; return code long --> long
+ rol eax,16
+ xchg ax,dx
+ rol eax,16
+
+; push eax ;; Save
+; push ecx ;; Save
+;
+; mov eax, addrCBLineInit
+;
+; mov ecx, cbcidTapi
+; shl ecx, 16
+; add ecx, ID_LINEINITIALIZE
+;
+; FREE_CALLBACK_TAPI
+;
+; pop ecx
+; pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_PHONESHUTDOWN
+;-----------------------------------------------------------------------;
+body_PHONESHUTDOWN16 macro
+bp_hLineApp equ <bp_top>
+; assume ds:DATA16
+ mov ax, seg addrCBPhoneInit
+ mov ds, ax
+
+ mov eax, dword ptr bp_hLineApp
+ push eax
+ call phoneShutdown
+
+; return code long --> long
+ rol eax,16
+ xchg ax,dx
+ rol eax,16
+
+; push eax ;; Save it
+; push ecx ;; Save it
+;
+; mov eax, addrCBPhoneInit
+;
+; mov ecx, cbcidTapi
+; shl ecx, 16
+; add ecx, ID_PHONEINITIALIZE
+;
+; FREE_CALLBACK_TAPI
+;
+; pop ecx
+; pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEFORWARD
+;-----------------------------------------------------------------------;
+body_LINEFORWARD macro
+
+bp_hLine equ <bp_top>
+bp_bAllAddresses equ <bp_top+4>
+bp_dwAddressID equ <bp_top+8>
+bp_lpForwardList equ <bp_top+12>
+bp_dwNumRingsNoAnswer equ <bp_top+16>
+bp_lphConsultCall equ <bp_top+20>
+bp_lpCallParams equ <bp_top+24>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: bAllAddresses
+; dword ptr [ebp+16]: dwAddressID
+; dword ptr [ebp+20]: lpForwardList
+; dword ptr [ebp+24]: dwNumRingsNoAnswer
+; dword ptr [ebp+28]: lphConsultCall
+; dword ptr [ebp+32]: lpCallParams
+;
+
+bp_lpForwardListTmp equ <dword ptr [bp-4]>
+bp_lphConsultCallTmp equ <dword ptr [bp-8]>
+bp_lpCallParamsTmp equ <dword ptr [bp-12]>
+
+
+ sub eax, eax
+ push eax ;bp_lpForwardListTmp
+ push eax ;bp_lphConsultCallTmp
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_bAllAddresses ;bAllAddresses: dword->dword
+ push dword ptr bp_dwAddressID ;dwAddressID: dword->dword
+ push dword ptr bp_lpForwardList
+ call MapLS
+ mov bp_lpForwardListTmp, eax
+ push eax
+ push dword ptr bp_dwNumRingsNoAnswer ;dwNumRingsNoAnswer: dword->dword
+ push dword ptr bp_lphConsultCall
+ call MapLS
+ mov bp_lphConsultCallTmp, eax
+ push eax
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineForward
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+ push dword ptr bp_lpForwardListTmp
+ call UnMapLS
+;
+; Don't UnMap lphConsultCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphConsultCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEMAKECALL
+;-----------------------------------------------------------------------;
+body_LINEMAKECALL macro
+
+bp_hLine equ <bp_top>
+bp_lphCall equ <bp_top+4>
+bp_lpszDestAddress equ <bp_top+8>
+bp_dwCountryCode equ <bp_top+12>
+bp_lpCallParams equ <bp_top+16>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: lphCall
+; dword ptr [ebp+16]: lpszDestAddress
+; dword ptr [ebp+20]: dwCountryCode
+; dword ptr [ebp+24]: lpCallParams
+;
+
+bp_lphCallTmp equ <dword ptr [bp-4]>
+bp_lpszDestAddressTmp equ <dword ptr [bp-8]>
+bp_lpCallParamsTmp equ <dword ptr [bp-12]>
+
+
+ sub eax, eax
+ push eax ;bp_lphCallTmp
+ push eax ;bp_lpszDestAddress
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_lphCall
+ call MapLS
+ mov bp_lphCallTmp, eax
+ push eax
+ push dword ptr bp_lpszDestAddress
+ call MapLS
+ mov bp_lpszDestAddressTmp, eax
+ push eax
+ push dword ptr bp_dwCountryCode ;dwCountryCode: dword->dword
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineMakeCall
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphCallTmp
+; call UnMapLS
+ push dword ptr bp_lpszDestAddressTmp
+ call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEUNPARK
+;-----------------------------------------------------------------------;
+body_LINEUNPARK macro
+
+bp_hLine equ <bp_top>
+bp_dwAddressID equ <bp_top+4>
+bp_lphCall equ <bp_top+8>
+bp_lpszDestAddress equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwAddressID
+; dword ptr [ebp+16]: lphCall
+; dword ptr [ebp+20]: lpszDestAddress
+;
+
+bp_lphCallTmp equ <dword ptr [bp-4]>
+bp_lpszDestAddressTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lphCallTmp
+ push eax ;bp_lpszDestAddress
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwCountryCode ;dwCountryCode: dword->dword
+ push dword ptr bp_lphCall
+ call MapLS
+ mov bp_lphCallTmp, eax
+ push eax
+ push dword ptr bp_lpszDestAddress
+ call MapLS
+ mov bp_lpszDestAddressTmp, eax
+ push eax
+
+ call lineUnpark
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphCallTmp
+; call UnMapLS
+ push dword ptr bp_lpszDestAddressTmp
+ call UnMapLS
+ pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEPICKUP
+;-----------------------------------------------------------------------;
+body_LINEPICKUP macro
+
+bp_hLine equ <bp_top>
+bp_dwAddressID equ <bp_top+4>
+bp_lphCall equ <bp_top+8>
+bp_lpszDestAddress equ <bp_top+12>
+bp_lpszGroupID equ <bp_top+16>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwAddressID
+; dword ptr [ebp+16]: lphCall
+; dword ptr [ebp+20]: lpszDestAddress
+; dword ptr [ebp+24]: lpszGroupID
+;
+
+bp_lphCallTmp equ <dword ptr [bp-4]>
+bp_lpszDestAddressTmp equ <dword ptr [bp-8]>
+bp_lpszGroupIDTmp equ <dword ptr [bp-12]>
+
+ sub eax, eax
+ push eax ;bp_lphCallTmp
+ push eax ;bp_lpszDestAddressTmp
+ push eax ;bp_lpszGroupIDTmp
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwAddressID ;dwAddressID: dword->dword
+ push dword ptr bp_lphCall
+ call MapLS
+ mov bp_lphCallTmp, eax
+ push eax
+ push dword ptr bp_lpszDestAddress
+ call MapLS
+ mov bp_lpszDestAddressTmp, eax
+ push eax
+ push dword ptr bp_lpszGroupID
+ call MapLS
+ mov bp_lpszGroupIDTmp, eax
+ push eax
+
+ call linePickup
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphCallTmp
+; call UnMapLS
+ push dword ptr bp_lpszDestAddressTmp
+ call UnMapLS
+ push dword ptr bp_lpszGroupIDTmp
+ call UnMapLS
+ pop eax
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINESETUPCONFERENCE
+;-----------------------------------------------------------------------;
+body_LINESETUPCONFERENCE macro
+
+bp_hCall equ <bp_top>
+bp_hLine equ <bp_top+4>
+bp_lphConfCall equ <bp_top+8>
+bp_lphConsultCall equ <bp_top+12>
+bp_dwNumParties equ <bp_top+16>
+bp_lpCallParams equ <bp_top+20>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: hLine
+; dword ptr [ebp+16]: lphConfCall
+; dword ptr [ebp+20]: lphConsultCall
+; dword ptr [ebp+24]: dwNumParties
+; dword ptr [ebp+28]: lpCallParams
+;
+
+bp_lphConfCallTmp equ <dword ptr [bp-4]>
+bp_lphConsultCallTmp equ <dword ptr [bp-8]>
+bp_lpCallParamsTmp equ <dword ptr [bp-12]>
+
+ sub eax, eax
+ push eax ;bp_lphConfCallTmp
+ push eax ;bp_lphConsultCallTmp
+ push eax ;bp_lpCallParamsTmp
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_lphConfCall
+ call MapLS
+ mov bp_lphConfCallTmp, eax
+ push eax
+ push dword ptr bp_lphConsultCall
+ call MapLS
+ mov bp_lphConsultCallTmp, eax
+ push eax
+ push dword ptr bp_dwNumParties ;dwNumParties: dword->dword
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineSetupConference
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphConfCallTmp and lphConsultCallTmp: Done in tapi.dll
+; due to async read/write.
+;
+; push dword ptr bp_lphConfCallTmp
+; call UnMapLS
+; push dword ptr bp_lphConsultCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINECOMPLETETRANSFER
+;-----------------------------------------------------------------------;
+body_LINECOMPLETETRANSFER macro
+
+bp_hCall equ <bp_top>
+bp_hConsultCall equ <bp_top+4>
+bp_lphConfCall equ <bp_top+8>
+bp_dwTransferMode equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: hConsultCall
+; dword ptr [ebp+16]: lphConfCall
+; dword ptr [ebp+20]: dwTransferMode
+;
+
+bp_lphConfCallTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lphConfCallTmp
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_hConsultCall ;hConsultCall: dword->dword
+ push dword ptr bp_lphConfCall
+ call MapLS
+ mov bp_lphConfCallTmp, eax
+ push eax
+ push dword ptr bp_dwTransferMode ;dwTransferMode: dword->dword
+
+ call lineCompleteTransfer
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lphConfCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphConfCallTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEPREPAREADDTOCONFERENCE
+;-----------------------------------------------------------------------;
+body_LINEPREPAREADDTOCONFERENCE macro
+
+bp_hConfCall equ <bp_top>
+bp_lphAddCall equ <bp_top+4>
+bp_lpCallParams equ <bp_top+8>
+;
+; dword ptr [ebp+8]: hConfCall
+; dword ptr [ebp+12]: lphAddCall
+; dword ptr [ebp+16]: lpCallParams
+;
+
+bp_lphAddCallTmp equ <dword ptr [bp-4]>
+bp_lpCallParamsTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lphAddCallTmp
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hConfCall ;hConfCall: dword->dword
+ push dword ptr bp_lphAddCall
+ call MapLS
+ mov bp_lphAddCallTmp, eax
+ push eax
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call linePrepareAddToConference
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+;
+; Don't UnMap lphAddCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphAddCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINESETUPTRANSFER
+;-----------------------------------------------------------------------;
+body_LINESETUPTRANSFER macro
+
+bp_hCall equ <bp_top>
+bp_lphConsultCall equ <bp_top+4>
+bp_lpCallParams equ <bp_top+8>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: lphConsultCall
+; dword ptr [ebp+16]: lpCallParams
+;
+
+bp_lphConsultCallTmp equ <dword ptr [bp-4]>
+bp_lpCallParamsTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lphConsultCallTmp
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_lphConsultCall
+ call MapLS
+ mov bp_lphConsultCallTmp, eax
+ push eax
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineSetupTransfer
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+;
+; Don't UnMap lphConsultCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphConsultCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+
+
+;-----------------------------------------------------------------------;
+; body_LINECOMPLETECALL
+;-----------------------------------------------------------------------;
+body_LINECOMPLETECALL macro
+
+bp_hCall equ <bp_top>
+bp_lpdwCompletionID equ <bp_top+4>
+bp_dwCompletionMode equ <bp_top+8>
+bp_dwMessageID equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: lpdwCompletionID
+; dword ptr [ebp+16]: dwCompletionMode
+; dword ptr [ebp+20]: dwMessageID
+;
+
+bp_lpdwCompletionIDTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lpdwCompletionID
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_lpdwCompletionID
+ call MapLS
+ mov bp_lpdwCompletionIDTmp, eax
+ push eax
+ push dword ptr bp_dwCompletionMode
+ push dword ptr bp_dwMessageID
+
+ call lineCompleteCall
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpdwCompletionIDTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpdwCompletionIDTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEDEVSPECIFIC
+;-----------------------------------------------------------------------;
+body_LINEDEVSPECIFIC macro
+
+bp_hLine equ <bp_top>
+bp_dwAddressID equ <bp_top+4>
+bp_hCall equ <bp_top+8>
+bp_lpParams equ <bp_top+12>
+bp_dwSize equ <bp_top+16>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwAddressID
+; dword ptr [ebp+16]: hCall
+; dword ptr [ebp+20]: lpParams
+; dword ptr [ebp+24]: dwSize
+;
+
+bp_lpParamsTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lpParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwAddressID ;dwAddressID: dword->dword
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_lpParams
+ call MapLS
+ mov bp_lpParamsTmp, eax
+ push eax
+ push dword ptr bp_dwSize ;dwSize: dword->dword
+
+ call lineDevSpecific
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpParams: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpParamsTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+;-----------------------------------------------------------------------;
+; body_PHONEDEVSPECIFIC
+;-----------------------------------------------------------------------;
+body_PHONEDEVSPECIFIC macro
+
+bp_hPhone equ <bp_top>
+bp_lpParams equ <bp_top+4>
+bp_dwSize equ <bp_top+8>
+;
+; dword ptr [ebp+8]: hPhone
+; dword ptr [ebp+12]: lpParams
+; dword ptr [ebp+16]: dwSize
+;
+
+;bp_lpParamsTmp equ <dword ptr [bp-4]>
+;
+ sub eax, eax
+ push eax ;bp_lpParams
+
+ push dword ptr bp_hPhone ;hPhone: dword->dword
+ push dword ptr bp_lpParams
+ call MapLS
+ mov bp_lpParamsTmp, eax
+ push eax
+ push dword ptr bp_dwSize ;dwSize: dword->dword
+
+ call phoneDevSpecific
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpParams: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpParamsTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINEDEVSPECIFICFEATURE
+;-----------------------------------------------------------------------;
+body_LINEDEVSPECIFICFEATURE macro
+
+bp_hLine equ <bp_top>
+bp_dwFeature equ <bp_top+4>
+bp_lpParams equ <bp_top+8>
+bp_dwSize equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwFeature
+; dword ptr [ebp+16]: lpParams
+; dword ptr [ebp+20]: dwSize
+;
+
+bp_lpParamsTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lpParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwFeature ;dwFeature: dword->dword
+ push dword ptr bp_lpParams
+ call MapLS
+ mov bp_lpParamsTmp, eax
+ push eax
+ push dword ptr bp_dwSize ;dwSize: dword->dword
+
+ call lineDevSpecificFeature
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpParams: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpParamsTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEGATHERDIGITS
+;-----------------------------------------------------------------------;
+body_LINEGATHERDIGITS macro
+
+bp_hCall equ <bp_top>
+bp_dwDigitModes equ <bp_top+4>
+bp_lpsDigits equ <bp_top+8>
+bp_dwNumDigits equ <bp_top+12>
+bp_lpszTermDigits equ <bp_top+16>
+bp_dwFirstDigitTimeout equ <bp_top+20>
+bp_dwInterDigitTimeout equ <bp_top+24>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: dwDigitModes
+; dword ptr [ebp+16]: lpsDigits
+; dword ptr [ebp+20]: dwNumDigits
+; dword ptr [ebp+24]: lpszTerminationDigits
+; dword ptr [ebp+28]: dwFirstDigitTimeout
+; dword ptr [ebp+32]: dwInterDigitTimeout
+;
+
+bp_lpsDigitsTmp equ <dword ptr [bp-4]>
+bp_lpszTermDigitsTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lpsDigitsTmp
+ push eax ;bp_lpszTerminationDigitsTmp
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_dwDigitModes ;dwDigitModes: dword->dword
+ push dword ptr bp_lpsDigits
+ call MapLS
+ mov bp_lpsDigitsTmp, eax
+ push eax
+ push dword ptr bp_dwNumDigits ;dwNumDigits: dword->dword
+ push dword ptr bp_lpszTermDigits
+ call MapLS
+ mov bp_lpszTermDigitsTmp, eax
+ push eax
+ push dword ptr bp_dwFirstDigitTimeout ;dwFirstDigitTimeout: dword->dword
+ push dword ptr bp_dwInterDigitTimeout ;dwInterDigitTimeout: dword->dword
+
+ call lineGatherDigits
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+;
+; Don't UnMap lpsDigits: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpsDigitsTmp
+; call UnMapLS
+ push dword ptr bp_lpszTermDigitsTmp
+ call UnMapLS
+
+ pop eax
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINEPARK
+;-----------------------------------------------------------------------;
+body_LINEPARK macro
+
+bp_hLine equ <bp_top>
+bp_dwParkMode equ <bp_top+4>
+bp_lpszDirAddress equ <bp_top+8>
+bp_lpNonDirAddress equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwParkMode
+; dword ptr [ebp+16]: lpszDirAddress
+; dword ptr [ebp+20]: lpNonDirAddress
+;
+
+bp_lpszDirAddressTmp equ <dword ptr [bp-4]>
+bp_lpNonDirAddressTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lpszDirAddressTmp
+ push eax ;bp_lpNonDirAddressTmp
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwParkMode ;dwParkMode: dworkd->dword
+ push dword ptr bp_lpszDirAddress
+ call MapLS
+ mov bp_lpszDirAddressTmp, eax
+ push eax
+ push dword ptr bp_lpNonDirAddress
+ call MapLS
+ mov bp_lpNonDirAddressTmp, eax
+ push eax
+
+ call linePark
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+ push dword ptr bp_lpszDirAddressTmp
+ call UnMapLS
+;
+; Don't UnMap lpNonDirAddressTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpNonDirAddressTmp
+; call UnMapLS
+
+ pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_TAPIREQUESTMEDIACALL
+;-----------------------------------------------------------------------;
+body_TAPIREQUESTMEDIACALL macro
+ mov eax, -16
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_TAPIREQUESTDROP
+;-----------------------------------------------------------------------;
+body_TAPIREQUESTDROP macro
+ mov eax, -16
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEREGISTERREQUESTRECIPIENT
+;-----------------------------------------------------------------------;
+body_LINEREGISTERREQUESTRECIPIENT macro
+
+bp_hLine equ <bp_top>
+bp_dwRegistrationInstance equ <bp_top+4>
+bp_dwRequestMode equ <bp_top+8>
+bp_dwEnable equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwRegistrationInstance
+; dword ptr [ebp+16]: dwRequestMode
+; dword ptr [ebp+20]: bEnable
+;
+
+;
+; sub eax, eax
+; push eax ;bp_lpszDirAddressTmp
+; push eax ;bp_lpNonDirAddressTmp
+;
+
+;
+; If this is a 32bit app asking to register for media calls, tell 'em
+; 'e's nuts.
+;
+ test dword ptr bp_dwRequestMode, 2 ;*** *** ***Or should this be 6?
+ jz @f
+
+ifdef DEBUG
+ DPRINT "32bit apps aren't allowed to register for Media calls"
+endif
+ mov eax, 80000038h
+ jmp Done_LRRR
+
+@@:
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwRegistrationInstance
+ push dword ptr bp_dwRequestMode
+ push dword ptr bp_dwEnable
+
+ call lineRegisterRequestRecipient
+
+ shl eax,16
+ shrd eax,edx,16
+
+Done_LRRR:
+
+endm
+
diff --git a/private/tapi/dev/sp/tsp1632/script/tapithk.thk b/private/tapi/dev/sp/tsp1632/script/tapithk.thk
new file mode 100644
index 000000000..2f656b5f6
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/tapithk.thk
@@ -0,0 +1,309 @@
+/*
+ * Lzexpand APIs thunks for Win32s
+ */
+//__foldwin32sstuff __foldwin32sstuff;
+//**********************************foldstyleinitialization = true;
+
+
+enablemapdirect1632 = true;
+//preload32=true;
+//flatthunks = false;
+
+#include "..\types.thk"
+
+
+typedef HANDLE HINSTANCE;
+typedef DWORD HTAPI;
+typedef HTAPI *LPHTAPI;
+typedef HTAPI HAPP;
+typedef HAPP HLINEAPP;
+typedef HAPP HPHONEAPP;
+typedef HAPP *LPHAPP;
+typedef HTAPI HCALL;
+typedef HCALL *LPHCALL;
+typedef HTAPI HLINE;
+typedef HLINE *LPHLINE;
+typedef HTAPI HPHONE;
+typedef HPHONE *LPHPHONE;
+typedef HICON *LPHICON;
+typedef void LINECALLBACK;
+typedef void PHONECALLBACK;
+typedef LPSTR LPCSTR;
+
+typedef HLINEAPP *LPHLINEAPP;
+typedef HPHONEAPP *LPHPHONEAPP;
+typedef LPVOID LPLINEEXTENSIONID;
+
+typedef WORD WPARAM;
+
+typedef LPVOID LPLINETRANSLATEOUTPUT; /* LP to data structure */
+typedef LPVOID LPLINETRANSLATECAPS; /* LP to data structure */
+typedef LPVOID LPLINEFORWARDLIST;
+typedef LPVOID LPLINECALLPARAMS;
+typedef LPVOID LPLINEGENERATETONE;
+typedef LPVOID LPLINEADDRESSCAPS;
+typedef LPVOID LPLINEADDRESSSTATUS;
+typedef LPVOID LPLINECALLINFO;
+typedef LPVOID LPLINECALLSTATUS;
+typedef LPVOID LPLINECALLLIST;
+typedef LPVOID LPLINEDEVCAPS;
+typedef LPVOID LPLINEDEVSTATUS;
+typedef LPVOID LPLINEMONITORTONE;
+typedef LPVOID LPVARSTRING;
+typedef LPVOID LPLINEDIALPARAMS;
+typedef LPVOID LPLINEMEDIACONTROLDIGIT;
+typedef LPVOID LPLINEMEDIACONTROLMEDIA;
+typedef LPVOID LPLINEMEDIACONTROLTONE;
+typedef LPVOID LPLINEMEDIACONTROLCALLSTATE;
+typedef LPVOID LPPHONEBUTTONINFO;
+typedef LPVOID LPPHONECAPS;
+typedef LPVOID LPPHONESTATUS;
+typedef LPVOID LPPHONEEXTENSIONID;
+typedef LPVOID LPLINECOUNTRYLIST;
+typedef LPVOID LPLINEPROVIDERLIST;
+
+
+
+
+typedef DWORD DRV_REQUESTID;
+typedef LPHLINE HDRVLINE;
+typedef LPHCALL HTAPICALL;
+typedef LPHCALL HDRVCALL;
+typedef LPHCALL LPHDRVCALL;
+
+typedef DWORD HDRVPHONE;
+
+
+
+
+// // /* Simple Telephony prototypes */
+// //
+// // LONG tapiRequestMakeCall (LPCSTR lpszDestAddress, LPCSTR lpszAppName, LPCSTR lpszCalledParty, LPCSTR lpszComment) =
+// // LONG tapiRequestMakeCall (LPCSTR lpszDestAddress, LPCSTR lpszAppName, LPCSTR lpszCalledParty, LPCSTR lpszComment)
+// // {
+// // }
+// //
+// // /*PROBLEM? WORD as parameter */
+// // LONG tapiRequestMediaCall (HWND hWnd, WORD wRequestID, LPCSTR lpszDeviceClass, LPCSTR lpDeviceID, DWORD dwSize,
+// // DWORD dwSecure, LPCSTR lpszDestAddress, LPCSTR lpszAppName, LPCSTR lpszCalledParty, LPCSTR lpszComment) =
+// // LONG tapiRequestMediaCall (HWND hWnd, WORD wRequestID, LPCSTR lpszDeviceClass, LPCSTR lpDeviceID, DWORD dwSize,
+// // DWORD dwSecure, LPCSTR lpszDestAddress, LPCSTR lpszAppName, LPCSTR lpszCalledParty, LPCSTR lpszComment)
+// // {
+// // // body = special;
+// // }
+// //
+// // /*PROBLEM? WORD as parameter */
+// // LONG tapiRequestDrop (HWND hWnd, WPARAM wRequestID) =
+// // LONG tapiRequestDrop (HWND hWnd, WPARAM wRequestID)
+// // {
+// // // body = special;
+// // }
+// //
+// // LONG tapiGetLocationInfo(LPSTR lpszCountryCode, LPSTR lpszCityCode) =
+// // LONG tapiGetLocationInfo(LPSTR lpszCountryCode, LPSTR lpszCityCode)
+// // {}
+
+//LONG lineRegisterRequestRecipient (HDRVLINEAPP hdLineApp, DWORD dwRegistrationInstance, DWORD dwRequestMode, DWORD bEnable) =
+//LONG lineRegisterRequestRecipient (HDRVLINEAPP hdLineApp, DWORD dwRegistrationInstance, DWORD dwRequestMode, DWORD bEnable)
+//{
+// body = special;
+//}
+
+
+/* Other TAPI functions */
+/*
+// hInstance = push;
+// lpfnCallback = push;
+LONG lineInitialize16 (LPHDRVLINEAPP lphdLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback,
+ LPCSTR lpszAppName, LPDWORD lpdwNumDevs) =
+LONG lineInitialize16 (LPHDRVLINEAPP lphdLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback,
+ LPCSTR lpszAppName, LPDWORD lpdwNumDevs)
+{
+// body = special;
+}
+
+
+LONG lineShutdown16 (HDRVLINEAPP hdLineApp) =
+LONG lineShutdown16 (HDRVLINEAPP hdLineApp)
+{
+// body = special;
+}
+
+
+// hInstance = push;
+// lpfnCallback = push;
+LONG phoneInitialize16 (LPHDRVPHONEAPP lphdPhoneApp, HINSTANCE hInstance, PHONECALLBACK lpfnCallback,
+ LPCSTR lpszAppName, LPDWORD lpdwNumDevs) =
+LONG phoneInitialize16 (LPHDRVPHONEAPP lphdPhoneApp, HINSTANCE hInstance, PHONECALLBACK lpfnCallback,
+ LPCSTR lpszAppName, LPDWORD lpdwNumDevs)
+{
+// body = special;
+}
+
+LONG phoneShutdown16 (HDRVPHONEAPP hdPhoneApp) =
+LONG phoneShutdown16 (HDRVPHONEAPP hdPhoneApp)
+{
+// body = special;
+}
+*/
+
+
+
+
+
+
+LONG TSPI_lineMakeCall (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineMakeCall (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode, LPLINECALLPARAMS lpCallParams)
+{
+// body = special;
+}
+
+LONG TSPI_lineSetupConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVLINE hdLine, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineSetupConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVLINE hdLine, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties, LPLINECALLPARAMS lpCallParams)
+{
+// body = special;
+}
+
+LONG TSPI_lineForward (DRV_REQUESTID dwRequestID, HDRVLINE hdLine,
+ DWORD bAllAddresses, DWORD dwAddressID,
+ LPLINEFORWARDLIST lpForwardList,
+ DWORD dwNumRingsNoAnswer, HTAPICALL htConsoleCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineForward (DRV_REQUESTID dwRequestID, HDRVLINE hdLine,
+ DWORD bAllAddresses, DWORD dwAddressID,
+ LPLINEFORWARDLIST lpForwardList,
+ DWORD dwNumRingsNoAnswer, HTAPICALL htConsoleCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS lpCallParams)
+{
+// body = special;
+}
+
+LONG TSPI_lineUnpark (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress) =
+LONG TSPI_lineUnpark (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress)
+{
+// body = special;
+}
+
+LONG TSPI_linePickup (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, LPCSTR lpszGroupID) =
+LONG TSPI_linePickup (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, LPCSTR lpszGroupID)
+{
+// body = special;
+}
+
+LONG TSPI_lineCompleteTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVCALL hdConsultCall, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, DWORD dwTransferMode) =
+LONG TSPI_lineCompleteTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVCALL hdConsultCall, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, DWORD dwTransferMode)
+{
+// body = special;
+}
+
+LONG TSPI_linePrepareAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_linePrepareAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams)
+{
+// body = special;
+}
+
+LONG TSPI_lineSetupTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineSetupTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams)
+{
+// body = special;
+}
+
+LONG TSPI_lineCompleteCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPDWORD lpdwCompletionID, DWORD dwCompletionMode, DWORD dwMessageID) =
+LONG TSPI_lineCompleteCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPDWORD lpdwCompletionID, DWORD dwCompletionMode, DWORD dwMessageID)
+{
+// body = special;
+}
+
+LONG TSPI_lineDevSpecific (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, LPVOID lpParams, DWORD dwSize) =
+LONG TSPI_lineDevSpecific (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, LPVOID lpParams, DWORD dwSize)
+{
+// body = special;
+}
+
+LONG TSPI_lineDevSpecificFeature (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwFeature, LPVOID lpParams, DWORD dwSize) =
+LONG TSPI_lineDevSpecificFeature (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwFeature, LPVOID lpParams, DWORD dwSize)
+{
+// body = special;
+}
+
+LONG TSPI_lineGatherDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitModes, LPSTR lpsDigits, DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits, DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout) =
+LONG TSPI_lineGatherDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitModes, LPSTR lpsDigits, DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits, DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout)
+{
+// body = special;
+}
+
+LONG TSPI_linePark (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwParkMode, LPCSTR lpszDirAddress, LPVARSTRING lpNonDirAddress) =
+LONG TSPI_linePark (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwParkMode, LPCSTR lpszDirAddress, LPVARSTRING lpNonDirAddress)
+{
+// body = special;
+}
+
+
+
+
+LONG TSPI_phoneDevSpecific (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, LPVOID lpParams, DWORD dwSize) =
+LONG TSPI_phoneDevSpecific (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, LPVOID lpParams, DWORD dwSize)
+{
+// body = special;
+}
+
+
+
+
+
+
+
+
+
+
+
+//*
+//*
+//* /* Private API: TAPI32 must run this thunk to clean up our act.
+//* *
+//* * We declare pCB32Tab as DWORD, not POINTER. We want the linear
+//* * address passed thru untouched.
+//* */
+//* VOID TapiThunkInit(DWORD pCB32Tab) =
+//* VOID TapiThunkInit(DWORD pCB32Tab)
+//* {
+//* }
+//* /* Private API: TAPI32 must run this thunk before any other.
+//* *
+//* * We declare pCB32Tab as DWORD, not POINTER. We want the linear
+//* * address passed thru untouched.
+//* */
+//* VOID TapiThunkTerminate(DWORD pCB32Tab) =
+//* VOID TapiThunkTerminate(DWORD pCB32Tab)
+//* {
+//* }
+//*
+//*
+
+
+
+
+
+
+/*
+typedef void (CALLBACK * LINECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) =
+typedef void (CALLBACK * LINECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{}
+*/
+
+
+/*
+typedef void (CALLBACK * PHONECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) =
+typedef void (CALLBACK * PHONECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{}
+*/
diff --git a/private/tapi/dev/sp/tsp1632/script/types.thk b/private/tapi/dev/sp/tsp1632/script/types.thk
new file mode 100644
index 000000000..ed9c77e85
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/script/types.thk
@@ -0,0 +1,102 @@
+typedef unsigned short USHORT;
+typedef short SHORT;
+typedef unsigned long ULONG;
+typedef long LONG;
+typedef unsigned int UINT;
+typedef int INT;
+typedef unsigned char UCHAR;
+
+typedef void VOID;
+typedef void *PVOID;
+typedef void *LPVOID;
+typedef UCHAR BYTE;
+typedef USHORT WORD;
+typedef ULONG DWORD;
+typedef UINT HANDLE;
+typedef WORD HANDLE16;
+typedef DWORD HANDLE32;
+typedef int BOOL;
+typedef char *LPSTR;
+typedef BYTE *PBYTE;
+typedef BYTE *LPBYTE;
+typedef USHORT SEL;
+typedef INT *LPINT;
+typedef UINT *LPUINT;
+typedef DWORD *LPDWORD;
+typedef LONG *LPLONG;
+typedef WORD *LPWORD;
+
+typedef HANDLE HWND;
+typedef HANDLE HDC;
+typedef HANDLE HBRUSH;
+typedef HANDLE HBITMAP;
+typedef HANDLE HRGN;
+typedef HANDLE HFONT;
+typedef HANDLE HCURSOR;
+typedef HANDLE HMENU;
+typedef HANDLE HPEN;
+typedef HANDLE HICON;
+typedef HANDLE HUSER; /* vanilla user handle */
+typedef HANDLE HPALETTE;
+typedef HANDLE HMF;
+typedef HANDLE HEMF;
+typedef HANDLE HCOLORSPACE;
+typedef HANDLE HMEM;
+typedef HANDLE HGDI; /* vanilla gdi handle */
+typedef HANDLE HGLOBAL;
+typedef HANDLE HRSRC;
+typedef HANDLE HACCEL;
+
+
+typedef WORD ATOM;
+
+typedef DWORD WNDPROC; /* handled inside USER */
+
+/* HACK! have it as a pointer to type which differes between 16 and 32
+ * so InLine translation of pointers handle it correctly
+ */
+typedef int * FARPROC; /* thunk layer handles this one */
+
+
+/**********************************************/
+typedef struct tagRECT {
+ INT left;
+ INT top;
+ INT right;
+ INT bottom;
+} RECT;
+typedef RECT *LPRECT;
+
+
+typedef struct tagPOINT {
+ INT x;
+ INT y;
+} POINT;
+typedef POINT *LPPOINT;
+
+
+typedef struct tagPOINTL {
+ LONG x;
+ LONG y;
+} POINTL;
+typedef POINTL *LPPOINTL;
+
+
+typedef struct tagOFSTRUCT {
+ BYTE cBytes;
+ BYTE fFixedDisk;
+ WORD nErrorCode;
+ WORD reserved1;
+ WORD reserved2;
+ BYTE szPathName[128];
+} OFSTRUCT;
+typedef OFSTRUCT *LPOFSTRUCT;
+
+
+typedef struct tagCHARSETINFO {
+ UINT ciCharset;
+ UINT ciACP;
+ DWORD ciSigCP[2];
+ DWORD ciSigU[4];
+} CHARSETINFO;
+typedef CHARSETINFO *LPCHARSETINFO;
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/debug.c b/private/tapi/dev/sp/tsp1632/tsp1632l/debug.c
new file mode 100644
index 000000000..ecaed6d5c
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/debug.c
@@ -0,0 +1,174 @@
+//
+//
+
+#if DBG
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <tapi.h>
+#include "debug.h"
+
+
+extern const char szINIfilename[];
+
+
+DWORD gdwDebugLevel;
+
+
+static char szNewBuff[256];
+
+
+DWORD TSP1632lDebugLevel = 0;
+static fTSP1632lDebugLevelValid = FALSE;
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+
+{
+ char buf[128] = "TSP1632l: ";
+// *** *** *** static char szFilename[] = filename;
+ if (!fTSP1632lDebugLevelValid)
+ {
+ TSP1632lDebugLevel = GetPrivateProfileInt( "Debug",
+ "TSP1632lDebugLevel",
+ 0,
+ szINIfilename );
+
+ if ( TSP1632lDebugLevel > 0 )
+ {
+ wsprintf(
+ &buf[10],
+ "TSP1632lDebugLevel= %d\n\r",
+ TSP1632lDebugLevel);
+
+ OutputDebugString((LPSTR)buf);
+
+
+ }
+
+ fTSP1632lDebugLevelValid = TRUE;
+ }
+
+
+ //
+ // Is the message otherwise "low" enough to display?
+ //
+ if (dwDbgLevel <= TSP1632lDebugLevel)
+ {
+ char buf[128] = "TSP1632l: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ vsprintf (&buf[10],
+ lpszFormat,
+ ap
+ );
+
+ lstrcat (buf, "\n");
+
+ OutputDebugString(buf);
+
+ va_end(ap);
+ }
+
+ return;
+}
+
+
+
+
+
+
+//VOID
+//DbgPrt(
+// IN DWORD dwDbgLevel,
+// IN PUCHAR lpszFormat,
+// IN ...
+// )
+///*++
+//
+//Routine Description:
+//
+// Formats the incoming debug message & calls DbgPrint
+//
+//Arguments:
+//
+// DbgLevel - level of message verboseness
+//
+// DbgMessage - printf-style format string, followed by appropriate
+// list of arguments
+//
+//Return Value:
+//
+//
+//--*/
+//{
+//
+// static BOOL fAlreadyGotIt = FALSE;
+// static char buf[128] = "TAPI CPL: ";
+//#define TEXT_START 10
+//
+// if (!fAlreadyGotIt)
+// {
+//
+// gdwDebugLevel = (DWORD) GetPrivateProfileInt(
+// "Debug",
+// "TSP1632l32DebugLevel",
+// 0x0,
+// "Telephon.ini"
+// );
+//
+// fAlreadyGotIt = TRUE;
+//
+// wsprintf(&buf[TEXT_START], "TSP1632l32DebugLevel=%d \r\n", gdwDebugLevel);
+// OutputDebugStringA(buf);
+// }
+//
+//
+// if (dwDbgLevel <= gdwDebugLevel)
+// {
+// va_list ap;
+//
+//
+// va_start(ap, lpszFormat);
+//
+// vsprintf (&buf[TEXT_START],
+// lpszFormat,
+// ap
+// );
+//
+// lstrcat (buf, "\n");
+//
+// OutputDebugStringA (buf);
+//
+// va_end(ap);
+// }
+//}
+//
+
+#endif
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/debug.h b/private/tapi/dev/sp/tsp1632/tsp1632l/debug.h
new file mode 100644
index 000000000..cd9ea2591
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/debug.h
@@ -0,0 +1,25 @@
+#if DBG
+
+
+#if !WIN32
+#define IN
+#define PUCHAR char *
+#endif
+
+
+
+#define DBGOUT(arg) DbgPrt arg
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/depend.mk b/private/tapi/dev/sp/tsp1632/tsp1632l/depend.mk
new file mode 100644
index 000000000..e69626f90
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/depend.mk
@@ -0,0 +1,9 @@
+.\tapi32.obj: ..\..\script\$(VERDIR)\tapi32.asm
+
+.\tapithk.obj: ..\..\script\$(VERDIR)\tapithk.asm
+
+.\tapifthk.obj: ..\..\script\$(VERDIR)\tapifthk.asm
+
+.\tsp1632l.obj: ..\tsp1632l.c ..\tsp1632l.h ..\debug.h
+
+.\debug.obj: ..\debug.c ..\debug.h
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/makefile b/private/tapi/dev/sp/tsp1632/tsp1632l/makefile
new file mode 100644
index 000000000..43dc5a869
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# tsp3216s.dll Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/makefile.def b/private/tapi/dev/sp/tsp1632/tsp1632l/makefile.def
new file mode 100644
index 000000000..fad78023b
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/makefile.def
@@ -0,0 +1,50 @@
+ROOT=..\..\..\..\..\..\..
+
+IS_OEM=1
+MASM6=1
+IS_32 = TRUE
+WIN32=1
+
+#DEFENTRY=DllEntryPoint
+#DLLENTRY=DllEntryPoint
+DEFENTRY=DllMain
+DLLENTRY=DllMain
+BUILDDLL=1
+
+
+DEPENDNAME=..\depend.mk
+
+DRVNAME=tsp1632l
+TARGETS=tsp1632l.dll
+
+SRCDIR=..
+ALTSRCDIR=..\..\script\$(VERDIR)
+
+
+L32EXE=tsp1632l.dll # Name of exe.
+L32DEF=..\tsp1632l.def # Our def file.
+L32MAP=tsp1632l.map # Our map file.
+L32SYM=tsp1632l.sym # Our sym file.
+#L32RES=server.res # Resource file.
+L32OBJS = tsp1632l.obj tapi32.obj tapithk.obj tapifthk.obj debug.obj
+L32LIBS= \
+ $(DEVROOT)\tools\c932\lib\crtdll.lib \
+ $(DEVROOT)\lib\user32.lib \
+ $(DEVROOT)\lib\kernel32.lib
+
+
+!include $(ROOT)\dev\master.mk
+
+
+INCLUDE=$(ROOT)\win\thunk;$(ROOT)\win\core\inc;$(INCLUDE)
+
+
+AFLAGS=$(AFLAGS) /Fl
+
+
+CFLAGS=$(CFLAGS) /Fc
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
+
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.c b/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.c
new file mode 100644
index 000000000..74419b9e1
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.c
@@ -0,0 +1,2369 @@
+/* TSP1632l.C
+ Copyright 1995 (C) Microsoft Corporation
+
+ 32-bit TAPI service provider to act as a cover for a system's 16-bit SPs
+
+ 16-bit part: TSP1632S.TSP
+ 32-bit part: TSP1632L.DLL
+
+
+ TODO:
+ 1) allow debug levels
+ 2) if OOM in InitializeSPs(), fail
+ 3) other OOM errors
+
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+#include <tapi.h>
+
+#define DONT_DECLARE_TSPI_FUNCTIONS 1
+#include <tspi.h>
+
+#include "tsp1632l.h"
+#include "debug.h"
+//#include <wownt16.h>
+
+
+
+BOOL WINAPI TapiThk_ThunkConnect32(LPSTR, LPSTR, DWORD, DWORD);
+BOOL WINAPI TapiFThk_ThunkConnect32(LPSTR, LPSTR, DWORD, DWORD);
+
+
+
+
+#define THUNK_TSPIAPI TSPIAPI __stdcall
+
+
+#if WIN32
+
+#define TSPIAPI
+
+#else
+
+#define TSPIAPI __export __far __pascal
+
+#endif
+
+typedef LONG (TSPIAPI* TSPAPIPROC)(void);
+
+
+#ifdef DEBUG
+#define TSP1632lDebugString(_x_) TSP1632lOutputDebug _x_
+#else
+#define TSP1632lDebugString(_x_)
+#endif
+
+
+#define THIS_FUNCTION_UNDER_CONSTRUCTION (LONG)TRUE
+// a default return value so that the compiler doesn't
+// whine about missing return values in incomplete functions
+
+
+// globals
+
+DWORD FAR PASCAL ghInst32; // handle into TSP1632L.DLL
+HINSTANCE ghThisInst; //This hinst
+
+int NumProviders = 0;
+DWORD gdwPPID;
+HINSTANCE FAR * hProviders = NULL; // array of handles to providers
+TSPAPIPROC FAR * lpfnProcAddress = NULL;
+DWORD FAR * dwPermanentProviderIDArray;
+DWORD FAR * dwNumLinesArray = NULL; // dwNumLinesArray[1] is how many
+DWORD FAR * dwNumPhonesArray = NULL; // lines are on provider 1
+
+DWORD gdwLineDeviceIDBase;
+DWORD gdwPhoneDeviceIDBase;
+
+FARPROC glpLineEventProc32, glpPhoneEventProc32,
+ glpAsyncCompletionProc32, glpLineCreateProc32, glpPhoneCreateProc32;
+
+
+const char szINIfilename[] = "TELEPHON.sl";
+
+
+// function definitions
+
+#ifdef DEBUG
+VOID TSP1632lOutputDebug(int level, LPSTR errString)
+ {
+ char outString[1024];
+
+ // if(level <= ???)
+ {
+ wsprintf(outString, "TSP1632l:(%d) %s\r\n", level, errString);
+ OutputDebugString(outString);
+ }
+ }
+#endif
+
+
+VOID
+InitializeSPs(VOID)
+ {
+ int iProvider;
+ char LibFileName[MAXBUFSIZE];
+ char szBuffer[MAXBUFSIZE];
+
+// ghInst32 = LoadLibraryEx32("TSP1632L.DLL", NULL, 0);
+//
+// glpLineEventProc32 = GetProcAddress32(ghInst32, "LineEventProc32");
+// glpPhoneEventProc32 = GetProcAddress32(ghInst32, "PhoneEventProc32");
+// glpAsyncCompletionProc32 = GetProcAddress32(
+// ghInst32,
+// "AsyncCompletionProc32"
+// );
+// glpLineCreateProc32 = GetProcAddress32(ghInst32, "LineCreateProc32");
+// glpPhoneCreateProc32 = GetProcAddress32(ghInst32, "PhoneCreateProc32");
+
+ NumProviders = GetPrivateProfileInt(
+ "Providers",
+ "NumProviders",
+ 0, // default
+ szINIfilename
+ );
+
+ dwPermanentProviderIDArray
+ = (DWORD FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(DWORD));
+
+ dwNumLinesArray
+ = (DWORD FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(DWORD));
+ dwNumPhonesArray
+ = (DWORD FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(DWORD));
+
+ hProviders =
+ (HINSTANCE FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(HINSTANCE));
+
+ lpfnProcAddress = (TSPAPIPROC FAR *)GlobalAllocPtr(
+ GPTR,
+ NumProviders * TSPI_PROC_LAST * sizeof(TSPAPIPROC)
+ );
+
+ if(
+ !dwPermanentProviderIDArray
+ || !dwNumLinesArray
+ || !dwNumPhonesArray
+ || !hProviders
+ || !lpfnProcAddress)
+ ;// out of memory - fail
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ {
+ wsprintf(szBuffer, "ProviderFilename%d", iProvider);
+ GetPrivateProfileString(
+ "Providers",
+ szBuffer,
+ "", // default
+ LibFileName,
+ MAXBUFSIZE,
+ szINIfilename
+ );
+
+ hProviders[iProvider] = LoadLibrary(LibFileName);
+
+DBGOUT((1, "Loading [%s]", LibFileName));
+
+ wsprintf(szBuffer, "ProviderID%d", iProvider);
+ dwPermanentProviderIDArray[iProvider] = GetPrivateProfileInt(
+ "Providers",
+ szBuffer,
+ 0, // default
+ szINIfilename
+ );
+ }
+ }
+
+
+VOID
+FreeAllMem(VOID)
+ {
+ int iProvider;
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ FreeLibrary(hProviders[iProvider]);
+
+ GlobalFreePtr(dwPermanentProviderIDArray);
+ GlobalFreePtr(dwNumLinesArray);
+ GlobalFreePtr(dwNumPhonesArray);
+ GlobalFreePtr(hProviders);
+ GlobalFreePtr(lpfnProcAddress);
+
+// FreeLibrary32(ghInst32);
+ }
+
+
+TSPAPIPROC
+GetProcAddressHashed(int iProvider, DWORD iFunction) // iFunction is 500-based
+ {
+ if(!lpfnProcAddress[(iProvider*TSPI_PROC_LAST)+(iFunction-TSPI_PROC_BASE)])
+ lpfnProcAddress[(iProvider*TSPI_PROC_LAST)+(iFunction-TSPI_PROC_BASE)]
+ = (TSPAPIPROC)GetProcAddress(
+ hProviders[iProvider],
+ (LPCSTR)iFunction
+ );
+
+ return lpfnProcAddress[
+ (iProvider*TSPI_PROC_LAST)+(iFunction-TSPI_PROC_BASE)
+ ];
+ }
+
+
+int iProviderFromDeviceID(DWORD dwDeviceID)
+ {
+ DWORD dwFirstDeviceIDonProvider = gdwLineDeviceIDBase;
+ int iProvider = 0;
+
+ // seeks the correct provider for this line
+ while(dwDeviceID >= dwFirstDeviceIDonProvider + dwNumLinesArray[iProvider])
+ {
+ dwFirstDeviceIDonProvider += dwNumLinesArray[iProvider];
+ ++iProvider;
+ }
+
+ return iProvider;
+ }
+
+
+int iProviderFromPermanentProviderID(DWORD dwPPID)
+ {
+ int iProvider;
+
+ // seeks the correct provider for this line
+ for ( iProvider = 0; iProvider < NumProviders; iProvider++)
+ {
+ if ( dwPPID == dwPermanentProviderIDArray[iProvider] )
+ {
+ return (iProvider);
+ }
+ }
+
+ return iProvider;
+ }
+
+
+//
+// ----------------------- 32-bit callback shells -----------------------------
+//
+
+VOID LineEventProc16(
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+ {
+ (*glpLineEventProc32)(
+ 6,
+ 0,
+ glpLineEventProc32,
+ htLine,
+ htCall,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+ }
+
+
+VOID PhoneEventProc16(
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+ {
+ (*glpPhoneEventProc32)(
+ 5,
+ 0,
+ glpPhoneEventProc32,
+ htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+ }
+
+
+VOID AsyncCompletionProc16(DRV_REQUESTID dwRequestID, LONG lResult)
+ {
+ (*glpAsyncCompletionProc32)(
+ 2,
+ 0,
+ glpAsyncCompletionProc32,
+ dwRequestID,
+ lResult);
+ }
+
+
+VOID LineCreateProc16(
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+ {
+ (*glpLineEventProc32)(
+ 6,
+ 0,
+ glpLineEventProc32,
+ htLine,
+ htCall,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+ }
+
+
+VOID PhoneCreateProc16(
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+ {
+ (*glpPhoneEventProc32)(
+ 5,
+ 0,
+ glpPhoneEventProc32,
+ htPhone,
+ dwMsg,
+ dwParam1,
+ dwParam2,
+ dwParam3
+ );
+ }
+
+//
+// -------------------- THUNK_TSPIAPI TSPI_line functions ---------------------------
+// -------------------- THUNK_TSPIAPI TSPI_line functions ---------------------------
+// -------------------- THUNK_TSPIAPI TSPI_line functions ---------------------------
+// -------------------- THUNK_TSPIAPI TSPI_line functions ---------------------------
+// -------------------- THUNK_TSPIAPI TSPI_line functions ---------------------------
+//
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineAccept(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineAccept"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEACCEPT))(
+ dwRequestID,
+ REALhdCall,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HDRVCALL hdConsultCall
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineAnswer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineAnswer"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEANSWER))(
+ dwRequestID,
+ REALhdCall,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineBlindTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode)
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineBlindTransfer"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEBLINDTRANSFER))(
+ dwRequestID,
+ REALhdCall,
+ lpszDestAddress,
+ dwCountryCode
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineClose"));
+
+ GlobalFreePtr((LPVOID)lpmLine);
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINECLOSE))(REALhdLine);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineCloseCall"));
+
+ GlobalFreePtr((LPVOID)lpmCall);
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINECLOSECALL))(REALhdCall);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineCompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPDWORD lpdwCompletionID,
+ DWORD dwCompletionMode,
+ DWORD dwMessageID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineCompleteTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVCALL hdConsultCall,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ DWORD dwTransferMode
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+ {
+ TSPAPIPROC lpfn;
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+
+ TSP1632lDebugString((2, "Entering TSPI_lineConfigDialog"));
+
+ lpfn = GetProcAddressHashed(iProvider, TSPI_LINECONFIGDIALOG);
+
+ if (lpfn)
+ return (*lpfn)( dwDeviceID, hwndOwner, lpszDeviceClass );
+
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineConfigDialogEdit(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass,
+ LPVOID const lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ )
+ {
+ TSPAPIPROC lpfn;
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+
+
+ lpfn = GetProcAddressHashed(iProvider, TSPI_LINECONFIGDIALOGEDIT);
+
+ if (lpfn)
+ return (*lpfn)( dwDeviceID, hwndOwner, lpszDeviceClass,
+ lpDeviceConfigIn, dwSize, lpDeviceConfigOut );
+
+
+ return(LINEERR_OPERATIONUNAVAIL);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+ {
+ TSPAPIPROC lpfn;
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+#pragma message("*** *** ***BUGBUG --verify this pointer before dereffing")
+ int iProvider = lpmLine->iProvider;
+
+
+ lpfn = GetProcAddressHashed(iProvider, TSPI_LINEDEVSPECIFIC);
+
+ if (lpfn)
+ return (*lpfn)( dwRequestID, hdLine, dwAddressID, hdCall, lpParams,
+ dwSize);
+
+
+ return(LINEERR_OPERATIONUNAVAIL);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineDevSpecificFeature(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwFeature,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineDial(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineDial"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEDIAL))(
+ dwRequestID,
+ REALhdCall,
+ lpszDestAddress,
+ dwCountryCode
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineDrop"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEDROP))(
+ dwRequestID,
+ REALhdCall,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineDropOnClose(
+ HDRVCALL hdCall
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineDropOnClose"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEDROPONCLOSE))(
+ REALhdCall
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineDropNoOwner(
+ HDRVCALL hdCall
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineDropNoOwner"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEDROPNOOWNER))(
+ REALhdCall
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineForward(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD bAllAddresses,
+ DWORD dwAddressID,
+ LPLINEFORWARDLIST const lpForwardList,
+ DWORD dwNumRingsNoAnswer,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGatherDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitModes,
+ LPSTR lpsDigits,
+ DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGenerateDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitMode,
+ LPCSTR lpszDigits,
+ DWORD dwDuration
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGenerateDigits"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGENERATEDIGITS))(
+ REALhdCall,
+ dwEndToEndID,
+ dwDigitMode,
+ lpszDigits,
+ dwDuration
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGenerateTone(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwToneMode,
+ DWORD dwDuration,
+ DWORD dwNumTones,
+ LPLINEGENERATETONE const lpTones
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGenerateTone"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGENERATETONE))(
+ REALhdCall,
+ dwEndToEndID,
+ dwToneMode,
+ dwDuration,
+ dwNumTones
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ DWORD dwFirstDeviceIDonProvider = gdwLineDeviceIDBase;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetAddressCaps"));
+
+ return(* GetProcAddressHashed(iProvider, TSPI_LINEGETADDRESSCAPS))(
+ dwDeviceID,
+ dwAddressID,
+ dwTSPIVersion,
+ dwExtVersion,
+ lpAddressCaps
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCSTR lpsAddress,
+ DWORD dwSize
+ )
+ {
+
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetAddressID"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETADDRESSID))(
+ REALhdLine,
+ lpdwAddressID,
+ dwAddressMode,
+ lpsAddress,
+ dwSize
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+ {
+
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetAddressStatus"));
+
+ return (* GetProcAddressHashed(lpmLine->iProvider, TSPI_LINEGETADDRESSSTATUS))(
+ REALhdLine,
+ dwAddressID,
+ lpAddressStatus
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetCallAddressID"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETCALLADDRESSID))(
+ REALhdCall,
+ lpdwAddressID
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetCallInfo"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETCALLINFO))(
+ REALhdCall,
+ lpCallInfo
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetCallStatus"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETCALLSTATUS))(
+ REALhdCall,
+ lpCallStatus
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetDevCaps"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETDEVCAPS))(
+ dwDeviceID,
+ dwTSPIVersion,
+ dwExtVersion,
+ lpLineDevCaps
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineGetDevCaps retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetDevConfig(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCSTR lpszDeviceClass
+ )
+ {
+
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetDevConfig"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETDEVCONFIG))(
+ dwDeviceID,
+ lpDeviceConfig,
+ lpszDeviceClass
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineGetDevConfig retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPLINEEXTENSIONID lpExtensionID
+ )
+ {
+
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetExtension"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETEXTENSIONID))(
+ dwDeviceID,
+ dwTSPIVersion,
+ lpExtensionID
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineGetExtensionID retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetIcon(
+ DWORD dwDeviceID,
+ LPCSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+ {
+
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetIcon"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETICON))(
+ dwDeviceID,
+ lpszDeviceClass,
+ lphIcon
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineGetIcon retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+ {
+
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetLineDevStatus"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETLINEDEVSTATUS))(
+ REALhdLine,
+ lpLineDevStatus
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+ {
+
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineGetNumAddressIDs"));
+
+ return (* GetProcAddressHashed(lpmLine->iProvider, TSPI_LINEGETNUMADDRESSIDS))(
+ REALhdLine,
+ lpdwNumAddressIDs
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineHold"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEHOLD))(
+ dwRequestID,
+ REALhdCall
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+ LPMYCALL lpmCall;
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineMakeCall"));
+
+ lpmCall = (MYCALL *)GlobalAllocPtr(GPTR, sizeof(MYCALL));
+ if(!lpmCall)
+ return(LINEERR_NOMEM);
+
+ *lphdCall = (HDRVCALL)lpmCall;
+
+ lpmCall->iProvider = iProvider;
+ lpmCall->dwDeviceID = lpmLine->dwDeviceID;
+
+ return (* GetProcAddressHashed(lpmCall->iProvider, TSPI_LINEMAKECALL))(
+ dwRequestID,
+ REALhdLine,
+ htCall,
+ &(lpmCall->hdCall),
+ lpszDestAddress,
+ dwCountryCode,
+ lpCallParams
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineMonitorDigits(
+ HDRVCALL hdCall,
+ DWORD dwDigitModes
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineMonitorMedia(
+ HDRVCALL hdCall,
+ DWORD dwMediaModes
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineMonitorTones(
+ HDRVCALL hdCall,
+ DWORD dwToneListID,
+ LPLINEMONITORTONE const lpToneList,
+ DWORD dwNumEntries
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+ {
+ TSP1632lDebugString((2, "Entering TSPI_lineNegotiateTSPIVersion"));
+
+_asm int 1;
+InitializeSPs();
+
+ *lpdwTSPIVersion = TAPI_CUR_VER;
+
+ return(0);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ LPMYLINE lpmLine;
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP1632lDebugString((2, "Entering TSPI_lineOpen"));
+
+ lpmLine = (MYLINE *)GlobalAllocPtr(GPTR, sizeof(MYLINE));
+ if(!lpmLine)
+ return(LINEERR_NOMEM);
+
+ *lphdLine = (HDRVLINE)lpmLine;
+
+ lpmLine->iProvider = iProvider;
+ lpmLine->dwDeviceID = dwDeviceID;
+ lpmLine->htLine = htLine;
+ lpmLine->lpfnEventProc = lpfnEventProc;
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEOPEN))(
+ dwDeviceID,
+ (HTAPILINE)lpmLine, // was htLine
+ &(lpmLine->hdLine),
+ dwTSPIVersion,
+ LineEventProc16
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineOpen retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_linePark(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwParkMode,
+ LPCSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_linePickup(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ LPCSTR lpszGroupID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_linePrepareAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineRedirect(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineRemoveFromConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSecureCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineSecureCall"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINESECURECALL))(
+ dwRequestID,
+ REALhdCall
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSelectExtVersion(
+ HDRVLINE hdLine,
+ DWORD dwExtVersion
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSendUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineSendUserUserInfo"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINESENDUSERUSERINFO))(
+ dwRequestID,
+ REALhdCall,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetCallParams(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwBearerMode,
+ DWORD dwMinRate,
+ DWORD dwMaxRate,
+ LPLINEDIALPARAMS const lpDialParams
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetCurrentLocation(
+ DWORD dwLocation
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineSetDefaultMediaDetection"));
+
+ return (* GetProcAddressHashed(
+ iProvider,
+ TSPI_LINESETDEFAULTMEDIADETECTION
+ ))(REALhdLine, dwMediaModes);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetDevConfig(
+ DWORD dwDeviceID,
+ LPVOID const lpDeviceConfig,
+ DWORD dwSize,
+ LPCSTR lpszDeviceClass
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetMediaControl(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPLINEMEDIACONTROLDIGIT const lpDigitList,
+ DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA const lpMediaList,
+ DWORD dwMediaNumEntries,
+ LPLINEMEDIACONTROLTONE const lpToneList,
+ DWORD dwToneNumEntries,
+ LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
+ DWORD dwCallStateNumEntries
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetStatusMessages(
+ HDRVLINE hdLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineSetStatusMessages"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINESETSTATUSMESSAGES))(
+ REALhdLine,
+ dwLineStates,
+ dwAddressStates
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetTerminal(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ DWORD dwTerminalModes,
+ DWORD dwTerminalID,
+ DWORD bEnable
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetupConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVLINE hdLine,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSetupTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineSwapHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdActiveCall,
+ HDRVCALL hdHeldCall
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineUncompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwCompletionID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineUnhold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP1632lDebugString((2, "Entering TSPI_lineUnhold"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEUNHOLD))(
+ dwRequestID,
+ REALhdCall
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineUnpark(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_lineReleaseUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+
+//
+// ----------------------- THUNK_TSPIAPI TSPI_phone functions -----------------------
+//
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneClose(
+ HDRVPHONE hdPhone
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetButtonInfo(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO lpButtonInfo
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetData(
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID lpData,
+ DWORD dwSize
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPPHONECAPS lpPhoneCaps
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetDisplay(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDisplay
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPPHONEEXTENSIONID lpExtensionID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetGain(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwGain
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetHookSwitch(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwHookSwitchDevs
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetIcon(
+ DWORD dwDeviceID,
+ LPCSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetID(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetLamp(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPDWORD lpdwLampMode
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetRing(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwRingMode,
+ LPDWORD lpdwVolume
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetStatus(
+ HDRVPHONE hdPhone,
+ LPPHONESTATUS lpPhoneStatus
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneGetVolume(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwVolume
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneOpen(
+ DWORD dwDeviceID,
+ HTAPIPHONE htPhone,
+ LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion,
+ PHONEEVENT lpfnEventProc
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ LPMYPHONE lpmPhone;
+
+ TSP1632lDebugString((2, "Entering TSPI_phoneOpen"));
+
+ lpmPhone = (MYPHONE *)GlobalAllocPtr(GPTR, sizeof(MYPHONE));
+ if(!lpmPhone)
+ return(PHONEERR_NOMEM);
+
+ *lphdPhone = (HDRVPHONE)lpmPhone;
+
+ lpmPhone->iProvider = iProvider;
+ lpmPhone->dwDeviceID = dwDeviceID;
+ lpmPhone->htPhone = htPhone;
+ lpmPhone->lpfnEventProc = lpfnEventProc;
+
+ return (* GetProcAddressHashed(iProvider, TSPI_PHONEOPEN))(
+ dwDeviceID,
+ (HTAPIPHONE)lpmPhone, // was htPhone
+ &(lpmPhone->hdPhone),
+ dwTSPIVersion,
+ PhoneEventProc16
+ );
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSelectExtVersion(
+ HDRVPHONE hdPhone,
+ DWORD dwExtVersion
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetButtonInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO const lpButtonInfo
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetData(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID const lpData,
+ DWORD dwSize
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetDisplay(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRow,
+ DWORD dwColumn,
+ LPCSTR lpsDisplay,
+ DWORD dwSize
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetGain(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwGain
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetHookSwitch(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDevs,
+ DWORD dwHookSwitchMode
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetLamp(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ DWORD dwLampMode
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetRing(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRingMode,
+ DWORD dwVolume
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetStatusMessages(
+ HDRVPHONE hdPhone,
+ DWORD dwPhoneStates,
+ DWORD dwButtonModes,
+ DWORD dwButtonStates
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_phoneSetVolume(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwVolume
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+
+
+//
+// ----------------------- THUNK_TSPIAPI TSPI_provider functions --------------------
+//
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+ {
+
+ int iProvider = iProviderFromPermanentProviderID(dwPermanentProviderID);
+ BOOL fAllFailed = TRUE;
+
+ TSP1632lDebugString((2, "Entering TSPI_providerConfig"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_PROVIDERCONFIG))(
+ hwndOwner,
+ dwPermanentProviderID
+ );
+
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc
+ )
+ {
+ int iProvider;
+ BOOL fAllFailed = TRUE;
+
+ TSP1632lDebugString((2, "Entering TSPI_providerInit"));
+
+ gdwLineDeviceIDBase = dwLineDeviceIDBase;
+ gdwPhoneDeviceIDBase = dwPhoneDeviceIDBase;
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ {
+ TSP1632lDebugString((2, "TSPI_providerInit initializing provider"));
+
+ if(!((* GetProcAddressHashed(iProvider, TSPI_PROVIDERINIT))(
+ dwTSPIVersion,
+ dwPermanentProviderIDArray[iProvider],
+ dwLineDeviceIDBase,
+ dwPhoneDeviceIDBase,
+ dwNumLinesArray[iProvider],
+ dwNumPhonesArray[iProvider],
+ AsyncCompletionProc16
+ )))
+ fAllFailed = FALSE; // if one succeeded, they didn't ALL fail
+
+ dwLineDeviceIDBase += dwNumLinesArray[iProvider];
+ dwPhoneDeviceIDBase += dwNumPhonesArray[iProvider];
+ }
+
+ if(fAllFailed)
+ {
+ DBGOUT((2, "TSPI_providerInit: all 16bit providers failed init!"));
+ return(LINEERR_OPERATIONFAILED);
+ }
+ else
+ return(ERR_NONE);
+
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion
+ )
+ {
+ int iProvider;
+
+ TSP1632lDebugString((2, "Entering TSPI_providerShutdown"));
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ (* GetProcAddressHashed(iProvider, TSPI_PROVIDERSHUTDOWN))(
+ dwTSPIVersion
+ );
+
+ FreeAllMem();
+
+ return(ERR_NONE);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+ {
+ int iProvider;
+
+ TSP1632lDebugString((2, "Entering TSPI_providerEnumDevices"));
+
+_asm int 1;
+
+ gdwPPID = dwPermanentProviderID;
+
+ *lpdwNumLines = 0;
+ *lpdwNumPhones = 0;
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ {
+ TSPAPIPROC lpfn;
+
+
+ lpfn = GetProcAddressHashed(iProvider, TSPI_PROVIDERENUMDEVICES);
+
+ if (lpfn)
+ (*lpfn)(
+ dwPermanentProviderIDArray[iProvider],
+ &(dwNumLinesArray[iProvider]),
+ &(dwNumPhonesArray[iProvider]),
+ hProvider,
+ LineCreateProc16,
+ PhoneCreateProc16
+ );
+
+ (*lpdwNumLines) += dwNumLinesArray[iProvider];
+ (*lpdwNumPhones) += dwNumPhonesArray[iProvider];
+ }
+
+ DBGOUT((2, " TSPI_providerEnumDevices: #lines= %d #phones= %d",
+ *lpdwNumLines,
+ *lpdwNumPhones));
+
+ return(ERR_NONE);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerCreateLineDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+THUNK_TSPIAPI
+TSPI_providerCreatePhoneDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+BOOL _stdcall
+//LibMain(
+// HINSTANCE hDllInstance,
+// WORD wDataSeg,
+// WORD wHeapSize,
+// LPSTR lpszCmdLine
+// )
+DllMain(
+ DWORD hDllInstance,
+ DWORD dwReason,
+ DWORD dwReserved)
+{
+// static long MyUsageCounter = 0;
+
+
+ DBGOUT((2, "TSP1632l: DllMain entered - %0ld\r\n", dwReason));
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+ ghThisInst = hDllInstance;
+
+ TapiThk_ThunkConnect32("TSP1632S.TSP", "TSP1632L.DLL", hDllInstance, dwReason);
+ TapiFThk_ThunkConnect32("TSP1632S.TSP", "TSP1632L.DLL", hDllInstance, dwReason);
+
+ break;
+
+
+ case DLL_PROCESS_DETACH:
+ break;
+
+
+ default:
+ OutputDebugString("TSP1632l: DllMain entered\r\n");
+ }
+
+
+ return(1); // success
+}
+
+
+
+WORD CALLBACK _loadds
+NewData(
+ )
+ {
+ return (ghThisInst); // success
+ }
+
+BOOL TapiCallbackThunk( HLINEAPP hDevice,
+ DWORD dwMessage,
+ DWORD dwInstance,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwcbProc32);
+
+DWORD CALLBACK _loadds
+NewData2(
+ )
+ {
+// return (DWORD)&TapiCallbackThunk;
+ }
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.def b/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.def
new file mode 100644
index 000000000..3e32b548d
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.def
@@ -0,0 +1,125 @@
+LIBRARY TSP1632l
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept @500
+ TSPI_lineAddToConference @501
+ TSPI_lineAnswer @502
+ TSPI_lineBlindTransfer @503
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineCompleteCall @506
+ TSPI_lineCompleteTransfer @507
+ TSPI_lineConditionalMediaDetection @508
+ TSPI_lineConfigDialog @509
+ TSPI_lineDevSpecific @510
+ TSPI_lineDevSpecificFeature @511
+ TSPI_lineDial @512
+ TSPI_lineDrop @513
+ TSPI_lineForward @514
+ TSPI_lineGatherDigits @515
+ TSPI_lineGenerateDigits @516
+ TSPI_lineGenerateTone @517
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetDevConfig @525
+ TSPI_lineGetExtensionID @526
+ TSPI_lineGetIcon @527
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineHold @531
+ TSPI_lineMakeCall @532
+ TSPI_lineMonitorDigits @533
+ TSPI_lineMonitorMedia @534
+ TSPI_lineMonitorTones @535
+ TSPI_lineNegotiateExtVersion @536
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_lineOpen @538
+ TSPI_linePark @539
+ TSPI_linePickup @540
+ TSPI_linePrepareAddToConference @541
+ TSPI_lineRedirect @542
+ TSPI_lineRemoveFromConference @543
+ TSPI_lineSecureCall @544
+ TSPI_lineSelectExtVersion @545
+ TSPI_lineSendUserUserInfo @546
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetCallParams @548
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetDevConfig @550
+ TSPI_lineSetMediaControl @551
+ TSPI_lineSetMediaMode @552
+ TSPI_lineSetStatusMessages @553
+ TSPI_lineSetTerminal @554
+ TSPI_lineSetupConference @555
+ TSPI_lineSetupTransfer @556
+ TSPI_lineSwapHold @557
+ TSPI_lineUncompleteCall @558
+ TSPI_lineUnhold @559
+ TSPI_lineUnpark @560
+
+ TSPI_phoneClose @561
+ TSPI_phoneConfigDialog @562
+ TSPI_phoneDevSpecific @563
+ TSPI_phoneGetButtonInfo @564
+ TSPI_phoneGetData @565
+ TSPI_phoneGetDevCaps @566
+ TSPI_phoneGetDisplay @567
+ TSPI_phoneGetExtensionID @568
+ TSPI_phoneGetGain @569
+ TSPI_phoneGetHookSwitch @570
+ TSPI_phoneGetIcon @571
+ TSPI_phoneGetID @572
+ TSPI_phoneGetLamp @573
+ TSPI_phoneGetRing @574
+ TSPI_phoneGetStatus @575
+ TSPI_phoneGetVolume @576
+ TSPI_phoneNegotiateExtVersion @577
+ TSPI_phoneNegotiateTSPIVersion @578
+ TSPI_phoneOpen @579
+ TSPI_phoneSelectExtVersion @580
+ TSPI_phoneSetButtonInfo @581
+ TSPI_phoneSetData @582
+ TSPI_phoneSetDisplay @583
+ TSPI_phoneSetGain @584
+ TSPI_phoneSetHookSwitch @585
+ TSPI_phoneSetLamp @586
+ TSPI_phoneSetRing @587
+ TSPI_phoneSetStatusMessages @588
+ TSPI_phoneSetVolume @589
+
+ TSPI_providerConfig @590
+ TSPI_providerInit @591
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerShutdown @594
+
+ TSPI_providerEnumDevices @595
+ TSPI_lineDropOnClose @596
+ TSPI_lineDropNoOwner @597
+ TSPI_providerCreateLineDevice @598
+ TSPI_providerCreatePhoneDevice @599
+ TSPI_lineSetCurrentLocation @600
+ TSPI_lineConfigDialogEdit @601
+ TSPI_lineReleaseUserUserInfo @602
+
+ WEP @1
+ LibMain @2
+; DllEntryPoint
+
+; Table of vital pointers for 32-bit half of GDI thunks
+
+; TAPITHKCONNECTIONDATALS ; @110 ;Internal
+; FT_TAPIFTHKTHKCONNECTIONDATA ; @111 ;Internal
+; Tapi32ConnectionDataSL
+
+ TapiThk_ThunkData32
+ TapiFThk_ThunkData32
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.h b/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.h
new file mode 100644
index 000000000..dc5fa151f
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632l/tsp1632l.h
@@ -0,0 +1,53 @@
+/* TSP3216S.H
+ Copyright 1995 (C) Microsoft Corporation
+
+ 32-bit TAPI service provider to act as a cover for a system's 16-bit SPs
+
+ 16-bit part: TSP3216S.DLL
+ 32-bit part: TSP3216L.DLL
+
+ t-jereh 20-July-1995
+
+ TODO:
+ 1) allow debug levels
+ 2) if oom in InitializeSPs(), fail
+
+ */
+
+#define MAXBUFSIZE 256 /* maximum buffer size */
+
+#define ERR_NONE 0 /* success return value */
+
+#define TAPI_CUR_VER 0x00010004
+
+#define TSPI_PROC_LAST 103 /* there are TSPI functions from 500 to 602 */
+
+
+// structs
+
+typedef struct tagMYLINE
+ {
+ HDRVLINE hdLine;
+ int iProvider;
+ DWORD dwDeviceID;
+ LINEEVENT lpfnEventProc;
+ HTAPILINE htLine;
+ } MYLINE, *LPMYLINE;
+
+
+typedef struct tagMYPHONE
+ {
+ HDRVPHONE hdPhone;
+ int iProvider;
+ DWORD dwDeviceID;
+ PHONEEVENT lpfnEventProc;
+ HTAPIPHONE htPhone;
+ } MYPHONE, *LPMYPHONE;
+
+
+typedef struct tagMYCALL
+ {
+ HDRVCALL hdCall;
+ int iProvider;
+ DWORD dwDeviceID;
+ } MYCALL, *LPMYCALL;
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632s/depend.mk b/private/tapi/dev/sp/tsp1632/tsp1632s/depend.mk
new file mode 100644
index 000000000..bce4481e3
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632s/depend.mk
@@ -0,0 +1,9 @@
+.\tapi32.obj: ..\..\script\$(VERDIR)\tapi32.asm
+
+.\tapithk.obj: ..\..\script\$(VERDIR)\tapithk.asm
+
+.\tapifthk.obj: ..\..\script\$(VERDIR)\tapifthk.asm
+
+.\tpiint32.obj: ..\tpiint32.asm
+
+.\tsp1632s.res: ..\tsp1632s.rc
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632s/makefile b/private/tapi/dev/sp/tsp1632/tsp1632s/makefile
new file mode 100644
index 000000000..274a6cf4b
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632s/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# tsp1632s.tsp Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632s/makefile.def b/private/tapi/dev/sp/tsp1632/tsp1632s/makefile.def
new file mode 100644
index 000000000..435aef87a
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632s/makefile.def
@@ -0,0 +1,51 @@
+ROOT=..\..\..\..\..\..\..
+
+IS_OEM=1
+MASM6=1
+IS_16 = 1
+
+
+BUILDDLL=1
+DEFENTRY=DllEntryPoint
+DLLENTRY=DllEntryPoint
+#DLLENTRY=LibMain
+
+
+DEPENDNAME=..\depend.mk
+
+TARGETS=tsp1632s.tsp
+
+
+ALTSRCDIR=..\..\script\$(VERDIR)
+SRCDIR=..
+
+#BUILD_COFF=1
+
+
+
+L16EXE=tsp1632s.tsp # Name of exe.
+L16DEF=..\tsp1632s.def # Our def file.
+L16MAP=tsp1632s.map # Our map file.
+L16SYM=tsp1632s.sym # Our sym file.
+L16RES=tsp1632s.res # Resource file.
+L16OBJS = $(DEVROOT)\sdk\lib16\libentry.obj tpiint32.obj tapi32.obj tapithk.obj tapifthk.obj
+
+L16LIBS= \
+ $(DEVROOT)\lib16\libw.lib \
+ $(DEVROOT)\tools\c816\lib\ldllcew.lib \
+ $(DEVROOT)\lib16\kernel.lib
+
+
+
+RCFLAGS=$(RCFLAGS) -40
+
+
+!include $(ROOT)\dev\master.mk
+#!include $(ROOT)\win\win32\win32.mk
+
+
+AFLAGS=$(AFLAGS) -Fl
+
+INCLUDE=$(ROOT)\win\thunk;$(ROOT)\win\core\inc;$(INCLUDE)
+#INCLUDE=$(ROOT)\win\thunk;$(INCLUDE)
+
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632s/tpiint32.asm b/private/tapi/dev/sp/tsp1632/tsp1632s/tpiint32.asm
new file mode 100644
index 000000000..9edcffc2d
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632s/tpiint32.asm
@@ -0,0 +1,844 @@
+ page ,132
+ TITLE $tapii32.asm
+ .listall
+
+ .386
+ OPTION READONLY
+ option oldstructs
+
+
+; .model FLAT
+ OPTION SEGMENT:USE16
+ .model LARGE,PASCAL
+
+
+
+; .fardata callbacks
+;.data
+CALLBACK SEGMENT PARA PUBLIC ''
+
+ public LineCallbackList
+ public PhoneCallbackList
+
+LineCallbackList dd 0
+PhoneCallbackList dd 0
+
+CALLBACK_NEXT equ 0
+CALLBACK_CALLBACK equ 4
+CALLBACK_HAPP equ 8
+CALLBACK_STRUCT_SIZE equ 0ch
+
+CALLBACK ENDS
+
+
+
+;GetpWin16Lock proto APIENTRY :ptr dword
+
+
+;externDef STDCALL lineInitialize16@20:near32
+;externDef STDCALL lineShutdown16@4:near32
+;externDef STDCALL phoneInitialize16@20:near32
+;externDef STDCALL phoneShutdown16@4:near32
+
+; ; ;IsBadCodePtr proto APIENTRY :ptr dword
+; ; ;
+; ; ;GlobalAlloc PROTO NEAR APIENTRY :DWORD, :DWORD
+; ; ;GlobalLock PROTO NEAR APIENTRY :DWORD
+; ; ;GlobalHandle PROTO NEAR APIENTRY :DWORD
+; ; ;GlobalUnlock PROTO NEAR APIENTRY :DWORD
+; ; ;GlobalFree PROTO NEAR APIENTRY :DWORD
+
+;AllocSLCallback PROTO NEAR APIENTRY :DWORD, :DWORD
+;FreeSLCallback PROTO NEAR APIENTRY :DWORD
+Tapi32ConnectPeerSL PROTO near pszDll16:dword, pszDll32:dword
+;
+;
+;externDef InitThkSL :near32
+;externDef FdThkCommon :near32
+;
+;TapiThunkInit PROTO near pCB32Tab:dword
+;TapiThunkTerminate PROTO near pCB32Tab:dword
+
+;TapiThkConnectPeerLS PROTO near pszDll16:dword, pszDll32:dword
+;FT_TapiFThkConnectToFlatThkPeer proto near pszDll16:dword, pszDll32:dword
+;NewData PROTO near
+NewData2 PROTO far
+;FreeLibrary16 PROTO NEAR STDCALL :DWORD
+
+
+
+
+TapiThk_ThunkConnect16 proto far pascal SpszDll16:word,
+ OpszDll16:word,
+ SpszDll32:word,
+ OpszDll32:word,
+ hInst:word,
+ dwReason:dword
+
+TapiFThk_ThunkConnect16 proto far pascal SpszDll16:word,
+ OpszDll16:word,
+ SpszDll32:word,
+ OpszDll32:word,
+ hInst:word,
+ dwReason:dword
+
+
+
+
+;* externDef TapiCB32BitTable :near32
+
+
+ .data
+
+
+lp16TapiCallbackThunk dd 0
+
+
+;
+; Pointer to the Win16 heirarchical critical section.
+;
+; public Win16Lock
+;Win16Lock dd 0
+
+
+
+pszDll16 db 'TSP1632s.TSP',0
+pszDll32 db 'TSP1632l.DLL',0
+
+
+cProcessAttach dw 0 ;Count of processes attached to our lib.
+
+
+; .code THUNK32
+ .code
+
+
+
+WEP proc far pascal
+ ret
+WEP endp
+
+LibMain proc far pascal wInst:WORD, uDataSeg:WORD, cbHeapSize:WORD,
+ lpszCmdLine:DWORD
+
+ invoke TapiThk_ThunkConnect16, seg pszDll16,
+ offset pszDll16,
+ seg pszDll32,
+ offset pszDll32,
+ wInst,
+ 1
+
+ invoke TapiFThk_ThunkConnect16, seg pszDll16,
+ offset pszDll16,
+ seg pszDll32,
+ offset pszDll32,
+ wInst,
+ 1
+
+
+
+; Initialize the 16->32 thunks.
+; invoke Tapi32ConnectPeerSL, ADDR pszDll16, ADDR pszDll32
+; or eax,eax
+
+
+mov ax, 1
+ ret
+LibMain endp
+
+;-----------------------------------------------------------------------;
+; Tapi DLL init routine
+; We expect lReason to be either DLL_PROCESS_ATTACH/DETACH (we take
+; action on these values) or DLL_THREAD_ATTACH/DETACH (we ignore
+; and return success). If there is anything else, we need to check
+; specifically and take appropriate action.
+;-----------------------------------------------------------------------;
+DllEntryPoint proc far pascal export lReason:DWORD, wInst:WORD,
+ wDS:WORD, wHeapSize:WORD,
+ dwReserved1:DWORD, wReserved:WORD
+
+
+ invoke TapiThk_ThunkConnect16, seg pszDll16,
+ offset pszDll16,
+ seg pszDll32,
+ offset pszDll32,
+ wInst,
+ 1
+
+ invoke TapiFThk_ThunkConnect16, seg pszDll16,
+ offset pszDll16,
+ seg pszDll32,
+ offset pszDll32,
+ wInst,
+ 1
+
+ invoke NewData2
+ mov word ptr lp16TapiCallbackThunk+2, dx
+ mov word ptr lp16TapiCallbackThunk , ax
+
+ jmp initok
+
+
+;;;;;09/18/95
+;;;;;09/18/95
+;;;;;09/18/95
+;;;;;09/18/95
+;;;;;09/18/95;**** invoke GetpWin16Lock, ADDR Win16Lock
+;;;;;09/18/95
+;;;;;09/18/95 mov eax, lReason
+;;;;;09/18/95 or eax, eax
+;;;;;09/18/95 jz dec_cProcess ;DLL_PROCESS_DETACH?
+;;;;;09/18/95 cmp eax, 1 ;DLL_PROCESS_ATTACH?
+;;;;;09/18/95 jne initok ;DLL_THREAD_ATTACH/DETACH (we don't do anything)
+;;;;;09/18/95
+;;;;;09/18/95
+;;;;;09/18/95 inc cProcessAttach ;Keep count of how many processes attach to our lib.
+;;;;;09/18/95
+;;;;;09/18/95; Do once-only initialization.
+;;;;;09/18/95;
+;;;;;09/18/95; mov al, 0
+;;;;;09/18/95; xchg al, fFirstTime
+;;;;;09/18/95; or al, al
+;;;;;09/18/95; jnz initThunk
+;;;;;09/18/95
+;;;;;09/18/95 cmp cProcessAttach, 1
+;;;;;09/18/95 jne initok
+;;;;;09/18/95
+;;;;;09/18/95; This means that we've done our once only initialization before, but
+;;;;;09/18/95; that cProcessAttach went down to zero at some point and is now back
+;;;;;09/18/95; to 1. When cProcessAttach becomes 0, TapiThunkTerminate gets called
+;;;;;09/18/95; which frees up our thunk table (by calling UnRegisterCBClient). So
+;;;;;09/18/95; now we need to do that initialization again by calling TapiThunkInit.
+;;;;;09/18/95; pushd offset TapiCB32BitTable
+;;;;;09/18/95; call TapiThunkInit
+;;;;;09/18/95; jmp initok
+;;;;;09/18/95
+;;;;;09/18/95
+;;;;;09/18/95initThunk:
+;;;;;09/18/95; invoke TapiThkConnectPeerLS, ADDR pszDll16, ADDR pszDll32
+;;;;;09/18/95 or eax,eax
+;;;;;09/18/95 jz exit
+;;;;;09/18/95
+;;;;;09/18/95; Now call our first thunk to further initialize.
+;;;;;09/18/95;******************* pushd offset TapiCB32BitTable
+;;;;;09/18/95;******************* call TapiThunkInit
+;;;;;09/18/95
+;;;;;09/18/95; Initialize the flat thunks.
+;;;;;09/18/95; invoke FT_TapiFThkConnectToFlatThkPeer, ADDR pszDll16, ADDR pszDll32
+;;;;;09/18/95 or eax,eax
+;;;;;09/18/95 jz exit
+;;;;;09/18/95
+;;;;;09/18/95; Initialize the 16->32 thunks.
+;;;;;09/18/95; invoke Tapi32ConnectPeerSL, ADDR pszDll16, ADDR pszDll32
+;;;;;09/18/95 or eax,eax
+;;;;;09/18/95 jz exit
+;;;;;09/18/95
+;;;;;09/18/95 invoke NewData2
+;;;;;09/18/95 mov word ptr lp16TapiCallbackThunk+2, dx
+;;;;;09/18/95 mov word ptr lp16TapiCallbackThunk , ax
+;;;;;09/18/95
+;;;;;09/18/95 jmp initok
+;;;;;09/18/95
+;;;;;09/18/95
+;;;;;09/18/95dec_cProcess:
+
+;* pushd offset TapiCB32BitTable
+;* call TapiThunkTerminate ;needed just for UnRegisterCBClient
+
+
+;
+; Well, we know we have to get rid of all inits and thunk callbacks for
+; this process...
+;
+
+;********************************** free all the callback thunks
+; ; ; ;
+; ; ; ; Run the linked list of callbacks & free 'em all.
+; ; ; ;
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ;
+; ; ; mov ebx, LineCallbackList ; Get the line list anchor
+; ; ;
+; ; ;FreeEmAll:
+; ; ; or ebx, ebx ; At last entry?
+; ; ; jz DoneFreez ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Call lineShutdown on this behalf
+; ; ; ;
+; ; ; push ebx ; Save this - just in case
+; ; ; push [ebx+CALLBACK_HAPP] ; Push the hLineApp
+; ; ; call lineShutdown16@4 ; Shut em down.
+; ; ; pop ebx ; Get back our value.
+; ; ;
+; ; ; push [ebx+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; push ebx ; Use this before freeing it.
+; ; ;
+; ; ; mov ebx, [ebx+CALLBACK_NEXT] ; Get next node in the list.
+; ; ;
+; ; ; ;
+; ; ; ; Free the node's memory chunk.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; jmp FreeEmAll ; Do the walk of life.
+; ; ;
+; ; ;DoneFreez:
+; ; ;
+; ; ; mov LineCallbackList, 0 ; Just in case...
+; ; ;
+; ; ;
+; ; ; mov ebx, PhoneCallbackList ; Get the phone list anchor
+; ; ;FreeEmAll2:
+; ; ; or ebx, ebx ; At last entry?
+; ; ; jz DoneFreez2 ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Call phoneShutdown on this behalf
+; ; ; ;
+; ; ; push ebx ; Save this - just in case
+; ; ; push [ebx+CALLBACK_HAPP] ; Push the hPhoneApp
+; ; ; call phoneShutdown16@4
+; ; ; pop ebx ; Get back our value.
+; ; ;
+; ; ; push [ebx+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; push ebx ; Use this before freeing it.
+; ; ;
+; ; ; mov ebx, [ebx+CALLBACK_NEXT] ; Get next node in the list.
+; ; ;
+; ; ; ;
+; ; ; ; Free the node's memory chunk.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; jmp FreeEmAll2 ; Do the walk of life.
+; ; ;
+; ; ;DoneFreez2:
+; ; ;
+; ; ; mov PhoneCallbackList, 0 ; Just in case...
+; ; ;
+; ; ; pop ebx ; Get the saved value.
+
+
+
+;;;;;09/18/95 dec cProcessAttach ;Update count of attached processes.
+;;;;;09/18/95 cmp cProcessAttach, 0
+;;;;;09/18/95 jne initok
+;;;;;09/18/95
+
+;**********************************
+
+
+;
+; It would have been really cool to have implemented orthogonal thunks, but
+; that didn't happen in M7 because of time pressure and because of potential
+; destabilizing effects.
+; The load count of tapi.dll at this point is 2 (one each for the two
+; thunk scripts that we have (flat and 16-bit thunks)). So we need to
+; call FreeLibrary16 twice to make sure that tapi.dll gets unloaded after
+; this point.
+; So why does tapi.dll hang around even after the last app. that attached
+; to it is gone? Well, per AtsushiK, that's because it uses the same loading
+; technology as kernel, gdi and user. Those libraries never needed to be
+; freed, so no one ever wrote the code to free them. That means that the
+; following hack will work. What's more, it will always work.
+; ---DeepakA
+; invoke GetTapiHInst
+
+
+; invoke NewData
+; push eax
+; push eax
+; push eax
+; call FreeLibrary16
+; call FreeLibrary16
+; call FreeLibrary16
+
+
+
+initok:
+ mov eax, 1 ;return success
+exit:
+ ret
+
+
+
+
+DllEntryPoint endp
+; end DllEntryPoint
+
+
+
+
+
+
+
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;lineInitialize proc near32 lphApp:DWORD, hInstance:DWORD, lpfnCallback:DWORD, lpsAppName:DWORD, lpdwNumDevs:DWORD
+; ; ;
+; ; ; ;
+; ; ; ; First, check the code pointer
+; ; ; ;
+; ; ; push lpfnCallback ; Push the apps callback address
+; ; ; call IsBadCodePtr ; Is is a valid code pointer?
+; ; ; or eax, eax
+; ; ; jnz BadCodePointer ; Nope. Go away.
+; ; ;
+; ; ;
+; ; ; push CALLBACK_STRUCT_SIZE
+; ; ; push 42h ;(GMEM_MOVABLE + GMEM_ZEROINIT)
+; ; ; call GlobalAlloc ; Get some memory for a new node.
+; ; ; push eax
+; ; ; call GlobalLock
+; ; ;
+; ; ; or eax, eax ; Did the call fail?
+; ; ; jz No_mo_mem ; Yerp - go away.
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ;
+; ; ; push eax ; We'll need this later (newnode ptr)
+; ; ; mov ebx, eax ; We'll also be using it very soon.
+; ; ;
+; ; ; push lpfnCallback ; Save 32bit address of callback
+; ; ; push lp16TapiCallbackThunk ; 16bit callback gotten at init time
+; ; ; call AllocSLCallback ; Get a callback
+; ; ;
+; ; ; ; check return code (0 = failed)
+; ; ; or eax, eax ; Did we fail?
+; ; ; jz No_mo_callbacks ; Yes, go away.
+; ; ;
+; ; ; mov [ebx+CALLBACK_CALLBACK], eax ;Save the callback address
+; ; ;
+; ; ; push lpdwNumDevs ; Prepare to call lineInitialize
+; ; ; push lpsAppName ; Prepare to call lineInitialize
+; ; ; push eax ; Prepare to call lineInitialize
+; ; ; push hInstance ; Prepare to call lineInitialize
+; ; ; push lphApp ; Prepare to call lineInitialize
+; ; ; call lineInitialize16@20
+; ; ;
+; ; ; or eax, eax ; Did lineInit fail?
+; ; ; jnz BadReturnCode ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Now that everything went well, add the new node to the list.
+; ; ; ;
+; ; ; pop ebx ; Get the node pointer
+; ; ;
+; ; ; mov eax, LineCallbackList ; Get pointer to first node
+; ; ; mov [ebx+CALLBACK_NEXT], eax ; Fix chain
+; ; ; mov LineCallbackList, ebx ; Insert this new node as first
+; ; ;
+; ; ; mov eax, [lphApp]
+; ; ; mov eax, [eax]
+; ; ; mov [ebx+CALLBACK_HAPP], eax ; Save the hLineApp
+; ; ;
+; ; ; xor eax, eax ; Set return code (we got 0 from init).
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadReturnCode:
+; ; ; xchg [esp], eax ; Get the struct pointer
+; ; ;
+; ; ; push eax ; We're gonna use this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the callback address
+; ; ; call FreeSLCallback ; Free the thunk callback
+; ; ;
+; ; ; ;
+; ; ; ; We've already pushed eax (the newnode pointer) so we don't gotta do
+; ; ; ; it here.
+; ; ; ;
+; ; ;
+; ; ; ;
+; ; ; ; Free the newnode chunk of mem.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop eax ; Get return code.
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadCodePointer:
+; ; ; mov eax, 80000035h
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;No_mo_callbacks:
+; ; ; pop eax ; Get out struct pointer
+; ; ;
+; ; ; ; Free it.
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ;No_mo_mem:
+; ; ; mov eax, 80000044h
+; ; ; ret
+; ; ;
+; ; ;lineInitialize endp
+; ; ;
+; ; ;
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;lineShutdown proc near32 hApp:DWORD
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ; push ecx ; Be polite and save this.
+; ; ;
+; ; ; push hApp
+; ; ;
+; ; ; call lineShutdown16@4
+; ; ;
+; ; ; push eax ; Save the return code.
+; ; ;
+; ; ; ;
+; ; ; ; Run the linked list of callbacks looking for this hLineApp
+; ; ; ;
+; ; ;
+; ; ; mov eax, LineCallbackList ; Get the list anchor
+; ; ; mov ebx, offset LineCallbackList ; The previous node.
+; ; ; mov ecx, hApp ; That which we seek.
+; ; ;
+; ; ;LoopAMundo:
+; ; ; or eax, eax ; At last entry?
+; ; ; jz NotFound ; Yup. Musta not been found.
+; ; ;
+; ; ; cmp [eax+CALLBACK_HAPP], ecx ; Is this that which we seek?
+; ; ; je GotIt ; Yep - shure is.
+; ; ;
+; ; ; mov ebx, eax ; Update the "previous" pointer.
+; ; ; mov eax, [eax+CALLBACK_NEXT] ; Get next node in the list
+; ; ; jmp LoopAMundo ; Do the walk of life.
+; ; ;
+; ; ;GotIt:
+; ; ; push eax ; We're gonna need this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; ;
+; ; ; ; Now take it out of the list.
+; ; ; ;
+; ; ;
+; ; ; pop eax ; Get back the node pointer.
+; ; ;
+; ; ; push [eax+CALLBACK_NEXT] ; Get this "next" pointer.
+; ; ; pop [ebx+CALLBACK_NEXT] ; and fix the chain.
+; ; ;
+; ; ; push eax ; Push the trash node pointer
+; ; ;
+; ; ; ; Free it.
+; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ;
+; ; ;NotFound:
+; ; ; ;
+; ; ; ; How is this possible?
+; ; ; ; Oh well. We can do nothing here.
+; ; ; ;
+; ; ;
+; ; ;
+; ; ; pop eax ; Retrieve the return code.
+; ; ;
+; ; ; pop ecx ; Get the saved value.
+; ; ; pop ebx ; Get the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;lineShutdown endp
+; ; ;
+; ; ;
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;phoneInitialize proc near32 lphApp:DWORD, hInstance:DWORD, lpfnCallback:DWORD, lpsAppName:DWORD, lpdwNumDevs:DWORD
+; ; ;
+; ; ; ;
+; ; ; ; First, check the code pointer
+; ; ; ;
+; ; ; push lpfnCallback ; Push the apps callback address
+; ; ; call IsBadCodePtr ; Is is a valid code pointer?
+; ; ; or eax, eax
+; ; ; jnz BadCodePointer ; Nope. Go away.
+; ; ;
+; ; ;
+; ; ; push CALLBACK_STRUCT_SIZE
+; ; ; push 42h ;(GMEM_MOVABLE + GMEM_ZEROINIT)
+; ; ; call GlobalAlloc ; Get some memory for a new node.
+; ; ; push eax
+; ; ; call GlobalLock
+; ; ;
+; ; ; or eax, eax ; Did the call fail?
+; ; ; jz No_mo_mem ; Yerp - go away.
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ;
+; ; ; push eax ; We'll need this later (newnode ptr)
+; ; ; mov ebx, eax ; We'll also be using it very soon.
+; ; ;
+; ; ; push lpfnCallback ; Save 32bit address of callback
+; ; ; push lp16TapiCallbackThunk ; 16bit callback gotten at init time
+; ; ; call AllocSLCallback ; Get a callback
+; ; ;
+; ; ; ; check return code (0 = failed)
+; ; ; or eax, eax ; Did we fail?
+; ; ; jz No_mo_callbacks ; Yes, go away.
+; ; ;
+; ; ; mov [ebx+CALLBACK_CALLBACK], eax ;Save the callback address
+; ; ;
+; ; ; push lpdwNumDevs ; Prepare to call phoneInitialize
+; ; ; push lpsAppName ; Prepare to call phoneInitialize
+; ; ; push eax ; Prepare to call phoneInitialize
+; ; ; push hInstance ; Prepare to call phoneInitialize
+; ; ; push lphApp ; Prepare to call phoneInitialize
+; ; ; call phoneInitialize16@20
+; ; ;
+; ; ; or eax, eax ; Did phoneInit fail?
+; ; ; jnz BadReturnCode ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Now that everything went well, add the new node to the list.
+; ; ; ;
+; ; ; pop ebx ; Get the node pointer
+; ; ; mov eax, PhoneCallbackList ; Get pointer to first node
+; ; ; mov [ebx+CALLBACK_NEXT], eax ; Fix chain
+; ; ; mov PhoneCallbackList, ebx ; Insert this new node as first
+; ; ;
+; ; ; mov eax, [lphApp]
+; ; ; mov eax, [eax]
+; ; ; mov [ebx+CALLBACK_HAPP], eax ; Save the hPhoneApp
+; ; ;
+; ; ; xor eax, eax ; Set return code (we got 0 from init).
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadReturnCode:
+; ; ; xchg [esp], eax ; Get the struct pointer
+; ; ;
+; ; ; push eax ; We're gonna use this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the callback address
+; ; ; call FreeSLCallback ; Free the thunk callback
+; ; ;
+; ; ; ;
+; ; ; ; We've already pushed eax (the newnode pointer) so we don't gotta do
+; ; ; ; it here.
+; ; ; ;
+; ; ;
+; ; ; ;
+; ; ; ; Free the newnode chunk of mem.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop eax ; Get return code.
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadCodePointer:
+; ; ; mov eax, 90000035h
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;No_mo_callbacks:
+; ; ; pop eax ; Get out struct pointer
+; ; ;
+; ; ; ; Free it.
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ;No_mo_mem:
+; ; ; mov eax, 90000044h
+; ; ; ret
+; ; ;
+; ; ;phoneInitialize endp
+; ; ;
+; ; ;
+; ; ;;phoneInitialize proc near32 lphApp:DWORD, hInstance:DWORD, lpfnCallback:DWORD, lpsAppName:DWORD, lpdwNumDevs:DWORD
+; ; ;;
+; ; ;; ;
+; ; ;; ; First, check the code pointer
+; ; ;; ;
+; ; ;; push lpfnCallback
+; ; ;; call IsBadCodePtr
+; ; ;; or eax, eax
+; ; ;; jz GoodPointer
+; ; ;;
+; ; ;; mov eax, 90000035h
+; ; ;; ret
+; ; ;;
+; ; ;;GoodPointer:
+; ; ;; push lpdwNumDevs
+; ; ;; push lpsAppName
+; ; ;;
+; ; ;; push lpfnCallback
+; ; ;; push lp16TapiCallbackThunk
+; ; ;; call AllocSLCallback
+; ; ;;
+; ; ;; ; check return code (0 = failed)
+; ; ;; or eax, eax
+; ; ;; jz No_mo_callbacks
+; ; ;;
+; ; ;;
+; ; ;; mov TapiCallbackThunk, eax
+; ; ;; push eax
+; ; ;;
+; ; ;; push hInstance
+; ; ;; push lphApp
+; ; ;;
+; ; ;; call phoneInitialize16@20
+; ; ;;
+; ; ;; ret
+; ; ;;
+; ; ;;
+; ; ;;No_mo_callbacks:
+; ; ;; mov eax, 90000044h
+; ; ;; ret
+; ; ;;
+; ; ;;phoneInitialize endp
+; ; ;
+; ; ;
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;phoneShutdown proc near32 hApp:DWORD
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ; push ecx ; Be polite and save this.
+; ; ;
+; ; ; push hApp
+; ; ;
+; ; ; call phoneShutdown16@4
+; ; ;
+; ; ; push eax ; Save the return code.
+; ; ;
+; ; ; ;
+; ; ; ; Run the linked list of callbacks looking for this hPhoneApp
+; ; ; ;
+; ; ;
+; ; ; mov eax, PhoneCallbackList ; Get the list anchor
+; ; ; mov ebx, offset PhoneCallbackList ; The previous node.
+; ; ; mov ecx, hApp ; That which we seek.
+; ; ;
+; ; ;LoopAMundo:
+; ; ; or eax, eax ; At last entry?
+; ; ; jz NotFound ; Yup. Musta not been found.
+; ; ;
+; ; ; cmp [eax+CALLBACK_HAPP], ecx ; Is this that which we seek?
+; ; ; je GotIt ; Yep - shure is.
+; ; ;
+; ; ; mov ebx, eax ; Update the "previous" pointer.
+; ; ; mov eax, [eax+CALLBACK_NEXT] ; Get next node in the list
+; ; ; jmp LoopAMundo ; Do the walk of life.
+; ; ;
+; ; ;GotIt:
+; ; ; push eax ; We're gonna need this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; ;
+; ; ; ; Now take it out of the list.
+; ; ; ;
+; ; ;
+; ; ; pop eax ; Get back the node pointer.
+; ; ;
+; ; ; push [eax+CALLBACK_NEXT] ; Get this "next" pointer.
+; ; ; pop [ebx+CALLBACK_NEXT] ; and fix the chain.
+; ; ;
+; ; ; push eax ; Push the trash node pointer
+; ; ;
+; ; ; ; Free it.
+; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ;
+; ; ;NotFound:
+; ; ; ;
+; ; ; ; How is this possible?
+; ; ; ; Oh well. We can do nothing here.
+; ; ; ;
+; ; ;
+; ; ;
+; ; ; pop eax ; Retrieve the return code.
+; ; ;
+; ; ; pop ecx ; Get the saved value.
+; ; ; pop ebx ; Get the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;
+; ; ;; push hApp
+; ; ;;
+; ; ;; call phoneShutdown16@4
+; ; ;;
+; ; ;; cmp TapiCallbackThunk, 0
+; ; ;; je Dont_free_me
+; ; ;;
+; ; ;; push eax ; We're gonna need this...
+; ; ;;
+; ; ;; push TapiCallbackThunk
+; ; ;; call FreeSLCallback
+; ; ;;
+; ; ;; pop eax ; Get back our _real_ return code...
+; ; ;;
+; ; ;; mov TapiCallbackThunk, 0
+; ; ;;
+; ; ;;
+; ; ;;Dont_free_me:
+; ; ;;
+; ; ;; ret
+; ; ;;
+; ; ;phoneShutdown endp
+; ; ;
+
+
+end
+
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.def b/private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.def
new file mode 100644
index 000000000..d04cb0dd4
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.def
@@ -0,0 +1,125 @@
+LIBRARY TSP1632s
+EXETYPE WINDOWS
+PROTMODE
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD FIXED SINGLE
+
+EXPORTS
+ WEP @1 RESIDENTNAME
+ DllEntryPoint @2 RESIDENTNAME
+ LibMain @3 RESIDENTNAME
+ TapiThk_ThunkData16 @5
+ TapiFThk_ThunkData16 @6
+
+ TSPI_lineAccept @500
+ TSPI_lineAddToConference @501
+ TSPI_lineAnswer @502
+ TSPI_lineBlindTransfer @503
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineCompleteCall @506
+ TSPI_lineCompleteTransfer @507
+ TSPI_lineConditionalMediaDetection @508
+ TSPI_lineConfigDialog @509
+ TSPI_lineDevSpecific @510
+ TSPI_lineDevSpecificFeature @511
+ TSPI_lineDial @512
+ TSPI_lineDrop @513
+ TSPI_lineForward @514
+ TSPI_lineGatherDigits @515
+ TSPI_lineGenerateDigits @516
+ TSPI_lineGenerateTone @517
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetDevConfig @525
+ TSPI_lineGetExtensionID @526
+ TSPI_lineGetIcon @527
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineHold @531
+ TSPI_lineMakeCall @532
+ TSPI_lineMonitorDigits @533
+ TSPI_lineMonitorMedia @534
+ TSPI_lineMonitorTones @535
+ TSPI_lineNegotiateExtVersion @536
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_lineOpen @538
+ TSPI_linePark @539
+ TSPI_linePickup @540
+ TSPI_linePrepareAddToConference @541
+ TSPI_lineRedirect @542
+ TSPI_lineRemoveFromConference @543
+ TSPI_lineSecureCall @544
+ TSPI_lineSelectExtVersion @545
+ TSPI_lineSendUserUserInfo @546
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetCallParams @548
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetDevConfig @550
+ TSPI_lineSetMediaControl @551
+ TSPI_lineSetMediaMode @552
+ TSPI_lineSetStatusMessages @553
+ TSPI_lineSetTerminal @554
+ TSPI_lineSetupConference @555
+ TSPI_lineSetupTransfer @556
+ TSPI_lineSwapHold @557
+ TSPI_lineUncompleteCall @558
+ TSPI_lineUnhold @559
+ TSPI_lineUnpark @560
+
+ TSPI_phoneClose @561
+ TSPI_phoneConfigDialog @562
+ TSPI_phoneDevSpecific @563
+ TSPI_phoneGetButtonInfo @564
+ TSPI_phoneGetData @565
+ TSPI_phoneGetDevCaps @566
+ TSPI_phoneGetDisplay @567
+ TSPI_phoneGetExtensionID @568
+ TSPI_phoneGetGain @569
+ TSPI_phoneGetHookSwitch @570
+ TSPI_phoneGetIcon @571
+ TSPI_phoneGetID @572
+ TSPI_phoneGetLamp @573
+ TSPI_phoneGetRing @574
+ TSPI_phoneGetStatus @575
+ TSPI_phoneGetVolume @576
+ TSPI_phoneNegotiateExtVersion @577
+ TSPI_phoneNegotiateTSPIVersion @578
+ TSPI_phoneOpen @579
+ TSPI_phoneSelectExtVersion @580
+ TSPI_phoneSetButtonInfo @581
+ TSPI_phoneSetData @582
+ TSPI_phoneSetDisplay @583
+ TSPI_phoneSetGain @584
+ TSPI_phoneSetHookSwitch @585
+ TSPI_phoneSetLamp @586
+ TSPI_phoneSetRing @587
+ TSPI_phoneSetStatusMessages @588
+ TSPI_phoneSetVolume @589
+
+ TSPI_providerConfig @590
+ TSPI_providerInit @591
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerShutdown @594
+
+ TSPI_providerEnumDevices @595
+ TSPI_lineDropOnClose @596
+ TSPI_lineDropNoOwner @597
+ TSPI_providerCreateLineDevice @598
+ TSPI_providerCreatePhoneDevice @599
+ TSPI_lineSetCurrentLocation @600
+ TSPI_lineConfigDialogEdit @601
+ TSPI_lineReleaseUserUserInfo @602
+
+IMPORTS
+ C16ThkSL01 = KERNEL.631
+ ThunkConnect16 = KERNEL.651
+
+
diff --git a/private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.rc b/private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.rc
new file mode 100644
index 000000000..000e2cef3
--- /dev/null
+++ b/private/tapi/dev/sp/tsp1632/tsp1632s/tsp1632s.rc
@@ -0,0 +1,24 @@
+//
+// (c) 1995 Microsoft Corporation. All Rights Reserved.
+//
+/* Version Numbering stuff */
+
+
+#include <windows.h>
+
+// Is the following FLAG good to use for this?
+#ifdef NT_INST
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Telephony 16bit SP support"
+#define VER_INTERNALNAME_STR "16bit SP support"
+#define VER_ORIGINALFILENAME_STR "tsp1632s.tsp"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/tsp3216/dirs b/private/tapi/dev/sp/tsp3216/dirs
new file mode 100644
index 000000000..8c36543e2
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/dirs
@@ -0,0 +1,25 @@
+!IF 0
+
+Copyright (c) 1989-92 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=\
+ tsp3216s \
+ tsp3216l
diff --git a/private/tapi/dev/sp/tsp3216/makefile b/private/tapi/dev/sp/tsp3216/makefile
new file mode 100644
index 000000000..ecfd2eb63
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/makefile
@@ -0,0 +1,25 @@
+!if "$(OS)" == "Windows_NT"
+
+!else
+
+##########################################################################
+#
+# Microsoft Confidential
+# Copyright (C) Microsoft Corporation 1995
+# All Rights Reserved.
+#
+##########################################################################
+
+
+ROOT = ..\..\..\..\..
+DIR = tsp3216
+
+IS_OEM=1
+
+DIRLIST = script tsp3216l tsp3216s
+
+!include $(ROOT)\root.mk
+
+NTMAKEENV=.
+
+!endif
diff --git a/private/tapi/dev/sp/tsp3216/script/debug/makefile b/private/tapi/dev/sp/tsp3216/script/debug/makefile
new file mode 100644
index 000000000..13446470b
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/debug/makefile
@@ -0,0 +1,3 @@
+VERDIR=debug
+DEBUG=1
+!include ..\subthk.mk
diff --git a/private/tapi/dev/sp/tsp3216/script/makefile b/private/tapi/dev/sp/tsp3216/script/makefile
new file mode 100644
index 000000000..335ff8e14
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/makefile
@@ -0,0 +1,14 @@
+# THUNK Make file
+#
+#
+# Build Environment
+
+ROOT=..\..\..\..\..\..
+IS_OEM=1
+
+VERSIONLIST=debug retail
+DEFAULTVERDIR=debug
+DIR=thunk
+#.SILENT:
+!include $(ROOT)\root.mk
+
diff --git a/private/tapi/dev/sp/tsp3216/script/retail/makefile b/private/tapi/dev/sp/tsp3216/script/retail/makefile
new file mode 100644
index 000000000..b5725e6a2
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/retail/makefile
@@ -0,0 +1,3 @@
+VERDIR=retail
+RETAIL=1
+!include ..\subthk.mk
diff --git a/private/tapi/dev/sp/tsp3216/script/subthk.mk b/private/tapi/dev/sp/tsp3216/script/subthk.mk
new file mode 100644
index 000000000..421da7105
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/subthk.mk
@@ -0,0 +1,52 @@
+# THUNK Make file
+#
+#
+
+# Build Environment
+ROOT=..\..\..\..\..\..\..
+IS_OEM=1
+
+# international mode
+
+!ifdef DBCS
+FDTHK = FdThkDB
+!else
+FDTHK = FdThk
+!endif
+
+THKASM = TapiThk.asm Tapi32.asm TapiFThk.asm
+FTHKASM = TapiFThk.asm
+
+
+TARGETS= $(THKASM)
+
+
+#DEPENDNAME=..\depend.mk
+
+#!include $(ROOT)\win\core\core.mk
+
+INCLUDE =
+
+#WIN32DEV=..\..\..\..\dev
+#WINCORE=..\..
+
+THUNKCOM = $(ROOT)\dev\tools\binr\thunk.exe
+
+THUNK = $(THUNKCOM) $(THUNKOPT)
+
+!IF "$(VERDIR)" == "maxdebug" || "$(VERDIR)" == "debug"
+THUNKOPT =
+!ELSE
+THUNKOPT =
+!ENDIF
+
+
+$(THKASM) : $(THUNKCOM) ..\$(@B).thk
+ $(THUNK) -NC THUNK16B -o $(@B) ..\$(@B).thk
+
+
+TapiThk.asm TapiFThk.asm Tapi32.asm: ..\TapiThk.inc
+
+showenv:
+ set
+
diff --git a/private/tapi/dev/sp/tsp3216/script/tapi32.inc b/private/tapi/dev/sp/tsp3216/script/tapi32.inc
new file mode 100644
index 000000000..ceb07849a
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/tapi32.inc
@@ -0,0 +1,11 @@
+; Callback24 PROTO NEAR STDCALL :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
+;Callback24 PROTO NEAR STDCALL :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
+
+include thkrp.inc
+include cbcheck.inc
+include thkframe.inc
+include public.inc
+include thkmacro.inc
+
+externDef Callback24:far16
+
diff --git a/private/tapi/dev/sp/tsp3216/script/tapi32.thk b/private/tapi/dev/sp/tsp3216/script/tapi32.thk
new file mode 100644
index 000000000..14315255e
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/tapi32.thk
@@ -0,0 +1,76 @@
+/*
+ * Lzexpand APIs thunks for Win32s
+ */
+//__foldwin32sstuff __foldwin32sstuff;
+//foldstyleinitialization = true;
+
+
+enablemapdirect1632 = true;
+//flatthunks = false;
+
+#include "..\types.thk"
+
+typedef HANDLE HINSTANCE;
+typedef DWORD HTAPI;
+typedef HTAPI *LPHTAPI;
+typedef HTAPI HAPP;
+typedef HAPP HLINEAPP;
+typedef HAPP HPHONEAPP;
+typedef HAPP *LPHAPP;
+typedef HTAPI HCALL;
+typedef HCALL *LPHCALL;
+typedef HTAPI HLINE;
+typedef HLINE *LPHLINE;
+typedef HTAPI HPHONE;
+typedef HPHONE *LPHPHONE;
+typedef HICON *LPHICON;
+typedef void LINECALLBACK;
+typedef void PHONECALLBACK;
+typedef LPSTR LPCSTR;
+
+typedef HLINEAPP *LPHLINEAPP;
+typedef HPHONEAPP *LPHPHONEAPP;
+typedef LPVOID LPLINEEXTENSIONID;
+
+typedef WORD WPARAM;
+
+typedef LPVOID LPLINETRANSLATEOUTPUT; /* LP to data structure */
+typedef LPVOID LPLINETRANSLATECAPS; /* LP to data structure */
+typedef LPVOID LPLINEFORWARDLIST;
+typedef LPVOID LPLINECALLPARAMS;
+typedef LPVOID LPLINEGENERATETONE;
+typedef LPVOID LPLINEADDRESSCAPS;
+typedef LPVOID LPLINEADDRESSSTATUS;
+typedef LPVOID LPLINECALLINFO;
+typedef LPVOID LPLINECALLSTATUS;
+typedef LPVOID LPLINECALLLIST;
+typedef LPVOID LPLINEDEVCAPS;
+typedef LPVOID LPLINEDEVSTATUS;
+typedef LPVOID LPLINEMONITORTONE;
+typedef LPVOID LPVARSTRING;
+typedef LPVOID LPLINEDIALPARAMS;
+typedef LPVOID LPLINEMEDIACONTROLDIGIT;
+typedef LPVOID LPLINEMEDIACONTROLMEDIA;
+typedef LPVOID LPLINEMEDIACONTROLTONE;
+typedef LPVOID LPLINEMEDIACONTROLCALLSTATE;
+typedef LPVOID LPPHONEBUTTONINFO;
+typedef LPVOID LPPHONECAPS;
+typedef LPVOID LPPHONESTATUS;
+typedef LPVOID LPPHONEEXTENSIONID;
+typedef LPVOID LPLINECOUNTRYLIST;
+typedef LPVOID LPLINEPROVIDERLIST;
+
+
+// Thunk for callback
+BOOL _TapiCallbackThunk( HLINEAPP hDevice,
+ DWORD dwMessage,
+ DWORD dwInstance,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD cbProc32)
+{
+ target = Callback28;
+}
+
+
diff --git a/private/tapi/dev/sp/tsp3216/script/tapicbid.inc b/private/tapi/dev/sp/tsp3216/script/tapicbid.inc
new file mode 100644
index 000000000..f78b6eb64
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/tapicbid.inc
@@ -0,0 +1,17 @@
+; Callback-type id's for TAPI callbacks. All callback-type id's are
+; 32-bits long and the upper 16-bits must be set to the module's
+; Callback Client id.
+;
+; WARNING -- WARNING -- WARNING
+;
+; Win32c.dll uses the lower 16 bits of CBID's to index directly into
+; the tables stored in GDI.EXE (gdicb16.asm) and GDI32.DLL (gdicb32.asm).
+; Those tables *must* match these id's or callbacks will fail miserably.
+; Do everyone a big favor and add new id's only at the end, and never
+; change an existing id.
+;
+
+; *** 9/29/95 bjm ID_LINEINITIALIZE equ 0
+; *** 9/29/95 bjm ID_PHONEINITIALIZE equ 1
+; *** 9/29/95 bjm ID_LINESHUTDOWN equ 2
+; *** 9/29/95 bjm ID_PHONESHUTDOWN equ 3
diff --git a/private/tapi/dev/sp/tsp3216/script/tapifthk.inc b/private/tapi/dev/sp/tsp3216/script/tapifthk.inc
new file mode 100644
index 000000000..e2099aa99
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/tapifthk.inc
@@ -0,0 +1 @@
+; empty file !
diff --git a/private/tapi/dev/sp/tsp3216/script/tapifthk.thk b/private/tapi/dev/sp/tsp3216/script/tapifthk.thk
new file mode 100644
index 000000000..4630115e1
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/tapifthk.thk
@@ -0,0 +1,563 @@
+/*
+ * Lzexpand APIs thunks for Win32s
+ */
+//__foldwin32sstuff __foldwin32sstuff;
+//foldstyleinitialization = true;
+
+enablemapdirect3216 = true;
+//flatthunks = true;
+//flatthunks = false;
+
+#include "..\types.thk"
+
+typedef DWORD HTAPI;
+typedef HTAPI *LPHTAPI;
+typedef HTAPI HAPP;
+typedef HAPP *LPHAPP;
+typedef HTAPI HLINEAPP;
+typedef HTAPI HPHONEAPP;
+typedef HTAPI HCALL;
+typedef HCALL *LPHCALL;
+typedef HTAPI HLINE;
+typedef HLINE *LPHLINE;
+typedef HTAPI HPHONE;
+typedef HPHONE *LPHPHONE;
+typedef HICON *LPHICON;
+typedef LPSTR LPCSTR;
+/* LPVOID in types.thk */
+typedef LPVOID LPLINETRANSLATEOUTPUT; /* LP to data structure */
+typedef LPVOID LPLINETRANSLATECAPS; /* LP to data structure */
+typedef LPVOID LPLINEFORWARDLIST;
+typedef LPVOID LPLINECALLPARAMS;
+typedef LPVOID LPLINEGENERATETONE;
+typedef LPVOID LPLINEADDRESSCAPS;
+typedef LPVOID LPLINEADDRESSSTATUS;
+typedef LPVOID LPLINECALLINFO;
+typedef LPVOID LPLINECALLSTATUS;
+typedef LPVOID LPLINECALLLIST;
+typedef LPVOID LPLINEDEVCAPS;
+typedef LPVOID LPLINEDEVSTATUS;
+typedef LPVOID LPLINEMONITORTONE;
+typedef LPVOID LPLINEEXTENSIONID;
+typedef LPVOID LPVARSTRING;
+typedef LPVOID LPLINEDIALPARAMS;
+typedef LPVOID LPLINEMEDIACONTROLDIGIT;
+typedef LPVOID LPLINEMEDIACONTROLMEDIA;
+typedef LPVOID LPLINEMEDIACONTROLTONE;
+typedef LPVOID LPLINEMEDIACONTROLCALLSTATE;
+typedef LPVOID LPPHONEBUTTONINFO;
+typedef LPVOID LPPHONECAPS;
+typedef LPVOID LPPHONESTATUS;
+typedef LPVOID LPPHONEEXTENSIONID;
+typedef LPVOID LPLINECOUNTRYLIST;
+typedef LPVOID LPLINEPROVIDERLIST;
+
+
+//
+//
+typedef DWORD DRV_REQUESTID;
+typedef DWORD HDRVLINE;
+typedef DWORD HDRVPHONE;
+typedef DWORD HTAPICALL;
+typedef DWORD HTAPILINE;
+typedef DWORD HDRVCALL;
+typedef HDRVCALL * LPHDRVCALL;
+typedef HDRVLINE * LPHDRVLINE;
+typedef HDRVPHONE * LPHDRVPHONE;
+
+typedef DWORD HTAPIPHONE;
+
+typedef DWORD LINEEVENT;
+typedef DWORD PHONEEVENT;
+
+//typedef LPVOID ASYNC_COMPLETION;
+typedef DWORD ASYNC_COMPLETION;
+
+typedef DWORD HPROVIDER;
+typedef LPVOID TUISPIDLLCALLBACK;
+//
+//
+
+
+
+
+//UINT GetTapiHInst(void) =
+//UINT GetTapiHInst(void)
+//{}
+
+
+UINT NewData(void) =
+UINT NewData(void)
+{}
+
+UINT NewData2(void) =
+UINT NewData2(void)
+{}
+
+
+
+
+
+
+
+LONG TSPI_lineDropNoOwner( HDRVCALL hdCall) =
+LONG TSPI_lineDropNoOwner( HDRVCALL hdCall)
+{
+}
+
+LONG TSPI_lineDropOnClose( HDRVCALL hdCall) =
+LONG TSPI_lineDropOnClose( HDRVCALL hdCall)
+{
+}
+
+LONG TSPI_lineGetCallAddressID( HDRVCALL hdCall, LPDWORD lpdwAddressID) =
+LONG TSPI_lineGetCallAddressID( HDRVCALL hdCall, LPDWORD lpdwAddressID)
+{
+}
+
+LONG TSPI_lineGetExtensionID( DWORD dwDeviceID, DWORD dwTSPIVersion, LPLINEEXTENSIONID lpExtensionID) =
+LONG TSPI_lineGetExtensionID( DWORD dwDeviceID, DWORD dwTSPIVersion, LPLINEEXTENSIONID lpExtensionID)
+{
+}
+
+LONG TSPI_lineGetNumAddressIDs( HDRVLINE hdLine, LPDWORD lpdwNumAddressIDs) =
+LONG TSPI_lineGetNumAddressIDs( HDRVLINE hdLine, LPDWORD lpdwNumAddressIDs)
+{
+}
+
+LONG TSPI_lineSelectExtVersion( HDRVLINE hdLine, DWORD dwExtVersion) =
+LONG TSPI_lineSelectExtVersion( HDRVLINE hdLine, DWORD dwExtVersion)
+{
+}
+
+LONG TSPI_lineConditionalMediaDetection( HDRVLINE hdLine, DWORD dwMediaModes, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineConditionalMediaDetection( HDRVLINE hdLine, DWORD dwMediaModes, LPLINECALLPARAMS lpCallParams)
+{
+}
+
+LONG TSPI_lineSetDefaultMediaDetection( HDRVLINE hdLine, DWORD dwMediaModes) =
+LONG TSPI_lineSetDefaultMediaDetection( HDRVLINE hdLine, DWORD dwMediaModes)
+{
+}
+
+LONG TSPI_phoneGetExtensionID( DWORD dwDeviceID, DWORD dwTSPIVersion, LPPHONEEXTENSIONID lpExtensionID) =
+LONG TSPI_phoneGetExtensionID( DWORD dwDeviceID, DWORD dwTSPIVersion, LPPHONEEXTENSIONID lpExtensionID)
+{
+}
+
+LONG TSPI_phoneSelectExtVersion( HDRVPHONE hdPhone, DWORD dwExtVersion) =
+LONG TSPI_phoneSelectExtVersion( HDRVPHONE hdPhone, DWORD dwExtVersion)
+{
+}
+
+LONG TSPI_providerConfig( HWND hwndOwner, DWORD dwPermanentProviderID) =
+LONG TSPI_providerConfig( HWND hwndOwner, DWORD dwPermanentProviderID)
+{
+}
+
+LONG TSPI_providerCreateLineDevice( DWORD dwTempID, DWORD dwDeviceID) =
+LONG TSPI_providerCreateLineDevice( DWORD dwTempID, DWORD dwDeviceID)
+{
+}
+
+LONG TSPI_providerCreatePhoneDevice( DWORD dwTempID, DWORD dwDeviceID) =
+LONG TSPI_providerCreatePhoneDevice( DWORD dwTempID, DWORD dwDeviceID)
+{
+}
+
+LONG TSPI_providerEnumDevices16( DWORD dwPermanentProviderID, LPDWORD lpdwNumLines, LPDWORD lpdwNumPhones, HPROVIDER hProvider, LINEEVENT lpfnLineCreateProc, PHONEEVENT lpfnPhoneCreateProc, HWND hWnd) =
+LONG TSPI_providerEnumDevices16( DWORD dwPermanentProviderID, LPDWORD lpdwNumLines, LPDWORD lpdwNumPhones, HPROVIDER hProvider, LINEEVENT lpfnLineCreateProc, PHONEEVENT lpfnPhoneCreateProc, HWND hWnd)
+{
+}
+
+LONG TSPI_providerInit16( DWORD dwTSPIVersion, DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase, DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines, DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc) =
+LONG TSPI_providerInit16( DWORD dwTSPIVersion, DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase, DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines, DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc)
+{
+}
+
+LONG TSPI_providerInstall( TUISPIDLLCALLBACK lpfnUIDLLCallback, HWND hwndOwner, DWORD dwPermanentProviderID) =
+LONG TSPI_providerInstall( TUISPIDLLCALLBACK lpfnUIDLLCallback, HWND hwndOwner, DWORD dwPermanentProviderID)
+{
+}
+
+LONG TSPI_providerRemove( TUISPIDLLCALLBACK lpfnUIDLLCallback, HWND hwndOwner, DWORD dwPermanentProviderID) =
+LONG TSPI_providerRemove( TUISPIDLLCALLBACK lpfnUIDLLCallback, HWND hwndOwner, DWORD dwPermanentProviderID)
+{
+}
+
+LONG TSPI_providerShutdown16( DWORD dwTSPIVersion) =
+LONG TSPI_providerShutdown16( DWORD dwTSPIVersion)
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* Tapi Address Translation procedures */
+
+LONG TSPI_lineSetCurrentLocation (DWORD dwLocation) =
+LONG TSPI_lineSetCurrentLocation (DWORD dwLocation)
+{}
+
+
+//LONG lineSetTollList (HLINEAPP hLineApp, DWORD dwPermanentLineID, LPCSTR lpszAddressIn, DWORD dwTollListOption) =
+//LONG lineSetTollList (HLINEAPP hLineApp, DWORD dwPermanentLineID, LPCSTR lpszAddressIn, DWORD dwTollListOption)
+//{}
+
+//LONG lineTranslateAddress (HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, LPCSTR lpszAddressIn,
+// DWORD dwCard, DWORD dwTranslateOptions, LPLINETRANSLATEOUTPUT lpTranslateOutput) =
+//LONG lineTranslateAddress (HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, LPCSTR lpszAddressIn,
+// DWORD dwCard, DWORD dwTranslateOptions, LPLINETRANSLATEOUTPUT lpTranslateOutput)
+//{}
+
+//LONG lineGetTranslateCaps (HLINEAPP hLineApp, DWORD dwAPIVersion, LPLINETRANSLATECAPS lpTranslateCaps) =
+//LONG lineGetTranslateCaps (HLINEAPP hLineApp, DWORD dwAPIVersion, LPLINETRANSLATECAPS lpTranslateCaps)
+//{}
+
+
+/* Tapi function prototypes */
+
+LONG TSPI_lineAccept (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineAccept (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HDRVCALL hdConsultCall) =
+LONG TSPI_lineAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HDRVCALL hdConsultCall)
+{}
+
+LONG TSPI_lineAnswer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineAnswer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineBlindTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) =
+LONG TSPI_lineBlindTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
+{}
+
+LONG TSPI_lineClose (HDRVLINE hdLine) =
+LONG TSPI_lineClose (HDRVLINE hdLine)
+{}
+
+LONG TSPI_lineCloseCall(HDRVCALL hdCall) =
+LONG TSPI_lineCloseCall(HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_lineConfigDialogEdit(DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass, LPVOID lpDeviceConfigIn, DWORD dwSize, LPVARSTRING lpDeviceConfigOut) =
+LONG TSPI_lineConfigDialogEdit(DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass, LPVOID lpDeviceConfigIn, DWORD dwSize, LPVARSTRING lpDeviceConfigOut)
+{}
+
+//LONG lineDeallocateCall (HDRVCALL hdCall) =
+//LONG lineDeallocateCall (HDRVCALL hdCall)
+//{}
+
+LONG TSPI_lineDial (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) =
+LONG TSPI_lineDial (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
+{}
+
+LONG TSPI_lineDrop (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineDrop (DWORD dwDeviceID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineGenerateDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitMode, LPCSTR lpszDigits, DWORD dwDuration) =
+LONG TSPI_lineGenerateDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitMode, LPCSTR lpszDigits, DWORD dwDuration)
+{}
+
+LONG TSPI_lineGenerateTone (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwToneMode, DWORD dwDuration,
+ DWORD dwNumTones, LPLINEGENERATETONE lpTones) =
+LONG TSPI_lineGenerateTone (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwToneMode, DWORD dwDuration,
+ DWORD dwNumTones, LPLINEGENERATETONE lpTones)
+{}
+
+LONG TSPI_lineGetAddressCaps (DWORD dwDeviceID, DWORD dwAddressID, DWORD dwAPIVersion,
+ DWORD dwExtVersion, LPLINEADDRESSCAPS lpAddressCaps) =
+LONG TSPI_lineGetAddressCaps (DWORD dwDeviceID, DWORD dwAddressID, DWORD dwAPIVersion,
+ DWORD dwExtVersion, LPLINEADDRESSCAPS lpAddressCaps)
+{}
+
+LONG TSPI_lineGetAddressID (HDRVLINE hdLine, LPDWORD lpdwAddressID, DWORD dwAddressMode, LPCSTR lpsAddress, DWORD dwSize) =
+LONG TSPI_lineGetAddressID (HDRVLINE hdLine, LPDWORD lpdwAddressID, DWORD dwAddressMode, LPCSTR lpsAddress, DWORD dwSize)
+{}
+
+LONG TSPI_lineGetAddressStatus (HDRVLINE hdLine, DWORD dwAddressID, LPLINEADDRESSSTATUS lpAddressStatus) =
+LONG TSPI_lineGetAddressStatus (HDRVLINE hdLine, DWORD dwAddressID, LPLINEADDRESSSTATUS lpAddressStatus)
+{}
+
+LONG TSPI_lineGetCallInfo (HDRVCALL hdCall, LPLINECALLINFO lpCallInfo) =
+LONG TSPI_lineGetCallInfo (HDRVCALL hdCall, LPLINECALLINFO lpCallInfo)
+{}
+
+LONG TSPI_lineGetCallStatus (HDRVCALL hdCall, LPLINECALLSTATUS lpCallStatus) =
+LONG TSPI_lineGetCallStatus (HDRVCALL hdCall, LPLINECALLSTATUS lpCallStatus)
+{}
+
+//LONG lineGetConfRelatedCalls (HDRVCALL hdCall, LPLINECALLLIST lpCallList) =
+//LONG lineGetConfRelatedCalls (HDRVCALL hdCall, LPLINECALLLIST lpCallList)
+//{}
+
+LONG TSPI_lineGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPLINEDEVCAPS lpLineDevCaps) =
+LONG TSPI_lineGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPLINEDEVCAPS lpLineDevCaps)
+{}
+
+LONG TSPI_lineGetDevConfig (DWORD dwDeviceID, LPVARSTRING lpDeviceConfig, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineGetDevConfig (DWORD dwDeviceID, LPVARSTRING lpDeviceConfig, LPCSTR lpszDeviceClass)
+{}
+
+//LONG lineGetNewCalls (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwSelect, LPLINECALLLIST lpCallList) =
+//LONG lineGetNewCalls (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwSelect, LPLINECALLLIST lpCallList)
+//{}
+
+LONG TSPI_lineGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon) =
+LONG TSPI_lineGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon)
+{}
+
+LONG TSPI_lineGetID16(HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineGetID16(HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_lineGetLineDevStatus (HDRVLINE hdLine, LPLINEDEVSTATUS lpLineDevStatus) =
+LONG TSPI_lineGetLineDevStatus (HDRVLINE hdLine, LPLINEDEVSTATUS lpLineDevStatus)
+{}
+
+LONG TSPI_lineHold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineHold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineReleaseUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineReleaseUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineMonitorDigits (HDRVCALL hdCall, DWORD dwDigitModes) =
+LONG TSPI_lineMonitorDigits (HDRVCALL hdCall, DWORD dwDigitModes)
+{}
+
+LONG TSPI_lineMonitorMedia (HDRVCALL hdCall, DWORD dwMediaModes) =
+LONG TSPI_lineMonitorMedia (HDRVCALL hdCall, DWORD dwMediaModes)
+{}
+
+LONG TSPI_lineMonitorTones (HDRVCALL hdCall, DWORD dwToneListID, LPLINEMONITORTONE lpToneList, DWORD dwNumEntries) =
+LONG TSPI_lineMonitorTones (HDRVCALL hdCall, DWORD dwToneListID, LPLINEMONITORTONE lpToneList, DWORD dwNumEntries)
+{}
+
+LONG TSPI_lineNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion) =
+LONG TSPI_lineNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTsPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion)
+{}
+
+LONG TSPI_lineNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwLowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion) =
+LONG TSPI_lineNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwLowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion)
+{}
+
+LONG TSPI_lineOpen (DWORD dwDeviceID, HTAPILINE htLine, LPHDRVLINE lphdLine, DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc) =
+LONG TSPI_lineOpen (DWORD dwDeviceID, HTAPILINE htLine, LPHDRVLINE lphdLine, DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc)
+{}
+
+LONG TSPI_lineRedirect (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) =
+LONG TSPI_lineRedirect (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
+{}
+
+LONG TSPI_lineRemoveFromConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineRemoveFromConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineSecureCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineSecureCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_lineSendUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize) =
+LONG TSPI_lineSendUserUserInfo (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
+{}
+
+LONG TSPI_lineSetAppSpecific (HDRVCALL hdCall, DWORD dwAppSpecific) =
+LONG TSPI_lineSetAppSpecific (HDRVCALL hdCall, DWORD dwAppSpecific)
+{}
+
+LONG TSPI_lineSetCallParams (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwBearerMode, DWORD dwMinRate, DWORD dwMaxRate, LPLINEDIALPARAMS lpDialParams) =
+LONG TSPI_lineSetCallParams (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwBearerMode, DWORD dwMinRate, DWORD dwMaxRate, LPLINEDIALPARAMS lpDialParams)
+{}
+
+//LONG lineSetCallPrivilege (HDRVCALL hdCall, DWORD dwCallPrivilege) =
+//LONG lineSetCallPrivilege (HDRVCALL hdCall, DWORD dwCallPrivilege)
+//{}
+
+LONG TSPI_lineSetDevConfig (DWORD dwDeviceID, LPVOID lpDeviceConfig, DWORD dwSize, LPCSTR lpszDeviceClass) =
+LONG TSPI_lineSetDevConfig (DWORD dwDeviceID, LPVOID lpDeviceConfig, DWORD dwSize, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_lineSetMediaControl (HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPLINEMEDIACONTROLDIGIT lpDigitList, DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA lpMediaList, DWORD dwMediaNumEntries, LPLINEMEDIACONTROLTONE lpToneList, DWORD dwToneNumEntries, LPLINEMEDIACONTROLCALLSTATE lpCallStateList, DWORD dwCallStateNumEntries) =
+LONG TSPI_lineSetMediaControl (HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect, LPLINEMEDIACONTROLDIGIT lpDigitList, DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA lpMediaList, DWORD dwMediaNumEntries, LPLINEMEDIACONTROLTONE lpToneList, DWORD dwToneNumEntries, LPLINEMEDIACONTROLCALLSTATE lpCallStateList, DWORD dwCallStateNumEntries)
+{}
+
+LONG TSPI_lineSetMediaMode (HDRVCALL hdCall, DWORD dwMediaModes) =
+LONG TSPI_lineSetMediaMode (HDRVCALL hdCall, DWORD dwMediaModes)
+{}
+
+//LONG lineSetNumRings (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwNumRings) =
+//LONG lineSetNumRings (HDRVLINE hdLine, DWORD dwAddressID, DWORD dwNumRings)
+//{}
+
+LONG TSPI_lineSetStatusMessages (HDRVLINE hdLine, DWORD dwLineStates, DWORD dwAddressStates) =
+LONG TSPI_lineSetStatusMessages (HDRVLINE hdLine, DWORD dwLineStates, DWORD dwAddressStates)
+{}
+
+LONG TSPI_lineSetTerminal (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect,
+ DWORD dwTerminalModes, DWORD dwTerminalID, DWORD bEnable) =
+LONG TSPI_lineSetTerminal (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, DWORD dwSelect,
+ DWORD dwTerminalModes, DWORD dwTerminalID, DWORD bEnable)
+{}
+
+LONG TSPI_lineSwapHold (DRV_REQUESTID dwRequestID, HDRVCALL hdActiveCall, HDRVCALL hdHeldCall) =
+LONG TSPI_lineSwapHold (DRV_REQUESTID dwRequestID, HDRVCALL hdActiveCall, HDRVCALL hdHeldCall)
+{}
+
+LONG TSPI_lineUncompleteCall (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwCompletionID) =
+LONG TSPI_lineUncompleteCall (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwCompletionID)
+{}
+
+LONG TSPI_lineUnhold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall) =
+LONG TSPI_lineUnhold (DRV_REQUESTID dwRequestID, HDRVCALL hdCall)
+{}
+
+LONG TSPI_phoneClose (HDRVPHONE hdPhone) =
+LONG TSPI_phoneClose (HDRVPHONE hdPhone)
+{}
+
+LONG TSPI_phoneConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass) =
+LONG TSPI_phoneConfigDialog (DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_phoneGetButtonInfo (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo) =
+LONG TSPI_phoneGetButtonInfo (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo)
+{}
+
+LONG TSPI_phoneGetData (HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize) =
+LONG TSPI_phoneGetData (HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize)
+{}
+
+LONG TSPI_phoneGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPPHONECAPS lpPhoneCaps) =
+LONG TSPI_phoneGetDevCaps (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwExtVersion, LPPHONECAPS lpPhoneCaps)
+{}
+
+LONG TSPI_phoneGetDisplay (HDRVPHONE hdPhone, LPVARSTRING lpDisplay) =
+LONG TSPI_phoneGetDisplay (HDRVPHONE hdPhone, LPVARSTRING lpDisplay)
+{}
+
+LONG TSPI_phoneGetGain (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwGain) =
+LONG TSPI_phoneGetGain (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwGain)
+{}
+
+LONG TSPI_phoneGetHookSwitch (HDRVPHONE hdPhone, LPDWORD lpdwHookSwitchDevs) =
+LONG TSPI_phoneGetHookSwitch (HDRVPHONE hdPhone, LPDWORD lpdwHookSwitchDevs)
+{}
+
+LONG TSPI_phoneGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon) =
+LONG TSPI_phoneGetIcon (DWORD dwDeviceID, LPCSTR lpszDeviceClass, LPHICON lphIcon)
+{}
+
+LONG TSPI_phoneGetID16(HDRVPHONE hdPhone, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass) =
+LONG TSPI_phoneGetID16(HDRVPHONE hdPhone, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass)
+{}
+
+LONG TSPI_phoneGetLamp (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPDWORD lpdwLampMode) =
+LONG TSPI_phoneGetLamp (HDRVPHONE hdPhone, DWORD dwButtonLampID, LPDWORD lpdwLampMode)
+{}
+
+LONG TSPI_phoneGetRing (HDRVPHONE hdPhone, LPDWORD lpdwRingMode, LPDWORD lpdwVolume) =
+LONG TSPI_phoneGetRing (HDRVPHONE hdPhone, LPDWORD lpdwRingMode, LPDWORD lpdwVolume)
+{}
+
+LONG TSPI_phoneGetStatus (HDRVPHONE hdPhone, LPPHONESTATUS lpPhoneStatus) =
+LONG TSPI_phoneGetStatus (HDRVPHONE hdPhone, LPPHONESTATUS lpPhoneStatus)
+{}
+
+//LONG phoneGetStatusMessages (HDRVPHONE hdPhone, LPDWORD lpdwPhoneStates, LPDWORD lpdwButtonModes, LPDWORD lpdwButtonStates) =
+//LONG phoneGetStatusMessages (HDRVPHONE hdPhone, LPDWORD lpdwPhoneStates, LPDWORD lpdwButtonModes, LPDWORD lpdwButtonStates)
+//{}
+
+LONG TSPI_phoneGetVolume (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwVolume) =
+LONG TSPI_phoneGetVolume (HDRVPHONE hdPhone, DWORD dwHookSwitchDev, LPDWORD lpdwVolume)
+{}
+
+LONG TSPI_phoneNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion) =
+LONG TSPI_phoneNegotiateExtVersion (DWORD dwDeviceID, DWORD dwTSPIVersion, DWORD dwLowVersion,
+ DWORD dwHighVersion, LPDWORD lpdwExtVersion)
+{}
+
+LONG TSPI_phoneNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwTSPILowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion) =
+LONG TSPI_phoneNegotiateTSPIVersion (DWORD dwDeviceID, DWORD dwTSPILowVersion, DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion)
+{}
+
+LONG TSPI_phoneOpen (DWORD dwDeviceID, HTAPIPHONE htPhone, LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion, PHONEEVENT lpfnEventProc) =
+LONG TSPI_phoneOpen (DWORD dwDeviceID, HTAPIPHONE htPhone, LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion, PHONEEVENT lpfnEventProc)
+{}
+
+LONG TSPI_phoneSetButtonInfo (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo) =
+LONG TSPI_phoneSetButtonInfo (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, LPPHONEBUTTONINFO lpButtonInfo)
+{}
+
+LONG TSPI_phoneSetData (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize) =
+LONG TSPI_phoneSetData (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwDataID, LPVOID lpData, DWORD dwSize)
+{}
+
+LONG TSPI_phoneSetDisplay (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRow, DWORD dwColumn, LPCSTR lpsDisplay, DWORD dwSize) =
+LONG TSPI_phoneSetDisplay (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRow, DWORD dwColumn, LPCSTR lpsDisplay, DWORD dwSize)
+{}
+
+LONG TSPI_phoneSetGain (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwGain) =
+LONG TSPI_phoneSetGain (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwGain)
+{}
+
+LONG TSPI_phoneSetHookSwitch (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDevs, DWORD dwHookSwitchMode) =
+LONG TSPI_phoneSetHookSwitch (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDevs, DWORD dwHookSwitchMode)
+{}
+
+LONG TSPI_phoneSetLamp (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, DWORD dwLampMode) =
+LONG TSPI_phoneSetLamp (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwButtonLampID, DWORD dwLampMode)
+{}
+
+LONG TSPI_phoneSetRing (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRingMode, DWORD dwVolume) =
+LONG TSPI_phoneSetRing (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwRingMode, DWORD dwVolume)
+{}
+
+LONG TSPI_phoneSetStatusMessages (HDRVPHONE hdPhone, DWORD dwPhoneStates, DWORD dwButtonModes, DWORD dwButtonStates) =
+LONG TSPI_phoneSetStatusMessages (HDRVPHONE hdPhone, DWORD dwPhoneStates, DWORD dwButtonModes, DWORD dwButtonStates)
+{}
+
+LONG TSPI_phoneSetVolume (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwVolume) =
+LONG TSPI_phoneSetVolume (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, DWORD dwHookSwitchDev, DWORD dwVolume)
+{}
+
diff --git a/private/tapi/dev/sp/tsp3216/script/tapithk.inc b/private/tapi/dev/sp/tsp3216/script/tapithk.inc
new file mode 100644
index 000000000..63ad5baca
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/tapithk.inc
@@ -0,0 +1,1234 @@
+
+CodeData equ <THUNK16BCodeData>
+
+include thkrp.inc
+include cbcheck.inc
+include thkframe.inc
+include public.inc
+include thkmacro.inc
+;include struc.inc
+
+include cbcid.inc
+include tapicbid.inc
+
+;externDef IsBadCodePtr:far16
+externDef CALLBACK_BODY_16:far16
+externDef Escape:far16
+externDef AllocCallback:far16
+externDef MapLS:far16
+externDef UnmapLS:far16
+ifdef DEBUG
+externDef _wsprintf:far16
+externDef OutputDebugString:far16
+endif
+
+externDef FreeCallback:far16
+
+
+externDef lineInitialize:far16
+externDef phoneInitialize:far16
+externDef lineShutdown:far16
+externDef phoneShutdown:far16
+
+
+public addrCBLineInit ;Address of callback routine passed in lineInitialize
+public addrCBPhoneInit ;Address of callback routine passed in phoneInitialize
+public cbcidTapi ;Callback ID for client returned by RegisterCBClient
+_DATA SEGMENT
+addrCBLineInit dd 0
+addrCBPhoneInit dd 0
+cbcidTapi dd 0
+_DATA ENDS
+
+ifdef DEBUG
+;; Writes message to debug port.
+;;
+;; Usage:
+;; DPRINT "I'm feeling buggy."
+;;
+DPRINT macro string
+ local mes, skip_mes
+
+ jmp skip_mes
+mes db &string&,13,10,0
+skip_mes:
+ push eax ;Save all registers not preserved by PASCAL format.
+ push ebx
+ push ecx
+ push edx
+
+ push cs ;Arg: OutputDebugString(lpstr)
+ push offset mes
+ call OutputDebugString
+
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+endm ;DPRINT
+endif
+
+
+;-----------------------------------------------------------------------;
+; body_LINEINITIALIZE16
+;-----------------------------------------------------------------------;
+body_LINEINITIALIZE16 macro
+
+;LONG lineInitialize16 (LPHLINEAPP lphLineApp,
+; HINSTANCE hInstance,
+; LINECALLBACK lpfnCallback,
+; LPCSTR lpszAppName,
+; LPDWORD lpdwNumDevs)
+;
+bp_lphLineApp equ <bp_top>
+bp_hInstance equ <bp_top+4>
+bp_lpfnCallback equ <bp_top+8>
+bp_lpszAppName equ <bp_top+12>
+bp_lpdwNumDevs equ <bp_top+16>
+;
+
+bp_lpszAppNameTmp equ <dword ptr [bp-4]>
+bp_lpdwNumDevsTmp equ <dword ptr [bp-8]>
+bp_lphLineAppTmp equ <dword ptr [bp-12]>
+
+ ;
+ ; First order of business: check the code pointer. If it's
+ ; bogus, we leave.
+ ;
+
+; push dword ptr bp_lpfnCallback
+; call IsBadCodePtr
+; or eax, eax
+; jnz DoNothing
+
+ sub eax, eax
+ push eax ;bp_lpszAppNameTmp
+ push eax ;bp_lpdwNumDevsTmp
+ push eax ;bp_lphLineAppTmp
+
+ push dword ptr bp_lphLineApp
+ call MapLS
+ mov bp_lphLineAppTmp, eax
+ push eax
+
+ mov eax, dword ptr bp_hInstance ; Get the hInst
+ or eax, eax ; Is it NULL?
+ jz @f ; Yup, and that's ok.
+ MAP_NULL_HINST eax ; Needs to be mapped.
+ push ax
+
+; mov ax, seg addrCBLineInit
+; mov ds, ax
+; mov eax, dword ptr bp_lpfnCallback
+; mov addrCBLineInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_LINEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+
+ push dword ptr bp_lpfnCallback
+
+ push dword ptr bp_lpszAppName
+ call MapLS
+ mov bp_lpszAppNameTmp, eax
+ push eax
+
+ push dword ptr bp_lpdwNumDevs
+ call MapLS
+ mov bp_lpdwNumDevsTmp, eax
+ push eax
+
+
+ call lineInitialize
+
+
+ shl eax,16 ; Convert the 16bit retcode...
+ shrd eax,edx,16 ; to a 32bit retcode.
+
+ push eax ; Save the retcode for later.
+
+ push dword ptr bp_lpdwNumDevsTmp
+ call UnMapLS
+
+ push dword ptr bp_lpszAppNameTmp
+ call UnMapLS
+
+ push dword ptr bp_lphLineAppTmp
+ call UnMapLS
+
+ pop eax ; Get the retcode
+
+;DoNothing:
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_PHONEINITIALIZE
+;-----------------------------------------------------------------------;
+body_PHONEINITIALIZE16 macro
+
+;LONG phoneInitialize (LPHPHONEAPP lphPhoneApp,
+; HINSTANCE hInstance,
+; PHONECALLBACK lpfnCallback,
+; LPCSTR lpszAppName,
+; LPDWORD lpdwNumDevs)
+;
+bp_lphPhoneApp equ <bp_top>
+bp_hInstance equ <bp_top+4>
+bp_lpfnCallback equ <bp_top+8>
+bp_lpszAppName equ <bp_top+12>
+bp_lpdwNumDevs equ <bp_top+16>
+;
+
+bp_lpszAppNameTmp equ <dword ptr [bp-4]>
+bp_lpdwNumDevsTmp equ <dword ptr [bp-8]>
+bp_lphPhoneAppTmp equ <dword ptr [bp-12]>
+
+ sub eax, eax
+ push eax ;bp_lpszAppNameTmp
+ push eax ;bp_lpdwNumDevsTmp
+ push eax ;bp_lphPhoneAppTmp
+
+ push dword ptr bp_lphPhoneApp
+ call MapLS
+ mov bp_lphPhoneAppTmp, eax
+ push eax
+
+ mov eax, dword ptr bp_hInstance ; Get the hInst
+ or eax, eax ; Is it NULL?
+ jz @f ; Yup, and that's ok.
+ MAP_NULL_HINST eax ; Needs to be mapped.
+ push ax
+
+; mov ax, seg addrCBPhoneInit
+; mov ds, ax
+; mov eax, dword ptr bp_lpfnCallback
+; mov addrCBPhoneInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_PHONEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+ push dword ptr bp_lpfnCallback
+
+ push dword ptr bp_lpszAppName
+ call MapLS
+ mov bp_lpszAppNameTmp, eax
+ push eax
+
+ push dword ptr bp_lpdwNumDevs
+ call MapLS
+ mov bp_lpdwNumDevsTmp, eax
+ push eax
+
+
+ call phoneInitialize
+
+
+ shl eax,16 ; Convert the 16bit retcode...
+ shrd eax,edx,16 ; to a 32bit retcode.
+
+ push eax ; Save the retcode for later.
+
+ push dword ptr bp_lpdwNumDevsTmp
+ call UnMapLS
+
+ push dword ptr bp_lpszAppNameTmp
+ call UnMapLS
+
+ push dword ptr bp_lphPhoneAppTmp
+ call UnMapLS
+
+ pop eax ; Get the retcode
+
+endm
+
+
+;-----------------------------------------------------------------------;
+;-----------------------------------------------------------------------;
+;PUSH__LINEINITIALIZE_hInstance macro iOffset, iJunk
+; local Null_OK
+;
+; mov eax, [bp+iOffset] ;;Allow NULL to be passed here (for now)
+; or eax, eax
+; jz Null_OK
+; MAP_NULL_HINST eax
+;Null_OK:
+; push ax
+;
+;endm ;PUSH__LINEINITIALIZE_hInstance
+;
+;
+;-----------------------------------------------------------------------;
+;-----------------------------------------------------------------------;
+;PUSH__PHONEINITIALIZE_hInstance macro iOffset, iJunk
+; local Null_OK
+;
+; mov eax, [bp+iOffset] ;;Allow NULL to be passed here (for now)
+; or eax, eax
+; jz Null_OK
+; MAP_NULL_HINST eax
+;Null_OK:
+; push ax
+;
+;endm ;PUSH__PHONEINITIALIZE_hInstance
+;
+;
+;;-----------------------------------------------------------------------;
+;; PUSH__LINEINITIALIZE_lpfnCallback (similar to PUSH_SetAbortProc_pfnAbort)
+;;-----------------------------------------------------------------------;
+;PUSH__LINEINITIALIZE_lpfnCallback macro iOffset, iTempOffset
+;; assume ds:DATA16
+;
+; mov ax, seg addrCBLineInit
+; mov ds, ax
+;
+; mov eax, dword ptr [bp+iOffset]
+; mov addrCBLineInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_LINEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+;endm
+;
+;
+;-----------------------------------------------------------------------;
+; PUSH__PHONEINITIALIZE_lpfnCallback
+;-----------------------------------------------------------------------;
+;PUSH__PHONEINITIALIZE_lpfnCallback macro iOffset, iTempOffset
+; assume ds:DATA16
+; mov ax, seg addrCBPhoneInit
+; mov ds, ax
+;
+; mov eax, dword ptr [bp+iOffset]
+; mov addrCBPhoneInit, eax
+; push eax
+; mov eax, cbcidTapi
+; shl eax, 16
+; add eax, ID_PHONEINITIALIZE
+; push eax
+; call AllocCallback
+; push dx
+; push ax
+;endm
+
+
+;==============================================================================
+; local macro, free resources allocated for a call-back function
+; check if it is a NULL pointer before calling FreeCallBack.
+; eax contains the 32-bit address of the mapped call-back function
+; ecx contains the callback ID ((cbcidTapi << 16) + ID[PHONE/LINE]INITIALIZE)
+;==============================================================================
+;FREE_CALLBACK_TAPI macro
+; local done
+;
+; or eax,eax
+; jz done ;don't process NULL pointers
+;
+; push bx ;save BX
+; push es ;save ES
+;
+; push eax ;32-bit callback address
+; push ecx
+; call FreeCallback
+;
+; pop es ;restore ES
+; pop bx ;restore BX
+;done:
+;endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINESHUTDOWN
+; Use FREE_CALLBACK instead of directly calling FreeCallback so that we
+; check for NULL pointers.
+;-----------------------------------------------------------------------;
+body_LINESHUTDOWN16 macro
+bp_hLineApp equ <bp_top>
+; assume ds:DATA16
+ mov ax, seg addrCBLineInit
+ mov ds, ax
+
+ mov eax, dword ptr bp_hLineApp
+ push eax
+ifdef DEBUG
+ int 3
+endif
+ call lineShutdown
+
+; return code long --> long
+ rol eax,16
+ xchg ax,dx
+ rol eax,16
+
+; push eax ;; Save
+; push ecx ;; Save
+;
+; mov eax, addrCBLineInit
+;
+; mov ecx, cbcidTapi
+; shl ecx, 16
+; add ecx, ID_LINEINITIALIZE
+;
+; FREE_CALLBACK_TAPI
+;
+; pop ecx
+; pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_PHONESHUTDOWN
+;-----------------------------------------------------------------------;
+body_PHONESHUTDOWN16 macro
+bp_hLineApp equ <bp_top>
+; assume ds:DATA16
+ mov ax, seg addrCBPhoneInit
+ mov ds, ax
+
+ mov eax, dword ptr bp_hLineApp
+ push eax
+ call phoneShutdown
+
+; return code long --> long
+ rol eax,16
+ xchg ax,dx
+ rol eax,16
+
+; push eax ;; Save it
+; push ecx ;; Save it
+;
+; mov eax, addrCBPhoneInit
+;
+; mov ecx, cbcidTapi
+; shl ecx, 16
+; add ecx, ID_PHONEINITIALIZE
+;
+; FREE_CALLBACK_TAPI
+;
+; pop ecx
+; pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEFORWARD
+;-----------------------------------------------------------------------;
+body_LINEFORWARD macro
+
+bp_hLine equ <bp_top>
+bp_bAllAddresses equ <bp_top+4>
+bp_dwAddressID equ <bp_top+8>
+bp_lpForwardList equ <bp_top+12>
+bp_dwNumRingsNoAnswer equ <bp_top+16>
+bp_lphConsultCall equ <bp_top+20>
+bp_lpCallParams equ <bp_top+24>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: bAllAddresses
+; dword ptr [ebp+16]: dwAddressID
+; dword ptr [ebp+20]: lpForwardList
+; dword ptr [ebp+24]: dwNumRingsNoAnswer
+; dword ptr [ebp+28]: lphConsultCall
+; dword ptr [ebp+32]: lpCallParams
+;
+
+bp_lpForwardListTmp equ <dword ptr [bp-4]>
+bp_lphConsultCallTmp equ <dword ptr [bp-8]>
+bp_lpCallParamsTmp equ <dword ptr [bp-12]>
+
+
+ sub eax, eax
+ push eax ;bp_lpForwardListTmp
+ push eax ;bp_lphConsultCallTmp
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_bAllAddresses ;bAllAddresses: dword->dword
+ push dword ptr bp_dwAddressID ;dwAddressID: dword->dword
+ push dword ptr bp_lpForwardList
+ call MapLS
+ mov bp_lpForwardListTmp, eax
+ push eax
+ push dword ptr bp_dwNumRingsNoAnswer ;dwNumRingsNoAnswer: dword->dword
+ push dword ptr bp_lphConsultCall
+ call MapLS
+ mov bp_lphConsultCallTmp, eax
+ push eax
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineForward
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+ push dword ptr bp_lpForwardListTmp
+ call UnMapLS
+;
+; Don't UnMap lphConsultCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphConsultCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEMAKECALL
+;-----------------------------------------------------------------------;
+body_LINEMAKECALL macro
+
+bp_hLine equ <bp_top>
+bp_lphCall equ <bp_top+4>
+bp_lpszDestAddress equ <bp_top+8>
+bp_dwCountryCode equ <bp_top+12>
+bp_lpCallParams equ <bp_top+16>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: lphCall
+; dword ptr [ebp+16]: lpszDestAddress
+; dword ptr [ebp+20]: dwCountryCode
+; dword ptr [ebp+24]: lpCallParams
+;
+
+bp_lphCallTmp equ <dword ptr [bp-4]>
+bp_lpszDestAddressTmp equ <dword ptr [bp-8]>
+bp_lpCallParamsTmp equ <dword ptr [bp-12]>
+
+
+ sub eax, eax
+ push eax ;bp_lphCallTmp
+ push eax ;bp_lpszDestAddress
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_lphCall
+ call MapLS
+ mov bp_lphCallTmp, eax
+ push eax
+ push dword ptr bp_lpszDestAddress
+ call MapLS
+ mov bp_lpszDestAddressTmp, eax
+ push eax
+ push dword ptr bp_dwCountryCode ;dwCountryCode: dword->dword
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineMakeCall
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphCallTmp
+; call UnMapLS
+ push dword ptr bp_lpszDestAddressTmp
+ call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEUNPARK
+;-----------------------------------------------------------------------;
+body_LINEUNPARK macro
+
+bp_hLine equ <bp_top>
+bp_dwAddressID equ <bp_top+4>
+bp_lphCall equ <bp_top+8>
+bp_lpszDestAddress equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwAddressID
+; dword ptr [ebp+16]: lphCall
+; dword ptr [ebp+20]: lpszDestAddress
+;
+
+bp_lphCallTmp equ <dword ptr [bp-4]>
+bp_lpszDestAddressTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lphCallTmp
+ push eax ;bp_lpszDestAddress
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwCountryCode ;dwCountryCode: dword->dword
+ push dword ptr bp_lphCall
+ call MapLS
+ mov bp_lphCallTmp, eax
+ push eax
+ push dword ptr bp_lpszDestAddress
+ call MapLS
+ mov bp_lpszDestAddressTmp, eax
+ push eax
+
+ call lineUnpark
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphCallTmp
+; call UnMapLS
+ push dword ptr bp_lpszDestAddressTmp
+ call UnMapLS
+ pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEPICKUP
+;-----------------------------------------------------------------------;
+body_LINEPICKUP macro
+
+bp_hLine equ <bp_top>
+bp_dwAddressID equ <bp_top+4>
+bp_lphCall equ <bp_top+8>
+bp_lpszDestAddress equ <bp_top+12>
+bp_lpszGroupID equ <bp_top+16>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwAddressID
+; dword ptr [ebp+16]: lphCall
+; dword ptr [ebp+20]: lpszDestAddress
+; dword ptr [ebp+24]: lpszGroupID
+;
+
+bp_lphCallTmp equ <dword ptr [bp-4]>
+bp_lpszDestAddressTmp equ <dword ptr [bp-8]>
+bp_lpszGroupIDTmp equ <dword ptr [bp-12]>
+
+ sub eax, eax
+ push eax ;bp_lphCallTmp
+ push eax ;bp_lpszDestAddressTmp
+ push eax ;bp_lpszGroupIDTmp
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwAddressID ;dwAddressID: dword->dword
+ push dword ptr bp_lphCall
+ call MapLS
+ mov bp_lphCallTmp, eax
+ push eax
+ push dword ptr bp_lpszDestAddress
+ call MapLS
+ mov bp_lpszDestAddressTmp, eax
+ push eax
+ push dword ptr bp_lpszGroupID
+ call MapLS
+ mov bp_lpszGroupIDTmp, eax
+ push eax
+
+ call linePickup
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphCallTmp
+; call UnMapLS
+ push dword ptr bp_lpszDestAddressTmp
+ call UnMapLS
+ push dword ptr bp_lpszGroupIDTmp
+ call UnMapLS
+ pop eax
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINESETUPCONFERENCE
+;-----------------------------------------------------------------------;
+body_LINESETUPCONFERENCE macro
+
+bp_hCall equ <bp_top>
+bp_hLine equ <bp_top+4>
+bp_lphConfCall equ <bp_top+8>
+bp_lphConsultCall equ <bp_top+12>
+bp_dwNumParties equ <bp_top+16>
+bp_lpCallParams equ <bp_top+20>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: hLine
+; dword ptr [ebp+16]: lphConfCall
+; dword ptr [ebp+20]: lphConsultCall
+; dword ptr [ebp+24]: dwNumParties
+; dword ptr [ebp+28]: lpCallParams
+;
+
+bp_lphConfCallTmp equ <dword ptr [bp-4]>
+bp_lphConsultCallTmp equ <dword ptr [bp-8]>
+bp_lpCallParamsTmp equ <dword ptr [bp-12]>
+
+ sub eax, eax
+ push eax ;bp_lphConfCallTmp
+ push eax ;bp_lphConsultCallTmp
+ push eax ;bp_lpCallParamsTmp
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_lphConfCall
+ call MapLS
+ mov bp_lphConfCallTmp, eax
+ push eax
+ push dword ptr bp_lphConsultCall
+ call MapLS
+ mov bp_lphConsultCallTmp, eax
+ push eax
+ push dword ptr bp_dwNumParties ;dwNumParties: dword->dword
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineSetupConference
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax
+;
+; Don't UnMap lphConfCallTmp and lphConsultCallTmp: Done in tapi.dll
+; due to async read/write.
+;
+; push dword ptr bp_lphConfCallTmp
+; call UnMapLS
+; push dword ptr bp_lphConsultCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINECOMPLETETRANSFER
+;-----------------------------------------------------------------------;
+body_LINECOMPLETETRANSFER macro
+
+bp_hCall equ <bp_top>
+bp_hConsultCall equ <bp_top+4>
+bp_lphConfCall equ <bp_top+8>
+bp_dwTransferMode equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: hConsultCall
+; dword ptr [ebp+16]: lphConfCall
+; dword ptr [ebp+20]: dwTransferMode
+;
+
+bp_lphConfCallTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lphConfCallTmp
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_hConsultCall ;hConsultCall: dword->dword
+ push dword ptr bp_lphConfCall
+ call MapLS
+ mov bp_lphConfCallTmp, eax
+ push eax
+ push dword ptr bp_dwTransferMode ;dwTransferMode: dword->dword
+
+ call lineCompleteTransfer
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lphConfCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphConfCallTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEPREPAREADDTOCONFERENCE
+;-----------------------------------------------------------------------;
+body_LINEPREPAREADDTOCONFERENCE macro
+
+bp_hConfCall equ <bp_top>
+bp_lphAddCall equ <bp_top+4>
+bp_lpCallParams equ <bp_top+8>
+;
+; dword ptr [ebp+8]: hConfCall
+; dword ptr [ebp+12]: lphAddCall
+; dword ptr [ebp+16]: lpCallParams
+;
+
+bp_lphAddCallTmp equ <dword ptr [bp-4]>
+bp_lpCallParamsTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lphAddCallTmp
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hConfCall ;hConfCall: dword->dword
+ push dword ptr bp_lphAddCall
+ call MapLS
+ mov bp_lphAddCallTmp, eax
+ push eax
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call linePrepareAddToConference
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+;
+; Don't UnMap lphAddCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphAddCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINESETUPTRANSFER
+;-----------------------------------------------------------------------;
+body_LINESETUPTRANSFER macro
+
+bp_hCall equ <bp_top>
+bp_lphConsultCall equ <bp_top+4>
+bp_lpCallParams equ <bp_top+8>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: lphConsultCall
+; dword ptr [ebp+16]: lpCallParams
+;
+
+bp_lphConsultCallTmp equ <dword ptr [bp-4]>
+bp_lpCallParamsTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lphConsultCallTmp
+ push eax ;bp_lpCallParams
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_lphConsultCall
+ call MapLS
+ mov bp_lphConsultCallTmp, eax
+ push eax
+ push dword ptr bp_lpCallParams
+ call MapLS
+ mov bp_lpCallParamsTmp, eax
+ push eax
+
+ call lineSetupTransfer
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+;
+; Don't UnMap lphConsultCallTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lphConsultCallTmp
+; call UnMapLS
+ push dword ptr bp_lpCallParamsTmp
+ call UnMapLS
+ pop eax
+
+endm
+
+
+
+;-----------------------------------------------------------------------;
+; body_LINECOMPLETECALL
+;-----------------------------------------------------------------------;
+body_LINECOMPLETECALL macro
+
+bp_hCall equ <bp_top>
+bp_lpdwCompletionID equ <bp_top+4>
+bp_dwCompletionMode equ <bp_top+8>
+bp_dwMessageID equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: lpdwCompletionID
+; dword ptr [ebp+16]: dwCompletionMode
+; dword ptr [ebp+20]: dwMessageID
+;
+
+bp_lpdwCompletionIDTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lpdwCompletionID
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_lpdwCompletionID
+ call MapLS
+ mov bp_lpdwCompletionIDTmp, eax
+ push eax
+ push dword ptr bp_dwCompletionMode
+ push dword ptr bp_dwMessageID
+
+ call lineCompleteCall
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpdwCompletionIDTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpdwCompletionIDTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEDEVSPECIFIC
+;-----------------------------------------------------------------------;
+body_LINEDEVSPECIFIC macro
+
+bp_hLine equ <bp_top>
+bp_dwAddressID equ <bp_top+4>
+bp_hCall equ <bp_top+8>
+bp_lpParams equ <bp_top+12>
+bp_dwSize equ <bp_top+16>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwAddressID
+; dword ptr [ebp+16]: hCall
+; dword ptr [ebp+20]: lpParams
+; dword ptr [ebp+24]: dwSize
+;
+
+bp_lpParamsTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lpParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwAddressID ;dwAddressID: dword->dword
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_lpParams
+ call MapLS
+ mov bp_lpParamsTmp, eax
+ push eax
+ push dword ptr bp_dwSize ;dwSize: dword->dword
+
+ call lineDevSpecific
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpParams: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpParamsTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+;-----------------------------------------------------------------------;
+; body_PHONEDEVSPECIFIC
+;-----------------------------------------------------------------------;
+body_PHONEDEVSPECIFIC macro
+
+bp_hPhone equ <bp_top>
+bp_lpParams equ <bp_top+4>
+bp_dwSize equ <bp_top+8>
+;
+; dword ptr [ebp+8]: hPhone
+; dword ptr [ebp+12]: lpParams
+; dword ptr [ebp+16]: dwSize
+;
+
+;bp_lpParamsTmp equ <dword ptr [bp-4]>
+;
+ sub eax, eax
+ push eax ;bp_lpParams
+
+ push dword ptr bp_hPhone ;hPhone: dword->dword
+ push dword ptr bp_lpParams
+ call MapLS
+ mov bp_lpParamsTmp, eax
+ push eax
+ push dword ptr bp_dwSize ;dwSize: dword->dword
+
+ call phoneDevSpecific
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpParams: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpParamsTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINEDEVSPECIFICFEATURE
+;-----------------------------------------------------------------------;
+body_LINEDEVSPECIFICFEATURE macro
+
+bp_hLine equ <bp_top>
+bp_dwFeature equ <bp_top+4>
+bp_lpParams equ <bp_top+8>
+bp_dwSize equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwFeature
+; dword ptr [ebp+16]: lpParams
+; dword ptr [ebp+20]: dwSize
+;
+
+bp_lpParamsTmp equ <dword ptr [bp-4]>
+
+ sub eax, eax
+ push eax ;bp_lpParams
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwFeature ;dwFeature: dword->dword
+ push dword ptr bp_lpParams
+ call MapLS
+ mov bp_lpParamsTmp, eax
+ push eax
+ push dword ptr bp_dwSize ;dwSize: dword->dword
+
+ call lineDevSpecificFeature
+
+ shl eax,16
+ shrd eax,edx,16
+
+; push eax
+;
+; Don't UnMap lpParams: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpParamsTmp
+; call UnMapLS
+; pop eax
+
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEGATHERDIGITS
+;-----------------------------------------------------------------------;
+body_LINEGATHERDIGITS macro
+
+bp_hCall equ <bp_top>
+bp_dwDigitModes equ <bp_top+4>
+bp_lpsDigits equ <bp_top+8>
+bp_dwNumDigits equ <bp_top+12>
+bp_lpszTermDigits equ <bp_top+16>
+bp_dwFirstDigitTimeout equ <bp_top+20>
+bp_dwInterDigitTimeout equ <bp_top+24>
+;
+; dword ptr [ebp+8]: hCall
+; dword ptr [ebp+12]: dwDigitModes
+; dword ptr [ebp+16]: lpsDigits
+; dword ptr [ebp+20]: dwNumDigits
+; dword ptr [ebp+24]: lpszTerminationDigits
+; dword ptr [ebp+28]: dwFirstDigitTimeout
+; dword ptr [ebp+32]: dwInterDigitTimeout
+;
+
+bp_lpsDigitsTmp equ <dword ptr [bp-4]>
+bp_lpszTermDigitsTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lpsDigitsTmp
+ push eax ;bp_lpszTerminationDigitsTmp
+
+ push dword ptr bp_hCall ;hCall: dword->dword
+ push dword ptr bp_dwDigitModes ;dwDigitModes: dword->dword
+ push dword ptr bp_lpsDigits
+ call MapLS
+ mov bp_lpsDigitsTmp, eax
+ push eax
+ push dword ptr bp_dwNumDigits ;dwNumDigits: dword->dword
+ push dword ptr bp_lpszTermDigits
+ call MapLS
+ mov bp_lpszTermDigitsTmp, eax
+ push eax
+ push dword ptr bp_dwFirstDigitTimeout ;dwFirstDigitTimeout: dword->dword
+ push dword ptr bp_dwInterDigitTimeout ;dwInterDigitTimeout: dword->dword
+
+ call lineGatherDigits
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+;
+; Don't UnMap lpsDigits: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpsDigitsTmp
+; call UnMapLS
+ push dword ptr bp_lpszTermDigitsTmp
+ call UnMapLS
+
+ pop eax
+endm
+
+;-----------------------------------------------------------------------;
+; body_LINEPARK
+;-----------------------------------------------------------------------;
+body_LINEPARK macro
+
+bp_hLine equ <bp_top>
+bp_dwParkMode equ <bp_top+4>
+bp_lpszDirAddress equ <bp_top+8>
+bp_lpNonDirAddress equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwParkMode
+; dword ptr [ebp+16]: lpszDirAddress
+; dword ptr [ebp+20]: lpNonDirAddress
+;
+
+bp_lpszDirAddressTmp equ <dword ptr [bp-4]>
+bp_lpNonDirAddressTmp equ <dword ptr [bp-8]>
+
+ sub eax, eax
+ push eax ;bp_lpszDirAddressTmp
+ push eax ;bp_lpNonDirAddressTmp
+
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwParkMode ;dwParkMode: dworkd->dword
+ push dword ptr bp_lpszDirAddress
+ call MapLS
+ mov bp_lpszDirAddressTmp, eax
+ push eax
+ push dword ptr bp_lpNonDirAddress
+ call MapLS
+ mov bp_lpNonDirAddressTmp, eax
+ push eax
+
+ call linePark
+
+ shl eax,16
+ shrd eax,edx,16
+
+ push eax ; Save it
+
+ push dword ptr bp_lpszDirAddressTmp
+ call UnMapLS
+;
+; Don't UnMap lpNonDirAddressTmp: Done in tapi.dll due to async read/write.
+;
+; push dword ptr bp_lpNonDirAddressTmp
+; call UnMapLS
+
+ pop eax
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_TAPIREQUESTMEDIACALL
+;-----------------------------------------------------------------------;
+body_TAPIREQUESTMEDIACALL macro
+ mov eax, -16
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_TAPIREQUESTDROP
+;-----------------------------------------------------------------------;
+body_TAPIREQUESTDROP macro
+ mov eax, -16
+endm
+
+
+;-----------------------------------------------------------------------;
+; body_LINEREGISTERREQUESTRECIPIENT
+;-----------------------------------------------------------------------;
+body_LINEREGISTERREQUESTRECIPIENT macro
+
+bp_hLine equ <bp_top>
+bp_dwRegistrationInstance equ <bp_top+4>
+bp_dwRequestMode equ <bp_top+8>
+bp_dwEnable equ <bp_top+12>
+;
+; dword ptr [ebp+8]: hLine
+; dword ptr [ebp+12]: dwRegistrationInstance
+; dword ptr [ebp+16]: dwRequestMode
+; dword ptr [ebp+20]: bEnable
+;
+
+;
+; sub eax, eax
+; push eax ;bp_lpszDirAddressTmp
+; push eax ;bp_lpNonDirAddressTmp
+;
+
+;
+; If this is a 32bit app asking to register for media calls, tell 'em
+; 'e's nuts.
+;
+ test dword ptr bp_dwRequestMode, 2 ;*** *** ***Or should this be 6?
+ jz @f
+
+ifdef DEBUG
+ DPRINT "32bit apps aren't allowed to register for Media calls"
+endif
+ mov eax, 80000038h
+ jmp Done_LRRR
+
+@@:
+ push dword ptr bp_hLine ;hLine: dword->dword
+ push dword ptr bp_dwRegistrationInstance
+ push dword ptr bp_dwRequestMode
+ push dword ptr bp_dwEnable
+
+ call lineRegisterRequestRecipient
+
+ shl eax,16
+ shrd eax,edx,16
+
+Done_LRRR:
+
+endm
+
diff --git a/private/tapi/dev/sp/tsp3216/script/tapithk.thk b/private/tapi/dev/sp/tsp3216/script/tapithk.thk
new file mode 100644
index 000000000..ab7b5c3aa
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/tapithk.thk
@@ -0,0 +1,288 @@
+/*
+ * Lzexpand APIs thunks for Win32s
+ */
+//__foldwin32sstuff __foldwin32sstuff;
+//foldstyleinitialization = true; //Want this?
+
+enablemapdirect3216 = true;
+//flatthunks = true;
+//flatthunks = false;
+
+#include "..\types.thk"
+
+typedef HANDLE HINSTANCE;
+typedef DWORD HTAPI;
+typedef HTAPI *LPHTAPI;
+typedef HTAPI HAPP;
+typedef HAPP HLINEAPP;
+typedef HAPP HPHONEAPP;
+typedef HAPP *LPHAPP;
+typedef HTAPI HCALL;
+typedef HCALL *LPHCALL;
+typedef HTAPI HLINE;
+typedef HLINE *LPHLINE;
+typedef HTAPI HPHONE;
+typedef HPHONE *LPHPHONE;
+typedef HICON *LPHICON;
+typedef void LINECALLBACK;
+typedef void PHONECALLBACK;
+typedef LPSTR LPCSTR;
+
+typedef HLINEAPP *LPHLINEAPP;
+typedef HPHONEAPP *LPHPHONEAPP;
+typedef LPVOID LPLINEEXTENSIONID;
+
+typedef WORD WPARAM;
+
+typedef LPVOID LPLINETRANSLATEOUTPUT; /* LP to data structure */
+typedef LPVOID LPLINETRANSLATECAPS; /* LP to data structure */
+typedef LPVOID LPLINEFORWARDLIST;
+typedef LPVOID LPLINECALLPARAMS;
+typedef LPVOID LPLINEGENERATETONE;
+typedef LPVOID LPLINEADDRESSCAPS;
+typedef LPVOID LPLINEADDRESSSTATUS;
+typedef LPVOID LPLINECALLINFO;
+typedef LPVOID LPLINECALLSTATUS;
+typedef LPVOID LPLINECALLLIST;
+typedef LPVOID LPLINEDEVCAPS;
+typedef LPVOID LPLINEDEVSTATUS;
+typedef LPVOID LPLINEMONITORTONE;
+typedef LPVOID LPVARSTRING;
+typedef LPVOID LPLINEDIALPARAMS;
+typedef LPVOID LPLINEMEDIACONTROLDIGIT;
+typedef LPVOID LPLINEMEDIACONTROLMEDIA;
+typedef LPVOID LPLINEMEDIACONTROLTONE;
+typedef LPVOID LPLINEMEDIACONTROLCALLSTATE;
+typedef LPVOID LPPHONEBUTTONINFO;
+typedef LPVOID LPPHONECAPS;
+typedef LPVOID LPPHONESTATUS;
+typedef LPVOID LPPHONEEXTENSIONID;
+typedef LPVOID LPLINECOUNTRYLIST;
+typedef LPVOID LPLINEPROVIDERLIST;
+
+
+typedef DWORD HDRV_REQUESTID;
+typedef DWORD DRV_REQUESTID;
+typedef DWORD HDRVLINE;
+typedef DWORD HDRVPHONE;
+typedef DWORD HTAPICALL;
+typedef DWORD HTAPILINE;
+typedef DWORD HDRVCALL;
+typedef HDRVCALL * LPHDRVCALL;
+typedef HDRVLINE * LPHDRVLINE;
+typedef HDRVPHONE * LPHDRVPHONE;
+
+typedef DWORD HTAPIPHONE;
+
+typedef DWORD LINEEVENT;
+typedef DWORD PHONEEVENT;
+
+
+//not in the TSPI house! /* Simple Telephony prototypes */
+//not in the TSPI house!
+//not in the TSPI house! LONG tapiRequestMakeCall (LPSTR lpszDestAddress, LPSTR lpszAppName, LPSTR lpszCalledParty, LPSTR lpszComment) =
+//not in the TSPI house! LONG tapiRequestMakeCall(LPSTR lpszDestAddress, LPSTR lpszAppName, LPSTR lpszCalledParty, LPSTR lpszComment)
+//not in the TSPI house! {
+//not in the TSPI house! }
+//not in the TSPI house!
+//not in the TSPI house! LONG tapiRequestMediaCall (HWND hWnd, WORD wRequestID, LPCSTR lpszDeviceClass, LPCSTR lpDeviceID, DWORD dwSize,
+//not in the TSPI house! DWORD dwSecure, LPCSTR lpszDestAddress, LPCSTR lpszAppName, LPCSTR lpszCalledParty, LPCSTR lpszComment) =
+//not in the TSPI house! LONG tapiRequestMediaCall (HWND hWnd, WORD wRequestID, LPCSTR lpszDeviceClass, LPCSTR lpDeviceID, DWORD dwSize,
+//not in the TSPI house! DWORD dwSecure, LPCSTR lpszDestAddress, LPCSTR lpszAppName, LPCSTR lpszCalledParty, LPCSTR lpszComment)
+//not in the TSPI house! {
+//not in the TSPI house! //BJM 10/25/95 temporary... body = special;
+//not in the TSPI house! }
+//not in the TSPI house!
+//not in the TSPI house! LONG tapiRequestDrop (HWND hWnd, WPARAM wRequestID) =
+//not in the TSPI house! LONG tapiRequestDrop (HWND hWnd, WPARAM wRequestID)
+//not in the TSPI house! {
+//not in the TSPI house! //BJM 10/25/95 temporary... body = special;
+//not in the TSPI house! }
+//not in the TSPI house!
+//not in the TSPI house! //LONG tapiGetLocationInfo(LPSTR lpszCountryCode, LPSTR lpszCityCode) =
+//not in the TSPI house! //LONG tapiGetLocationInfo(LPSTR lpszCountryCode, LPSTR lpszCityCode)
+//not in the TSPI house! //{}
+//not in the TSPI house!
+//not in the TSPI house!
+//not in the TSPI house! /* Other TAPI functions */
+//not in the TSPI house! /*
+//not in the TSPI house! // hInstance = push;
+//not in the TSPI house! // lpfnCallback = push;
+//not in the TSPI house! LONG lineInitialize16 (LPHDRVLINEAPP lphdLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback,
+//not in the TSPI house! LPCSTR lpszAppName, LPDWORD lpdwNumDevs) =
+//not in the TSPI house! LONG lineInitialize16 (LPHDRVLINEAPP lphdLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback,
+//not in the TSPI house! LPCSTR lpszAppName, LPDWORD lpdwNumDevs)
+//not in the TSPI house! {
+//not in the TSPI house! //BJM 10/25/95 temporary... body = special;
+//not in the TSPI house! }
+//not in the TSPI house!
+//not in the TSPI house!
+//not in the TSPI house! LONG lineShutdown16 (HDRVLINEAPP hdLineApp) =
+//not in the TSPI house! LONG lineShutdown16 (HDRVLINEAPP hdLineApp)
+//not in the TSPI house! {
+//BJM 10/25/95 temporary... body = special;
+//not in the TSPI house! }
+//not in the TSPI house!
+//not in the TSPI house!
+//not in the TSPI house! // hInstance = push;
+//not in the TSPI house! // lpfnCallback = push;
+//not in the TSPI house! LONG phoneInitialize16 (LPHDRVPHONEAPP lphdPhoneApp, HINSTANCE hInstance, PHONECALLBACK lpfnCallback,
+//not in the TSPI house! LPCSTR lpszAppName, LPDWORD lpdwNumDevs) =
+//not in the TSPI house! LONG phoneInitialize16 (LPHDRVPHONEAPP lphdPhoneApp, HINSTANCE hInstance, PHONECALLBACK lpfnCallback,
+//not in the TSPI house! LPCSTR lpszAppName, LPDWORD lpdwNumDevs)
+//not in the TSPI house! {
+//not in the TSPI house! //BJM 10/25/95 temporary... body = special;
+//not in the TSPI house! }
+//not in the TSPI house!
+//not in the TSPI house! LONG phoneShutdown16 (HDRVPHONEAPP hdPhoneApp) =
+//not in the TSPI house! LONG phoneShutdown16 (HDRVPHONEAPP hdPhoneApp)
+//not in the TSPI house! {
+//not in the TSPI house! //BJM 10/25/95 temporary... body = special;
+//not in the TSPI house! }
+//not in the TSPI house! */
+
+
+
+
+
+
+
+LONG TSPI_lineForward (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD bAllAddresses, DWORD dwAddressID, LPLINEFORWARDLIST lpForwardList,
+ DWORD dwNumRingsNoAnswer, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineForward (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD bAllAddresses, DWORD dwAddressID, LPLINEFORWARDLIST lpForwardList,
+ DWORD dwNumRingsNoAnswer, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineMakeCall16 (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineMakeCall16 (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, DWORD dwCountryCode, LPLINECALLPARAMS lpCallParams)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineUnpark (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress) =
+LONG TSPI_lineUnpark (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_linePickup (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, LPCSTR lpszGroupID) =
+LONG TSPI_linePickup (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HTAPICALL htCall, LPHDRVCALL lphdCall, LPCSTR lpszDestAddress, LPCSTR lpszGroupID)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineSetupConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVLINE hdLine, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineSetupConference (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVLINE hdLine, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties, LPLINECALLPARAMS lpCallParams)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineCompleteTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVCALL hdConsultCall, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, DWORD dwTransferMode) =
+LONG TSPI_lineCompleteTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HDRVCALL hdConsultCall, HTAPICALL htConfCall, LPHDRVCALL lphdConfCall, DWORD dwTransferMode)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_linePrepareAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_linePrepareAddToConference (DRV_REQUESTID dwRequestID, HDRVCALL hdConfCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineSetupTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams) =
+LONG TSPI_lineSetupTransfer (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, HTAPICALL htConsultCall, LPHDRVCALL lphdConsultCall, LPLINECALLPARAMS lpCallParams)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineCompleteCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPDWORD lpdwCompletionID, DWORD dwCompletionMode, DWORD dwMessageID) =
+LONG TSPI_lineCompleteCall (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, LPDWORD lpdwCompletionID, DWORD dwCompletionMode, DWORD dwMessageID)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineDevSpecific (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, LPVOID lpParams, DWORD dwSize) =
+LONG TSPI_lineDevSpecific (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwAddressID, HDRVCALL hdCall, LPVOID lpParams, DWORD dwSize)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineDevSpecificFeature (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwFeature, LPVOID lpParams, DWORD dwSize) =
+LONG TSPI_lineDevSpecificFeature (DRV_REQUESTID dwRequestID, HDRVLINE hdLine, DWORD dwFeature, LPVOID lpParams, DWORD dwSize)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_lineGatherDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitModes, LPSTR lpsDigits, DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits, DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout) =
+LONG TSPI_lineGatherDigits (HDRVCALL hdCall, DWORD dwEndToEndID, DWORD dwDigitModes, LPSTR lpsDigits, DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits, DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+LONG TSPI_linePark (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwParkMode, LPCSTR lpszDirAddress, LPVARSTRING lpNonDirAddress) =
+LONG TSPI_linePark (DRV_REQUESTID dwRequestID, HDRVCALL hdCall, DWORD dwParkMode, LPCSTR lpszDirAddress, LPVARSTRING lpNonDirAddress)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+
+
+
+LONG TSPI_phoneDevSpecific (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, LPVOID lpParams, DWORD dwSize) =
+LONG TSPI_phoneDevSpecific (DRV_REQUESTID dwRequestID, HDRVPHONE hdPhone, LPVOID lpParams, DWORD dwSize)
+{
+//BJM 10/25/95 temporary... body = special;
+}
+
+
+
+//*
+//*
+//* /* Private API: TAPI32 must run this thunk to clean up our act.
+//* *
+//* * We declare pCB32Tab as DWORD, not POINTER. We want the linear
+//* * address passed thru untouched.
+//* */
+//* VOID TapiThunkInit(DWORD pCB32Tab) =
+//* VOID TapiThunkInit(DWORD pCB32Tab)
+//* {
+//* }
+//* /* Private API: TAPI32 must run this thunk before any other.
+//* *
+//* * We declare pCB32Tab as DWORD, not POINTER. We want the linear
+//* * address passed thru untouched.
+//* */
+//* VOID TapiThunkTerminate(DWORD pCB32Tab) =
+//* VOID TapiThunkTerminate(DWORD pCB32Tab)
+//* {
+//* }
+//*
+//*
+
+
+
+
+
+
+/*
+typedef void (CALLBACK * LINECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) =
+typedef void (CALLBACK * LINECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{}
+*/
+
+
+/*
+typedef void (CALLBACK * PHONECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) =
+typedef void (CALLBACK * PHONECALLBACK) (DWORD hDevice, DWORD dwMessage, DWORD dwInstance,
+ DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{}
+*/
diff --git a/private/tapi/dev/sp/tsp3216/script/types.thk b/private/tapi/dev/sp/tsp3216/script/types.thk
new file mode 100644
index 000000000..ed9c77e85
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/script/types.thk
@@ -0,0 +1,102 @@
+typedef unsigned short USHORT;
+typedef short SHORT;
+typedef unsigned long ULONG;
+typedef long LONG;
+typedef unsigned int UINT;
+typedef int INT;
+typedef unsigned char UCHAR;
+
+typedef void VOID;
+typedef void *PVOID;
+typedef void *LPVOID;
+typedef UCHAR BYTE;
+typedef USHORT WORD;
+typedef ULONG DWORD;
+typedef UINT HANDLE;
+typedef WORD HANDLE16;
+typedef DWORD HANDLE32;
+typedef int BOOL;
+typedef char *LPSTR;
+typedef BYTE *PBYTE;
+typedef BYTE *LPBYTE;
+typedef USHORT SEL;
+typedef INT *LPINT;
+typedef UINT *LPUINT;
+typedef DWORD *LPDWORD;
+typedef LONG *LPLONG;
+typedef WORD *LPWORD;
+
+typedef HANDLE HWND;
+typedef HANDLE HDC;
+typedef HANDLE HBRUSH;
+typedef HANDLE HBITMAP;
+typedef HANDLE HRGN;
+typedef HANDLE HFONT;
+typedef HANDLE HCURSOR;
+typedef HANDLE HMENU;
+typedef HANDLE HPEN;
+typedef HANDLE HICON;
+typedef HANDLE HUSER; /* vanilla user handle */
+typedef HANDLE HPALETTE;
+typedef HANDLE HMF;
+typedef HANDLE HEMF;
+typedef HANDLE HCOLORSPACE;
+typedef HANDLE HMEM;
+typedef HANDLE HGDI; /* vanilla gdi handle */
+typedef HANDLE HGLOBAL;
+typedef HANDLE HRSRC;
+typedef HANDLE HACCEL;
+
+
+typedef WORD ATOM;
+
+typedef DWORD WNDPROC; /* handled inside USER */
+
+/* HACK! have it as a pointer to type which differes between 16 and 32
+ * so InLine translation of pointers handle it correctly
+ */
+typedef int * FARPROC; /* thunk layer handles this one */
+
+
+/**********************************************/
+typedef struct tagRECT {
+ INT left;
+ INT top;
+ INT right;
+ INT bottom;
+} RECT;
+typedef RECT *LPRECT;
+
+
+typedef struct tagPOINT {
+ INT x;
+ INT y;
+} POINT;
+typedef POINT *LPPOINT;
+
+
+typedef struct tagPOINTL {
+ LONG x;
+ LONG y;
+} POINTL;
+typedef POINTL *LPPOINTL;
+
+
+typedef struct tagOFSTRUCT {
+ BYTE cBytes;
+ BYTE fFixedDisk;
+ WORD nErrorCode;
+ WORD reserved1;
+ WORD reserved2;
+ BYTE szPathName[128];
+} OFSTRUCT;
+typedef OFSTRUCT *LPOFSTRUCT;
+
+
+typedef struct tagCHARSETINFO {
+ UINT ciCharset;
+ UINT ciACP;
+ DWORD ciSigCP[2];
+ DWORD ciSigU[4];
+} CHARSETINFO;
+typedef CHARSETINFO *LPCHARSETINFO;
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/debug.c b/private/tapi/dev/sp/tsp3216/tsp3216l/debug.c
new file mode 100644
index 000000000..595700d07
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/debug.c
@@ -0,0 +1,135 @@
+//
+//
+
+#if DBG
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <tapi.h>
+#include "debug.h"
+
+
+
+extern TCHAR gszProviderKey[];
+extern DWORD gdwPermanentProviderID;
+
+
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+
+{
+ static fTSP3216lDebugLevelValid = FALSE;
+ static char buf[128] = "TSP3216l: ";
+ static DWORD TSP3216lDebugLevel = 0;
+
+ if (!fTSP3216lDebugLevelValid)
+ {
+
+ DWORD dwDataSize;
+ DWORD dwDataType;
+ HKEY hKey;
+ TCHAR KeyName[128];
+
+
+ //
+ // We determine if we should translate by simply trying to retrive a
+ // value with the name of lpszDeviceClass. If we succeed, we'll
+ // translate.
+ //
+ wsprintf(KeyName, "%s%d", gszProviderKey, gdwPermanentProviderID);
+
+
+//{
+// TCHAR buf[500];
+// wsprintf(buf, "Looking in key [%s] for it", KeyName);
+// OutputDebugString(buf);
+//}
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ KeyName,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof(TSP3216lDebugLevel);
+
+ RegQueryValueEx(
+ hKey,
+ "DebugLevel",
+ 0,
+ &dwDataType,
+ (LPVOID)&TSP3216lDebugLevel,
+ &dwDataSize
+ );
+
+ RegCloseKey( hKey );
+
+
+ if ( TSP3216lDebugLevel > 0 )
+ {
+ wsprintf(
+ &buf[10],
+ "TSP3216lDebugLevel= %d\n\r",
+ TSP3216lDebugLevel);
+
+ OutputDebugString((LPSTR)buf);
+
+ fTSP3216lDebugLevelValid = TRUE;
+ }
+
+ }
+
+
+ //
+ // Is the message otherwise "low" enough to display?
+ //
+ if (dwDbgLevel <= TSP3216lDebugLevel)
+ {
+ char buf[128] = "TSP3216l: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ wvsprintf (&buf[10],
+ lpszFormat,
+ ap
+ );
+
+ lstrcat (buf, "\n");
+
+ OutputDebugString(buf);
+
+ va_end(ap);
+ }
+
+ return;
+}
+
+#endif
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/debug.h b/private/tapi/dev/sp/tsp3216/tsp3216l/debug.h
new file mode 100644
index 000000000..11abf22ec
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/debug.h
@@ -0,0 +1,25 @@
+#if DBG
+
+
+#if !WIN32
+#define IN
+#define PUCHAR char *
+#endif
+
+
+
+#define DBGOUT(arg) DbgPrt arg
+
+extern VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/depend.mk b/private/tapi/dev/sp/tsp3216/tsp3216l/depend.mk
new file mode 100644
index 000000000..90679717a
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/depend.mk
@@ -0,0 +1,11 @@
+.\tapi32.obj: ..\..\script\$(VERDIR)\tapi32.asm
+
+.\tapithk.obj: ..\..\script\$(VERDIR)\tapithk.asm
+
+.\tapifthk.obj: ..\..\script\$(VERDIR)\tapifthk.asm
+
+.\tsp3216l.obj: ..\tsp3216l.c ..\debug.h
+
+.\debug.obj: ..\debug.c ..\debug.h
+
+.\tsp3216l.res: ..\tsp3216l.rc
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/makefile b/private/tapi/dev/sp/tsp3216/tsp3216l/makefile
new file mode 100644
index 000000000..3ad36ddab
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# tsp3216l.tsp Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/makefile.def b/private/tapi/dev/sp/tsp3216/tsp3216l/makefile.def
new file mode 100644
index 000000000..fe108c0cf
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/makefile.def
@@ -0,0 +1,56 @@
+ROOT=..\..\..\..\..\..\..
+
+IS_OEM=1
+MASM6=1
+IS_32 = 1
+WANT_C1032=1
+WIN32=1
+
+
+BUILDDLL=1
+DLLENTRY=DllEntryPoint
+
+
+DEPENDNAME=..\depend.mk
+
+TARGETS=tsp3216l.tsp tsp3216l.sym
+
+
+ALTSRCDIR=..\..\script\$(VERDIR)
+SRCDIR=..
+
+SYMDIR=.
+
+BUILD_COFF=1
+
+
+L32EXE=tsp3216l.tsp # Name of exe.
+L32DEF=..\tsp3216l.def # Our def file.
+L32MAP=tsp3216l.map # Our map file.
+L32SYM=tsp3216l.sym # Our sym file.
+L32RES=tsp3216l.res # Resource file.
+
+L32OBJS = tapi32.obj tapithk.obj tapifthk.obj tsp3216l.obj debug.obj
+
+L32LIBS= \
+ $(DEVROOT)\lib\kernel32.lib \
+ $(DEVROOT)\lib\advapi32.lib \
+ $(DEVROOT)\lib\wow32.lib \
+ $(DEVROOT)\lib\user32.lib
+
+
+L32FLAGS=-MAP
+
+!include $(ROOT)\dev\master.mk
+#!include $(ROOT)\win\win32\win32.mk
+
+
+#INCLUDE=..\..\script;$(ROOT)\win\thunk;$(INCLUDE)
+#INCLUDE=$(ROOT)\win\thunk;$(INCLUDE);.;..
+INCLUDE=..\..\tsp3216s;$(INCLUDE)
+
+CFLAGS=$(CFLAGS) -DWIN32=100 -DWIN_32=100 -Ox
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/sources b/private/tapi/dev/sp/tsp3216/tsp3216l/sources
new file mode 100644
index 000000000..e9568dcca
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/sources
@@ -0,0 +1,47 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ John Rogers (JohnRo) 25-Oct-1991
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+Revision History:
+
+!ENDIF
+
+MAJORCOMP=net
+MINORCOMP=tapi
+
+TARGETNAME=tsp3216l
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=PROGRAM
+TARGETLIBS=\nt\public\sdk\lib\*\kernel32.lib
+
+INCLUDES=..\..\..\inc;\nt\public\sdk\inc;.
+
+C_DEFINES=-DWINVER=0x0400
+
+USE_CRTDLL=1
+
+SOURCES=tsp3216l.c \
+ tsp3216l.rc
+
+UMTYPE=windows
+
+!IFNDEF 386_WARNING_LEVEL
+386_WARNING_LEVEL=/W3
+!ENDIF
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/tpiint32.old b/private/tapi/dev/sp/tsp3216/tsp3216l/tpiint32.old
new file mode 100644
index 000000000..8fbf38a3e
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/tpiint32.old
@@ -0,0 +1,760 @@
+ page ,132
+ TITLE $tapii32.asm
+ .listall
+
+ .386
+ OPTION READONLY
+ option oldstructs
+
+
+ .model FLAT
+
+
+
+; .fardata callbacks
+;.data
+CALLBACK SEGMENT PARA USE32 PUBLIC ''
+
+ public LineCallbackList
+ public PhoneCallbackList
+
+LineCallbackList dd 0
+PhoneCallbackList dd 0
+
+CALLBACK_NEXT equ 0
+CALLBACK_CALLBACK equ 4
+CALLBACK_HAPP equ 8
+CALLBACK_STRUCT_SIZE equ 0ch
+
+CALLBACK ENDS
+
+
+
+;GetpWin16Lock proto APIENTRY :ptr dword
+
+
+externDef STDCALL lineInitialize16@20:near32
+externDef STDCALL lineShutdown16@4:near32
+externDef STDCALL phoneInitialize16@20:near32
+externDef STDCALL phoneShutdown16@4:near32
+
+; ; ;IsBadCodePtr proto APIENTRY :ptr dword
+; ; ;
+; ; ;GlobalAlloc PROTO NEAR APIENTRY :DWORD, :DWORD
+; ; ;GlobalLock PROTO NEAR APIENTRY :DWORD
+; ; ;GlobalHandle PROTO NEAR APIENTRY :DWORD
+; ; ;GlobalUnlock PROTO NEAR APIENTRY :DWORD
+; ; ;GlobalFree PROTO NEAR APIENTRY :DWORD
+
+AllocSLCallback PROTO NEAR APIENTRY :DWORD, :DWORD
+FreeSLCallback PROTO NEAR APIENTRY :DWORD
+Tapi32ConnectPeerSL PROTO near pszDll16:dword, pszDll32:dword
+
+
+externDef InitThkSL :near32
+externDef FdThkCommon :near32
+
+;TapiThunkInit PROTO near pCB32Tab:dword
+;TapiThunkTerminate PROTO near pCB32Tab:dword
+
+TapiThkConnectPeerLS PROTO near pszDll16:dword, pszDll32:dword
+FT_TapiFThkConnectToFlatThkPeer proto near pszDll16:dword, pszDll32:dword
+NewData PROTO near
+NewData2 PROTO near
+FreeLibrary16 PROTO NEAR STDCALL :DWORD
+
+;* externDef TapiCB32BitTable :near32
+
+
+ .data
+
+
+lp16TapiCallbackThunk dd 0
+
+
+;
+; Pointer to the Win16 heirarchical critical section.
+;
+; public Win16Lock
+;Win16Lock dd 0
+
+
+
+pszDll16 db 'TSP3216s.DLL',0
+pszDll32 db 'TSP3216l.TSP',0
+
+
+cProcessAttach dw 0 ;Count of processes attached to our lib.
+
+
+ .code THUNK32
+
+
+
+;-----------------------------------------------------------------------;
+; Tapi DLL init routine
+; We expect lReason to be either DLL_PROCESS_ATTACH/DETACH (we take
+; action on these values) or DLL_THREAD_ATTACH/DETACH (we ignore
+; and return success). If there is anything else, we need to check
+; specifically and take appropriate action.
+;-----------------------------------------------------------------------;
+DllEntryPoint proc near32 hModule:DWORD, lReason:DWORD, lContext:DWORD
+
+
+;**** invoke GetpWin16Lock, ADDR Win16Lock
+
+ mov eax, lReason
+ or eax, eax
+ jz dec_cProcess ;DLL_PROCESS_DETACH?
+ cmp eax, 1 ;DLL_PROCESS_ATTACH?
+ jne initok ;DLL_THREAD_ATTACH/DETACH (we don't do anything)
+
+
+ inc cProcessAttach ;Keep count of how many processes attach to our lib.
+
+; Do once-only initialization.
+;
+; mov al, 0
+; xchg al, fFirstTime
+; or al, al
+; jnz initThunk
+
+ cmp cProcessAttach, 1
+ jne initok
+
+; This means that we've done our once only initialization before, but
+; that cProcessAttach went down to zero at some point and is now back
+; to 1. When cProcessAttach becomes 0, TapiThunkTerminate gets called
+; which frees up our thunk table (by calling UnRegisterCBClient). So
+; now we need to do that initialization again by calling TapiThunkInit.
+; pushd offset TapiCB32BitTable
+; call TapiThunkInit
+; jmp initok
+
+
+initThunk:
+ invoke TapiThkConnectPeerLS, ADDR pszDll16, ADDR pszDll32
+ or eax,eax
+ jz exit
+
+; Now call our first thunk to further initialize.
+;******************* pushd offset TapiCB32BitTable
+;******************* call TapiThunkInit
+
+; Initialize the flat thunks.
+ invoke FT_TapiFThkConnectToFlatThkPeer, ADDR pszDll16, ADDR pszDll32
+ or eax,eax
+ jz exit
+
+; Initialize the 16->32 thunks.
+ invoke Tapi32ConnectPeerSL, ADDR pszDll16, ADDR pszDll32
+ or eax,eax
+ jz exit
+
+ invoke NewData2
+ mov word ptr lp16TapiCallbackThunk+2, dx
+ mov word ptr lp16TapiCallbackThunk , ax
+
+ jmp initok
+
+
+dec_cProcess:
+
+;* pushd offset TapiCB32BitTable
+;* call TapiThunkTerminate ;needed just for UnRegisterCBClient
+
+
+;
+; Well, we know we have to get rid of all inits and thunk callbacks for
+; this process...
+;
+
+;********************************** free all the callback thunks
+; ; ; ;
+; ; ; ; Run the linked list of callbacks & free 'em all.
+; ; ; ;
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ;
+; ; ; mov ebx, LineCallbackList ; Get the line list anchor
+; ; ;
+; ; ;FreeEmAll:
+; ; ; or ebx, ebx ; At last entry?
+; ; ; jz DoneFreez ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Call lineShutdown on this behalf
+; ; ; ;
+; ; ; push ebx ; Save this - just in case
+; ; ; push [ebx+CALLBACK_HAPP] ; Push the hLineApp
+; ; ; call lineShutdown16@4 ; Shut em down.
+; ; ; pop ebx ; Get back our value.
+; ; ;
+; ; ; push [ebx+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; push ebx ; Use this before freeing it.
+; ; ;
+; ; ; mov ebx, [ebx+CALLBACK_NEXT] ; Get next node in the list.
+; ; ;
+; ; ; ;
+; ; ; ; Free the node's memory chunk.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; jmp FreeEmAll ; Do the walk of life.
+; ; ;
+; ; ;DoneFreez:
+; ; ;
+; ; ; mov LineCallbackList, 0 ; Just in case...
+; ; ;
+; ; ;
+; ; ; mov ebx, PhoneCallbackList ; Get the phone list anchor
+; ; ;FreeEmAll2:
+; ; ; or ebx, ebx ; At last entry?
+; ; ; jz DoneFreez2 ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Call phoneShutdown on this behalf
+; ; ; ;
+; ; ; push ebx ; Save this - just in case
+; ; ; push [ebx+CALLBACK_HAPP] ; Push the hPhoneApp
+; ; ; call phoneShutdown16@4
+; ; ; pop ebx ; Get back our value.
+; ; ;
+; ; ; push [ebx+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; push ebx ; Use this before freeing it.
+; ; ;
+; ; ; mov ebx, [ebx+CALLBACK_NEXT] ; Get next node in the list.
+; ; ;
+; ; ; ;
+; ; ; ; Free the node's memory chunk.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; jmp FreeEmAll2 ; Do the walk of life.
+; ; ;
+; ; ;DoneFreez2:
+; ; ;
+; ; ; mov PhoneCallbackList, 0 ; Just in case...
+; ; ;
+; ; ; pop ebx ; Get the saved value.
+
+
+
+ dec cProcessAttach ;Update count of attached processes.
+ cmp cProcessAttach, 0
+ jne initok
+
+
+;**********************************
+
+
+;
+; It would have been really cool to have implemented orthogonal thunks, but
+; that didn't happen in M7 because of time pressure and because of potential
+; destabilizing effects.
+; The load count of tapi.dll at this point is 2 (one each for the two
+; thunk scripts that we have (flat and 16-bit thunks)). So we need to
+; call FreeLibrary16 twice to make sure that tapi.dll gets unloaded after
+; this point.
+; So why does tapi.dll hang around even after the last app. that attached
+; to it is gone? Well, per AtsushiK, that's because it uses the same loading
+; technology as kernel, gdi and user. Those libraries never needed to be
+; freed, so no one ever wrote the code to free them. That means that the
+; following hack will work. What's more, it will always work.
+; ---DeepakA
+; invoke GetTapiHInst
+ invoke NewData
+ push eax
+ push eax
+ push eax
+ call FreeLibrary16
+ call FreeLibrary16
+ call FreeLibrary16
+
+
+
+initok:
+ mov eax, 1 ;return success
+exit:
+ ret
+
+
+
+
+DllEntryPoint endp
+; end DllEntryPoint
+
+
+
+
+
+
+
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;lineInitialize proc near32 lphApp:DWORD, hInstance:DWORD, lpfnCallback:DWORD, lpsAppName:DWORD, lpdwNumDevs:DWORD
+; ; ;
+; ; ; ;
+; ; ; ; First, check the code pointer
+; ; ; ;
+; ; ; push lpfnCallback ; Push the apps callback address
+; ; ; call IsBadCodePtr ; Is is a valid code pointer?
+; ; ; or eax, eax
+; ; ; jnz BadCodePointer ; Nope. Go away.
+; ; ;
+; ; ;
+; ; ; push CALLBACK_STRUCT_SIZE
+; ; ; push 42h ;(GMEM_MOVABLE + GMEM_ZEROINIT)
+; ; ; call GlobalAlloc ; Get some memory for a new node.
+; ; ; push eax
+; ; ; call GlobalLock
+; ; ;
+; ; ; or eax, eax ; Did the call fail?
+; ; ; jz No_mo_mem ; Yerp - go away.
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ;
+; ; ; push eax ; We'll need this later (newnode ptr)
+; ; ; mov ebx, eax ; We'll also be using it very soon.
+; ; ;
+; ; ; push lpfnCallback ; Save 32bit address of callback
+; ; ; push lp16TapiCallbackThunk ; 16bit callback gotten at init time
+; ; ; call AllocSLCallback ; Get a callback
+; ; ;
+; ; ; ; check return code (0 = failed)
+; ; ; or eax, eax ; Did we fail?
+; ; ; jz No_mo_callbacks ; Yes, go away.
+; ; ;
+; ; ; mov [ebx+CALLBACK_CALLBACK], eax ;Save the callback address
+; ; ;
+; ; ; push lpdwNumDevs ; Prepare to call lineInitialize
+; ; ; push lpsAppName ; Prepare to call lineInitialize
+; ; ; push eax ; Prepare to call lineInitialize
+; ; ; push hInstance ; Prepare to call lineInitialize
+; ; ; push lphApp ; Prepare to call lineInitialize
+; ; ; call lineInitialize16@20
+; ; ;
+; ; ; or eax, eax ; Did lineInit fail?
+; ; ; jnz BadReturnCode ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Now that everything went well, add the new node to the list.
+; ; ; ;
+; ; ; pop ebx ; Get the node pointer
+; ; ;
+; ; ; mov eax, LineCallbackList ; Get pointer to first node
+; ; ; mov [ebx+CALLBACK_NEXT], eax ; Fix chain
+; ; ; mov LineCallbackList, ebx ; Insert this new node as first
+; ; ;
+; ; ; mov eax, [lphApp]
+; ; ; mov eax, [eax]
+; ; ; mov [ebx+CALLBACK_HAPP], eax ; Save the hLineApp
+; ; ;
+; ; ; xor eax, eax ; Set return code (we got 0 from init).
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadReturnCode:
+; ; ; xchg [esp], eax ; Get the struct pointer
+; ; ;
+; ; ; push eax ; We're gonna use this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the callback address
+; ; ; call FreeSLCallback ; Free the thunk callback
+; ; ;
+; ; ; ;
+; ; ; ; We've already pushed eax (the newnode pointer) so we don't gotta do
+; ; ; ; it here.
+; ; ; ;
+; ; ;
+; ; ; ;
+; ; ; ; Free the newnode chunk of mem.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop eax ; Get return code.
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadCodePointer:
+; ; ; mov eax, 80000035h
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;No_mo_callbacks:
+; ; ; pop eax ; Get out struct pointer
+; ; ;
+; ; ; ; Free it.
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ;No_mo_mem:
+; ; ; mov eax, 80000044h
+; ; ; ret
+; ; ;
+; ; ;lineInitialize endp
+; ; ;
+; ; ;
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;lineShutdown proc near32 hApp:DWORD
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ; push ecx ; Be polite and save this.
+; ; ;
+; ; ; push hApp
+; ; ;
+; ; ; call lineShutdown16@4
+; ; ;
+; ; ; push eax ; Save the return code.
+; ; ;
+; ; ; ;
+; ; ; ; Run the linked list of callbacks looking for this hLineApp
+; ; ; ;
+; ; ;
+; ; ; mov eax, LineCallbackList ; Get the list anchor
+; ; ; mov ebx, offset LineCallbackList ; The previous node.
+; ; ; mov ecx, hApp ; That which we seek.
+; ; ;
+; ; ;LoopAMundo:
+; ; ; or eax, eax ; At last entry?
+; ; ; jz NotFound ; Yup. Musta not been found.
+; ; ;
+; ; ; cmp [eax+CALLBACK_HAPP], ecx ; Is this that which we seek?
+; ; ; je GotIt ; Yep - shure is.
+; ; ;
+; ; ; mov ebx, eax ; Update the "previous" pointer.
+; ; ; mov eax, [eax+CALLBACK_NEXT] ; Get next node in the list
+; ; ; jmp LoopAMundo ; Do the walk of life.
+; ; ;
+; ; ;GotIt:
+; ; ; push eax ; We're gonna need this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; ;
+; ; ; ; Now take it out of the list.
+; ; ; ;
+; ; ;
+; ; ; pop eax ; Get back the node pointer.
+; ; ;
+; ; ; push [eax+CALLBACK_NEXT] ; Get this "next" pointer.
+; ; ; pop [ebx+CALLBACK_NEXT] ; and fix the chain.
+; ; ;
+; ; ; push eax ; Push the trash node pointer
+; ; ;
+; ; ; ; Free it.
+; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ;
+; ; ;NotFound:
+; ; ; ;
+; ; ; ; How is this possible?
+; ; ; ; Oh well. We can do nothing here.
+; ; ; ;
+; ; ;
+; ; ;
+; ; ; pop eax ; Retrieve the return code.
+; ; ;
+; ; ; pop ecx ; Get the saved value.
+; ; ; pop ebx ; Get the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;lineShutdown endp
+; ; ;
+; ; ;
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;phoneInitialize proc near32 lphApp:DWORD, hInstance:DWORD, lpfnCallback:DWORD, lpsAppName:DWORD, lpdwNumDevs:DWORD
+; ; ;
+; ; ; ;
+; ; ; ; First, check the code pointer
+; ; ; ;
+; ; ; push lpfnCallback ; Push the apps callback address
+; ; ; call IsBadCodePtr ; Is is a valid code pointer?
+; ; ; or eax, eax
+; ; ; jnz BadCodePointer ; Nope. Go away.
+; ; ;
+; ; ;
+; ; ; push CALLBACK_STRUCT_SIZE
+; ; ; push 42h ;(GMEM_MOVABLE + GMEM_ZEROINIT)
+; ; ; call GlobalAlloc ; Get some memory for a new node.
+; ; ; push eax
+; ; ; call GlobalLock
+; ; ;
+; ; ; or eax, eax ; Did the call fail?
+; ; ; jz No_mo_mem ; Yerp - go away.
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ;
+; ; ; push eax ; We'll need this later (newnode ptr)
+; ; ; mov ebx, eax ; We'll also be using it very soon.
+; ; ;
+; ; ; push lpfnCallback ; Save 32bit address of callback
+; ; ; push lp16TapiCallbackThunk ; 16bit callback gotten at init time
+; ; ; call AllocSLCallback ; Get a callback
+; ; ;
+; ; ; ; check return code (0 = failed)
+; ; ; or eax, eax ; Did we fail?
+; ; ; jz No_mo_callbacks ; Yes, go away.
+; ; ;
+; ; ; mov [ebx+CALLBACK_CALLBACK], eax ;Save the callback address
+; ; ;
+; ; ; push lpdwNumDevs ; Prepare to call phoneInitialize
+; ; ; push lpsAppName ; Prepare to call phoneInitialize
+; ; ; push eax ; Prepare to call phoneInitialize
+; ; ; push hInstance ; Prepare to call phoneInitialize
+; ; ; push lphApp ; Prepare to call phoneInitialize
+; ; ; call phoneInitialize16@20
+; ; ;
+; ; ; or eax, eax ; Did phoneInit fail?
+; ; ; jnz BadReturnCode ; Yup, go away.
+; ; ;
+; ; ; ;
+; ; ; ; Now that everything went well, add the new node to the list.
+; ; ; ;
+; ; ; pop ebx ; Get the node pointer
+; ; ; mov eax, PhoneCallbackList ; Get pointer to first node
+; ; ; mov [ebx+CALLBACK_NEXT], eax ; Fix chain
+; ; ; mov PhoneCallbackList, ebx ; Insert this new node as first
+; ; ;
+; ; ; mov eax, [lphApp]
+; ; ; mov eax, [eax]
+; ; ; mov [ebx+CALLBACK_HAPP], eax ; Save the hPhoneApp
+; ; ;
+; ; ; xor eax, eax ; Set return code (we got 0 from init).
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadReturnCode:
+; ; ; xchg [esp], eax ; Get the struct pointer
+; ; ;
+; ; ; push eax ; We're gonna use this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the callback address
+; ; ; call FreeSLCallback ; Free the thunk callback
+; ; ;
+; ; ; ;
+; ; ; ; We've already pushed eax (the newnode pointer) so we don't gotta do
+; ; ; ; it here.
+; ; ; ;
+; ; ;
+; ; ; ;
+; ; ; ; Free the newnode chunk of mem.
+; ; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop eax ; Get return code.
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;BadCodePointer:
+; ; ; mov eax, 90000035h
+; ; ; pop ebx ; Get back the saved value.
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;No_mo_callbacks:
+; ; ; pop eax ; Get out struct pointer
+; ; ;
+; ; ; ; Free it.
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ; pop ebx ; Get back the saved value.
+; ; ;
+; ; ;No_mo_mem:
+; ; ; mov eax, 90000044h
+; ; ; ret
+; ; ;
+; ; ;phoneInitialize endp
+; ; ;
+; ; ;
+; ; ;;phoneInitialize proc near32 lphApp:DWORD, hInstance:DWORD, lpfnCallback:DWORD, lpsAppName:DWORD, lpdwNumDevs:DWORD
+; ; ;;
+; ; ;; ;
+; ; ;; ; First, check the code pointer
+; ; ;; ;
+; ; ;; push lpfnCallback
+; ; ;; call IsBadCodePtr
+; ; ;; or eax, eax
+; ; ;; jz GoodPointer
+; ; ;;
+; ; ;; mov eax, 90000035h
+; ; ;; ret
+; ; ;;
+; ; ;;GoodPointer:
+; ; ;; push lpdwNumDevs
+; ; ;; push lpsAppName
+; ; ;;
+; ; ;; push lpfnCallback
+; ; ;; push lp16TapiCallbackThunk
+; ; ;; call AllocSLCallback
+; ; ;;
+; ; ;; ; check return code (0 = failed)
+; ; ;; or eax, eax
+; ; ;; jz No_mo_callbacks
+; ; ;;
+; ; ;;
+; ; ;; mov TapiCallbackThunk, eax
+; ; ;; push eax
+; ; ;;
+; ; ;; push hInstance
+; ; ;; push lphApp
+; ; ;;
+; ; ;; call phoneInitialize16@20
+; ; ;;
+; ; ;; ret
+; ; ;;
+; ; ;;
+; ; ;;No_mo_callbacks:
+; ; ;; mov eax, 90000044h
+; ; ;; ret
+; ; ;;
+; ; ;;phoneInitialize endp
+; ; ;
+; ; ;
+; ; ;;****************************************************************************
+; ; ;;****************************************************************************
+; ; ;phoneShutdown proc near32 hApp:DWORD
+; ; ;
+; ; ; push ebx ; Be polite and save this.
+; ; ; push ecx ; Be polite and save this.
+; ; ;
+; ; ; push hApp
+; ; ;
+; ; ; call phoneShutdown16@4
+; ; ;
+; ; ; push eax ; Save the return code.
+; ; ;
+; ; ; ;
+; ; ; ; Run the linked list of callbacks looking for this hPhoneApp
+; ; ; ;
+; ; ;
+; ; ; mov eax, PhoneCallbackList ; Get the list anchor
+; ; ; mov ebx, offset PhoneCallbackList ; The previous node.
+; ; ; mov ecx, hApp ; That which we seek.
+; ; ;
+; ; ;LoopAMundo:
+; ; ; or eax, eax ; At last entry?
+; ; ; jz NotFound ; Yup. Musta not been found.
+; ; ;
+; ; ; cmp [eax+CALLBACK_HAPP], ecx ; Is this that which we seek?
+; ; ; je GotIt ; Yep - shure is.
+; ; ;
+; ; ; mov ebx, eax ; Update the "previous" pointer.
+; ; ; mov eax, [eax+CALLBACK_NEXT] ; Get next node in the list
+; ; ; jmp LoopAMundo ; Do the walk of life.
+; ; ;
+; ; ;GotIt:
+; ; ; push eax ; We're gonna need this in a sec...
+; ; ;
+; ; ; push [eax+CALLBACK_CALLBACK] ; Push the thunk thing.
+; ; ; call FreeSLCallback ; Be free...
+; ; ;
+; ; ; ;
+; ; ; ; Now take it out of the list.
+; ; ; ;
+; ; ;
+; ; ; pop eax ; Get back the node pointer.
+; ; ;
+; ; ; push [eax+CALLBACK_NEXT] ; Get this "next" pointer.
+; ; ; pop [ebx+CALLBACK_NEXT] ; and fix the chain.
+; ; ;
+; ; ; push eax ; Push the trash node pointer
+; ; ;
+; ; ; ; Free it.
+; ; ;
+; ; ; call GlobalHandle
+; ; ; push eax
+; ; ; push eax
+; ; ; call GlobalUnlock
+; ; ; call GlobalFree
+; ; ;
+; ; ;
+; ; ;NotFound:
+; ; ; ;
+; ; ; ; How is this possible?
+; ; ; ; Oh well. We can do nothing here.
+; ; ; ;
+; ; ;
+; ; ;
+; ; ; pop eax ; Retrieve the return code.
+; ; ;
+; ; ; pop ecx ; Get the saved value.
+; ; ; pop ebx ; Get the saved value.
+; ; ;
+; ; ; ret
+; ; ;
+; ; ;
+; ; ;
+; ; ;; push hApp
+; ; ;;
+; ; ;; call phoneShutdown16@4
+; ; ;;
+; ; ;; cmp TapiCallbackThunk, 0
+; ; ;; je Dont_free_me
+; ; ;;
+; ; ;; push eax ; We're gonna need this...
+; ; ;;
+; ; ;; push TapiCallbackThunk
+; ; ;; call FreeSLCallback
+; ; ;;
+; ; ;; pop eax ; Get back our _real_ return code...
+; ; ;;
+; ; ;; mov TapiCallbackThunk, 0
+; ; ;;
+; ; ;;
+; ; ;;Dont_free_me:
+; ; ;;
+; ; ;; ret
+; ; ;;
+; ; ;phoneShutdown endp
+; ; ;
+
+
+end
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.c b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.c
new file mode 100644
index 000000000..4180d8114
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.c
@@ -0,0 +1,1282 @@
+#include <windows.h>
+#include <windowsx.h>
+#include <winuser.h>
+#include <wownt32.h>
+
+#include <tapi.h>
+#include <tspi.h>
+
+#include "tsp3216.h"
+#include "debug.h"
+
+
+LONG PASCAL TapiThk_ThunkConnect32 (
+ LPSTR pszDll16,
+ LPSTR pszDll32,
+ DWORD hInstance,
+ DWORD lReason
+ );
+
+LONG PASCAL TapiFThk_ThunkConnect32 (
+ LPSTR pszDll16,
+ LPSTR pszDll32,
+ DWORD hInstance,
+ DWORD lReason
+ );
+
+LONG PASCAL Tapi32_ThunkConnect32 (
+ LPSTR pszDll16,
+ LPSTR pszDll32,
+ DWORD hInstance,
+ DWORD lReason
+ );
+
+const char pszDll16[] = "TSP3216S.DLL";
+const char pszDll32[] = "TSP3216L.TSP";
+
+
+
+//***************************************************************************
+//***************************************************************************
+enum {
+ MYMSG_STARTER = TSP3216L_MESSAGE,
+ MYMSG_PROVIDERINIT,
+ MYMSG_PROVIDERSHUTDOWN,
+ MYMSG_PROVIDERCONFIG,
+ MYMSG_LINECONFIGDIALOG,
+ MYMSG_LINECONFIGDIALOGEDIT,
+ MYMSG_PHONECONFIGDIALOG,
+ MYMSG_LINEMAKECALL
+ };
+
+
+//***************************************************************************
+DWORD cProcessAttach = 0;
+
+
+//***************************************************************************
+HWND ghWnd = NULL;
+CRITICAL_SECTION gcs;
+
+
+//***************************************************************************
+TCHAR gszProviderKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Telephony\\Providers\\Provider";
+
+DWORD gdwPermanentProviderID;
+
+
+DWORD gdwThreadParms[2];
+enum {
+ THE_HINST,
+ THE_LREASON
+ };
+
+
+
+//***************************************************************************
+LRESULT CALLBACK MyWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LPVOID TspAlloc( UINT nSize )
+{
+ return LocalAlloc( LPTR, nSize );
+}
+
+
+
+LPVOID TspFree( LPVOID p )
+{
+ return LocalFree( p );
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+void InitThunks( void )
+{
+ TapiThk_ThunkConnect32(
+ (LPSTR)pszDll16,
+ (LPSTR)pszDll32,
+ gdwThreadParms[THE_HINST],
+ gdwThreadParms[THE_LREASON]
+ );
+
+ TapiFThk_ThunkConnect32(
+ (LPSTR)pszDll16,
+ (LPSTR)pszDll32,
+ gdwThreadParms[THE_HINST],
+ gdwThreadParms[THE_LREASON]
+ );
+
+ Tapi32_ThunkConnect32(
+ (LPSTR)pszDll16,
+ (LPSTR)pszDll32,
+ gdwThreadParms[THE_HINST],
+ gdwThreadParms[THE_LREASON]
+ );
+
+ InitializeCriticalSection( &gcs );
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+
+UINT PASCAL NewData( void );
+
+
+void FreeThunks( void )
+{
+ HINSTANCE hInst;
+ hInst = (HINSTANCE)NewData();
+ FreeLibrary16( hInst );
+ FreeLibrary16( hInst );
+ FreeLibrary16( hInst );
+
+
+ DeleteCriticalSection( &gcs );
+
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+DWORD WINAPI TheUIThread( LPVOID lpThreadParameter )
+{
+ MSG msg;
+
+ WNDCLASS wndclass = {
+ 0,
+ MyWndProc,
+ 0,
+ 0,
+ (HANDLE)gdwThreadParms[THE_HINST],
+ 0,
+ 0,
+ 0,
+ 0,
+ "Tsp3216LWindowClass"
+ };
+
+
+DBGOUT((2, "The UI thread"));
+
+
+ //
+ // We need _another_ goddamn window.
+ //
+
+ RegisterClass( &wndclass );
+
+ ghWnd = CreateWindow(
+ "Tsp3216LWindowClass",
+ "Tsp3216LWindow",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ (HANDLE)gdwThreadParms[THE_HINST],
+ NULL
+ );
+
+
+DBGOUT((2, "Starting message loop in ui thread"));
+
+ while (GetMessage(&msg, 0, 0, 0) != 0)
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+DBGOUT((2, "Done message loop in ui thread"));
+
+ ghWnd = NULL;
+
+ return (msg.wParam);
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG WINAPI DllEntryPoint(
+ DWORD hModule,
+ DWORD lReason,
+ DWORD lContext
+ )
+{
+
+
+DBGOUT((2, "Entering DllEntryPoint reason=0x%08lx", lReason));
+
+
+ switch ( lReason )
+ {
+ case 0:
+ {
+#if DBG
+{
+TCHAR cName[MAX_PATH];
+TCHAR buf[256];
+GetModuleFileName( NULL, cName, MAX_PATH);
+wsprintf(buf, "DllEntryPoint - 0 process detach [%s]\r\n", cName);
+OutputDebugString(buf);
+}
+#endif
+
+
+ FreeThunks();
+ }
+ break;
+
+
+
+ case 1:
+ {
+#if DBG
+{
+TCHAR cName[MAX_PATH];
+TCHAR buf[256];
+GetModuleFileName( NULL, cName, MAX_PATH);
+wsprintf(buf, "DllEntryPoint - 1 process attach [%s]\r\n", cName);
+OutputDebugString(buf);
+}
+#endif
+
+
+ //
+ // Yeah, I know it's not threadsafe. Ask me if I care.
+ //
+ gdwThreadParms[THE_HINST] = (DWORD)hModule;
+ gdwThreadParms[THE_LREASON] = (DWORD)lReason;
+
+
+ InitThunks();
+ }
+ break;
+
+ }
+
+DBGOUT((2, "Leaving DllEntryPoint"));
+
+ return TRUE;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG PASCAL TSPI_lineConfigDialog (
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ );
+
+LONG PASCAL TSPI_lineConfigDialogEdit(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass,
+ LPVOID lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ );
+
+
+LONG
+TSPIAPI
+TSPI_providerGenericDialogData(
+ DWORD dwObjectID,
+ DWORD dwObjectType,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+// LONG lResult = LINEERR_OPERATIONUNAVAIL;
+
+
+ DBGOUT((2, "In TSPI_providerGenericDialogData"));
+
+ DBGOUT((11, " Msg=0x%08lx", ((LPDWORD)lpParams)[0]));
+
+// return SendMessage( ghWnd, ((LPDWORD)lpParams)[0], 0, (LPARAM)&(((LPDWORD)lpParams)[1]) );
+// return
+ PostMessage( ghWnd, ((LPDWORD)lpParams)[0], 0, (LPARAM)&(((LPDWORD)lpParams)[1]) );
+ return 0;
+
+// return lResult;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+TSPIAPI
+TSPI_providerUIIdentify(
+ LPSTR pszUIDllName
+ )
+{
+
+ DBGOUT((2, "In TSPI_providerUIIdentify"));
+
+ lstrcpy( pszUIDllName, "TSP3216L.TSP" );
+
+ return 0;
+
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+TSPIAPI
+TUISPI_lineConfigDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+{
+ DWORD dwParms[] = {
+ MYMSG_LINECONFIGDIALOG,
+ dwDeviceID,
+ (DWORD)hwndOwner,
+ (DWORD)lpszDeviceClass
+ };
+
+
+//BUGBUG: Can't pass strings across a callback
+
+ DBGOUT((2, "In TUISPI_lineConfigDialog"));
+ DBGOUT((11, " dwDeviceID=0x%08lx", dwDeviceID));
+ DBGOUT((11, " hwndOwner =0x%08lx", hwndOwner));
+ DBGOUT((11, " lpszDeviceClass=0x%08lx", lpszDeviceClass));
+
+ (*lpfnUIDLLCallback)(
+ dwDeviceID,
+ TUISPIDLL_OBJECT_LINEID,
+ dwParms,
+ sizeof(dwParms)
+ );
+
+//BUGBUG how do we wait and/or return error code?
+ return 0;
+
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+TSPIAPI
+TUISPI_lineConfigDialogEdit(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass,
+ LPVOID const lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ )
+{
+ DWORD dwParms[] = {
+ MYMSG_LINECONFIGDIALOGEDIT,
+ dwDeviceID,
+ (DWORD)hwndOwner,
+ (DWORD)lpszDeviceClass,
+ (DWORD)lpDeviceConfigIn,
+ dwSize,
+ (DWORD)lpDeviceConfigOut
+ };
+
+
+ DBGOUT((2, "In TUISPI_lineConfigDialogEdit"));
+
+ (*lpfnUIDLLCallback)(
+ dwDeviceID,
+ TUISPIDLL_OBJECT_LINEID,
+ dwParms,
+ sizeof(dwParms)
+ );
+
+//BUGBUG how do we wait and/or return error code?
+ return 0;
+
+
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+TSPIAPI
+TSPI_phoneConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ );
+
+LONG
+TSPIAPI
+TUISPI_phoneConfigDialog(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+{
+ DWORD dwParms[] = {
+ MYMSG_PHONECONFIGDIALOG,
+ dwDeviceID,
+ (DWORD)hwndOwner,
+ (DWORD)lpszDeviceClass
+ };
+
+
+//BUGBUG: Can't pass strings across a callback
+
+ DBGOUT((2, "In TUISPI_phoneConfigDialog"));
+ DBGOUT((11, " dwDeviceID=0x%08lx", dwDeviceID));
+ DBGOUT((11, " hwndOwner =0x%08lx", hwndOwner));
+ DBGOUT((11, " lpszDeviceClass=0x%08lx", lpszDeviceClass));
+
+ (*lpfnUIDLLCallback)(
+ dwDeviceID,
+ TUISPIDLL_OBJECT_PHONEID,
+ dwParms,
+ sizeof(dwParms)
+ );
+
+//BUGBUG how do we wait and/or return error code?
+
+ return 0;
+
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ );
+
+LONG
+TSPIAPI
+TUISPI_providerConfig(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+ DWORD dwParms[] = {
+ MYMSG_PROVIDERCONFIG,
+ (DWORD)hwndOwner,
+ dwPermanentProviderID
+ };
+
+
+//BUGBUG: Can't pass strings across a callback
+
+ DBGOUT((2, "In TUISPI_providerConfig"));
+ DBGOUT((11, " hwndOwner =0x%08lx", hwndOwner));
+ DBGOUT((11, " dwPermanentProviderID=0x%08lx", dwPermanentProviderID));
+
+ (*lpfnUIDLLCallback)(
+ 0, //BUGBUG Is this correct?
+ TUISPIDLL_OBJECT_LINEID,
+ dwParms,
+ sizeof(dwParms)
+ );
+
+//BUGBUG how do we wait and/or return error code?
+
+ return 0;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+TSPIAPI
+TUISPI_providerInstall(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+
+ DBGOUT((2, "In TUISPI_providerInstall"));
+
+ return 0;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+TSPIAPI
+TUISPI_providerRemove(
+ TUISPIDLLCALLBACK lpfnUIDLLCallback,
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+{
+
+ DBGOUT((2, "In TUISPI_providerRemove"));
+
+ return 0;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+
+
+
+LONG
+PASCAL
+TSPI_providerEnumDevices16( // TSPI v1.4
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc,
+ HWND hSecretWnd
+ );
+
+
+LONG PASCAL TSPI_providerEnumDevices(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc
+ )
+{
+ DWORD dwThreadID;
+
+
+ DBGOUT((2, "In TSPI_providerEnumDevices"));
+
+ //
+ // BUGBUG There's gotta be a better way to earn a buck...
+ //
+
+ if ( NULL == CreateThread( NULL,
+ 0,
+ TheUIThread,
+ (LPVOID)&gdwThreadParms,
+ 0,
+ &dwThreadID
+ )
+ )
+ {
+ //
+ // The CreateThread failed!!
+ //
+ DBGOUT((1, "CreateThread() failed!!!!"));
+ return LINEERR_OPERATIONFAILED;
+ }
+
+
+ while ( !ghWnd)
+ {
+ Sleep(0);
+ }
+
+
+ return TSPI_providerEnumDevices16(
+ dwPermanentProviderID,
+ lpdwNumLines,
+ lpdwNumPhones,
+ hProvider,
+ lpfnLineCreateProc,
+ lpfnPhoneCreateProc,
+ ghWnd
+ );
+
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+
+
+
+LONG
+PASCAL
+TSPI_lineGetID16(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ );
+
+
+LONG
+PASCAL
+TSPI_lineGetID(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+
+ )
+{
+ LONG lResult;
+
+ DBGOUT((2, "Entering TSPI_lineGetID"));
+
+
+ DBGOUT((20, "lpszDeviceClass=[%s]", lpszDeviceClass));
+
+ lResult = TSPI_lineGetID16(
+ hdLine,
+ dwAddressID,
+ hdCall,
+ dwSelect,
+ lpDeviceID,
+ lpszDeviceClass
+ );
+
+ //
+ // Only continue if the operation was successful
+ //
+ if ( 0 == lResult )
+ {
+
+ //
+ // Is this a handle that we should translate?
+ //
+
+ DWORD dwDataSize;
+ DWORD dwDataType;
+ HKEY hKey;
+ TCHAR buf[64];
+ TCHAR KeyName[128];
+
+
+ //
+ // We determine if we should translate by simply trying to retrive a
+ // value with the name of lpszDeviceClass. If we succeed, we'll
+ // translate.
+ //
+ // We'll use the value as an offset into the string part (AN OFFSET
+ // FROM THE START OF VAR DATA, NOT FROM THE START OF THE STRUCT!!!)
+ // of where we can find the handle.
+ //
+ wsprintf(KeyName, "%s%d", gszProviderKey, gdwPermanentProviderID);
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ KeyName,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof(buf);
+
+
+ DBGOUT((11, "Looking in key [%s] for [%s]", KeyName, lpszDeviceClass));
+
+
+ lResult = RegQueryValueEx(
+ hKey,
+ lpszDeviceClass,
+ 0,
+ &dwDataType,
+ buf,
+ &dwDataSize
+ );
+
+ RegCloseKey( hKey );
+
+
+ if ( 0 == lResult )
+ {
+ HANDLE hTemp;
+#if DBG
+ LONG lRet;
+
+ lRet =
+#endif
+ DuplicateHandle( GetCurrentProcess(),
+ *(LPHANDLE)((LPBYTE)lpDeviceID +
+ lpDeviceID->dwStringOffset +
+ *(LPDWORD)buf
+ ),
+ hTargetProcess,
+ &hTemp,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS |
+ DUPLICATE_CLOSE_SOURCE
+ );
+
+// CloseHandle( *(LPHANDLE)( (LPBYTE)lpDeviceID +
+// lpDeviceID->dwStringOffset +
+// *(LPDWORD)buf ) );
+
+
+ *(LPHANDLE)( (LPBYTE)lpDeviceID +
+ lpDeviceID->dwStringOffset +
+ *(LPDWORD)buf ) =
+ hTemp;
+
+ DBGOUT((2, " Duplicate handle return code=0x%08lx", lRet));
+ }
+#if DBG
+ else
+ {
+ DBGOUT((2, " We won't dupe this handle. [%s]", lpszDeviceClass));
+ }
+#endif
+
+ lResult = 0; //What else can we do? Do we fail this if the dupe failed?
+
+ }
+
+
+ DBGOUT((2, "Leaving TSPI_lineGetID - lResult=0x%08lx", lResult));
+
+ return lResult;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG
+PASCAL
+TSPI_phoneGetID16(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ );
+
+
+LONG
+PASCAL
+TSPI_phoneGetID(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass,
+ HANDLE hTargetProcess
+
+ )
+{
+ LONG lResult;
+
+ DBGOUT((2, "Entering TSPI_phoneGetID"));
+
+
+ DBGOUT((20, "lpszDeviceClass=[%s]", lpszDeviceClass));
+
+ lResult = TSPI_phoneGetID16(
+ hdPhone,
+ lpDeviceID,
+ lpszDeviceClass
+ );
+
+ //
+ // Only continue if the operation was successful
+ //
+ if ( 0 == lResult )
+ {
+
+ //
+ // Is this a handle that we should translate?
+ //
+
+ DWORD dwDataSize;
+ DWORD dwDataType;
+ HKEY hKey;
+ TCHAR buf[64];
+ TCHAR KeyName[128];
+
+
+ //
+ // We determine if we should translate by simply trying to retrive a
+ // value with the name of lpszDeviceClass. If we succeed, we'll
+ // translate.
+ //
+ // We'll use the value as an offset into the string part (AN OFFSET
+ // FROM THE START OF VAR DATA, NOT FROM THE START OF THE STRUCT!!!)
+ // of where we can find the handle.
+ //
+ wsprintf(KeyName, "%s%d", gszProviderKey, gdwPermanentProviderID);
+
+ RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ KeyName,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+ );
+
+ dwDataSize = sizeof(buf);
+
+
+ DBGOUT((20, "Looking in key [%s] for [%s]", KeyName, lpszDeviceClass));
+
+
+ lResult = RegQueryValueEx(
+ hKey,
+ lpszDeviceClass,
+ 0,
+ &dwDataType,
+ buf,
+ &dwDataSize
+ );
+
+ RegCloseKey( hKey );
+
+
+ if ( 0 == lResult )
+ {
+ HANDLE hTemp;
+#if DBG
+ LONG lRet;
+
+ lRet =
+#endif
+ DuplicateHandle( GetCurrentProcess(),
+ *(LPHANDLE)((LPBYTE)lpDeviceID +
+ lpDeviceID->dwStringOffset +
+ *(LPDWORD)buf
+ ),
+ hTargetProcess,
+ &hTemp,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS
+// DUPLICATE_CLOSE_SOURCE
+ );
+
+ CloseHandle( *(LPHANDLE)( (LPBYTE)lpDeviceID +
+ lpDeviceID->dwStringOffset +
+ *(LPDWORD)buf ) );
+
+ *(LPHANDLE)( (LPBYTE)lpDeviceID +
+ lpDeviceID->dwStringOffset +
+ *(LPDWORD)buf ) =
+ hTemp;
+
+ DBGOUT((20, " Duplicate handle return code=0x%08lx", lRet));
+ }
+#if DBG
+ else
+ {
+ DBGOUT((20, " We won't dupe this handle. [%s]", lpszDeviceClass));
+ }
+#endif
+
+ lResult = 0; //What else can we do? Do we fail this if the dupe failed?
+
+ }
+
+
+ DBGOUT((2, "Leaving TSPI_phoneGetID - lResult=0x%08lx", lResult));
+
+ return lResult;
+}
+
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+
+LONG
+PASCAL
+TSPI_providerInit16(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceBaseID,
+ DWORD dwPhoneDeviceBaseID,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc
+ );
+
+LONG
+TSPIAPI
+TSPI_providerInit(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc,
+ LPDWORD lpdwTSPIOptions // TAPI v2.0
+ )
+{
+ DWORD pParams[7];
+
+ DBGOUT((2, "In 32-providerinit"));
+ DBGOUT((11, " dwTSPIVersion =0x%08lx", dwTSPIVersion));
+ DBGOUT((11, " dwPermanentProviderID=0x%08lx", dwPermanentProviderID));
+
+
+ gdwPermanentProviderID = dwPermanentProviderID;
+
+ *lpdwTSPIOptions = 0;
+
+ pParams[0] = dwTSPIVersion;
+ pParams[1] = dwPermanentProviderID;
+ pParams[2] = dwLineDeviceIDBase;
+ pParams[3] = dwPhoneDeviceIDBase;
+ pParams[4] = dwNumLines;
+ pParams[5] = dwNumPhones;
+ pParams[6] = (DWORD)lpfnCompletionProc;
+
+ return SendMessage( ghWnd, MYMSG_PROVIDERINIT, 0, (LPARAM)pParams);
+
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+
+LONG
+PASCAL
+TSPI_providerShutdown16(
+ DWORD dwTSPIVersion
+ );
+
+LONG
+TSPIAPI
+TSPI_providerShutdown(
+ DWORD dwTSPIVersion
+ )
+{
+ LONG lResult;
+
+ DBGOUT((2, "In 32-providerShutdown"));
+
+
+ lResult = SendMessage( ghWnd, MYMSG_PROVIDERSHUTDOWN, 0, dwTSPIVersion);
+
+ //
+ // Is the UI thread still around?
+ //
+ if ( ghWnd )
+ {
+ SendMessage(ghWnd, WM_CLOSE, 0, 0);
+
+ //
+ // Verify that the other thread has done its work and killed
+ // the window
+ //
+ while ( ghWnd )
+ {
+ Sleep(0);
+ }
+ }
+
+ return lResult;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+
+LONG
+PASCAL
+TSPI_lineMakeCall16(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ );
+
+LONG
+TSPIAPI
+TSPI_lineMakeCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ LONG lResult;
+ DWORD pParams[7];
+
+
+ DBGOUT((2, "In 32-linemakecall"));
+
+ pParams[0] = (DWORD)dwRequestID;
+ pParams[1] = (DWORD)hdLine;
+ pParams[2] = (DWORD)htCall;
+ pParams[3] = (DWORD)lphdCall;
+ pParams[4] = (DWORD)lpszDestAddress;
+ pParams[5] = (DWORD)dwCountryCode;
+ pParams[6] = (DWORD)lpCallParams;
+
+
+ lResult = SendMessage( ghWnd, MYMSG_LINEMAKECALL, 0, (LPARAM)pParams);
+
+
+ return lResult;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+LONG PASCAL TapiCallbackThunk( DWORD dwDevice,
+ DWORD dwMessage,
+ DWORD dwInstance,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3,
+ DWORD dwjunk
+ )
+{
+
+
+ DBGOUT((2, "TapiCallbackThunk <<<----------------"));
+
+ return 0;
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+void HandleCallback( PCOPYDATASTRUCT pCds )
+{
+ DWORD dwCallbackType = ((LPDWORD)pCds->lpData)[0];
+ LPDWORD lpdwCallbackData = (LPDWORD)pCds->lpData;
+
+
+
+ switch ( dwCallbackType )
+ {
+
+ case CALLBACK_ASYNCCOMPLETION:
+ DBGOUT((2, "AsyncCompletion"));
+ (((ASYNC_COMPLETION)(pCds->dwData)))( lpdwCallbackData[1],
+ lpdwCallbackData[2]
+ );
+ break;
+
+
+
+ case CALLBACK_LINEEVENT:
+
+ DBGOUT((2, "LineEvent"));
+
+ if ( lpdwCallbackData[3] == LINE_NEWCALL )
+ {
+ lpdwCallbackData[5] = (DWORD)WOWGetVDMPointer(
+ lpdwCallbackData[5],
+ sizeof(DWORD),
+ 1
+ );
+ }
+
+ //FALTHROUGH!!!
+
+ case CALLBACK_LINECREATE:
+
+ if ( dwCallbackType == CALLBACK_LINECREATE )
+ {
+ DBGOUT((2, "LineCreate"));
+ }
+
+
+ (((FARPROC)(pCds->dwData)))( lpdwCallbackData[1],
+ lpdwCallbackData[2],
+ lpdwCallbackData[3],
+ lpdwCallbackData[4],
+ lpdwCallbackData[5],
+ lpdwCallbackData[6]
+ );
+
+#if DBG
+ if ( dwCallbackType == CALLBACK_LINEEVENT &&
+ lpdwCallbackData[3] == LINE_NEWCALL )
+ DBGOUT((11, "Returned htCall=0x%08lx", *(LPDWORD)(lpdwCallbackData[5])));
+#endif
+ break;
+
+
+ case CALLBACK_PHONEEVENT:
+ DBGOUT((2, "PhoneEvent"));
+ case CALLBACK_PHONECREATE:
+ DBGOUT((2, "PhoneCreate?"));
+ (((FARPROC)(pCds->dwData)))( lpdwCallbackData[1],
+ lpdwCallbackData[2],
+ lpdwCallbackData[3],
+ lpdwCallbackData[4],
+ lpdwCallbackData[5]
+ );
+ break;
+
+
+#if DBG
+ default:
+ DBGOUT((1, "Invalid callback type!!"));
+ // Should rip or assert?
+ break;
+#endif
+ }
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LRESULT CALLBACK _loadds MyWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
+{
+
+ DBGOUT((91, "msggg"));
+
+ switch( nMsg )
+ {
+
+ case TSP3216L_MESSAGE:
+ if ((wParam == 1) && (lParam == 2) )
+ DBGOUT((0," Got a message thingy"));
+ break;
+
+
+ case MYMSG_PROVIDERINIT:
+ DBGOUT((2, "Got a providerInit message"));
+ return TSPI_providerInit16(
+ ((LPDWORD)lParam)[0],
+ ((LPDWORD)lParam)[1],
+ ((LPDWORD)lParam)[2],
+ ((LPDWORD)lParam)[3],
+ ((LPDWORD)lParam)[4],
+ ((LPDWORD)lParam)[5],
+ (ASYNC_COMPLETION)((LPDWORD)lParam)[6]
+ );
+ break;
+
+
+ case MYMSG_PROVIDERSHUTDOWN:
+ DBGOUT((2, "Got a providerShutdown message"));
+ return TSPI_providerShutdown16(
+ lParam
+ );
+ break;
+
+
+ case MYMSG_PROVIDERCONFIG:
+ DBGOUT((2, "Got a providerConfig message"));
+ return TSPI_providerConfig(
+ (HWND)((LPDWORD)lParam)[0],
+ ((LPDWORD)lParam)[1]
+ );
+ break;
+
+
+ case MYMSG_LINEMAKECALL:
+ DBGOUT((2, "Got a lineMakeCall message"));
+ return TSPI_lineMakeCall16(
+ (DRV_REQUESTID)((LPDWORD)lParam)[0],
+ (HDRVLINE)((LPDWORD)lParam)[1],
+ (HTAPICALL)((LPDWORD)lParam)[2],
+ (LPHDRVCALL)((LPDWORD)lParam)[3],
+ (LPCSTR)((LPDWORD)lParam)[4],
+ (DWORD)((LPDWORD)lParam)[5],
+ (LPLINECALLPARAMS)((LPDWORD)lParam)[6]
+ );
+ break;
+
+
+ case MYMSG_LINECONFIGDIALOG:
+ DBGOUT((2, "Got a lineConfigDialog message"));
+ return TSPI_lineConfigDialog(
+ ((LPDWORD)lParam)[0],
+ (HWND)((LPDWORD)lParam)[1],
+ (LPCSTR)((LPDWORD)lParam)[2]
+ );
+ break;
+
+
+ case MYMSG_PHONECONFIGDIALOG:
+ DBGOUT((2, "Got a phoneConfigDialog message"));
+ return TSPI_phoneConfigDialog(
+ ((LPDWORD)lParam)[0],
+ (HWND)((LPDWORD)lParam)[1],
+ (LPCSTR)((LPDWORD)lParam)[2]
+ );
+ break;
+
+
+ case WM_COPYDATA:
+ DBGOUT((11, "VaHoo!"));
+
+ HandleCallback( (PCOPYDATASTRUCT)lParam );
+
+ break;
+
+
+ case WM_CLOSE:
+ DestroyWindow( hWnd );
+ break;
+
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+
+ default:
+ return DefWindowProc( hWnd, nMsg, wParam, lParam);
+ }
+ DBGOUT((2, "msggg done"));
+
+ return(FALSE);
+}
+
+
+
+
+
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.def b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.def
new file mode 100644
index 000000000..5ac7556a6
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.def
@@ -0,0 +1,130 @@
+LIBRARY TSP3216l
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept @500
+ TSPI_lineAddToConference @501
+ TSPI_lineAnswer @502
+ TSPI_lineBlindTransfer @503
+ TSPI_lineClose @504
+ TSPI_lineCloseCall @505
+ TSPI_lineCompleteCall @506
+ TSPI_lineCompleteTransfer @507
+ TSPI_lineConditionalMediaDetection @508
+ TSPI_lineConfigDialog @509
+ TSPI_lineDevSpecific @510
+ TSPI_lineDevSpecificFeature @511
+ TSPI_lineDial @512
+ TSPI_lineDrop @513
+ TSPI_lineForward @514
+ TSPI_lineGatherDigits @515
+ TSPI_lineGenerateDigits @516
+ TSPI_lineGenerateTone @517
+ TSPI_lineGetAddressCaps @518
+ TSPI_lineGetAddressID @519
+ TSPI_lineGetAddressStatus @520
+ TSPI_lineGetCallAddressID @521
+ TSPI_lineGetCallInfo @522
+ TSPI_lineGetCallStatus @523
+ TSPI_lineGetDevCaps @524
+ TSPI_lineGetDevConfig @525
+ TSPI_lineGetExtensionID @526
+ TSPI_lineGetIcon @527
+ TSPI_lineGetID @528
+ TSPI_lineGetLineDevStatus @529
+ TSPI_lineGetNumAddressIDs @530
+ TSPI_lineHold @531
+ TSPI_lineMakeCall @532
+ TSPI_lineMonitorDigits @533
+ TSPI_lineMonitorMedia @534
+ TSPI_lineMonitorTones @535
+ TSPI_lineNegotiateExtVersion @536
+ TSPI_lineNegotiateTSPIVersion @537
+ TSPI_lineOpen @538
+ TSPI_linePark @539
+ TSPI_linePickup @540
+ TSPI_linePrepareAddToConference @541
+ TSPI_lineRedirect @542
+ TSPI_lineRemoveFromConference @543
+ TSPI_lineSecureCall @544
+ TSPI_lineSelectExtVersion @545
+ TSPI_lineSendUserUserInfo @546
+ TSPI_lineSetAppSpecific @547
+ TSPI_lineSetCallParams @548
+ TSPI_lineSetDefaultMediaDetection @549
+ TSPI_lineSetDevConfig @550
+ TSPI_lineSetMediaControl @551
+ TSPI_lineSetMediaMode @552
+ TSPI_lineSetStatusMessages @553
+ TSPI_lineSetTerminal @554
+ TSPI_lineSetupConference @555
+ TSPI_lineSetupTransfer @556
+ TSPI_lineSwapHold @557
+ TSPI_lineUncompleteCall @558
+ TSPI_lineUnhold @559
+ TSPI_lineUnpark @560
+
+ TSPI_phoneClose @561
+ TSPI_phoneConfigDialog @562
+ TSPI_phoneDevSpecific @563
+ TSPI_phoneGetButtonInfo @564
+ TSPI_phoneGetData @565
+ TSPI_phoneGetDevCaps @566
+ TSPI_phoneGetDisplay @567
+ TSPI_phoneGetExtensionID @568
+ TSPI_phoneGetGain @569
+ TSPI_phoneGetHookSwitch @570
+ TSPI_phoneGetIcon @571
+ TSPI_phoneGetID @572
+ TSPI_phoneGetLamp @573
+ TSPI_phoneGetRing @574
+ TSPI_phoneGetStatus @575
+ TSPI_phoneGetVolume @576
+ TSPI_phoneNegotiateExtVersion @577
+ TSPI_phoneNegotiateTSPIVersion @578
+ TSPI_phoneOpen @579
+ TSPI_phoneSelectExtVersion @580
+ TSPI_phoneSetButtonInfo @581
+ TSPI_phoneSetData @582
+ TSPI_phoneSetDisplay @583
+ TSPI_phoneSetGain @584
+ TSPI_phoneSetHookSwitch @585
+ TSPI_phoneSetLamp @586
+ TSPI_phoneSetRing @587
+ TSPI_phoneSetStatusMessages @588
+ TSPI_phoneSetVolume @589
+
+ TSPI_providerConfig @590
+ TSPI_providerInit @591
+ TSPI_providerInstall @592
+ TSPI_providerRemove @593
+ TSPI_providerShutdown @594
+
+ TSPI_providerEnumDevices @595
+ TSPI_lineDropOnClose @596
+ TSPI_lineDropNoOwner @597
+ TSPI_providerCreateLineDevice @598
+ TSPI_providerCreatePhoneDevice @599
+ TSPI_lineSetCurrentLocation @600
+ TSPI_lineConfigDialogEdit @601
+ TSPI_lineReleaseUserUserInfo @602
+
+ TSPI_providerGenericDialogData @608
+ TSPI_providerUIIdentify @609
+
+ TUISPI_lineConfigDialog @610
+ TUISPI_lineConfigDialogEdit @611
+ TUISPI_phoneConfigDialog @612
+ TUISPI_providerConfig @613
+ TUISPI_providerInstall @616
+ TUISPI_providerRemove @617
+
+
+
+
+ TapiThk_ThunkData32
+ TapiFThk_ThunkData32
+
+ Tapi32_ThunkData32
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.h b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.h
new file mode 100644
index 000000000..99744d0ff
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.h
@@ -0,0 +1,49 @@
+/* TSP3216L.H
+ Copyright 1995 (C) Microsoft Corporation
+
+ 32-bit TAPI service provider to act as a cover for a system's 16-bit SPs
+
+ 16-bit part: TSP3216S.DLL
+ 32-bit part: TSP3216L.DLL
+
+ t-jereh 20-July-1995
+
+ TODO:
+ 1) allow debug levels
+ 2) if oom in InitializeSPs(), fail
+
+ */
+
+#define ERR_NONE 0 /* success return value */
+
+#define TSPI_PROC_LAST 103 /* there are TSPI functions from 500 to 602 */
+
+
+// structs
+
+typedef struct tagMYLINE
+ {
+ HDRVLINE hdLine;
+ int iProvider;
+ DWORD dwDeviceID;
+ LINEEVENT lpfnEventProc;
+ HTAPILINE htLine;
+ } MYLINE, *LPMYLINE;
+
+
+typedef struct tagMYPHONE
+ {
+ HDRVPHONE hdPhone;
+ int iProvider;
+ DWORD dwDeviceID;
+ PHONEEVENT lpfnEventProc;
+ HTAPIPHONE htPhone;
+ } MYPHONE, *LPMYPHONE;
+
+
+typedef struct tagMYCALL
+ {
+ HDRVCALL hdCall;
+ int iProvider;
+ DWORD dwDeviceID;
+ } MYCALL, *LPMYCALL;
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.mak b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.mak
new file mode 100644
index 000000000..81db3f3af
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.mak
@@ -0,0 +1,177 @@
+# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=Win32 Debug
+!MESSAGE No configuration specified. Defaulting to Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "tsp3216l.mak" CFG="Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "Win32 Debug"
+MTL=MkTypLib.exe
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "WinRel"
+# PROP BASE Intermediate_Dir "WinRel"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "WinRel"
+# PROP Intermediate_Dir "WinRel"
+OUTDIR=.\WinRel
+INTDIR=.\WinRel
+
+ALL : $(OUTDIR)/tsp3216l.dll $(OUTDIR)/tsp3216l.bsc
+
+$(OUTDIR) :
+ if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
+
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE CPP /nologo /MT /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /c
+# ADD CPP /nologo /MT /W3 /GX /YX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "DEBUG" /FR /c
+CPP_PROJ=/nologo /MT /W3 /GX /YX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "DEBUG" /FR$(INTDIR)/ /Fp$(OUTDIR)/"tsp3216l.pch" /Fo$(INTDIR)/ /c
+CPP_OBJS=.\WinRel/
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o$(OUTDIR)/"tsp3216l.bsc"
+BSC32_SBRS= \
+ $(INTDIR)/tsp3216l.sbr
+
+$(OUTDIR)/tsp3216l.bsc : $(OUTDIR) $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:windows /DLL /MACHINE:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wow32.lib /NOLOGO /SUBSYSTEM:windows /DLL /MACHINE:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib wow32.lib /NOLOGO /SUBSYSTEM:windows /DLL /INCREMENTAL:no\
+ /PDB:$(OUTDIR)/"tsp3216l.pdb" /MACHINE:I386 /DEF:".\TSP3216L.DEF"\
+ /OUT:$(OUTDIR)/"tsp3216l.dll" /IMPLIB:$(OUTDIR)/"tsp3216l.lib"
+DEF_FILE=.\TSP3216L.DEF
+LINK32_OBJS= \
+ $(INTDIR)/tsp3216l.obj
+
+$(OUTDIR)/tsp3216l.dll : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "WinDebug"
+# PROP BASE Intermediate_Dir "WinDebug"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "WinDebug"
+# PROP Intermediate_Dir "WinDebug"
+OUTDIR=.\WinDebug
+INTDIR=.\WinDebug
+
+ALL : $(OUTDIR)/tsp3216l.dll $(OUTDIR)/tsp3216l.bsc
+
+$(OUTDIR) :
+ if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
+
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+# ADD BASE CPP /nologo /MT /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /c
+# ADD CPP /nologo /MT /W3 /GX /Zi /YX /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "DEBUG" /FR /c
+CPP_PROJ=/nologo /MT /W3 /GX /Zi /YX /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
+ /D "DEBUG" /FR$(INTDIR)/ /Fp$(OUTDIR)/"tsp3216l.pch" /Fo$(INTDIR)/\
+ /Fd$(OUTDIR)/"tsp3216l.pdb" /c
+CPP_OBJS=.\WinDebug/
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o$(OUTDIR)/"tsp3216l.bsc"
+BSC32_SBRS= \
+ $(INTDIR)/tsp3216l.sbr
+
+$(OUTDIR)/tsp3216l.bsc : $(OUTDIR) $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:windows /DLL /DEBUG /MACHINE:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wow32.lib /NOLOGO /SUBSYSTEM:windows /DLL /DEBUG /MACHINE:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib wow32.lib /NOLOGO /SUBSYSTEM:windows /DLL /INCREMENTAL:yes\
+ /PDB:$(OUTDIR)/"tsp3216l.pdb" /DEBUG /MACHINE:I386 /DEF:".\TSP3216L.DEF"\
+ /OUT:$(OUTDIR)/"tsp3216l.dll" /IMPLIB:$(OUTDIR)/"tsp3216l.lib"
+DEF_FILE=.\TSP3216L.DEF
+LINK32_OBJS= \
+ $(INTDIR)/tsp3216l.obj
+
+$(OUTDIR)/tsp3216l.dll : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Group "Source Files"
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\tsp3216l.c
+
+$(INTDIR)/tsp3216l.obj : $(SOURCE) $(INTDIR)
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\TSP3216L.DEF
+# End Source File
+# End Group
+# End Project
+################################################################################
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.rc b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.rc
new file mode 100644
index 000000000..fa099ea3f
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216l/tsp3216l.rc
@@ -0,0 +1,24 @@
+//
+// (c) 1995 Microsoft Corporation. All Rights Reserved.
+//
+/* Version Numbering stuff */
+
+
+#include <windows.h>
+
+// Is the following FLAG good to use for this?
+#if WINNT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Telephony 16bit SP support"
+#define VER_INTERNALNAME_STR "16bit SP support"
+#define VER_ORIGINALFILENAME_STR "tsp3216l.tsp"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/debug.c b/private/tapi/dev/sp/tsp3216/tsp3216s/debug.c
new file mode 100644
index 000000000..a2796f5e7
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/debug.c
@@ -0,0 +1,176 @@
+//
+//
+
+#if DBG
+
+
+#include <windows.h>
+#include <windowsx.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <tapi.h>
+#include "debug.h"
+
+
+
+extern const char far szINIfilename[];
+
+DWORD gdwDebugLevel;
+
+
+static char szNewBuff[256];
+
+
+DWORD TSP3216sDebugLevel = 0;
+static fTSP3216sDebugLevelValid = FALSE;
+
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+
+{
+ static char buf[128] = "TSP3216s: ";
+
+ if (!fTSP3216sDebugLevelValid)
+ {
+//TSP3216sDebugLevel = 0;
+ TSP3216sDebugLevel = GetPrivateProfileInt( "Debug",
+ "TSP3216sDebugLevel",
+ 0,
+ szINIfilename );
+
+ if ( TSP3216sDebugLevel > 0 )
+ {
+ wsprintf(
+ &buf[10],
+ "TSP3216sDebugLevel= %d\n\r",
+ TSP3216sDebugLevel);
+
+ OutputDebugString((LPSTR)buf);
+
+
+ fTSP3216sDebugLevelValid = TRUE;
+ }
+
+ }
+
+
+ //
+ // Is the message otherwise "low" enough to display?
+ //
+ if (dwDbgLevel <= TSP3216sDebugLevel)
+ {
+ char buf[128] = "TSP3216s: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ vsprintf (&buf[10],
+ lpszFormat,
+ ap
+ );
+
+ lstrcat (buf, "\n");
+
+ OutputDebugString(buf);
+
+ va_end(ap);
+ }
+
+ return;
+}
+
+
+
+
+
+
+//VOID
+//DbgPrt(
+// IN DWORD dwDbgLevel,
+// IN PUCHAR lpszFormat,
+// IN ...
+// )
+///*++
+//
+//Routine Description:
+//
+// Formats the incoming debug message & calls DbgPrint
+//
+//Arguments:
+//
+// DbgLevel - level of message verboseness
+//
+// DbgMessage - printf-style format string, followed by appropriate
+// list of arguments
+//
+//Return Value:
+//
+//
+//--*/
+//{
+//
+// static BOOL fAlreadyGotIt = FALSE;
+// static char buf[128] = "TAPI CPL: ";
+//#define TEXT_START 10
+//
+// if (!fAlreadyGotIt)
+// {
+//
+// gdwDebugLevel = (DWORD) GetPrivateProfileInt(
+// "Debug",
+// "TSP3216s32DebugLevel",
+// 0x0,
+// "Telephon.ini"
+// );
+//
+// fAlreadyGotIt = TRUE;
+//
+// wsprintf(&buf[TEXT_START], "TSP3216s32DebugLevel=%d \r\n", gdwDebugLevel);
+// OutputDebugStringA(buf);
+// }
+//
+//
+// if (dwDbgLevel <= gdwDebugLevel)
+// {
+// va_list ap;
+//
+//
+// va_start(ap, lpszFormat);
+//
+// vsprintf (&buf[TEXT_START],
+// lpszFormat,
+// ap
+// );
+//
+// lstrcat (buf, "\n");
+//
+// OutputDebugStringA (buf);
+//
+// va_end(ap);
+// }
+//}
+//
+
+#endif
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/debug.h b/private/tapi/dev/sp/tsp3216/tsp3216s/debug.h
new file mode 100644
index 000000000..11abf22ec
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/debug.h
@@ -0,0 +1,25 @@
+#if DBG
+
+
+#if !WIN32
+#define IN
+#define PUCHAR char *
+#endif
+
+
+
+#define DBGOUT(arg) DbgPrt arg
+
+extern VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR DbgMessage,
+ IN ...
+ );
+
+#else
+
+#define DBGOUT(arg)
+
+#endif
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/depend.mk b/private/tapi/dev/sp/tsp3216/tsp3216s/depend.mk
new file mode 100644
index 000000000..13a65e752
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/depend.mk
@@ -0,0 +1,11 @@
+.\tapi32.obj: ..\..\script\$(VERDIR)\tapi32.asm
+
+.\tapithk.obj: ..\..\script\$(VERDIR)\tapithk.asm
+
+.\tapifthk.obj: ..\..\script\$(VERDIR)\tapifthk.asm
+
+.\tsp3216s.obj: ..\tsp3216s.c ..\tsp3216s.h ..\debug.h
+
+.\debug.obj: ..\debug.c ..\debug.h
+
+.\tsp3216s.res: ..\tsp3216s.c
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/makefile b/private/tapi/dev/sp/tsp3216/tsp3216s/makefile
new file mode 100644
index 000000000..43dc5a869
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/makefile
@@ -0,0 +1,29 @@
+!if "$(OS)" == "Windows_NT"
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!else
+
+##############################################################################
+#
+# tsp3216s.dll Make file
+#
+##############################################################################
+
+#Ok, we're doing a Win9x build.
+
+ROOT=..\..\..\..\..\..
+
+VERSIONLIST=debug retail
+
+DEPENDNAME=depend.mk
+
+COMMONMKFILE=makefile.def
+
+IS_OEM=TRUE
+IS_32 = TRUE
+
+!include $(ROOT)\dev\master.mk
+
+!endif
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/makefile.def b/private/tapi/dev/sp/tsp3216/tsp3216s/makefile.def
new file mode 100644
index 000000000..6b793cff4
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/makefile.def
@@ -0,0 +1,49 @@
+ROOT=..\..\..\..\..\..\..
+
+IS_OEM=1
+IS_16 = TRUE
+
+DEFENTRY=LibMain
+BUILDDLL=1
+
+
+
+DEPENDNAME=..\depend.mk
+
+DRVNAME=tsp3216s
+TARGETS=tsp3216s.dll tsp3216s.sym
+
+
+SRCDIR=..
+ALTSRCDIR=..\..\script\$(VERDIR)
+
+SYMDIR=.
+
+
+#BUILD_COFF=1
+
+
+
+L16EXE=tsp3216s.dll # Name of exe.
+L16DEF=..\tsp3216s.def # Our def file.
+L16MAP=tsp3216s.map # Our map file.
+L16SYM=tsp3216s.sym # Our sym file.
+L16RES=tsp3216s.res # Resource file.
+L16OBJS= $(DEVROOT)\sdk\lib16\libentry.obj tsp3216s.obj tapi32.obj tapithk.obj tapifthk.obj debug.obj
+L16LIBS= \
+ $(DEVROOT)\tools\c816\lib\ldllcew.lib \
+ $(DEVROOT)\lib16\libw.lib \
+ $(DEVROOT)\lib16\kernel.lib
+
+!include $(ROOT)\dev\master.mk
+
+
+INCLUDE=..\..\..\..\inc;$(ROOT)\win\thunk;$(ROOT)\win\core\inc;$(INCLUDE)
+
+
+CFLAGS=$(CFLAGS) -AL -DDONT_DECLARE_TSPI_FUNCTIONS=1 -DTAPI_CURRENT_VERSION=0x00010004
+
+!IF "$(VERDIR)" == "debug"
+CFLAGS = $(CFLAGS) -DDBG=1
+!endif
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216.h b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216.h
new file mode 100644
index 000000000..4b4959868
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216.h
@@ -0,0 +1,10 @@
+#define TSP3216L_MESSAGE (WM_USER+10)
+
+enum {CALLBACK_ASYNCCOMPLETION,
+ CALLBACK_LINEEVENT,
+ CALLBACK_PHONEEVENT,
+ CALLBACK_LINECREATE,
+ CALLBACK_PHONECREATE
+ } CALLBACK_TYPES;
+
+
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.c b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.c
new file mode 100644
index 000000000..7ef04caef
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.c
@@ -0,0 +1,3659 @@
+/* TSP3216S.C
+ Copyright 1995 (C) Microsoft Corporation
+
+ 32-bit TAPI service provider to act as a cover for a system's 16-bit SPs
+
+ 16-bit part: TSP3216S.DLL
+ 32-bit part: TSP3216L.DLL
+
+ t-jereh 20-July-1995
+
+ TODO:
+ 1) allow debug levels
+ 2) if OOM in InitializeSPs(), fail
+ 3) other OOM errors
+
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+#include <tapi.h>
+#include <tspi.h>
+
+#include "tsp3216.h"
+#include "tsp3216s.h"
+#include "debug.h"
+//#include <wownt16.h>
+
+
+#undef TSPIAPI
+#define TSPIAPI PASCAL __loadds
+
+
+#define TSPAPI _export _far _pascal __loadds
+typedef LONG (TSPAPI* TSPAPIPROC)(void);
+
+#if DBG
+#define TSP3216SDebugString(_x_) DbgPrt _x_
+//#define TSP3216SDebugString(_x_) TSP3216SOutputDebug _x_
+#else
+#define TSP3216SDebugString(_x_)
+#endif
+
+#define THIS_FUNCTION_UNDER_CONSTRUCTION (LONG)LINEERR_OPERATIONUNAVAIL
+#define THIS_PHONEFUNCTION_UNDER_CONSTRUCTION (LONG)PHONEERR_OPERATIONUNAVAIL
+// a default return value so that the compiler doesn't
+// whine about missing return values in incomplete functions
+
+
+// globals
+
+DWORD FAR PASCAL ghInst32; // handle into TSP3216L.DLL
+HINSTANCE ghThisInst; //This hinst
+
+HWND ghWnd = NULL; //hWnd of TSP3216L's window.
+
+//***************************************************************************
+int NumProviders = 0;
+DWORD gdwPPID;
+HINSTANCE FAR * hProviders = NULL; // array of handles to providers
+TSPAPIPROC FAR * lpfnProcAddress = NULL;
+
+DWORD FAR * dwPermanentProviderIDArray;
+DWORD FAR * dwNumLinesArray = NULL; // dwNumLinesArray[1] is how many
+DWORD FAR * dwNumPhonesArray = NULL; // lines are on provider 1
+DWORD gdwLineDeviceIDBase;
+DWORD gdwPhoneDeviceIDBase;
+
+
+
+FARPROC glpLineEventProc32, glpPhoneEventProc32;
+FARPROC glpLineCreateProc32, glpPhoneCreateProc32;
+
+FARPROC glpAsyncCompletionProc32 = NULL;
+
+
+const char far szINIfilename[] = "TELEPHON.INI";
+
+
+#define BOGUS_REQUEST_ID (0xfffffffd)
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_LineBlank1(
+ DWORD dwBlank1
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_LineBlank1 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_LineBlank2(
+ DWORD dwBlank1,
+ DWORD dwBlank2
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_LineBlank2 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_LineBlank3(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_LineBlank3 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_LineBlank4(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_LineBlank4 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_LineBlank5(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_LineBlank5 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_LineBlank6(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_LineBlank6 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_LineBlank7(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_LineBlank7 - lResult=LINEERR_OPERATIONUNAVAIL"));
+ return LINEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_PhoneBlank1(
+ DWORD dwBlank1
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_PhoneBlank1 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_PhoneBlank2(
+ DWORD dwBlank1,
+ DWORD dwBlank2
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_PhoneBlank2 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_PhoneBlank3(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_PhoneBlank3 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_PhoneBlank4(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_PhoneBlank4 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_PhoneBlank5(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_PhoneBlank5 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_PhoneBlank6(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_PhoneBlank6 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_PhoneBlank7(
+ DWORD dwBlank1,
+ DWORD dwBlank2,
+ DWORD dwBlank3,
+ DWORD dwBlank4,
+ DWORD dwBlank5,
+ DWORD dwBlank6,
+ DWORD dwBlank7
+ )
+{
+ TSP3216SDebugString((2, "Entering/leaving TSPI_PhoneBlank7 - lResult=PHONEERR_OPERATIONUNAVAIL"));
+ return PHONEERR_OPERATIONUNAVAIL;
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+// function definitions
+
+#ifdef DEBUG
+VOID TSP3216SOutputDebug(int level, LPSTR errString)
+ {
+ char outString[1024];
+
+ // if(level <= ???)
+ {
+ wsprintf(outString, "TSP3216S:(%d) %s\r\n", level, errString);
+ OutputDebugString(outString);
+ }
+ }
+#endif
+
+
+VOID
+InitializeSPs(VOID)
+ {
+ int iProvider;
+ int iCurProvider;
+ char LibFileName[MAXBUFSIZE];
+ char szBuffer[MAXBUFSIZE];
+
+// ghInst32 = LoadLibraryEx32("TSP3216L.DLL", NULL, 0);
+//
+// glpLineEventProc32 = GetProcAddress32(ghInst32, "LineEventProc32");
+// glpPhoneEventProc32 = GetProcAddress32(ghInst32, "PhoneEventProc32");
+// glpAsyncCompletionProc32 = GetProcAddress32(
+// ghInst32,
+// "AsyncCompletionProc32"
+// );
+// glpLineCreateProc32 = GetProcAddress32(ghInst32, "LineCreateProc32");
+// glpPhoneCreateProc32 = GetProcAddress32(ghInst32, "PhoneCreateProc32");
+
+
+ NumProviders = GetPrivateProfileInt(
+ "Providers",
+ "NumProviders",
+ 0, // default
+ &szINIfilename[0]
+ );
+
+ dwPermanentProviderIDArray
+ = (DWORD FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(DWORD));
+
+ dwNumLinesArray
+ = (DWORD FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(DWORD));
+ dwNumPhonesArray
+ = (DWORD FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(DWORD));
+
+ hProviders =
+ (HINSTANCE FAR *)GlobalAllocPtr(GPTR, NumProviders * sizeof(HINSTANCE));
+
+ lpfnProcAddress = (TSPAPIPROC FAR *)GlobalAllocPtr(
+ GPTR,
+ NumProviders * TSPI_PROC_LAST * sizeof(TSPAPIPROC)
+ );
+
+ if(
+ !dwPermanentProviderIDArray
+ || !dwNumLinesArray
+ || !dwNumPhonesArray
+ || !hProviders
+ || !lpfnProcAddress)
+ ;// out of memory - fail
+
+
+ iCurProvider = 0;
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ {
+ wsprintf(szBuffer, "ProviderFilename%d", iProvider);
+ GetPrivateProfileString(
+ "Providers",
+ szBuffer,
+ "", // default
+ LibFileName,
+ MAXBUFSIZE,
+ szINIfilename
+ );
+
+DBGOUT((1, "Loading [%s] - provider # %d", LibFileName, iProvider));
+
+ hProviders[iCurProvider] = LoadLibrary(LibFileName);
+
+ //
+ // Only add it to the list if it's real.
+ //
+ if ( hProviders[iCurProvider] > 32 )
+ {
+
+ wsprintf(szBuffer, "ProviderID%d", iProvider);
+ dwPermanentProviderIDArray[iCurProvider] = GetPrivateProfileInt(
+ "Providers",
+ szBuffer,
+ 0, // default
+ szINIfilename
+ );
+
+ iCurProvider++;
+ }
+#if DBG
+ else
+ {
+DBGOUT((1, " %s provider # %d FAILED TO LOAD!", LibFileName, iProvider));
+ }
+#endif
+
+ }
+
+ //
+ // Adjust the global for how many SPs actually loaded.
+ //
+ NumProviders = iCurProvider;
+
+ }
+
+
+VOID
+FreeAllMem(VOID)
+ {
+ int iProvider;
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ FreeLibrary(hProviders[iProvider]);
+
+ GlobalFreePtr(dwPermanentProviderIDArray);
+ GlobalFreePtr(dwNumLinesArray);
+ GlobalFreePtr(dwNumPhonesArray);
+ GlobalFreePtr(hProviders);
+ GlobalFreePtr(lpfnProcAddress);
+
+// FreeLibrary32(ghInst32);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+TSPAPIPROC
+GetProcAddressHashed(int iProvider, DWORD iFunction, UINT nNumParms) // iFunction is 500-based
+ {
+
+ static TSPAPIPROC DefaultLineTable[] = {
+ (TSPAPIPROC)TSPI_LineBlank1,
+ (TSPAPIPROC)TSPI_LineBlank2,
+ (TSPAPIPROC)TSPI_LineBlank3,
+ (TSPAPIPROC)TSPI_LineBlank4,
+ (TSPAPIPROC)TSPI_LineBlank5,
+ (TSPAPIPROC)TSPI_LineBlank6,
+ (TSPAPIPROC)TSPI_LineBlank7
+ };
+
+ static TSPAPIPROC DefaultPhoneTable[] = {
+ (TSPAPIPROC)TSPI_PhoneBlank1,
+ (TSPAPIPROC)TSPI_PhoneBlank2,
+ (TSPAPIPROC)TSPI_PhoneBlank3,
+ (TSPAPIPROC)TSPI_PhoneBlank4,
+ (TSPAPIPROC)TSPI_PhoneBlank5,
+ (TSPAPIPROC)TSPI_PhoneBlank6,
+ (TSPAPIPROC)TSPI_PhoneBlank7
+ };
+
+ TSPAPIPROC *pfn;
+ TSPAPIPROC *FunctionTable;
+
+
+ //
+ // Find out if it's a phone function or a line function
+ //
+ if (
+ (iFunction >= TSPI_PHONECLOSE)
+ &&
+ (iFunction <= TSPI_PHONESETVOLUME)
+ )
+ {
+ //
+ // It's a phone function
+ //
+ FunctionTable = DefaultPhoneTable;
+ }
+ else
+ {
+ //
+ // It's a line function
+ //
+ FunctionTable = DefaultLineTable;
+ }
+
+ if ( nNumParms > (sizeof(DefaultLineTable)/sizeof(TSPAPIPROC)) )
+ {
+ DBGOUT((1, ">Num funcs function was requested!"));
+ return 0;
+ }
+
+ pfn = &lpfnProcAddress[(iProvider*TSPI_PROC_LAST)+(iFunction-TSPI_PROC_BASE)];
+
+ if( NULL == *pfn )
+ {
+ *pfn = (TSPAPIPROC)GetProcAddress(
+ hProviders[iProvider],
+ (LPCSTR)iFunction
+ );
+
+ //
+ // Did it fail?
+ //
+ if( NULL == *pfn )
+ {
+ *pfn = FunctionTable[ nNumParms - 1 ];
+ }
+ }
+
+ return *pfn;
+ }
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+int iProviderFromDeviceID(DWORD dwDeviceID)
+ {
+ DWORD dwFirstDeviceIDonProvider = gdwLineDeviceIDBase;
+ int iProvider = 0;
+
+ // seeks the correct provider for this line
+ while(dwDeviceID >= dwFirstDeviceIDonProvider + dwNumLinesArray[iProvider])
+ {
+ dwFirstDeviceIDonProvider += dwNumLinesArray[iProvider];
+ ++iProvider;
+ }
+
+ return iProvider;
+ }
+
+
+//
+// ----------------------- 32-bit callback shells -----------------------------
+//
+
+
+//
+// We load up dwData with the 32bit callback address.
+//
+
+/* LPARAM of WM_COPYDATA */ /* ;Internal NT */
+typedef struct tagCOPYDATASTRUCT /* ;Internal NT */
+{ /* ;Internal NT */
+ DWORD dwData; /* ;Internal NT */
+ DWORD cbData; /* ;Internal NT */
+ LPSTR lpData; /* ;Internal NT */
+} COPYDATASTRUCT, FAR *LPCOPYDATASTRUCT; /* ;Internal NT */
+
+
+
+LINEEVENT PASCAL __loadds __export LineEventProc16(
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ DWORD LineEventStruct[6+1];
+
+ COPYDATASTRUCT cds = { 0,
+ sizeof(LineEventStruct),
+ (LPSTR)&LineEventStruct
+ };
+
+
+DBGOUT((1, "Line event callback"));
+DBGOUT((11, " htLine =0x%08lx", (DWORD)htLine));
+DBGOUT((11, " (Mapping htLine to 0x%08lx)", LineEventStruct[1]));
+DBGOUT((11, " htCall =0x%08lx", (DWORD)htCall));
+DBGOUT((11, " dwMsg =0x%08lx", dwMsg));
+DBGOUT((11, " dwParam1=0x%08lx", dwParam1));
+DBGOUT((11, " dwParam2=0x%08lx", dwParam2));
+DBGOUT((11, " dwParam3=0x%08lx", dwParam3));
+
+ cds.dwData = (DWORD)glpLineEventProc32;
+
+ LineEventStruct[0] = CALLBACK_LINEEVENT;
+ LineEventStruct[1] = (DWORD)htLine;
+ LineEventStruct[2] = (DWORD)htCall;
+ LineEventStruct[3] = dwMsg;
+ LineEventStruct[4] = dwParam1;
+ LineEventStruct[5] = dwParam2;
+ LineEventStruct[6] = dwParam3;
+
+
+ if (!IsBadReadPtr(htLine, sizeof(MYLINE)) )
+ {
+ LineEventStruct[1] = (DWORD)((LPMYLINE)htLine)->htLine;
+ }
+#if DBG
+ else
+ {
+ TSP3216SDebugString((1, "But the htLine was BAD!!!!"));
+ //return (LINEERR_INVALPARAM);
+ return LINEERR_INVALPOINTER;
+ }
+#endif
+
+
+
+ switch (dwMsg)
+ {
+ case LINE_LINEDEVSTATE:
+ {
+ TSP3216SDebugString((2, "Got a LINE_LINEDEVSTATE msg"));
+ }
+ break;
+
+
+ case LINE_NEWCALL:
+ {
+ LPMYCALL lpmCall;
+ LPMYLINE lpmLine;
+ int iProvider;
+ HDRVLINE REALhdLine;
+
+ TSP3216SDebugString((2, "Got a LINE_NEWCALL"));
+
+
+ lpmLine = (MYLINE *)htLine;
+ iProvider = lpmLine->iProvider;
+ REALhdLine = lpmLine->hdLine;
+
+
+ lpmCall = (MYCALL *)GlobalAllocPtr(GPTR, sizeof(MYCALL));
+
+ if(!lpmCall)
+ {
+ TSP3216SDebugString((1, "GlobalAlloc failed for hCall!"));
+ return LINEERR_NOMEM;
+
+ }
+
+ lpmCall->iProvider = iProvider;
+ lpmCall->dwDeviceID = lpmLine->dwDeviceID;
+
+
+ //
+ // Tell TAPI that _our_ hCall is the real one...
+ // (and save the one from the SP)
+ //
+ lpmCall->hdCall = (HDRVCALL)dwParam1;
+ LineEventStruct[4] = (DWORD)lpmCall;
+
+// //
+// // Give TAPI a pointer to _our_ mem to write _it's_ handle
+// //
+// *(LPHTAPICALL)dwParam2 = lpmCall;
+// LineEventStruct[5] = &(lpmCall->htCall);
+
+ }
+ break;
+
+ }
+
+
+
+
+ SendMessage( ghWnd, WM_COPYDATA, NULL, (LPARAM)&cds );
+
+#if DBG
+ if ( LINE_NEWCALL == dwMsg )
+ {
+ DBGOUT((11, "Returned htCall=0x%08lx", *((LPDWORD)dwParam2) ));
+ }
+#endif
+
+}
+
+
+PHONEEVENT PASCAL __loadds __export PhoneEventProc16(
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ DWORD PhoneEventStruct[5+1];
+
+ COPYDATASTRUCT cds = { 0,
+ sizeof(PhoneEventStruct),
+ (LPSTR)&PhoneEventStruct
+ };
+
+
+DBGOUT((1, "Phone event callback"));
+DBGOUT((11, " htPhone =0x%08lx", (DWORD)htPhone));
+DBGOUT((11, " dwMsg =0x%08lx", dwMsg));
+DBGOUT((11, " dwParam1=0x%08lx", dwParam1));
+DBGOUT((11, " dwParam2=0x%08lx", dwParam2));
+DBGOUT((11, " dwParam3=0x%08lx", dwParam3));
+
+
+ cds.dwData = (DWORD)glpPhoneEventProc32;
+
+ PhoneEventStruct[0] = CALLBACK_PHONEEVENT;
+ PhoneEventStruct[1] = (DWORD)htPhone;
+ PhoneEventStruct[2] = dwMsg;
+ PhoneEventStruct[3] = dwParam1;
+ PhoneEventStruct[4] = dwParam2;
+ PhoneEventStruct[5] = dwParam3;
+
+ SendMessage( ghWnd, WM_COPYDATA, NULL, (LPARAM)&cds );
+
+ return 0;
+}
+
+
+
+
+
+ASYNC_COMPLETION PASCAL __export __loadds AsyncCompletionProc16(DRV_REQUESTID dwRequestID,
+ LONG lResult)
+{
+ DWORD AsyncCompletionStruct[2+1];
+
+ COPYDATASTRUCT cds = { 0,
+ sizeof(AsyncCompletionStruct),
+ (LPSTR)&AsyncCompletionStruct
+ };
+
+
+DBGOUT((1, "Async completion callback"));
+DBGOUT((11, " dwRequestID=0x%08lx", dwRequestID));
+DBGOUT((11, " lResult =0x%08lx", lResult));
+
+
+ if ( BOGUS_REQUEST_ID == dwRequestID )
+ {
+ DBGOUT((2, " This is a reply we should ignore"));
+ //BUGBUG: maybe: If there's an error returned, should we return that?
+ return 0;
+ }
+
+ cds.dwData = (DWORD)glpAsyncCompletionProc32;
+
+ AsyncCompletionStruct[0] = CALLBACK_ASYNCCOMPLETION;
+ AsyncCompletionStruct[1] = dwRequestID;
+ AsyncCompletionStruct[2] = lResult;
+
+
+ SendMessage( ghWnd, WM_COPYDATA, NULL, (LPARAM)&cds );
+}
+
+
+
+LINEEVENT PASCAL __loadds __export LineCreateProc16(
+ HTAPILINE htLine,
+ HTAPICALL htCall,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+ DWORD LineCreateStruct[6+1];
+
+ COPYDATASTRUCT cds = { 0,
+ sizeof(LineCreateStruct),
+ (LPSTR)&LineCreateStruct
+ };
+
+
+DBGOUT((1, "Line Create callback"));
+
+ cds.dwData = (DWORD)glpLineCreateProc32;
+
+ LineCreateStruct[0] = CALLBACK_LINECREATE;
+ LineCreateStruct[1] = (DWORD)htLine;
+ LineCreateStruct[2] = (DWORD)htCall;
+ LineCreateStruct[3] = dwMsg;
+ LineCreateStruct[4] = dwParam1;
+ LineCreateStruct[5] = dwParam2;
+ LineCreateStruct[6] = dwParam3;
+
+
+ SendMessage( ghWnd, WM_COPYDATA, NULL, (LPARAM)&cds );
+
+ return 0;
+}
+
+
+
+PHONEEVENT PASCAL __loadds __export PhoneCreateProc16(
+ HTAPIPHONE htPhone,
+ DWORD dwMsg,
+ DWORD dwParam1,
+ DWORD dwParam2,
+ DWORD dwParam3
+ )
+{
+
+ DWORD PhoneCreateStruct[5 + 1];
+
+ COPYDATASTRUCT cds = { 0,
+ sizeof(PhoneCreateStruct),
+ (LPSTR)&PhoneCreateStruct
+ };
+
+
+DBGOUT((1, "Phone Create callback"));
+
+ cds.dwData = (DWORD)glpPhoneCreateProc32;
+
+ PhoneCreateStruct[0] = CALLBACK_PHONECREATE;
+ PhoneCreateStruct[1] = (DWORD)htPhone;
+ PhoneCreateStruct[2] = dwMsg;
+ PhoneCreateStruct[3] = dwParam1;
+ PhoneCreateStruct[4] = dwParam2;
+ PhoneCreateStruct[5] = dwParam3;
+
+
+ SendMessage( ghWnd, WM_COPYDATA, NULL, (LPARAM)&cds );
+
+ return 0;
+}
+
+
+
+//
+// -------------------- TSPIAPI TSPI_line functions ---------------------------
+//
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineAccept(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineAccept"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEACCEPT, 4))(
+ dwRequestID,
+ REALhdCall,
+ lpsUserUserInfo,
+ dwSize);
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HDRVCALL hdConsultCall
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdConfCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ LPMYCALL lpmConsultCall = (MYCALL *)hdConsultCall;
+ HDRVCALL REALhdConsultCall = lpmConsultCall->hdCall;
+
+
+ TSP3216SDebugString((2, "Entering TSPI_lineAddToConference"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEADDTOCONFERENCE,3))(
+ dwRequestID,
+ REALhdCall,
+ REALhdConsultCall);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineAnswer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineAnswer"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEANSWER, 4))(
+ dwRequestID,
+ REALhdCall,
+ lpsUserUserInfo,
+ dwSize);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineBlindTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode)
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineBlindTransfer"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEBLINDTRANSFER, 4))(
+ dwRequestID,
+ REALhdCall,
+ lpszDestAddress,
+ dwCountryCode
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineClose(
+ HDRVLINE hdLine
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineClose"));
+
+ GlobalFreePtr((LPVOID)lpmLine);
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINECLOSE, 1))(REALhdLine);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineCloseCall(
+ HDRVCALL hdCall
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineCloseCall"));
+
+ GlobalFreePtr((LPVOID)lpmCall);
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINECLOSECALL, 1))(REALhdCall);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineCompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPDWORD lpdwCompletionID,
+ DWORD dwCompletionMode,
+ DWORD dwMessageID
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineCompleteCall"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINECOMPLETECALL, 5))(
+ dwRequestID,
+ REALhdCall,
+ lpdwCompletionID,
+ dwCompletionMode,
+ REALhdCall
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineCompleteTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVCALL hdConsultCall,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ DWORD dwTransferMode
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ LPMYCALL lpmConsultCall = (MYCALL *)hdConsultCall;
+ HDRVCALL REALhdConsultCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineCompleteTransfer"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+
+// NEED TO DO the work for lphdConfCall
+//
+// return (* GetProcAddressHashed(iProvider, TSPI_LINECOMPLETETRANSFER, 5))(
+// dwRequestID,
+// REALhdCall,
+// lpdwCompletionID,
+// dwCompletionMode,
+// REALhdCall
+// );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineConditionalMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineConditionalMediaDetection"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_LINECONDITIONALMEDIADETECTION, 3))(
+ REALhdLine,
+ dwMediaModes,
+ lpCallParams);
+
+ TSP3216SDebugString((2, "Leaving TSPI_lineConditionalMediaDetection"));
+ return lResult;
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+ {
+
+ int iProvider;
+
+#if DBG
+ LONG lResult = 0;
+#endif
+
+
+ TSP3216SDebugString((2, "Entering TSPI_lineConfigDialog"));
+ TSP3216SDebugString((11, " dwDeviceID=0x%08lx", dwDeviceID));
+ TSP3216SDebugString((11, " hwndOwner=0x%08lx", (DWORD)hwndOwner));
+ TSP3216SDebugString((11, " lpszDeviceClass=0x%08lx", lpszDeviceClass));
+#if DBG
+ if ( !IsBadStringPtr(lpszDeviceClass, 1) )
+ TSP3216SDebugString((11, " *lpszDeviceClass=[%s]", lpszDeviceClass));
+#endif
+
+_asm int 1;
+
+ iProvider = iProviderFromDeviceID(dwDeviceID);
+
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINECONFIGDIALOG, 3))(
+ dwDeviceID,
+ hwndOwner,
+ lpszDeviceClass
+ );
+
+#if DBG
+ return lResult;
+#endif
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineConfigDialogEdit(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass,
+ LPVOID const lpDeviceConfigIn,
+ DWORD dwSize,
+ LPVARSTRING lpDeviceConfigOut
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineConfigDialogEdit"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineDevSpecific"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineDevSpecificFeature(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwFeature,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineDevSpecificFeature"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineDial(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineDial"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEDIAL, 4))(
+ dwRequestID,
+ REALhdCall,
+ lpszDestAddress,
+ dwCountryCode
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineDrop(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineDrop"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEDROP, 4))(
+ dwRequestID,
+ REALhdCall,
+ lpsUserUserInfo,
+ dwSize
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineDropOnClose(
+ HDRVCALL hdCall
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineDropOnClose"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEDROPONCLOSE, 1))(
+ REALhdCall
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineDropNoOwner(
+ HDRVCALL hdCall
+ )
+{
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSPAPIPROC *pfn;
+ LONG lResult;
+
+
+ TSP3216SDebugString((2, "Entering TSPI_lineDropNoOwner"));
+
+
+ pfn = (TSPAPIPROC)GetProcAddressHashed(iProvider, TSPI_LINEDROPNOOWNER, 1);
+
+ if (pfn == (TSPAPIPROC)TSPI_LineBlank1)
+ {
+ lResult = (*pfn)( REALhdCall );
+ }
+ else
+ {
+ TSP3216SDebugString((4, " This SP does not export DROPNOOWNER, so we'll call LINEDROP"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_LINEDROP, 4))(
+ (DWORD) BOGUS_REQUEST_ID,
+ (DWORD) REALhdCall,
+ (DWORD) NULL,
+ (DWORD) 0
+ );
+
+ //
+ // Did we get an error back sync?
+ //
+ if (
+ (lResult < 0)
+ &&
+ (lResult != BOGUS_REQUEST_ID)
+ )
+ {
+ //
+ // Yup. Return it.
+ //
+ }
+ else
+ {
+ //
+ // No, we got back the req id. Return success.
+ //
+ lResult = 0;
+ }
+ }
+
+ TSP3216SDebugString((3, "Leaving TSPI_lineDropNoOwner, return code=0x%08lx", lResult));
+ return lResult;
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineForward(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD bAllAddresses,
+ DWORD dwAddressID,
+ LPLINEFORWARDLIST const lpForwardList,
+ DWORD dwNumRingsNoAnswer,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineForward"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGatherDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitModes,
+ LPSTR lpsDigits,
+ DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineGatherDigits"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGenerateDigits(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwDigitMode,
+ LPCSTR lpszDigits,
+ DWORD dwDuration
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGenerateDigits"));
+ TSP3216SDebugString((11, " hdCall =0x%08lx", hdCall));
+ TSP3216SDebugString((11, " dwEndToEndID=0x%08lx", dwEndToEndID));
+ TSP3216SDebugString((11, " lpszDigits =0x%08lx", lpszDigits));
+ TSP3216SDebugString((12, " *lpszDigits =%s", lpszDigits));
+ TSP3216SDebugString((11, " dwDuration =0x%08lx", dwDuration));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGENERATEDIGITS, 5))(
+ REALhdCall,
+ dwEndToEndID,
+ dwDigitMode,
+ lpszDigits,
+ dwDuration );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGenerateTone(
+ HDRVCALL hdCall,
+ DWORD dwEndToEndID,
+ DWORD dwToneMode,
+ DWORD dwDuration,
+ DWORD dwNumTones,
+ LPLINEGENERATETONE const lpTones
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGenerateTone"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGENERATETONE, 6))(
+ REALhdCall,
+ dwEndToEndID,
+ dwToneMode,
+ dwDuration,
+ dwNumTones,
+ lpTones );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetAddressCaps(
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEADDRESSCAPS lpAddressCaps
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ DWORD dwFirstDeviceIDonProvider = gdwLineDeviceIDBase;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetAddressCaps"));
+
+ return(* GetProcAddressHashed(iProvider, TSPI_LINEGETADDRESSCAPS, 5))(
+ dwDeviceID,
+ dwAddressID,
+ dwTSPIVersion,
+ dwExtVersion,
+ lpAddressCaps
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetAddressID(
+ HDRVLINE hdLine,
+ LPDWORD lpdwAddressID,
+ DWORD dwAddressMode,
+ LPCSTR lpsAddress,
+ DWORD dwSize
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetAddressID"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETADDRESSID, 5))(
+ REALhdLine,
+ lpdwAddressID,
+ dwAddressMode,
+ lpsAddress,
+ dwSize
+ );
+
+#if DBG
+ TSP3216SDebugString((2, "Leaving TSPI_lineGetAddressID"));
+ return lResult;
+#endif
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetAddressStatus(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ LPLINEADDRESSSTATUS lpAddressStatus
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetAddressStatus"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_LINEGETADDRESSSTATUS, 3))(
+ REALhdLine,
+ dwAddressID,
+ lpAddressStatus);
+
+ TSP3216SDebugString((2, "Leaving TSPI_lineGetAddressStatus"));
+ return lResult;
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetCallAddressID(
+ HDRVCALL hdCall,
+ LPDWORD lpdwAddressID
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetCallAddressID"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETCALLADDRESSID, 2))(
+ REALhdCall,
+ lpdwAddressID
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetCallInfo(
+ HDRVCALL hdCall,
+ LPLINECALLINFO lpCallInfo
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetCallInfo"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETCALLINFO, 2))(
+ REALhdCall,
+ lpCallInfo
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetCallStatus(
+ HDRVCALL hdCall,
+ LPLINECALLSTATUS lpCallStatus
+ )
+ {
+
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetCallStatus"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEGETCALLSTATUS, 2))(
+ REALhdCall,
+ lpCallStatus
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+ TSP3216SDebugString((2, "...debugmode..."));
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetDevCaps"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETDEVCAPS, 4))(
+ dwDeviceID,
+ dwTSPIVersion,
+ dwExtVersion,
+ lpLineDevCaps
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineGetDevCaps retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetDevConfig(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCSTR lpszDeviceClass
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetDevConfig"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETDEVCONFIG, 3))(
+ dwDeviceID,
+ lpDeviceConfig,
+ lpszDeviceClass
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineGetDevConfig retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPLINEEXTENSIONID lpExtensionID
+ )
+{
+
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ TSPAPIPROC lpfn;
+#if DBG
+ LONG lResult = 0;
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetExtensionID"));
+
+ lpfn = (TSPAPIPROC)GetProcAddressHashed(iProvider, TSPI_LINEGETEXTENSIONID, 3);
+
+ if (lpfn != TSPI_LineBlank3)
+ {
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (*lpfn)(
+ dwDeviceID,
+ dwTSPIVersion,
+ lpExtensionID
+ );
+ }
+ else
+ {
+ TSP3216SDebugString((2, " SP# %d does not support TSPI_lineGetExtensionID. (We'll fill in zeros.)", iProvider));
+
+ lpExtensionID->dwExtensionID0 = 0;
+ lpExtensionID->dwExtensionID1 = 0;
+ lpExtensionID->dwExtensionID2 = 0;
+ lpExtensionID->dwExtensionID3 = 0;
+ }
+
+
+
+#if DBG
+ TSP3216SDebugString((2, "Leaving TSPI_lineGetExtensionID retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetIcon(
+ DWORD dwDeviceID,
+ LPCSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetIcon"));
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINEGETICON, 3))(
+ dwDeviceID,
+ lpszDeviceClass,
+ lphIcon
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineGetIcon retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetID16(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+ {
+ LPMYLINE lpmLine = 0;
+ int iProvider = 0;
+ HDRVLINE REALhdLine = 0;
+
+ LONG lResult;
+
+ LPMYCALL lpmCall = 0;
+ HDRVCALL REALhdCall = 0;
+
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetID"));
+
+
+ switch ( dwSelect )
+ {
+ case LINECALLSELECT_LINE:
+ {
+ lpmLine = (MYLINE *)hdLine;
+ iProvider = lpmLine->iProvider;
+ REALhdLine = lpmLine->hdLine;
+ }
+ break;
+
+
+ case LINECALLSELECT_ADDRESS:
+ {
+ lpmLine = (MYLINE *)hdLine;
+ iProvider = lpmLine->iProvider;
+ REALhdLine = lpmLine->hdLine;
+ }
+ break;
+
+
+ case LINECALLSELECT_CALL:
+ {
+ lpmCall = (MYCALL *)hdCall;
+ REALhdCall = lpmCall->hdCall;
+ }
+ break;
+
+
+ default:
+ TSP3216SDebugString((2, "Leaving TSPI_lineGetID - 2lResult=0x%08lx", lResult));
+ return LINEERR_INVALPARAM;
+ }
+
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_LINEGETID, 6))(
+ REALhdLine,
+ dwAddressID,
+ REALhdCall,
+ dwSelect,
+ lpDeviceID,
+ lpszDeviceClass );
+
+ TSP3216SDebugString((2, "Leaving TSPI_lineGetID - lResult=0x%08lx", lResult));
+ return lResult;
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetLineDevStatus(
+ HDRVLINE hdLine,
+ LPLINEDEVSTATUS lpLineDevStatus
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetLineDevStatus"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_LINEGETLINEDEVSTATUS, 2))(
+ REALhdLine,
+ lpLineDevStatus);
+
+ TSP3216SDebugString((2, "Leaving TSPI_lineGetLineDevStatus"));
+ return lResult;
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineGetNumAddressIDs(
+ HDRVLINE hdLine,
+ LPDWORD lpdwNumAddressIDs
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+ LONG lResult;
+
+
+ TSP3216SDebugString((2, "Entering TSPI_lineGetNumAddressIDs"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_LINEGETNUMADDRESSIDS, 2))(
+ REALhdLine,
+ lpdwNumAddressIDs );
+
+ TSP3216SDebugString((2, "Leaving TSPI_lineGetNumAddressIDs - returning 0x%08lx", lResult));
+ return lResult;
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineHold"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEHOLD, 2))(
+ dwRequestID,
+ REALhdCall
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineMakeCall16(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+ LPMYCALL lpmCall;
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineMakeCall16"));
+ DBGOUT((11, " dwRequestID = 0x%08lx", dwRequestID));
+ DBGOUT((11, " *lpszDestAddress = [%s]", lpszDestAddress));
+ DBGOUT((11, " dwCountryCode = 0x%08lx", dwCountryCode));
+
+ lpmCall = (MYCALL *)GlobalAllocPtr(GPTR, sizeof(MYCALL));
+ if(!lpmCall)
+ return(LINEERR_NOMEM);
+
+ *lphdCall = (HDRVCALL)lpmCall;
+
+ lpmCall->htCall = htCall;
+ lpmCall->iProvider = iProvider;
+ lpmCall->dwDeviceID = lpmLine->dwDeviceID;
+
+ lResult = (* GetProcAddressHashed(lpmCall->iProvider, TSPI_LINEMAKECALL, 7))(
+ dwRequestID,
+ REALhdLine,
+ htCall, // WAS SECONDLY (HTAPICALL)lpmCall, // Was htCall,
+ &(lpmCall->hdCall),
+ lpszDestAddress,
+ dwCountryCode,
+ lpCallParams
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_lineMakeCall16 - returning 0x%08lx", lResult));
+ return lResult;
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineMonitorDigits(
+ HDRVCALL hdCall,
+ DWORD dwDigitModes
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineMonitorDigits"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEMONITORDIGITS, 2))(
+ REALhdCall,
+ dwDigitModes
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineMonitorMedia(
+ HDRVCALL hdCall,
+ DWORD dwMediaModes
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineMonitorMedia"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEMONITORMEDIA, 2))(
+ REALhdCall,
+ dwMediaModes
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineMonitorTones(
+ HDRVCALL hdCall,
+ DWORD dwToneListID,
+ LPLINEMONITORTONE const lpToneList,
+ DWORD dwNumEntries
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineMonitorTones"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINEMONITORTONES, 4))(
+ REALhdCall,
+ dwToneListID,
+ lpToneList,
+ dwNumEntries
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+ {
+
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_lineNegotiateExtVersion"));
+
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_LINENEGOTIATEEXTVERSION, 5))(
+ dwDeviceID,
+ dwTSPIVersion,
+ dwLowVersion,
+ dwHighVersion,
+ lpdwExtVersion
+ );
+
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineNegotiateExeVersion retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineNegotiateTSPIVersion"));
+
+//BUGBUG Need to call to service providers and keep track of their
+// versions, no?
+
+ *lpdwTSPIVersion = TAPI_CUR_VER;
+
+ return(0);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineOpen(
+ DWORD dwDeviceID,
+ HTAPILINE htLine,
+ LPHDRVLINE lphdLine,
+ DWORD dwTSPIVersion,
+ LINEEVENT lpfnEventProc
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ LPMYLINE lpmLine;
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_lineOpen"));
+ TSP3216SDebugString((11, " dwDeviceID =0x%08lx", dwDeviceID));
+ TSP3216SDebugString((11, " htLine =0x%08lx", htLine));
+ TSP3216SDebugString((11, " lphdLine =0x%08lx", lphdLine));
+ TSP3216SDebugString((11, " dwTSPIVersion=0x%08lx", dwTSPIVersion));
+ TSP3216SDebugString((11, " lpfnEventProc=0x%08lx", lpfnEventProc));
+
+
+ glpLineEventProc32 = lpfnEventProc;
+
+
+ lpmLine = (MYLINE *)GlobalAllocPtr(GPTR, sizeof(MYLINE));
+ if(!lpmLine)
+ return(LINEERR_NOMEM);
+
+ *lphdLine = (HDRVLINE)lpmLine;
+
+ lpmLine->iProvider = iProvider;
+ lpmLine->dwDeviceID = dwDeviceID;
+ lpmLine->htLine = htLine;
+ lpmLine->lpfnEventProc = lpfnEventProc;
+
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+
+ (* GetProcAddressHashed(iProvider, TSPI_LINEOPEN, 5))(
+ dwDeviceID,
+ (HTAPILINE)lpmLine, // was htLine
+ &(lpmLine->hdLine),
+ dwTSPIVersion,
+ LineEventProc16
+ );
+
+#if DBG
+ DBGOUT((2, "Leaving TSPI_lineOpen retcode=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_linePark(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwParkMode,
+ LPCSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_linePark"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_linePickup(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress,
+ LPCSTR lpszGroupID
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_linePickup"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_linePrepareAddToConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_linePrepareAddToConference"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineRedirect(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineRedirect"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineRemoveFromConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineRemoveFromConference"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSecureCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSecureCall"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSelectExtVersion(
+ HDRVLINE hdLine,
+ DWORD dwExtVersion
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSelectExtVersion"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSendUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSendUserUserInfo"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetAppSpecific(
+ HDRVCALL hdCall,
+ DWORD dwAppSpecific
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineSetAppSpecific"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINESETAPPSPECIFIC, 2))(
+ REALhdCall,
+ dwAppSpecific
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetCallParams(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ DWORD dwBearerMode,
+ DWORD dwMinRate,
+ DWORD dwMaxRate,
+ LPLINEDIALPARAMS const lpDialParams
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineSetCallParams"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINESETCALLPARAMS, 6))(
+ dwRequestID,
+ REALhdCall,
+ dwBearerMode,
+ dwMinRate,
+ dwMaxRate,
+ lpDialParams
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetCurrentLocation(
+ DWORD dwLocation
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSetCurrentLocation"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetDefaultMediaDetection(
+ HDRVLINE hdLine,
+ DWORD dwMediaModes
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineSetDefaultMediaDetection"));
+
+ return (* GetProcAddressHashed(
+ iProvider,
+ TSPI_LINESETDEFAULTMEDIADETECTION,
+ 2
+ ))(REALhdLine, dwMediaModes);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetDevConfig(
+ DWORD dwDeviceID,
+ LPVOID const lpDeviceConfig,
+ DWORD dwSize,
+ LPCSTR lpszDeviceClass
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ DWORD dwFirstDeviceIDonProvider = gdwLineDeviceIDBase;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineSetDevConfig"));
+
+ return(* GetProcAddressHashed(iProvider, TSPI_LINESETDEVCONFIG, 4))(
+ dwDeviceID,
+ lpDeviceConfig,
+ dwSize,
+ lpszDeviceClass
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetMediaControl(
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ LPLINEMEDIACONTROLDIGIT const lpDigitList,
+ DWORD dwDigitNumEntries,
+ LPLINEMEDIACONTROLMEDIA const lpMediaList,
+ DWORD dwMediaNumEntries,
+ LPLINEMEDIACONTROLTONE const lpToneList,
+ DWORD dwToneNumEntries,
+ LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
+ DWORD dwCallStateNumEntries
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSetMediaControl"));
+
+
+ // dwSelect!!!
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetMediaMode(
+ HDRVCALL hdCall,
+ DWORD dwMediaMode
+ )
+ {
+ LPMYCALL lpmCall = (MYCALL *)hdCall;
+ int iProvider = lpmCall->iProvider;
+ HDRVCALL REALhdCall = lpmCall->hdCall;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineSetMediaMode"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINESETMEDIAMODE, 2))(
+ REALhdCall,
+ dwMediaMode
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetStatusMessages(
+ HDRVLINE hdLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+ {
+ LPMYLINE lpmLine = (MYLINE *)hdLine;
+ int iProvider = lpmLine->iProvider;
+ HDRVLINE REALhdLine = lpmLine->hdLine;
+
+ TSP3216SDebugString((2, "Entering TSPI_lineSetStatusMessages"));
+
+ return (* GetProcAddressHashed(iProvider, TSPI_LINESETSTATUSMESSAGES, 3))(
+ REALhdLine,
+ dwLineStates,
+ dwAddressStates
+ );
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetTerminal(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HDRVCALL hdCall,
+ DWORD dwSelect,
+ DWORD dwTerminalModes,
+ DWORD dwTerminalID,
+ DWORD bEnable
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSetTerminal"));
+
+ // dwSelect!!!
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetupConference(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HDRVLINE hdLine,
+ HTAPICALL htConfCall,
+ LPHDRVCALL lphdConfCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ DWORD dwNumParties,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSetupConference"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSetupTransfer(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall,
+ HTAPICALL htConsultCall,
+ LPHDRVCALL lphdConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSetupTransfer"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineSwapHold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdActiveCall,
+ HDRVCALL hdHeldCall
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineSwapHold"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineUncompleteCall(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwCompletionID
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineUncompleteCall"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineUnhold(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineUnhold"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineUnpark(
+ DRV_REQUESTID dwRequestID,
+ HDRVLINE hdLine,
+ DWORD dwAddressID,
+ HTAPICALL htCall,
+ LPHDRVCALL lphdCall,
+ LPCSTR lpszDestAddress
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineUnpark"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+LONG
+TSPIAPI
+TSPI_lineReleaseUserUserInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVCALL hdCall
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_lineReleaseUserUserInfo"));
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+
+//
+// ----------------------- TSPIAPI TSPI_phone functions -----------------------
+//
+
+LONG
+TSPIAPI
+TSPI_phoneClose(
+ HDRVPHONE hdPhone
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneClose"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONECLOSE, 1))(
+ REALhdPhone
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneClose - lResult=0x%08lx", lResult));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneConfigDialog(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCSTR lpszDeviceClass
+ )
+ {
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneDevSpecific(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneDevSpecific"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetButtonInfo(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO lpButtonInfo
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetButtonInfo"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetData(
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID lpData,
+ DWORD dwSize
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetData"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDevCaps(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwExtVersion,
+ LPPHONECAPS lpPhoneCaps
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetDevCaps"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONEGETDEVCAPS, 4))(
+ dwDeviceID,
+ //BUGBUG What version to send down here?
+ dwTSPIVersion,
+ //BUGBUG What version to send down here?
+ dwExtVersion,
+ lpPhoneCaps
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetDevCaps"));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetDisplay(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDisplay
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetDisplay"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetExtensionID(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ LPPHONEEXTENSIONID lpExtensionID
+ )
+{
+ LONG lResult;
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ FARPROC lpfn;
+
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetExtensionID"));
+
+
+ lpfn = GetProcAddressHashed(iProvider, TSPI_PHONEGETEXTENSIONID, 3);
+
+ //
+ // Does this service provider export this function?
+ //
+ if (lpfn != TSPI_PhoneBlank3)
+ {
+ lResult = (* lpfn)(
+ dwDeviceID,
+ dwTSPIVersion,
+ lpExtensionID
+ );
+ }
+ else
+ {
+ //
+ // Nope. Fill it fulla rocks.
+ //
+ TSP3216SDebugString((2, " SP# %ld does not support TSPI_phoneGetExtensionID. (We'll zero it)", (DWORD)iProvider));
+
+ lpExtensionID->dwExtensionID0 = 0;
+ lpExtensionID->dwExtensionID1 = 0;
+ lpExtensionID->dwExtensionID2 = 0;
+ lpExtensionID->dwExtensionID3 = 0;
+
+ lResult = 0;
+ }
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetExtensionID - lResult=0x%08lx",lResult));
+ return lResult;
+}
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetGain(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwGain
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetGain"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONEGETGAIN, 3))(
+ REALhdPhone,
+ dwHookSwitchDev,
+ lpdwGain
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetGain"));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetHookSwitch(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwHookSwitchDevs
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetHookSwitch"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONEGETHOOKSWITCH, 2))(
+ REALhdPhone,
+ lpdwHookSwitchDevs
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetHoosSwitch"));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetIcon(
+ DWORD dwDeviceID,
+ LPCSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetIcon"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONEGETICON, 3))(
+ dwDeviceID,
+ lpszDeviceClass,
+ lphIcon
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetIcon"));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetID16(
+ HDRVPHONE hdPhone,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetID"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONEGETID, 3))(
+ REALhdPhone,
+ lpDeviceID,
+ lpszDeviceClass
+ );
+
+//BUGBUG - Do we have to dupe the handle like on lineGetID?
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetID - lResult=0x%08lx",
+ lResult));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetLamp(
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPDWORD lpdwLampMode
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetLamp"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetRing(
+ HDRVPHONE hdPhone,
+ LPDWORD lpdwRingMode,
+ LPDWORD lpdwVolume
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetRing"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetStatus(
+ HDRVPHONE hdPhone,
+ LPPHONESTATUS lpPhoneStatus
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetStatus"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONEGETSTATUS, 2))(
+ REALhdPhone,
+ lpPhoneStatus
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetStatus - lResult=0x%08lx",
+ lResult));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneGetVolume(
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ LPDWORD lpdwVolume
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneGetVolume"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONEGETVOLUME, 3))(
+ REALhdPhone,
+ dwHookSwitchDev,
+ lpdwVolume
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneGetVolume - lResult=0x%08lx",
+ lResult));
+
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateExtVersion(
+ DWORD dwDeviceID,
+ DWORD dwTSPIVersion,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwExtVersion
+ )
+ {
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneNegotiateExtVersion"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneNegotiateTSPIVersion(
+ DWORD dwDeviceID,
+ DWORD dwLowVersion,
+ DWORD dwHighVersion,
+ LPDWORD lpdwTSPIVersion
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneNegotiateTSPIVersion"));
+
+ *lpdwTSPIVersion = TAPI_CUR_VER;
+
+ return(0);
+// return (* GetProcAddressHashed(iProvider, TSPI_PHONEOPEN, 4))(
+// dwDeviceID,
+// dwLowVersion,
+// dwHighVersion,
+// lpdwTSPIVersion
+// );
+//
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneOpen(
+ DWORD dwDeviceID,
+ HTAPIPHONE htPhone,
+ LPHDRVPHONE lphdPhone,
+ DWORD dwTSPIVersion,
+ PHONEEVENT lpfnEventProc
+ )
+ {
+ int iProvider = iProviderFromDeviceID(dwDeviceID);
+ LPMYPHONE lpmPhone;
+#if DBG
+ LONG lResult;
+#endif
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneOpen"));
+
+ glpPhoneEventProc32 = lpfnEventProc;
+
+ lpmPhone = (MYPHONE *)GlobalAllocPtr(GPTR, sizeof(MYPHONE));
+ if(!lpmPhone)
+ return(PHONEERR_NOMEM);
+
+ *lphdPhone = (HDRVPHONE)lpmPhone;
+
+ lpmPhone->iProvider = iProvider;
+ lpmPhone->dwDeviceID = dwDeviceID;
+ lpmPhone->htPhone = htPhone;
+ lpmPhone->lpfnEventProc = lpfnEventProc;
+
+#if DBG
+ lResult =
+#else
+ return
+#endif
+ (* GetProcAddressHashed(iProvider, TSPI_PHONEOPEN, 5))(
+ dwDeviceID,
+ htPhone, //WAS SECONDLY (HTAPIPHONE)lpmPhone, // was htPhone
+ &(lpmPhone->hdPhone),
+ dwTSPIVersion,
+ PhoneEventProc16
+ );
+
+#if DBG
+ TSP3216SDebugString((2, "Leaving TSPI_phoneOpen - lResult=0x%08lx", lResult));
+ return lResult;
+#endif
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSelectExtVersion(
+ HDRVPHONE hdPhone,
+ DWORD dwExtVersion
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneSelectExtVersion"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetButtonInfo(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO const lpButtonInfo
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetButtonInfo"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetData(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwDataID,
+ LPVOID const lpData,
+ DWORD dwSize
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetData"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetDisplay(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRow,
+ DWORD dwColumn,
+ LPCSTR lpsDisplay,
+ DWORD dwSize
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetDisplay"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetGain(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwGain
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetGain"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONESETGAIN, 4))(
+ dwRequestID,
+ REALhdPhone,
+ dwHookSwitchDev,
+ dwGain
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneSetGain - lResult=0x%08lx",
+ lResult));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetHookSwitch(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDevs,
+ DWORD dwHookSwitchMode
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetHookSwitch"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONESETHOOKSWITCH, 4))(
+ dwRequestID,
+ REALhdPhone,
+ dwHookSwitchDevs,
+ dwHookSwitchMode
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneSetHookSwitch - lResult=0x%08lx",
+ lResult));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetLamp(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwButtonLampID,
+ DWORD dwLampMode
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetLamp"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetRing(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwRingMode,
+ DWORD dwVolume
+ )
+ {
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetRing"));
+
+ return(THIS_PHONEFUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetStatusMessages(
+ HDRVPHONE hdPhone,
+ DWORD dwPhoneStates,
+ DWORD dwButtonModes,
+ DWORD dwButtonStates
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetStatusMessages"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONESETSTATUSMESSAGES, 4))(
+ REALhdPhone,
+ dwPhoneStates,
+ dwButtonModes,
+ dwButtonStates
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneSetStatusMessages"));
+ return lResult;
+ }
+
+
+LONG
+TSPIAPI
+TSPI_phoneSetVolume(
+ DRV_REQUESTID dwRequestID,
+ HDRVPHONE hdPhone,
+ DWORD dwHookSwitchDev,
+ DWORD dwVolume
+ )
+ {
+ LPMYPHONE lpmPhone = (MYPHONE *)hdPhone;
+ int iProvider = lpmPhone->iProvider;
+ HDRVPHONE REALhdPhone = lpmPhone->hdPhone;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_phoneSetVolume"));
+
+ lResult = (* GetProcAddressHashed(iProvider, TSPI_PHONESETVOLUME, 4))(
+ dwRequestID,
+ REALhdPhone,
+ dwHookSwitchDev,
+ dwVolume
+ );
+
+ TSP3216SDebugString((2, "Leaving TSPI_phoneSetVolume - lResult=0x%08lx",
+ lResult));
+ return lResult;
+ }
+
+
+
+
+//
+// ----------------------- TSPIAPI TSPI_provider functions --------------------
+//
+
+LONG
+TSPIAPI
+TSPI_providerConfig(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_providerInit16(
+ DWORD dwTSPIVersion,
+ DWORD dwPermanentProviderID,
+ DWORD dwLineDeviceIDBase,
+ DWORD dwPhoneDeviceIDBase,
+ DWORD dwNumLines,
+ DWORD dwNumPhones,
+ ASYNC_COMPLETION lpfnCompletionProc
+ )
+ {
+ int iProvider;
+ BOOL fAllFailed = TRUE;
+ LONG lResult;
+
+ TSP3216SDebugString((2, "Entering TSPI_providerInit"));
+DBGOUT((1, " Completion addr=0x%08lx", (DWORD)lpfnCompletionProc));
+
+ gdwLineDeviceIDBase = dwLineDeviceIDBase;
+ gdwPhoneDeviceIDBase = dwPhoneDeviceIDBase;
+
+ glpAsyncCompletionProc32 = lpfnCompletionProc;
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ {
+ DBGOUT((2, "TSPI_providerInit initializing provider #%d", iProvider));
+
+ if(!(lResult = (* GetProcAddressHashed(iProvider, TSPI_PROVIDERINIT, 7))(
+ dwTSPIVersion,
+ dwPermanentProviderIDArray[iProvider],
+ dwLineDeviceIDBase,
+ dwPhoneDeviceIDBase,
+ dwNumLinesArray[iProvider],
+ dwNumPhonesArray[iProvider],
+ AsyncCompletionProc16
+ )))
+ {
+ fAllFailed = FALSE; // if one succeeded, they didn't ALL fail
+ }
+#if DBG
+ else
+ {
+ DBGOUT((1, " provider # %d failed TSPI_PROVIDERINIT err=0x%08lx",
+ iProvider, lResult));
+ }
+#endif
+
+ dwLineDeviceIDBase += dwNumLinesArray[iProvider];
+ dwPhoneDeviceIDBase += dwNumPhonesArray[iProvider];
+ }
+
+ if(fAllFailed)
+ {
+ DBGOUT((2, "TSPI_providerInit: all 16bit providers failed init!"));
+ return(LINEERR_OPERATIONFAILED);
+ }
+ else
+ return(ERR_NONE);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_providerInstall(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_providerRemove(
+ HWND hwndOwner,
+ DWORD dwPermanentProviderID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_providerShutdown16(
+ DWORD dwTSPIVersion
+ )
+ {
+ int iProvider;
+
+ TSP3216SDebugString((2, "Entering TSPI_providerShutdown"));
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ (* GetProcAddressHashed(iProvider, TSPI_PROVIDERSHUTDOWN, 1))(
+ dwTSPIVersion
+ );
+
+ FreeAllMem();
+
+ return(ERR_NONE);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_providerEnumDevices16(
+ DWORD dwPermanentProviderID,
+ LPDWORD lpdwNumLines,
+ LPDWORD lpdwNumPhones,
+ HPROVIDER hProvider,
+ LINEEVENT lpfnLineCreateProc,
+ PHONEEVENT lpfnPhoneCreateProc,
+ HWND hSecretWnd
+ )
+ {
+ int iProvider;
+
+ TSP3216SDebugString((2, "Entering TSPI_providerEnumDevices"));
+
+
+ ghWnd = hSecretWnd;
+
+ glpLineCreateProc32 = lpfnLineCreateProc;
+ glpPhoneCreateProc32 = lpfnPhoneCreateProc;
+
+
+ PostMessage( ghWnd, TSP3216L_MESSAGE, 1,2);
+
+ InitializeSPs();
+ gdwPPID = dwPermanentProviderID;
+
+ *lpdwNumLines = 0;
+ *lpdwNumPhones = 0;
+
+ for(iProvider = 0; iProvider < NumProviders; ++iProvider)
+ {
+ TSPAPIPROC lpfn;
+
+
+ lpfn = GetProcAddressHashed(iProvider, TSPI_PROVIDERENUMDEVICES, 6);
+
+DBGOUT((1, " TSPI_providerEnumDevices: provider #%d - lpfn=0x%08lx",
+ iProvider, (DWORD)lpfn));
+
+ if (lpfn != TSPI_LineBlank6)
+ {
+ (*lpfn)(
+ dwPermanentProviderIDArray[iProvider],
+ &(dwNumLinesArray[iProvider]),
+ &(dwNumPhonesArray[iProvider]),
+ hProvider,
+ LineCreateProc16,
+ PhoneCreateProc16
+ );
+
+DBGOUT((1, " provider=%d #lines= %ld #phones= %ld",
+ iProvider,
+ dwNumLinesArray[iProvider],
+ dwNumPhonesArray[iProvider] ));
+
+
+ (*lpdwNumLines) += dwNumLinesArray[iProvider];
+ (*lpdwNumPhones) += dwNumPhonesArray[iProvider];
+ }
+
+ }
+
+ DBGOUT((2, " TSPI_providerEnumDevices: #providers=%d #lines= %d #phones= %d",
+ NumProviders,
+ *lpdwNumLines,
+ *lpdwNumPhones));
+
+ return(ERR_NONE);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_providerCreateLineDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+LONG
+TSPIAPI
+TSPI_providerCreatePhoneDevice(
+ DWORD dwTempID,
+ DWORD dwDeviceID
+ )
+ {
+
+ return(THIS_FUNCTION_UNDER_CONSTRUCTION);
+ }
+
+
+int CALLBACK
+LibMain(
+ HINSTANCE hDllInstance,
+ WORD wDataSeg,
+ WORD wHeapSize,
+ LPSTR lpszCmdLine
+ )
+ {
+
+#if DBG
+ OutputDebugString("TSP3216s: Libmain entered\r\n");
+#endif
+
+ ghThisInst = hDllInstance;
+
+ return(1); // success
+ }
+
+
+//int
+//DllEntryPoint(
+// HINSTANCE hDllInstance,
+// WORD wDataSeg,
+// WORD wHeapSize,
+// LPSTR lpszCmdLine
+// )
+
+
+BOOL FAR PASCAL __export TapiThk_ThunkConnect16( LPSTR, LPSTR, WORD, DWORD);
+BOOL FAR PASCAL __export TapiFThk_ThunkConnect16( LPSTR, LPSTR, WORD, DWORD);
+
+BOOL FAR PASCAL __export Tapi32_ThunkConnect16( LPSTR, LPSTR, WORD, DWORD);
+
+
+BOOL FAR PASCAL __export DllEntryPoint(
+ DWORD dwReason,
+ WORD hInst,
+ WORD wDS,
+ WORD wHeapSize,
+ DWORD dwReserved1,
+ WORD dwReserved2
+ )
+ {
+// static UINT nUseCount = 0;
+// UINT n;
+
+
+ DBGOUT((1, "DllEntryPoint entered reason=%lx\r\n", dwReason));
+
+
+// if ( dwReason == 0 )
+// nUseCount--;
+
+ if ( dwReason == 1 )
+ {
+ TapiThk_ThunkConnect16( "TSP3216S.DLL", "TSP3216L.TSP", hInst, dwReason);
+ TapiFThk_ThunkConnect16( "TSP3216S.DLL", "TSP3216L.TSP", hInst, dwReason);
+
+ Tapi32_ThunkConnect16( "TSP3216S.DLL", "TSP3216L.TSP", hInst, dwReason);
+
+
+// nUseCount++;
+ }
+
+// if (dwReason == 0)
+// {
+// for ( n=0; n<NumProviders; n++)
+// {
+// FreeLibrary(hProviders[n]);
+// }
+// }
+
+
+ return(1); // success
+ }
+
+WORD CALLBACK _loadds
+NewData(
+ )
+ {
+ return (ghThisInst); // success
+ }
+
+DWORD CALLBACK _loadds
+NewData2(
+ )
+ {
+// return (DWORD)&_TapiCallbackThunk;
+ return 0;
+ }
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.def b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.def
new file mode 100644
index 000000000..e4da6dac0
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.def
@@ -0,0 +1,132 @@
+LIBRARY TSP3216s
+PROTMODE
+CODE MOVEABLE DISCARDABLE
+DATA PRELOAD
+
+EXPORTS
+ TSPI_lineAccept
+ TSPI_lineAddToConference
+ TSPI_lineAnswer
+ TSPI_lineBlindTransfer
+ TSPI_lineClose
+ TSPI_lineCloseCall
+ TSPI_lineCompleteCall
+ TSPI_lineCompleteTransfer
+ TSPI_lineConditionalMediaDetection
+ TSPI_lineConfigDialog
+ TSPI_lineDevSpecific
+ TSPI_lineDevSpecificFeature
+ TSPI_lineDial
+ TSPI_lineDrop
+ TSPI_lineForward
+ TSPI_lineGatherDigits
+ TSPI_lineGenerateDigits
+ TSPI_lineGenerateTone
+ TSPI_lineGetAddressCaps
+ TSPI_lineGetAddressID
+ TSPI_lineGetAddressStatus
+ TSPI_lineGetCallAddressID
+ TSPI_lineGetCallInfo
+ TSPI_lineGetCallStatus
+ TSPI_lineGetDevCaps
+ TSPI_lineGetDevConfig
+ TSPI_lineGetExtensionID
+ TSPI_lineGetIcon
+ TSPI_lineGetID16
+ TSPI_lineGetLineDevStatus
+ TSPI_lineGetNumAddressIDs
+ TSPI_lineHold
+ TSPI_lineMakeCall16
+ TSPI_lineMonitorDigits
+ TSPI_lineMonitorMedia
+ TSPI_lineMonitorTones
+ TSPI_lineNegotiateExtVersion
+ TSPI_lineNegotiateTSPIVersion
+ TSPI_lineOpen
+ TSPI_linePark
+ TSPI_linePickup
+ TSPI_linePrepareAddToConference
+ TSPI_lineRedirect
+ TSPI_lineRemoveFromConference
+ TSPI_lineSecureCall
+ TSPI_lineSelectExtVersion
+ TSPI_lineSendUserUserInfo
+ TSPI_lineSetAppSpecific
+ TSPI_lineSetCallParams
+ TSPI_lineSetDefaultMediaDetection
+ TSPI_lineSetDevConfig
+ TSPI_lineSetMediaControl
+ TSPI_lineSetMediaMode
+ TSPI_lineSetStatusMessages
+ TSPI_lineSetTerminal
+ TSPI_lineSetupConference
+ TSPI_lineSetupTransfer
+ TSPI_lineSwapHold
+ TSPI_lineUncompleteCall
+ TSPI_lineUnhold
+ TSPI_lineUnpark
+
+ TSPI_phoneClose
+ TSPI_phoneConfigDialog
+ TSPI_phoneDevSpecific
+ TSPI_phoneGetButtonInfo
+ TSPI_phoneGetData
+ TSPI_phoneGetDevCaps
+ TSPI_phoneGetDisplay
+ TSPI_phoneGetExtensionID
+ TSPI_phoneGetGain
+ TSPI_phoneGetHookSwitch
+ TSPI_phoneGetIcon
+ TSPI_phoneGetID16
+ TSPI_phoneGetLamp
+ TSPI_phoneGetRing
+ TSPI_phoneGetStatus
+ TSPI_phoneGetVolume
+ TSPI_phoneNegotiateExtVersion
+ TSPI_phoneNegotiateTSPIVersion
+ TSPI_phoneOpen
+ TSPI_phoneSelectExtVersion
+ TSPI_phoneSetButtonInfo
+ TSPI_phoneSetData
+ TSPI_phoneSetDisplay
+ TSPI_phoneSetGain
+ TSPI_phoneSetHookSwitch
+ TSPI_phoneSetLamp
+ TSPI_phoneSetRing
+ TSPI_phoneSetStatusMessages
+ TSPI_phoneSetVolume
+
+ TSPI_providerConfig
+ TSPI_providerInit16
+ TSPI_providerInstall
+ TSPI_providerRemove
+ TSPI_providerShutdown16
+
+ TSPI_providerEnumDevices16
+ TSPI_lineDropOnClose
+ TSPI_lineDropNoOwner
+ TSPI_providerCreateLineDevice
+ TSPI_providerCreatePhoneDevice
+ TSPI_lineSetCurrentLocation
+ TSPI_lineConfigDialogEdit
+ TSPI_lineReleaseUserUserInfo
+
+ WEP @1 RESIDENTNAME
+ LibMain @2
+ DllEntryPoint @3 RESIDENTNAME
+
+; Table of vital pointers for 32-bit half of GDI thunks
+
+ NewData
+
+ TapiThk_ThunkData16
+ TapifThk_ThunkData16
+ Tapi32_ThunkData16
+
+; TAPITHKCONNECTIONDATALS ; @110 ;Internal
+; FT_TAPIFTHKTHKCONNECTIONDATA ; @111 ;Internal
+; Tapi32ConnectionDataSL
+
+IMPORTS
+ C16ThkSL01 = KERNEL.631
+ ThunkConnect16 = KERNEL.651
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.h b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.h
new file mode 100644
index 000000000..92e2a786b
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.h
@@ -0,0 +1,55 @@
+/* TSP3216S.H
+ Copyright 1995 (C) Microsoft Corporation
+
+ 32-bit TAPI service provider to act as a cover for a system's 16-bit SPs
+
+ 16-bit part: TSP3216S.DLL
+ 32-bit part: TSP3216L.DLL
+
+ t-jereh 20-July-1995
+
+ TODO:
+ 1) allow debug levels
+ 2) if oom in InitializeSPs(), fail
+
+ */
+
+#define MAXBUFSIZE 256 /* maximum buffer size */
+
+#define ERR_NONE 0 /* success return value */
+
+#define TAPI_CUR_VER 0x00010004
+
+#define TSPI_PROC_LAST 103 /* there are TSPI functions from 500 to 602 */
+
+
+// structs
+
+typedef struct tagMYLINE
+ {
+ HDRVLINE hdLine;
+ int iProvider;
+ DWORD dwDeviceID;
+ LINEEVENT lpfnEventProc;
+ HTAPILINE htLine;
+ } MYLINE, FAR *LPMYLINE;
+
+
+typedef struct tagMYPHONE
+ {
+ HDRVPHONE hdPhone;
+ int iProvider;
+ DWORD dwDeviceID;
+ PHONEEVENT lpfnEventProc;
+ HTAPIPHONE htPhone;
+ } MYPHONE, FAR *LPMYPHONE;
+
+
+typedef struct tagMYCALL
+ {
+ HDRVCALL hdCall;
+ int iProvider;
+ DWORD dwDeviceID;
+ HTAPICALL htCall;
+
+ } MYCALL, FAR *LPMYCALL;
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.mak b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.mak
new file mode 100644
index 000000000..1eb4d9618
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.mak
@@ -0,0 +1,89 @@
+# Microsoft Visual C++ generated build script - Do not modify
+
+PROJ = TSP3216S
+DEBUG = 1
+PROGTYPE = 1
+CALLER = \WINDOWS\DIALER.EXE
+ARGS =
+DLLS = \WINDOWS\SYSTEM\TAPI.DLL
+D_RCDEFINES = -d_DEBUG
+R_RCDEFINES = -dNDEBUG
+ORIGIN = MSVC
+ORIGIN_VER = 1.00
+PROJPATH = C:\ROOT\TELECOM\TAPI\DEV\SP\TSP3216\TSP3216S\
+USEMFC = 0
+CC = cl
+CPP = cl
+CXX = cl
+CCREATEPCHFLAG =
+CPPCREATEPCHFLAG =
+CUSEPCHFLAG =
+CPPUSEPCHFLAG =
+FIRSTC = TSP3216.C
+FIRSTCPP =
+RC = rc
+CFLAGS_D_WDLL = /nologo /G2 /W3 /Zi /ALw /Od /D "_DEBUG" /D "DEBUG" /D "DEBUG" /Fc /FR /GD /Fd"TSP3216.PDB"
+CFLAGS_R_WDLL = /nologo /W3 /ALw /O1 /D "NDEBUG" /FR /GD
+LFLAGS_D_WDLL = /NOLOGO /ONERROR:NOEXE /NOD /PACKC:61440 /CO /NOE /ALIGN:16 /MAP:FULL
+LFLAGS_R_WDLL = /NOLOGO /ONERROR:NOEXE /NOD /PACKC:61440 /NOE /ALIGN:16 /MAP:FULL
+LIBS_D_WDLL = oldnames libw commdlg shell olecli olesvr ldllcew
+LIBS_R_WDLL = oldnames libw commdlg shell olecli olesvr ldllcew
+RCFLAGS = /nologo
+RESFLAGS = /nologo
+RUNFLAGS =
+DEFFILE = TSP3216S.DEF
+OBJS_EXT =
+LIBS_EXT =
+!if "$(DEBUG)" == "1"
+CFLAGS = $(CFLAGS_D_WDLL)
+LFLAGS = $(LFLAGS_D_WDLL)
+LIBS = $(LIBS_D_WDLL)
+MAPFILE = nul
+RCDEFINES = $(D_RCDEFINES)
+!else
+CFLAGS = $(CFLAGS_R_WDLL)
+LFLAGS = $(LFLAGS_R_WDLL)
+LIBS = $(LIBS_R_WDLL)
+MAPFILE = nul
+RCDEFINES = $(R_RCDEFINES)
+!endif
+!if [if exist MSVC.BND del MSVC.BND]
+!endif
+SBRS = TSP3216S.SBR
+
+
+TSP3216S_DEP = c:\root\telecom\tapi\dev\inc\tapi.h \
+ c:\root\telecom\tapi\dev\inc\tspi.h \
+ c:\root\telecom\tapi\dev\sp\tsp3216\tsp3216s\tsp3216s.h \
+ \mstools\include\wownt16.h
+
+
+all: $(PROJ).DLL $(PROJ).BSC
+
+TSP3216S.OBJ: TSP3216S.C $(TSP3216S_DEP)
+ $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c TSP3216S.C
+
+
+$(PROJ).DLL:: TSP3216S.OBJ $(OBJS_EXT) $(DEFFILE)
+ echo >NUL @<<$(PROJ).CRF
+TSP3216S.OBJ +
+$(OBJS_EXT)
+$(PROJ).DLL
+$(MAPFILE)
+c:\msvc\lib\+
+$(LIBS)
+$(DEFFILE);
+<<
+ link $(LFLAGS) @$(PROJ).CRF
+ $(RC) $(RESFLAGS) $@
+ implib /nowep $(PROJ).LIB $(PROJ).DLL
+
+
+run: $(PROJ).DLL
+ $(PROJ) $(RUNFLAGS)
+
+
+$(PROJ).BSC: $(SBRS)
+ bscmake @<<
+/o$@ $(SBRS)
+<<
diff --git a/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.rc b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.rc
new file mode 100644
index 000000000..cde1aa013
--- /dev/null
+++ b/private/tapi/dev/sp/tsp3216/tsp3216s/tsp3216s.rc
@@ -0,0 +1,19 @@
+#include "windows.h"
+
+
+#if WINNT
+#include <ntverp.h>
+#else
+#include <version.h>
+#endif
+
+
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) Telephony API Thunk-o-matic"
+#define VER_INTERNALNAME_STR "TSP3216S"
+#define VER_ORIGINALFILENAME_STR "TSP3216S.DLL"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1995. All Rights Reserved."
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+
+#include <common.ver>