Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1538 lines
36 KiB

//****************************************************************************
//
// Module: Unimdm
// File: wndthrd.c
//
// Copyright (c) 1992-1995, Microsoft Corporation, all rights reserved
//
// Revision History
//
//
// 5/4/95 Viroon Touranachun Moved from modem.c
//
//
// Description: Asynchronous thread to handle the UI window
//
//****************************************************************************
#include "unimdm.h"
#include "umdmspi.h"
#include "wndthrd.h"
#include "rcids.h"
#define DLG_CMD_FREE_INSTANCE 0
#define DLG_CMD_CREATE 1
#define DLG_CMD_DESTROY 2
// Dialog Information
//
typedef struct tagDlgInfo {
DWORD dwCmd;
DWORD idLine;
DWORD dwType;
} DLGINFO, *PDLGINFO;
// Remote handle
//
typedef struct tagRemHandle {
HANDLE handle;
DWORD pid;
} REMHANDLE, *PREMHANDLE;
typedef struct _UI_THREAD_NODE {
struct _UI_THREAD_NODE *Next;
CRITICAL_SECTION CriticalSection;
HWND hWnd;
HTAPIDIALOGINSTANCE htDlgInst;
TUISPIDLLCALLBACK pfnUIDLLCallback;
PDLGNODE DlgList;
UINT RefCount;
} UI_THREAD_NODE, *PUI_THREAD_NODE;
typedef struct UI_THREAD_LIST {
CRITICAL_SECTION CriticalSection;
PUI_THREAD_NODE ListHead;
} UI_THREAD_LIST, *PUI_THREAD_LIST;
#define WM_MDM_TERMINATE WM_USER+0x0100
#define WM_MDM_TERMINATE_WND WM_USER+0x0101
#define WM_MDM_TERMINATE_WND_NOTIFY WM_USER+0x0102
#define WM_MDM_DLG WM_USER+0x0113
//****************************************************************************
// Function Prototypes
//****************************************************************************
PDLGNODE NewDlgNode (HWND Parent,DWORD idLine, DWORD dwType);
BOOL DeleteDlgNode (HWND Parent,PDLGNODE pDlgNode);
PDLGNODE FindDlgNode (HWND Parent, DWORD idLine, DWORD dwType);
BOOL IsDlgListMessage(HWND Parent,MSG* pmsg);
void CleanupDlgList (HWND Parent);
DWORD StartMdmDialog(HWND hwnd, DWORD idLine, DWORD dwType);
DWORD DestroyMdmDialog(HWND hwnd,DWORD idLine, DWORD dwType);
LRESULT MdmWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND CreateTalkDropDlg(HWND hwndOwner, DWORD idLine);
HWND CreateManualDlg(HWND hwndOwner, DWORD idLine);
HWND CreateTerminalDlg(HWND hwndOwner, DWORD idLine);
TCHAR gszMdmWndClass[] = UNIMODEM_WNDCLASS;
UI_THREAD_LIST UI_ThreadList;
VOID WINAPI
UI_ProcessAttach(
VOID
)
{
UI_ThreadList.ListHead=NULL;
InitializeCriticalSection(&UI_ThreadList.CriticalSection);
return;
}
VOID WINAPI
UI_ProcessDetach(
VOID
)
{
UI_ThreadList.ListHead=NULL;
DeleteCriticalSection(&UI_ThreadList.CriticalSection);
return;
}
VOID WINAPI
AddThreadNode(
PUI_THREAD_LIST List,
PUI_THREAD_NODE Node
)
{
EnterCriticalSection(&List->CriticalSection);
Node->Next=List->ListHead;
List->ListHead=Node;
LeaveCriticalSection(&List->CriticalSection);
return;
}
VOID WINAPI
RemoveNode(
PUI_THREAD_LIST List,
PUI_THREAD_NODE Node
)
{
PUI_THREAD_NODE Current;
PUI_THREAD_NODE Prev;
EnterCriticalSection(&List->CriticalSection);
Prev=NULL;
Current=List->ListHead;
while (Current != NULL) {
if (Current == Node) {
if (Current == List->ListHead) {
List->ListHead=Current->Next;
} else {
Prev->Next=Current->Next;
}
break;
}
Prev=Current;
Current=Current->Next;
}
EnterCriticalSection(&Node->CriticalSection);
Node->RefCount--;
LeaveCriticalSection(&Node->CriticalSection);
LeaveCriticalSection(&List->CriticalSection);
return;
}
UINT WINAPI
RemoveReference(
PUI_THREAD_NODE Node
)
{
UINT TempCount;
EnterCriticalSection(&Node->CriticalSection);
TempCount=--Node->RefCount;
LeaveCriticalSection(&Node->CriticalSection);
return TempCount;
}
HWND WINAPI
FindThreadWindow(
PUI_THREAD_LIST List,
HTAPIDIALOGINSTANCE htDlgInst
)
{
PUI_THREAD_NODE Node;
HWND Window=NULL;
EnterCriticalSection(&List->CriticalSection);
Node=List->ListHead;
while (Node != NULL && Window == NULL) {
EnterCriticalSection(&Node->CriticalSection);
if (Node->htDlgInst == htDlgInst) {
//
// found it
//
Window=Node->hWnd;
Node->RefCount++;
}
LeaveCriticalSection(&Node->CriticalSection);
Node=Node->Next;
}
LeaveCriticalSection(&List->CriticalSection);
return Window;
}
TUISPIDLLCALLBACK WINAPI
GetCallbackProc(
HWND hdlg
)
{
PUI_THREAD_NODE Node;
Node=(PUI_THREAD_NODE)GetWindowLong(hdlg,GWL_USERDATA);
return Node->pfnUIDLLCallback;
}
//****************************************************************************
// LONG TSPIAPI TUISPI_providerGenericDialog(
// TUISPIDLLCALLBACK pfnUIDLLCallback,
// HTAPIDIALOGINSTANCE htDlgInst,
// LPVOID lpParams,
// DWORD dwSize)
//
// Functions: Create modem instance
//
// Return: ERROR_SUCCESS if successful
//****************************************************************************
LONG TSPIAPI TUISPI_providerGenericDialog(
TUISPIDLLCALLBACK pfnUIDLLCallback,
HTAPIDIALOGINSTANCE htDlgInst,
LPVOID lpParams,
DWORD dwSize,
HANDLE hEvent)
{
MSG msg;
WNDCLASS wc;
DWORD dwRet;
PUI_THREAD_NODE Node;
DBG_ENTER_UL("TUISPI_providerGenericDialog", htDlgInst);
Node=LocalAlloc(LPTR, sizeof(UI_THREAD_NODE));
if (Node == NULL) {
return ERROR_NOT_ENOUGH_MEMORY;
}
InitializeCriticalSection(&Node->CriticalSection);
Node->pfnUIDLLCallback=pfnUIDLLCallback;
Node->htDlgInst=htDlgInst;
Node->RefCount=1;
Node->DlgList=NULL;
wc.style = CS_NOCLOSE; // Do not allow end-user to close
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = ghInstance; // Application that owns the class.
wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpfnWndProc = MdmWndProc; // Function to retrieve messages.
wc.lpszClassName = gszMdmWndClass; // Name used in call to CreateWindow.
RegisterClass(&wc);
// Create the main invisible window
//
Node->hWnd = CreateWindow(
gszMdmWndClass, // The window class
szNull, // Text for window title bar.
WS_OVERLAPPEDWINDOW, // Window style.
CW_USEDEFAULT, // Default horizontal position.
CW_USEDEFAULT, // Default vertical position.
CW_USEDEFAULT, // Default width.
CW_USEDEFAULT, // Default height.
NULL, // Overlapped windows have no parent.
NULL, // Use the window class menu.
ghInstance, // This instance owns this window.
Node // Pointer not needed.
);
SetEvent(hEvent);
// Cannot create a window, bail out
//
if (Node->hWnd == NULL)
{
dwRet = LINEERR_OPERATIONFAILED;
goto Cleanup_Exit;
};
AddThreadNode(
&UI_ThreadList,
Node
);
// Get message loop
//
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.hwnd != NULL)
{
// The message is for a specific UI window, dispatch the message
//
if (!IsDlgListMessage(Node->hWnd,&msg))
{
TranslateMessage(&msg); // Translate virtual key code
DispatchMessage(&msg); // Dispatches message to the window
}
}
}
DestroyWindow(Node->hWnd);
ASSERT(Node->RefCount == 0);
dwRet = ERROR_SUCCESS;
Cleanup_Exit:
// Free the allocated resources
//
LocalFree(Node);
DBG_EXIT_UL("TUISPI_providerGenericDialog", ERROR_SUCCESS);
return ERROR_SUCCESS;
}
//****************************************************************************
// LONG TSPIAPI TUISPI_providerGenericDialogData(
// HTAPIDIALOGINSTANCE htDlgInst,
// LPVOID lpParams,
// DWORD dwSize)
//
// Functions: Request an action from the modem instance
//
// Return: ERROR_SUCCESS if successful
//****************************************************************************
LONG TSPIAPI TUISPI_providerGenericDialogData(
HTAPIDIALOGINSTANCE htDlgInst,
LPVOID lpParams,
DWORD dwSize
)
{
PDLGINFO pDlgInfo = (PDLGINFO)lpParams;
HWND ParentWindow;
UINT RefCount;
PUI_THREAD_NODE Node;
DBG_ENTER_UL("TUISPI_providerGenericDialogData", htDlgInst);
ParentWindow=FindThreadWindow(
&UI_ThreadList,
htDlgInst
);
if (ParentWindow == NULL) {
return ERROR_SUCCESS;
}
Node=(PUI_THREAD_NODE)GetWindowLong(ParentWindow, GWL_USERDATA);
if (NULL == lpParams) {
//
// tapi want thread to exit, remove from list and dec ref count
//
RemoveNode(
&UI_ThreadList,
Node
);
}
else
{
ASSERT(dwSize == sizeof(*pDlgInfo));
switch(pDlgInfo->dwCmd)
{
case DLG_CMD_CREATE:
StartMdmDialog(ParentWindow,pDlgInfo->idLine, pDlgInfo->dwType);
break;
case DLG_CMD_DESTROY:
DestroyMdmDialog(ParentWindow,pDlgInfo->idLine, pDlgInfo->dwType);
break;
case DLG_CMD_FREE_INSTANCE:
//
// server wants thread to exit, remove from list and dec refcount
//
RemoveNode(
&UI_ThreadList,
Node
);
break;
default:
break;
}
}
if (0 == RemoveReference(Node)) {
//
// it's gone, count dec'ed when remove from list
//
PostMessage(ParentWindow, WM_MDM_TERMINATE, 0, 0);
}
DBG_EXIT_UL("TUISPI_providerGenericDialogData", ERROR_SUCCESS);
return ERROR_SUCCESS;
}
//****************************************************************************
// PDLGNODE NewDlgNode(DWORD, DWORD)
//
// Function: Add a new dialog box to the list
//
// Returns: a pointer to the dialog node if the dialog can be added
//
//****************************************************************************
PDLGNODE NewDlgNode (HWND Parent, DWORD idLine, DWORD dwType)
{
PDLGNODE pDlgNode;
PUI_THREAD_NODE UI_Node=(PUI_THREAD_NODE)GetWindowLong(Parent, GWL_USERDATA);
// Allocate a new dialog node
//
if ((pDlgNode = (PDLGNODE)LocalAlloc(LPTR, sizeof(*pDlgNode)))
== NULL)
return NULL;
// Insert the new node into the dialog list
//
pDlgNode->idLine = idLine;
pDlgNode->dwType = dwType;
pDlgNode->Parent = Parent;
INITCRITICALSECTION(pDlgNode->hSem);
// Insert the new node to the list
//
ENTERCRITICALSECTION(UI_Node->CriticalSection);
pDlgNode->pNext = UI_Node->DlgList;
UI_Node->DlgList = pDlgNode;
LEAVECRITICALSECTION(UI_Node->CriticalSection);
return pDlgNode;
}
//****************************************************************************
// BOOL DeleteDlgNode(PDLGNODE)
//
// Function: Remove a dialog box to the list
//
// Returns: TRUE if the dialog exist and removed
//
//****************************************************************************
BOOL DeleteDlgNode (HWND Parent, PDLGNODE pDlgNode)
{
PDLGNODE pCurDlg, pPrevDlg;
PUI_THREAD_NODE UI_Node=(PUI_THREAD_NODE)GetWindowLong(Parent, GWL_USERDATA);
// Exclusively access the modem list
//
ENTERCRITICALSECTION(UI_Node->CriticalSection);
// Start from the head of the CB list
//
pPrevDlg = NULL;
pCurDlg = UI_Node->DlgList;
// traverse the list to find the specified CB
//
while (pCurDlg != NULL)
{
if (pCurDlg == pDlgNode)
{
// Is there a previous control block?
//
if (pPrevDlg == NULL)
{
// head of the list
//
UI_Node->DlgList = pCurDlg->pNext;
}
else
{
pPrevDlg->pNext = pCurDlg->pNext;
};
break;
};
pPrevDlg = pCurDlg;
pCurDlg = pCurDlg->pNext;
};
// Finish accessing the modem list
//
LEAVECRITICALSECTION(UI_Node->CriticalSection);
// Have we found the dialog box in the list?
//
if (pCurDlg != NULL)
{
// Wait until no one else is using the line
//
ENTERCRITICALSECTION(pCurDlg->hSem);
DELETECRITICALSECTION(pCurDlg->hSem);
LocalFree(pCurDlg);
return TRUE;
}
else
{
return FALSE;
};
}
//****************************************************************************
// PDLGNODE FindDlgNode(DWORD, DWORD)
//
// Function: Find the dialog node for the line dev
//
// Returns: a pointer to the dialog node if the dialog exist and removed.
// The dialog node's semaphore is claimed.
//
//****************************************************************************
PDLGNODE FindDlgNode (HWND Parent, DWORD idLine, DWORD dwType)
{
PDLGNODE pCurDlg;
PUI_THREAD_NODE UI_Node=(PUI_THREAD_NODE)GetWindowLong(Parent, GWL_USERDATA);
// Exclusively access the modem list
//
ENTERCRITICALSECTION(UI_Node->CriticalSection);
// Start from the head of the CB list
//
pCurDlg = UI_Node->DlgList;
// traverse the list to find the specified CB
//
while (pCurDlg != NULL)
{
ENTERCRITICALSECTION(pCurDlg->hSem);
if ((pCurDlg->idLine == idLine) &&
(pCurDlg->dwType == dwType) &&
(pCurDlg->Parent == Parent) )
{
break;
};
LEAVECRITICALSECTION(pCurDlg->hSem);
pCurDlg = pCurDlg->pNext;
};
// Finish accessing the modem list
//
LEAVECRITICALSECTION(UI_Node->CriticalSection);
return pCurDlg;
}
//****************************************************************************
// BOOL IsDlgListMessage(MSG* pmsg)
//
// Function: Run the message throught the dialogbox list
//
// Returns: TRUE if the message is one of the dialog box's and FALSE otherwise
//
//****************************************************************************
BOOL IsDlgListMessage(HWND Parent, MSG* pmsg)
{
PDLGNODE pDlgNode, pNext;
BOOL fRet = FALSE;
PUI_THREAD_NODE UI_Node=(PUI_THREAD_NODE)GetWindowLong(Parent, GWL_USERDATA);
// Exclusively access the modem list
//
ENTERCRITICALSECTION(UI_Node->CriticalSection);
// Walk the dialog box list
//
pDlgNode = UI_Node->DlgList;
while(pDlgNode != NULL && !fRet)
{
ENTERCRITICALSECTION(pDlgNode->hSem);
// Check whether the message belongs to this dialog
//
if (IsWindow(pDlgNode->hDlg) && IsDialogMessage(pDlgNode->hDlg, pmsg))
{
// Yes, we are done!
//
fRet = TRUE;
};
LEAVECRITICALSECTION(pDlgNode->hSem);
// Check the next dialog
//
pDlgNode = pDlgNode->pNext;
};
// Finish accessing the modem list
//
LEAVECRITICALSECTION(UI_Node->CriticalSection);
return fRet;
}
//****************************************************************************
// void CleanupDlgList()
//
// Function: Clean up the dialogbox list
//
// Returns: None
//
//****************************************************************************
void CleanupDlgList (HWND Parent)
{
PDLGNODE pDlgNode, pNext;
PUI_THREAD_NODE UI_Node=(PUI_THREAD_NODE)GetWindowLong(Parent, GWL_USERDATA);
// Exclusively access the modem list
//
ENTERCRITICALSECTION(UI_Node->CriticalSection);
// Walk the dialog box list
//
pDlgNode = UI_Node->DlgList;
while(pDlgNode != NULL)
{
ENTERCRITICALSECTION(pDlgNode->hSem);
// Destroy the dialog box first
//
DestroyWindow(pDlgNode->hDlg);
// Free the CB and move onto the next dialog
//
pNext = pDlgNode->pNext;
DELETECRITICALSECTION(pDlgNode->hSem);
LocalFree(pDlgNode);
pDlgNode = pNext;
}
// Finish accessing the modem list
//
UI_Node->DlgList=NULL;
LEAVECRITICALSECTION(UI_Node->CriticalSection);
return;
}
//****************************************************************************
// DWORD StartMdmDialog(DWORD, DWORD)
//
// Function: Start modem dialog
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
// ERROR_OUTOFMEMORY if fails
//
//****************************************************************************
DWORD StartMdmDialog(HWND Parent, DWORD idLine, DWORD dwType)
{
PDLGNODE pDlgNode;
DWORD dwRet;
// Create the talk/drop dialog node
//
pDlgNode = NewDlgNode(Parent, idLine, dwType);
if (pDlgNode != NULL)
{
PostMessage(Parent, WM_MDM_DLG, (WPARAM)idLine, (LPARAM)dwType);
dwRet = ERROR_SUCCESS;
}
else
{
dwRet = ERROR_OUTOFMEMORY;
};
return dwRet;
}
//****************************************************************************
// DWORD DestroyMdmDialog(DWORD, DWORD)
//
// Function: destroy talk/drop dialog
//
// Notes: This function is called from the state machine thread
//
// Returns: none
//
//****************************************************************************
DWORD DestroyMdmDialog(HWND Parent,DWORD idLine, DWORD dwType)
{
#ifdef DEBUG
PDLGNODE pDlgNode;
// Search for the dialog
//
pDlgNode = FindDlgNode(Parent, idLine, dwType);
// Check if the talkdrop dialog is available
//
if (pDlgNode != NULL)
{
LEAVECRITICALSECTION(pDlgNode->hSem);
}
else
{
DPRINTF("Could not find the associated dialog node");
ASSERT(0);
};
#endif // DEBUG
PostMessage(Parent, WM_MDM_TERMINATE_WND, (WPARAM)idLine,
(LPARAM)dwType);
return ERROR_SUCCESS;
}
//****************************************************************************
// LRESULT MdmWndProc(HWND, UINT, WPARAM, LPARAM)
//
// Function: Main window for the modem window thread.
//
// Returns: 0 or 1
//
//****************************************************************************
LRESULT MdmWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// Determine the command
//
switch(message)
{
case WM_CREATE:
{
LPCREATESTRUCT lpcs=(LPCREATESTRUCT) lParam;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)lpcs->lpCreateParams);
break;
}
case WM_MDM_TERMINATE:
//
// The thread is being terminated
// Destroy all the windows
//
CleanupDlgList(hwnd);
PostQuitMessage(ERROR_SUCCESS);
break;
case WM_MDM_TERMINATE_WND:
case WM_MDM_TERMINATE_WND_NOTIFY:
{
PDLGNODE pDlgNode;
// Search for the dialog node
//
if ((pDlgNode = FindDlgNode(hwnd,(DWORD)wParam, (DWORD)lParam)) == NULL)
{
break;
};
// The window is requested to be destroyed
//
DestroyWindow(pDlgNode->hDlg);
// If the modem dialog structure is available
// notify the state machine thread
//
if (message == WM_MDM_TERMINATE_WND_NOTIFY)
{
DLGREQ DlgReq;
TUISPIDLLCALLBACK Callback;
DlgReq.dwCmd = UI_REQ_COMPLETE_ASYNC;
DlgReq.dwParam = pDlgNode->dwStatus;
Callback=GetCallbackProc(hwnd);
(*Callback)(pDlgNode->idLine, TUISPIDLL_OBJECT_LINEID,
(LPVOID)&DlgReq, sizeof(DlgReq));
};
// Remove it from the dialog list
//
LEAVECRITICALSECTION(pDlgNode->hSem);
DeleteDlgNode(hwnd,pDlgNode);
break;
}
case WM_MDM_DLG:
{
PDLGNODE pDlgNode;
//
// Find the dialog node
//
pDlgNode = FindDlgNode(hwnd,(DWORD)wParam, (DWORD)lParam);
if (pDlgNode != NULL)
{
if (pDlgNode->hDlg == NULL)
{
switch(lParam)
{
case TALKDROP_DLG:
//
// Create a talk-drop dialog box
//
pDlgNode->hDlg = CreateTalkDropDlg(hwnd, (DWORD)pDlgNode);
break;
case MANUAL_DIAL_DLG:
//
// Create a talk-drop dialog box
//
pDlgNode->hDlg = CreateManualDlg(hwnd, (DWORD)pDlgNode);
break;
case TERMINAL_DLG:
//
// Create a talk-drop dialog box
//
pDlgNode->hDlg = CreateTerminalDlg(hwnd, (DWORD)wParam);
break;
default:
break;
};
}
else
{
DPRINTF("Another dialog of the same type exists.");
ASSERT(0);
};
LEAVECRITICALSECTION(pDlgNode->hSem);
};
break;
}
default:
return(DefWindowProc(hwnd, message, wParam, lParam));
};
return 0;
}
//****************************************************************************
// void EndMdmDialog(DWORD, DWORD, DWORD)
//
// Function: Request to end dialog from the dialog itself.
//
// Returns: None
//
//****************************************************************************
void EndMdmDialog(HWND Parent, DWORD idLine, DWORD dwType, DWORD dwStatus)
{
PDLGNODE pDlgNode;
// Look for the dialog node
//
if ((pDlgNode = FindDlgNode(Parent, idLine, dwType)) != NULL)
{
pDlgNode->dwStatus = dwStatus;
// Notify the dialog box result
//
PostMessage(Parent, WM_MDM_TERMINATE_WND_NOTIFY, (WPARAM)idLine,
(LPARAM)dwType);
LEAVECRITICALSECTION(pDlgNode->hSem);
};
return;
}
//****************************************************************************
//****************************************************************************
//************ The following calls are in the context of TAPISRV**************
//****************************************************************************
//****************************************************************************
//****************************************************************************
// DWORD CreateMdmDlgInstance (PLINEDEV pLineDev)
//
// Function: Start dialog instance
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
//
//****************************************************************************
DWORD CreateMdmDlgInstance (PLINEDEV pLineDev)
{
HANDLE hEvent;
TUISPICREATEDIALOGINSTANCEPARAMS cdip;
DBG_PLD_ENTER("CreateMdmDlgInstance");
ASSERT(pLineDev->dwPendingID != INVALID_PENDINGID);
// Package the params
//
cdip.dwRequestID = pLineDev->dwPendingID;
cdip.hdDlgInst = (HDRVDIALOGINSTANCE)pLineDev;
cdip.htDlgInst = NULL;
cdip.lpszUIDLLName = gszTSPFilename;
cdip.lpParams = NULL;
cdip.dwSize = 0;
// Notify TAPI to start a dialog instance
//
(*(pLineDev->lpfnEvent))((HTAPILINE)ghProvider, NULL,
LINE_CREATEDIALOGINSTANCE,
(DWORD)(&cdip),
0, 0);
pLineDev->hDlgInst = cdip.htDlgInst;
DBG_PLD_EXIT("CreateMdmDlgInstance", ERROR_SUCCESS);
return ERROR_SUCCESS;
}
//****************************************************************************
// DWORD DestroyMdmDlgInstance (PLINEDEV pLineDev)
//
// Function: Destroy dialog instance
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
//
//****************************************************************************
DWORD DestroyMdmDlgInstance (PLINEDEV pLineDev)
{
DLGINFO DlgInfo;
DBG_PLD_ENTER("DestroyMdmDlgInstance");
if (pLineDev->hDlgInst == NULL)
{
DBG_PLD_EXIT("DestroyMdmDlgInstance", ERROR_SUCCESS);
return ERROR_SUCCESS;
}
// Package the parameters
//
DlgInfo.idLine = 0;
DlgInfo.dwType = 0;
DlgInfo.dwCmd = DLG_CMD_FREE_INSTANCE;
// Notify TAPI to stop a dialog instance
//
(*(pLineDev->lpfnEvent))((HTAPILINE)pLineDev->hDlgInst, NULL,
LINE_SENDDIALOGINSTANCEDATA,
(DWORD)(&DlgInfo),
sizeof(DlgInfo),
0);
pLineDev->hDlgInst = NULL;
DBG_PLD_EXIT("DestroyMdmDlgInstance", ERROR_SUCCESS);
return ERROR_SUCCESS;
}
//****************************************************************************
// DWORD SPStartMdmDialog (PLINEDEV pLineDev, DWORD dwType)
//
// Function: Create a dialog in the dialog instance
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
//
//****************************************************************************
DWORD SPStartMdmDialog (PLINEDEV pLineDev, DWORD dwType)
{
DLGINFO DlgInfo;
// Package the parameters
//
DlgInfo.idLine = pLineDev->dwID;
DlgInfo.dwType = dwType;
DlgInfo.dwCmd = DLG_CMD_CREATE;
// Notify TAPI to start a dialog
//
(*(pLineDev->lpfnEvent))((HTAPILINE)pLineDev->hDlgInst, NULL,
LINE_SENDDIALOGINSTANCEDATA,
(DWORD)(&DlgInfo),
sizeof(DlgInfo),
0);
return ERROR_SUCCESS;
}
//****************************************************************************
// DWORD SPDestroyMdmDialog (PLINEDEV pLineDev, DWORD dwType)
//
// Function: Destroy a dialog in the dialog instance
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
//
//****************************************************************************
DWORD SPDestroyMdmDialog (PLINEDEV pLineDev, DWORD dwType)
{
DLGINFO DlgInfo;
// Package the parameters
//
DlgInfo.idLine = pLineDev->dwID;
DlgInfo.dwType = dwType;
DlgInfo.dwCmd = DLG_CMD_DESTROY;
// Notify TAPI to start a dialog
//
(*(pLineDev->lpfnEvent))((HTAPILINE)pLineDev->hDlgInst, NULL,
LINE_SENDDIALOGINSTANCEDATA,
(DWORD)(&DlgInfo),
sizeof(DlgInfo),
0);
return ERROR_SUCCESS;
}
//****************************************************************************
// DWORD TalkDropDialog(PLINEDEV)
//
// Function: Start talkdrop dialog
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
// LINEERR_NOMEM if fails
//
//****************************************************************************
DWORD TalkDropDialog(PLINEDEV pLineDev)
{
DWORD dwRet;
if(IS_UI_DLG_UP(pLineDev, UI_DLG_TALKDROP))
{
DPRINTF("Attempting to display another TalkDrop dialog.");
ASSERT(0);
return ERROR_SUCCESS;
};
if ((dwRet = SPStartMdmDialog(pLineDev, TALKDROP_DLG))
== ERROR_SUCCESS)
{
START_UI_DLG(pLineDev, UI_DLG_TALKDROP);
};
return dwRet;
}
//****************************************************************************
// DWORD DestroyTalkDropDialog(PLINEDEV)
//
// Function: Start talkdrop dialog
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
// ERROR_OUTOFMEMORY if fails
//
//****************************************************************************
DWORD DestroyTalkDropDialog(PLINEDEV pLineDev)
{
if (!IS_UI_DLG_UP(pLineDev, UI_DLG_TALKDROP))
return ERROR_SUCCESS;
return SPDestroyMdmDialog(pLineDev, TALKDROP_DLG);
}
//****************************************************************************
// DWORD ManualDialog(PLINEDEV)
//
// Function: Start manual-dial dialog
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
// ERROR_OUTOFMEMORY if fails
//
//****************************************************************************
DWORD ManualDialog(PLINEDEV pLineDev)
{
DWORD dwRet;
if(IS_UI_DLG_UP(pLineDev, UI_DLG_MANUAL))
{
DPRINTF("Attempting to display another Manual-dial dialog.");
ASSERT(0);
return ERROR_SUCCESS;
};
if ((dwRet = SPStartMdmDialog(pLineDev, MANUAL_DIAL_DLG))
== ERROR_SUCCESS)
{
START_UI_DLG(pLineDev, UI_DLG_MANUAL);
};
return dwRet;
}
//****************************************************************************
// DWORD DestroyManualDialog(PLINEDEV)
//
// Function: Start talkdrop dialog
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
// ERROR_OUTOFMEMORY if fails
//
//****************************************************************************
DWORD DestroyManualDialog(PLINEDEV pLineDev)
{
if (!IS_UI_DLG_UP(pLineDev, UI_DLG_MANUAL))
return ERROR_SUCCESS;
return SPDestroyMdmDialog(pLineDev, MANUAL_DIAL_DLG);
}
//****************************************************************************
// DWORD TerminalDialog(PLINEDEV)
//
// Function: Start terminal dialog
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
// ERROR_OUTOFMEMORY if fails
//
//****************************************************************************
DWORD TerminalDialog(PLINEDEV pLineDev)
{
DWORD dwRet;
if(IS_UI_DLG_UP(pLineDev, UI_DLG_TERMINAL))
{
DPRINTF("Attempting to display another Terminal dialog.");
ASSERT(0);
return ERROR_SUCCESS;
};
if ((dwRet = SPStartMdmDialog(pLineDev, TERMINAL_DLG))
== ERROR_SUCCESS)
{
START_UI_DLG(pLineDev, UI_DLG_TERMINAL);
};
return dwRet;
}
//****************************************************************************
// DWORD DestroyTerminalDialog(PLINEDEV)
//
// Function: Start talkdrop dialog
//
// Notes: This function is called from the state machine thread
//
// Return: ERROR_SUCCESS if dialog box is successfully created
// ERROR_OUTOFMEMORY if fails
//
//****************************************************************************
DWORD DestroyTerminalDialog(PLINEDEV pLineDev)
{
if (!IS_UI_DLG_UP(pLineDev, UI_DLG_TERMINAL))
return ERROR_SUCCESS;
return SPDestroyMdmDialog(pLineDev, TERMINAL_DLG);
}
//****************************************************************************
// LONG
// TSPIAPI
// TSPI_providerGenericDialogData(
// DWORD dwObjectID,
// DWORD dwObjectType,
// LPVOID lpParams,
// DWORD dwSize)
//
// Functions: Callback from UI DLL to TSP
//
// Return: ERROR_SUCCESS if successful
//****************************************************************************
LONG
TSPIAPI
TSPI_providerGenericDialogData(
DWORD dwObjectID,
DWORD dwObjectType,
LPVOID lpParams,
DWORD dwSize
)
{
PLINEDEV pLineDev;
PDLGREQ pDlgReq = (PDLGREQ)lpParams;
DWORD dwRet = ERROR_SUCCESS;
DBG_ENTER_UL("TSPI_providerGenericDialogData", dwObjectID);
ASSERT (dwObjectType == TUISPIDLL_OBJECT_LINEID);
// Find the corresponding modem device
//
if ((pLineDev = GetCBfromID(dwObjectID)) == NULL)
{
DBG_EXIT_UL("TSPI_providerGenericDialogData", LINEERR_NODEVICE);
return LINEERR_NODEVICE;
}
// Determine the request
//
switch(pDlgReq->dwCmd)
{
case UI_REQ_COMPLETE_ASYNC:
MdmAsyncContinue(pLineDev,
pDlgReq->dwParam);
break;
case UI_REQ_END_DLG:
switch(pDlgReq->dwParam)
{
case TALKDROP_DLG:
STOP_UI_DLG(pLineDev, UI_DLG_TALKDROP);
break;
case MANUAL_DIAL_DLG:
STOP_UI_DLG(pLineDev, UI_DLG_MANUAL);
break;
case TERMINAL_DLG:
STOP_UI_DLG(pLineDev, UI_DLG_TERMINAL);
break;
};
break;
case UI_REQ_HANGUP_LINE:
// Make a direct call to unimodem to drop the line
//
if ((pLineDev->DevState != DEVST_DISCONNECTED)
&&
(pLineDev->DevState != DEVST_DISCONNECTING)) {
UnimodemHangup(pLineDev, TRUE);
}
break;
case UI_REQ_TERMINAL_INFO:
{
PTERMREQ pTermReq = (PTERMREQ)pDlgReq;
HANDLE hTargetProcess;
// Duplicate sync event handle
//
if ((hTargetProcess = OpenProcess(PROCESS_DUP_HANDLE, TRUE,
pTermReq->DlgReq.dwParam)) != NULL)
{
if (!DuplicateHandle(GetCurrentProcess(), pLineDev->hDevice,
hTargetProcess, &pTermReq->hDevice, 0, FALSE,
DUPLICATE_SAME_ACCESS))
{
pTermReq->hDevice = NULL;
};
CloseHandle(hTargetProcess);
};
// Get the terminal type
//
pTermReq->dwTermType = (pLineDev->DevState == DEVST_PORTPOSTTERMINAL)?
TERMINAL_POST : TERMINAL_PRE;
break;
}
case UI_REQ_GET_PROP:
{
PPROPREQ pPropReq = (PPROPREQ)pDlgReq;
ASSERT(pLineDev->pDevCfg != NULL);
// If the line is active, we need to get the current modem setting.
//
if (pLineDev->hDevice != INVALID_DEVICE)
{
DWORD cb = pLineDev->pDevCfg->commconfig.dwSize;
// Get the modem configuration
//
UnimodemGetCommConfig(pLineDev,
&(pLineDev->pDevCfg->commconfig),
&cb);
};
pPropReq->dwCfgSize = pLineDev->pDevCfg->dfgHdr.dwSize;
pPropReq->dwMdmType = (DWORD)pLineDev->bDeviceType;
pPropReq->dwMdmCaps = pLineDev->dwDevCapFlags;
pPropReq->dwMdmOptions = pLineDev->dwModemOptions;
lstrcpyn(pPropReq->szDeviceName, pLineDev->szDeviceName,
sizeof(pPropReq->szDeviceName));
break;
}
case UI_REQ_GET_DEVCFG:
{
ASSERT (pLineDev->pDevCfg != NULL);
// If the line is active, we need to get the current modem setting.
//
if (pLineDev->hDevice != INVALID_DEVICE)
{
DWORD cb = pLineDev->pDevCfg->commconfig.dwSize;
// Get the modem configuration
//
UnimodemGetCommConfig(pLineDev,
&(pLineDev->pDevCfg->commconfig),
&cb);
};
CopyMemory((LPBYTE)(pDlgReq+1), (LPBYTE)pLineDev->pDevCfg, pDlgReq->dwParam);
break;
}
case UI_REQ_SET_DEVCFG:
{
ASSERT (pLineDev->pDevCfg != NULL);
// Save the changes back
//
CopyMemory((LPBYTE)pLineDev->pDevCfg, (LPBYTE)(pDlgReq+1), pDlgReq->dwParam);
// If the line is active, we need to propagate the current modem setting.
//
if (pLineDev->hDevice != INVALID_DEVICE)
{
// Set the modem configuration
//
UnimodemSetCommConfig(pLineDev,
&(pLineDev->pDevCfg->commconfig),
pLineDev->pDevCfg->commconfig.dwSize);
};
break;
}
case UI_REQ_GET_PHONENUMBER:
{
PNUMBERREQ pNumberReq = (PNUMBERREQ)pDlgReq;
// ASSERT(sizeof(pNumberReq->szPhoneNumber) == sizeof(pLineDev->szAddress));
if ((DEVST_PORTCONNECTING == pLineDev->DevState)
||
(DEVST_MANUALDIALING == pLineDev->DevState)) {
lstrcpyA(pNumberReq->szPhoneNumber,pLineDev->szAddress);
} else {
lstrcpyA(pNumberReq->szPhoneNumber,"");
}
break;
}
default:
break;
}
RELEASE_LINEDEV(pLineDev);
DBG_EXIT_UL("TSPI_providerGenericDialogData", dwRet);
return dwRet;
}
//****************************************************************************
// LONG
// TSPIAPI
// TSPI_providerFreeDialogInstance(
// HDRVDIALOGINSTANCE hdDlgInstance)
//
// Functions: Indicates the dialog instance was freed
//
// Return: ERROR_SUCCESS if successful
//****************************************************************************
LONG
TSPIAPI
TSPI_providerFreeDialogInstance(
HDRVDIALOGINSTANCE hdDlgInstance
)
{
DBG_ENTER_UL("TSPI_providerFreeDialogInstance", hdDlgInstance);
DBG_EXIT_UL("TSPI_providerFreeDialogInstance", ERROR_SUCCESS);
return ERROR_SUCCESS;
}
//****************************************************************************
// LONG
// TSPIAPI
// TSPI_providerUIIdentify(
// LPTSTR lpszUIDllName)
//
// Functions: Retreives the UI Dll Name
//
// Return: ERROR_SUCCESS if successful
//****************************************************************************
LONG
TSPIAPI
TSPI_providerUIIdentify(
LPTSTR lpszUIDllName
)
{
DBG_ENTER("TSPI_providerUIIdentify");
lstrcpy(lpszUIDllName, gszTSPFilename);
DBG_EXIT_UL("TSPI_providerUIIdentify", ERROR_SUCCESS);
return ERROR_SUCCESS;
}