CHATDLG.C

/*++ 

Copyright (c) 1995 Intel Corp

Module Name:

chatdlg.c

Abstract:

Contains dialog-box procedures for the WinSock2 Chat sample
application. See qoschat.rc for the actual resource script.

--*/

#include "nowarn.h" /* turn off benign warnings */
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
#endif
#include <windows.h>
#include "nowarn.h" /* some warnings may have been turned back on */
#include <winsock2.h>
#include <stdlib.h>
#include <assert.h>
#include "qoschat.h"
#include "chatsock.h"
#include "chatdlg.h"





BOOL APIENTRY
ChooseFamilyDlgProc(
IN HWND DialogWindow,
IN UINT Message,
IN WPARAM WParam,
IN LPARAM LParam)
/*++

Routine Description:

Callback function that processes messages sent to the 'Choose
Family' dialog box.

Implementation

This dialog box is used to query the user as to which supported
protocol he wishes to use for the chat connection he wishes to
make. The available protocols are listed in the IDC_FAM_LB
listbox via the FillInFamilies function in socket.c.

It is expected that this dialog box gets the WM_INITDIALOG
message with a LParam that is a pointer to the CONNDATA structure
for the impending connection. The result of this function is that
the ProtocolInfo field of the ConnData struct is filled with a
pointer to the protocol information structure the user chose in
the listbox.

Arguments:

DialogWindow - Supplies handle of the dialog box.

Message - Supplies the message identifier

WParam - Supplies the first message parameter

LParam - Supplies the second message parameter

Return Value:

TRUE -- This function handled the message.

FALSE -- This function did not handle the message.

--*/
{
int LBIndex; // index of the item chosen
static PCONNDATA ConnData = NULL; // connection-specific data

switch (Message) {

case WM_INITDIALOG:

// Get the parameter and fill in the listbox with the
// available protocols.
ConnData = (PCONNDATA)LParam;
assert(ConnData != NULL);
if (!FillInFamilies(DialogWindow, IDC_FAM_LB)) {
MessageBox(DialogWindow, "FillInFamilies failed.", "Error.",
MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
EndDialog(DialogWindow, FALSE);
}

return(TRUE);

case WM_COMMAND:

switch (WParam) {

case IDOK:

// Get the index of the listbox item the user has chosen.
LBIndex = (int)SendMessage(GetDlgItem(DialogWindow, IDC_FAM_LB),
LB_GETCURSEL, 0, 0);
if (LBIndex == LB_ERR) {

// Nothing was selected.
MessageBox(DialogWindow, "Choose an item, or hit cancel.",
"No Selection?",
MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
return(TRUE);
}

// Get the protocol associated with the listbox item the
// user selected.
ConnData->ProtocolInfo = GetProtoFromIndex(LBIndex);
assert(ConnData->ProtocolInfo != NULL);
EndDialog(DialogWindow, TRUE);
return(TRUE);

case IDCANCEL:

// Kill the dialog box.
EndDialog(DialogWindow, FALSE);
return(TRUE);

default:

return(FALSE);
} // switch (WParam)

default:

return(FALSE);
} // switch (Message)

} // ChooseFamilyDlgProc()





BOOL APIENTRY
InetConnDlgProc(
IN HWND DialogWindow,
IN UINT Message,
IN WPARAM WParam,
IN LPARAM LParam)

/*++

Routine Description:

Callback function that processes messages sent to the internet
connection info dialog box.

Implementation

This dialog box gets two strings from the user: the internet
address and port to which she wants to make a chat connection.
When the user clicks on the OK button, these two strings are
converted into a sockaddr_in structure and a pointer to this
structure is saved in the connection window's CONNDATA structure.

NOTE: No name resolution takes place here! The address edit
control expects up to 15 characters, and this string is expected
to be in.dotted.decimal.notation. When RNR is available, this is
where it would be called upon to provide the appropriate
sockaddr_in structure. Actually, this dialog box would be
replaced with a protocol independent name dialog box; RNR would do
all the rest...

Arguments:

DialogWindow - Supplies handle of the dialog box.

Message - Supplies the message identifier

WParam - Supplies the first message parameter

LParam - Supplies the second message parameter

Return Value:

TRUE -- This function handled the message.

FALSE -- This function did not handle the message; or the message
was WM_INITDIALOG and we set the focus.

--*/

{
char PortText[INET_PORT_LEN + 1]; // holds port string
char AddressText[INET_ADDR_LEN + 1];// holds addr string
static PCONNDATA ConnData = NULL; // conn-specific data
struct sockaddr_in *SockAddrInet; // Inet socket address
u_long InetAddr; // Inet-style address
u_short InetPort; // Inet-style port
int Port; // intermediate var.
BOOL PortStringTranslated; // for GetDlgItemInt
struct hostent *host;

switch (Message) {

case WM_INITDIALOG:

// Get the connection data pointer, initialize the dialog box.
ConnData = (PCONNDATA)LParam;
assert(ConnData != NULL);
SendMessage(GetDlgItem(DialogWindow, IDC_INET_ADDRESS),
EM_LIMITTEXT, (WPARAM)INET_ADDR_LEN, 0);
SendMessage(GetDlgItem(DialogWindow, IDC_INET_PORT),
EM_LIMITTEXT, (WPARAM)INET_PORT_LEN, 0);
wsprintf(PortText,"%d", INET_DEFAULT_PORT);
SendMessage(GetDlgItem(DialogWindow, IDC_INET_PORT),
WM_SETTEXT, 0, (LPARAM)PortText);
SetFocus(GetDlgItem(DialogWindow, IDC_INET_ADDRESS));
return(FALSE);

case WM_COMMAND:

switch (WParam) {

case IDOK:

// The user has pressed the 'OK' button. Extract the
// internet address into a buffer and check the value the
// user typed for the port.
GetDlgItemText(DialogWindow,
IDC_INET_ADDRESS,
AddressText,
INET_ADDR_LEN);
strcpy(ConnData->PeerAddress, AddressText);
Port = (int)GetDlgItemInt(DialogWindow,
IDC_INET_PORT,
&PortStringTranslated,
TRUE);
if ((Port < 0) || (Port > 65535) || !PortStringTranslated) {
MessageBox(DialogWindow,
"Please choose a port between 0 and 65535.",
"Bad Port.",
MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
return(TRUE);
}

// Convert the address string to an unsigned long, and
// convert the port integer to an unsigned short. If all
// goes well, fill in the fields and end the dialog box.
// If not, inform the user and *don't* kill the dialog box.
InetAddr = inet_addr(AddressText);
if (InetAddr == INADDR_NONE) {
host = gethostbyname(AddressText);
if (host) {
InetAddr = *((u_long *)host->h_addr_list[0]);
}
}
InetPort = (u_short)Port;
if ((InetAddr != INADDR_NONE) && (InetAddr != 0)) {

// Allocate memory for an internet-style socket address;
// point ConnData->SockAddr at this memory, and
// use a local pointer to a struct sockaddr_in to
// reference the fields.
ConnData->RemoteSockAddr.len = sizeof(struct sockaddr_in);
ConnData->RemoteSockAddr.buf =
malloc(ConnData->RemoteSockAddr.len);
if (ConnData->RemoteSockAddr.buf == NULL) {
ChatSysError("malloc()",
"InetConnDlgProc()",
TRUE);
}

SockAddrInet =
(struct sockaddr_in *)ConnData->RemoteSockAddr.buf;
SockAddrInet->sin_family = AF_INET;
SockAddrInet->sin_port = InetPort;
SockAddrInet->sin_addr.S_un.S_addr = InetAddr;
EndDialog(DialogWindow, TRUE);
return(TRUE);

}

MessageBox(DialogWindow,
"Invalid Internet address. Try again or cancel.",
"Error", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
return(TRUE);

case IDCANCEL:

// The user has pressed cancel. Kill the dialog box.
EndDialog(DialogWindow, FALSE);
return(TRUE);

default:

break;
} // switch (WParam)

break;
} // switch (Message)

return(FALSE);
} // InetConnDlgProc()





BOOL APIENTRY
DefaultConnDlgProc(
IN HWND DialogWindow,
IN UINT Message,
IN WPARAM WParam,
IN LPARAM LParam)
/*++

Routine Description:

Callback function that processes messages sent to the default
connection info dialog box.

Implementation

This dialog box is the default when chat doesn't recognize a
particular address family. The user enters actual hex digits and
the hex value is stored in the SocketAddress associated with the
connection. Obviously, this requires the user to know how to
interpret the structure of the socket address for this address
family.

Arguments:

DialogWindow - Supplies handle of the dialog box.

Message - Supplies the message identifier

WParam - Supplies the first message parameter

LParam - Supplies the second message parameter

Return Value:

TRUE -- This function handled the message.

FALSE -- This function did not handle the message.

--*/
{

static PCONNDATA ConnData = NULL; // connection data
static int AddrLen; // length of addresses
char AddrText[MAX_SOCKADDR_LEN * 2]; // address string

switch (Message) {

case WM_INITDIALOG:

// Get the parameter and figure out how long addresses for
// this protocol may be.
ConnData = (PCONNDATA)LParam;
assert(ConnData != NULL);

AddrLen = ConnData->ProtocolInfo->iMaxSockAddr;

if (AddrLen > MAX_SOCKADDR_LEN) {
MessageBox(DialogWindow,
"Sorry, socket addresses are too big. Aborting.",
"Error.", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
EndDialog(DialogWindow, FALSE);
}

// Limit the amount of text in the edit control to twice
// AddrLen, i.e. 2 hex characters per byte.
SendMessage(GetDlgItem(DialogWindow, IDC_ADDRESS), EM_LIMITTEXT,
(WPARAM)(AddrLen * 2), 0);
return(TRUE);

case WM_COMMAND:

switch (WParam) {

case IDOK:

// The user clicked 'OK'. Get the text from the edit
// control, and convert the hex string into bytes and put
// the bytes into the socket address for this connection.
GetDlgItemText(DialogWindow, IDC_ADDRESS, AddrText,
MAX_SOCKADDR_LEN * 2);
ConnData->RemoteSockAddr.len = AddrLen;
ConnData->RemoteSockAddr.buf =
malloc(ConnData->RemoteSockAddr.len);
if (ConnData->RemoteSockAddr.buf == NULL) {
ChatSysError("malloc()",
"DefaultConnDlgProc()",
TRUE);
}

if (TranslateHex(ConnData->RemoteSockAddr.buf,
ConnData->RemoteSockAddr.len,
AddrText,
DialogWindow)) {
EndDialog(DialogWindow, TRUE);
}
return(TRUE);

case IDCANCEL:

// Kill the dialog box.
EndDialog(DialogWindow, FALSE);
return(TRUE);

default:

return(FALSE);
} // switch (WParam)

default:

return(FALSE);
} // switch (Message)

} // DefaultConnDlgProc()





BOOL APIENTRY
NameAndSubjectDlgProc(
IN HWND DialogWindow,
IN UINT Message,
IN WPARAM WParam,
IN LPARAM LParam)
/*++

Routine Description:

Callback function that processes messages sent to the name and
subject dialog box.

Implementation

This dialog box is brought up in MakeConnection (see socket.c)
only if the protocol for the connection to be made supports
connection-time data transfer. The user fills in the two fields
and this data is packed the WSABUF which is referenced through a
pointer passed in during WM_INITDIALOG processing.

Arguments:

DialogWindow - Supplies handle of the dialog box.

Message - Supplies the message identifier

WParam - Supplies the first message parameter

LParam - Supplies the second message parameter

Return Value:

TRUE -- This function handled the message.

FALSE -- This function did not handle the message; or the message
was WM_INITDIALOG and we set the focus.

--*/
{

static LPWSABUF CallerBuffer; // caller user data
char NameText[NAME_LEN + 1]; // name string
char SubjectText[SUB_LEN + 1];// subject string

switch (Message) {

case WM_INITDIALOG:

// Get the parameter and initialize the dialog box.
CallerBuffer = (LPWSABUF)LParam;
assert(CallerBuffer != NULL);

SendMessage(GetDlgItem(DialogWindow, IDC_CALLERNAME),
EM_LIMITTEXT, (WPARAM)NAME_LEN, 0);
SendMessage(GetDlgItem(DialogWindow, IDC_SUBJECT),
EM_LIMITTEXT, (WPARAM)SUB_LEN, 0);
SetFocus(GetDlgItem(DialogWindow, IDC_CALLERNAME));
return(FALSE);

case WM_COMMAND:

switch (WParam) {

case IDOK:

// Get the strings the user has typed.
GetDlgItemText(DialogWindow,
IDC_CALLERNAME,
NameText,
NAME_LEN);
GetDlgItemText(DialogWindow,
IDC_SUBJECT,
SubjectText,
SUB_LEN);

CallerBuffer->len = strlen(NameText) + strlen(SubjectText) + 2;
CallerBuffer->buf = (char *)malloc(CallerBuffer->len);
if (CallerBuffer->buf == NULL) {
ChatSysError("malloc()",
"NameAndSubjectDlgProc()",
TRUE);
}

if (!PackTwoStrings(CallerBuffer->buf,
CallerBuffer->len,
NameText,
SubjectText)) {
MessageBox(DialogWindow, "PackTwoStrings failed. Aborting.",
"Error.", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
EndDialog(DialogWindow, FALSE);
}

EndDialog(DialogWindow, TRUE);
return(TRUE);

case IDCANCEL:

// Kill the dialog box.
EndDialog(DialogWindow, FALSE);
return(TRUE);

default:

return(FALSE);
} // switch (WParam)

default:

return(FALSE);
} // switch (Message)

} // NameAndSubjectDlgProc()





BOOL APIENTRY
AcceptConnectionDlgProc(
IN HWND DialogWindow,
IN UINT Message,
IN WPARAM WParam,
IN LPARAM LParam)

/*++

Routine Description:

Callback function that processes messages sent to the
AcceptConnection dialog box. Get's the callee's name and copies
it into the CalleeBuffer, which is passed in as a parameter to the
WM_INITDIALOG message.

Arguments:

DialogWindow - Supplies handle of the AcceptConnection dialog box

Message - Supplies the message identifier

WParam - Supplies the first message parameter

LParam - Supplies the second message parameter

Return Value:

TRUE -- This function handled the message.

FALSE -- This function did not handle the message; or the message
was WM_INITDIALOG and we set the focus.

--*/

{
static LPWSABUF CalleeData; // callee user data

switch (Message) {

case WM_INITDIALOG:

CalleeData = (LPWSABUF)LParam;
assert(CalleeData != NULL);

// Determine how much room there is in the user data buffer.
// Limit the text to NAME_LEN characters, or less if we
// don't have room for that many.
if (CalleeData->len < (NAME_LEN + 1)) {
SendMessage(GetDlgItem(DialogWindow, IDC_CALLERNAME),
EM_LIMITTEXT, (WPARAM)(CalleeData->len - 1),
0);
} else {
SendMessage(GetDlgItem(DialogWindow, IDC_CALLERNAME),
EM_LIMITTEXT, (WPARAM)NAME_LEN, 0);
}
SetFocus(GetDlgItem(DialogWindow, IDC_CALLEENAME));
return(FALSE);

case WM_COMMAND:

switch (WParam) {

case IDOK:

// Get the name from the control and but it in CalleeData.
GetDlgItemText(DialogWindow,
IDC_CALLEENAME,
CalleeData->buf,
NAME_LEN);
CalleeData->len = strlen(CalleeData->buf + 1);
EndDialog(DialogWindow, TRUE);
return(TRUE);

case IDCANCEL:

// Kill the dialog box
EndDialog(DialogWindow, FALSE);
return(TRUE);

default:

break;

}

break;
} // switch (Message)

return(FALSE);
} // AcceptConnectionDlgProc()





BOOL APIENTRY
InetListenPortDlgProc(
IN HWND DialogWindow,
IN UINT Message,
IN WPARAM WParam,
IN LPARAM LParam)
/*++

Routine Description:

Callback function that processes messages sent to the
listening port dialog box.

Arguments:

DialogWindow - Supplies handle of the AcceptConnection dialog box

Message - Supplies the message identifier

WParam - Supplies the first message parameter

LParam - Supplies the second message parameter

Return Value:

TRUE -- This function handled the message.

FALSE -- This function did not handle the message; or the message
was WM_INITDIALOG and we set the focus.

--*/
{

static struct sockaddr_in *SockAddrInet; // Inet sockaddress
int Port; // Inet port
BOOL PortStringTranslated; // for GetDlgItemInt
char PortText[INET_PORT_LEN+1]; // Inet port string

switch (Message) {

case WM_INITDIALOG:

// Get the parameter and initialize the dialog box.
SockAddrInet = (struct sockaddr_in *)LParam;
assert(SockAddrInet != NULL);
SendMessage(GetDlgItem(DialogWindow, IDC_LISTEN_PORT),
EM_LIMITTEXT, (WPARAM)INET_PORT_LEN, 0);
wsprintf(PortText,"%d", INET_DEFAULT_PORT);
SendMessage(GetDlgItem(DialogWindow, IDC_LISTEN_PORT),
WM_SETTEXT, 0, (LPARAM)PortText);
SetFocus(GetDlgItem(DialogWindow, IDC_LISTEN_PORT));
return(FALSE);

case WM_COMMAND:

switch (WParam) {

case IDOK:

// Get the port.
Port = (int)GetDlgItemInt(DialogWindow,
IDC_LISTEN_PORT,
&PortStringTranslated,
TRUE);
if ((Port < 0) || (Port > 65535) || !PortStringTranslated) {
MessageBox(DialogWindow,
"Please choose a port between 0 and 65535.",
"Bad Port.",
MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
return(TRUE);
}

SockAddrInet->sin_port = (u_short)Port;
EndDialog(DialogWindow, TRUE);
return(TRUE);

case IDCANCEL:

// Kill the dialog box.
EndDialog(DialogWindow, FALSE);
return(TRUE);

default:
break;
}
break;

} // switch (Message)

return(FALSE);
} // InetListenPortDlgProc()





BOOL APIENTRY
DefaultListenAddrDlgProc(
IN HWND DialogWindow,
IN UINT Message,
IN WPARAM WParam,
IN LPARAM LParam)
/*++

Routine Description:

Callback function that processes messages sent to the default
listening address dialog box.

Arguments:

DialogWindow - Supplies handle of the AcceptConnection dialog box

Message - Supplies the message identifier

WParam - Supplies the first message parameter

LParam - Supplies the second message parameter

Return Value:

TRUE -- This function handled the message.

FALSE -- This function did not handle the message; or the message
was WM_INITDIALOG and we set the focus.

--*/
{

static LPWSABUF SockAddrBuf;
static char *AddrText;
static int AddrTextLen;

switch (Message) {

case WM_INITDIALOG:

// Get the parameter and initialize the dialog box.
SockAddrBuf = (LPWSABUF)LParam;
assert(SockAddrBuf != NULL);

AddrTextLen = SockAddrBuf->len * 2 + 1;
AddrText = (char *)malloc(AddrTextLen);

SendMessage(GetDlgItem(DialogWindow, IDC_LISTEN_ADDR),
EM_LIMITTEXT, AddrTextLen - 1, 0);
wsprintf(AddrText,"%X",
((struct sockaddr *)SockAddrBuf->buf)->sa_family);
SendMessage(GetDlgItem(DialogWindow, IDC_LISTEN_ADDR),
WM_SETTEXT, 0, (LPARAM)AddrText);
SetFocus(GetDlgItem(DialogWindow, IDC_LISTEN_ADDR));
return(FALSE);

case WM_COMMAND:

switch (WParam) {

case IDOK:

// The user clicked 'OK'. Get the text from the edit
// control, and convert the hex string into bytes and put
// the bytes into the socket address for this connection.
GetDlgItemText(DialogWindow, IDC_LISTEN_ADDR, AddrText,
AddrTextLen);
if (TranslateHex(SockAddrBuf->buf,
SockAddrBuf->len,
AddrText,
DialogWindow)) {
EndDialog(DialogWindow, TRUE);
}

EndDialog(DialogWindow, TRUE);
free(AddrText);
return(TRUE);

case IDCANCEL:

// Kill the dialog box.
EndDialog(DialogWindow, FALSE);
free(AddrText);
return(TRUE);

default:
break;
}
break;

} // switch (Message)

return(FALSE);
} // DefaultListenAddrDlgProc()