/*

	Look Who's Listening dialogue handlers

*/

#include "netfone.h"

struct sockaddr_in lookhost;   		// Look who's listening host, if any

//  EDITRETURN  --  Edit control which notifies parent of return key. 

static WNDPROC lpfnOldEdit = NULL;

#define WM_EDITRETURN	(WM_USER + 1002) 

LONG WINAPI editReturn(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

	if (message == WM_GETDLGCODE) {
		return DLGC_WANTALLKEYS;		// We want to see Tab, Return, etc.
	}

	if ((message == WM_KEYDOWN && wParam == VK_TAB) ||
		(message == WM_KEYDOWN && wParam == VK_RETURN)) {
		if ((lParam & (1 << 31)) == 0) {
			SendMessage(GetParent(hWnd), WM_COMMAND,
				MAKELONG(GetWindowLong(hWnd, GWL_ID), WM_EDITRETURN),
				(LPARAM) hWnd);
		}
		return 0L;
	}
	
	//	Must eat return and tab WM_CHAR messages to avoid inane "bing"
	if ((message == WM_CHAR) &&
		((wParam == '\t')) || (wParam == '\r')) {
		return 0L;
	}

	return CallWindowProc(lpfnOldEdit, hWnd, message, wParam, lParam);
}

/*	SENDLWLMESSAGE	--	If enabled, send a message identifying us
                        to the selected Look Who's Listening server.  */

int sendLwlMessage(HWND hDlg, int dobye)
{
	int sock;

	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == INVALID_SOCKET) {
        int serr = WSAGetLastError();
						            
        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(54),
                serr, SockerrToString(serr));
		return FALSE;
	}
	if (connect(sock, (struct sockaddr *) &(lookhost), sizeof lookhost) >= 0) {
		if (dobye) {
			char v[128];
			int l;

            l = rtp_make_bye(v, ssrc, rstring(IDS_T_RAISON_EXITING), FALSE);
			if (send(sock, v, l, 0) < 0) {
		        int serr = WSAGetLastError();
								            
		        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(55),
		                serr, SockerrToString(serr));
		        closesocket(sock);
				return FALSE;
			}
		} else {
			if (send(sock, (char *) sdes, sdesl, 0) < 0) {
		        int serr = WSAGetLastError();
								            
		        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(56),
		                serr, SockerrToString(serr));
		        closesocket(sock);
				return FALSE;
			}
		}
	} else {
        int serr = WSAGetLastError();
								            
        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(57),
                serr, SockerrToString(serr));
        closesocket(sock);
		return FALSE;
	}
	closesocket(sock);
	return TRUE;
}

//	LWL_RECONNECT  --  Reconnect to current Look Who's Listening server

int lwl_reconnect(HWND hDlg)
{
	lwl_t_published = FALSE;
    if (lwl_s_server[0] == 0 || lwl_s_email[0] == 0) {
    	lwl_s_publish = FALSE;
    }
						
	//	Remake session identity information
					
	if (sdes != NULL) {
		free(sdes);
		sdes = NULL;
	}
	if (lwl_s_email[0] != 0) {
		sdesl = rtp_make_sdes(&sdes, ssrc, NETFONE_COMMAND_PORT,
							  lwl_s_exact, FALSE);
	}
	if (rtpsdes != NULL) {
		free(rtpsdes);
		rtpsdes = NULL;
	}
	rtpsdesl = rtp_make_sdes(&rtpsdes, ssrc, NETFONE_COMMAND_PORT,
							 FALSE, TRUE);
	if (vatid != NULL) {
		free(vatid);
		vatid = NULL;
	}
	vatidl = makeVATid(&vatid, 0L);
					
	/*	If the user wishes to publish this information, look
		up the host where it's to be published.  */
					
	if (lwl_s_publish) {
		lookhost.sin_family = AF_INET;
		lookhost.sin_port = htons(NETFONE_COMMAND_PORT + 2);
		lookhost.sin_addr.s_addr = inet_addr(lwl_s_server);
		if (lookhost.sin_addr.s_addr == INADDR_NONE) {
			LPHOSTENT h = gethostbyname(lwl_s_server);
							
			if (h == NULL) {
	            int serr = WSAGetLastError();
						            
		        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(41),
		                (LPSTR) lwl_s_server,
		                serr, SockerrToString(serr));
		        return FALSE;
			} else {
				memcpy(&lookhost.sin_addr.s_addr, (h->h_addr),
					sizeof lookhost.sin_addr.s_addr);
			}
		}
		if (lwl_t_pending) {
			lwl_t_pending = 2;
		} else {
			lwl_t_resend = 2;				// Set to resend in two seconds
		}
		lwl_t_published = lwl_s_publish;
	}
	return TRUE;
}

//	LWL_TELL_PROC  --  Look Who's Listening publish dialogue procedure

BOOL CALLBACK lwl_tell_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static int serverDefault;

    switch (message) {
        case WM_INITDIALOG:
        	{
				CheckDlgButton(hDlg, IDC_LWLS_UNLISTED, lwl_s_publish);
				CheckDlgButton(hDlg, IDC_LWLS_EXACT, lwl_s_exact);
				if ((serverDefault = (lwl_s_server[0] == 0)) != 0) {
					SetDlgItemText(hDlg, IDC_LWLS_SERVER, rstring(IDS_T_LWL_DEFAULT_SERVER));
				} else {
					SetDlgItemText(hDlg, IDC_LWLS_SERVER, lwl_s_server);
				}
				SetDlgItemText(hDlg, IDC_LWLS_EMAIL, lwl_s_email);
				SetDlgItemText(hDlg, IDC_LWLS_FULLNAME, lwl_s_fullname);
				SetDlgItemText(hDlg, IDC_LWLS_PHONE, lwl_s_phone);
				SetDlgItemText(hDlg, IDC_LWLS_LOCATION, lwl_s_location);
			}
            break;

        case WM_COMMAND:
            switch ((short) WM_COMMAND_ID(wParam)) {
                case IDOK:
                
                	/* If information is currently published, revoke it in
                	   case we're about to publish a changed version. */
                	   
                	if (lwl_t_published && !lwl_t_pending) {
                		sendLwlMessage(hDlg, TRUE);		// Send BYE message
                		lwl_t_published = FALSE;
                	}
                
                	lwl_s_publish = IsDlgButtonChecked(hDlg, IDC_LWLS_UNLISTED);
                	lwl_s_exact = IsDlgButtonChecked(hDlg, IDC_LWLS_EXACT);
                	if (!serverDefault) {
						GetDlgItemText(hDlg, IDC_LWLS_SERVER, lwl_s_server, sizeof lwl_s_server);
					}
					GetDlgItemText(hDlg, IDC_LWLS_EMAIL, lwl_s_email, sizeof lwl_s_email);
					GetDlgItemText(hDlg, IDC_LWLS_FULLNAME, lwl_s_fullname, sizeof lwl_s_fullname);
					GetDlgItemText(hDlg, IDC_LWLS_PHONE, lwl_s_phone, sizeof lwl_s_phone);
					GetDlgItemText(hDlg, IDC_LWLS_LOCATION, lwl_s_location, sizeof lwl_s_location);
					if (lwl_reconnect(hDlg)) {
	                	EndDialog(hDlg, TRUE);
	                }
                    break;

                case IDCANCEL:
                    EndDialog(hDlg, FALSE);
                    break;
                    
                case IDC_LWLS_SERVER:
                	if (WM_COMMAND_NOTIFY == EN_CHANGE) {
                		serverDefault = FALSE;
                	}
                	break;
		        	
                case ID_HELP:
                	displayHelpTopic(IDS_HELP_LWL_TELL);
                	break;

                default:
                    break;
            }
            break;
        	
        default:
        	break;	    	
    }
    return FALSE;
}

//	LWL_TELL_SETTINGS  --  Set Look Who's Listening published properties

VOID lwl_tell_settings(HWND hwnd)
{
    DialogBox(hInst, MAKEINTRESOURCE(IDD_LWL_TELL), hwnd, lwl_tell_proc);
    return;
}

struct lwl {
	struct lwl *next;					// Next connection
	long ltime;							// Time of last update
	unsigned long ssrc;					// Session source descriptor
	long naddr;							// Internet address
	unsigned short port;				// Port address
	LPSTR cname;						// Canonical name 
	LPSTR name;							// User name
	LPSTR email;						// Electronic mail address
	LPSTR phone;						// Telephone number
	LPSTR loc;							// Geographic location
	LPSTR tool;							// Application name
};

static struct lwl *conn;				// Connection chain
static struct lwl *ctail;				// Connection chain tail
static int diasel = -1;					// Selected item in results box

/*	DUPSDESITEM  --  Make a copy of an SDES item and advance the pointer
					 past it.  */

static LPSTR dupSdesItem(char **cp)
{
	char *ip = *cp;
	int l = ip[1];
	LPSTR bp;

	bp = GlobalAllocPtr(GPTR, l + 1);
	if (bp != NULL) {
		memcpy(bp, ip + 2, l);
		bp[l] = 0;
	}
	*cp = ip + l + 2;
	return bp;
}

//	DESTROYLWL	--	Release storage associated with an LWL list item.

static void destroyLwl(struct lwl *lw)
{
	if (lw->cname != NULL) {
		GlobalFreePtr(lw->cname);
	}
	if (lw->name != NULL) {
		GlobalFreePtr(lw->name);
	}
	if (lw->email != NULL) {
		GlobalFreePtr(lw->email);
	}
	if (lw->phone != NULL) {
		GlobalFreePtr(lw->phone);
	}
	if (lw->loc != NULL) {
		GlobalFreePtr(lw->loc);
	}
	if (lw->tool != NULL) {
		GlobalFreePtr(lw->tool);
	}
	GlobalFreePtr(lw);
}

//	FREELWLCHAIN  --  Release all items in LWL chain

static void freeLwlChain(void)
{
	while (conn != NULL) {
		struct lwl *co = conn;
		
		conn = co->next;
		destroyLwl(co);
	}
}

//	LWLITEM  --  Get LWL chain item by zero-based index

static struct lwl *lwlItem(int i)
{
	struct lwl *co = conn;

	while (co != NULL && i-- > 0) {
		co = co->next;
	}
	return co;
}

//  ENABLE_ASK_INPUTS  --  Enable/Disable Look Who's Listening query requests

static void enable_ask_inputs(HWND hDlg, int enable)
{
#define EnableD(x) EnableWindow(GetDlgItem(hDlg, x), enable)
	EnableD(IDC_LWLA_SERVER);
	EnableD(IDC_LWLA_QUERY);
	EnableD(IDC_LWLA_SEARCH);
	EnableD(IDOK);
}

#define nTextItems	5

//	UPDATESERVERMESSAGE  --  Update server message on initial connect or server change

static void updateServerMessage(HWND hDlg)
{
	struct sockaddr_in askhost;
	char sv[512];
	char *serv = sv, *cp;
//	rtcp_t *rp = (rtcp_t *) sv;
	SOCKET sock;
	int l;

	enable_ask_inputs(hDlg, FALSE);                	    
    GetDlgItemText(hDlg, IDC_LWLA_SERVER, sv, sizeof sv);
    if (sv[0] == '(') {
    	serv++;
    	if ((cp = strchr(serv, ')')) != NULL) {
    		*cp = 0;
    	}
    }
	askhost.sin_family = AF_INET;
	askhost.sin_port = htons(NETFONE_COMMAND_PORT + 2);
	askhost.sin_addr.s_addr = inet_addr(serv);
	if (askhost.sin_addr.s_addr == INADDR_NONE) {
		LPHOSTENT h;

		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
							(LPARAM) (LPCSTR) rstring(IDS_T_LWLA_LOOKUP));
		h = gethostbyname(serv);
		if (h == NULL) {
            int serr = WSAGetLastError();
			
			if (serr != WSAEINTR) {							            
	        	MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(41),
	                	(LPSTR) serv,
	                	serr, SockerrToString(serr));
	        }
			SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
			enable_ask_inputs(hDlg, TRUE);
			/* The server lookup failed.  Set the focus back to the server box
			   and select its entire contents so the user can easily enter
			   another. */
			SetFocus(GetDlgItem(hDlg, IDC_LWLA_SERVER));
			SendDlgItemMessage(hDlg, IDC_LWLA_SERVER, EM_SETSEL, 0, -1);
	        return;
		} else {
			memcpy(&askhost.sin_addr.s_addr, (h->h_addr),
				sizeof askhost.sin_addr.s_addr);
		}
	}

	// Create the socket and connect to host
				
	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
						(LPARAM) (LPCSTR) rstring(IDS_T_LWLA_CONNECT));
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == INVALID_SOCKET) {
        int serr = WSAGetLastError();
											            
        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(54),
                serr, SockerrToString(serr));
		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
		enable_ask_inputs(hDlg, TRUE);                	    
		return;
	}
				
	if (connect(sock, (struct sockaddr *) &askhost, sizeof askhost) < 0) {
        int serr = WSAGetLastError();
													            
        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(57),
                serr, SockerrToString(serr));
        closesocket(sock);
		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
		enable_ask_inputs(hDlg, TRUE);                	    
        return;
	}
	*((short *) sv) = (short) ((RTP_VERSION << 14) | RTCP_APP | (1 << 8));
	*((long *) (sv + 4)) = 0;
	memcpy(sv + 8, rstring(IDS_T_LWL_GETMESSAGE), 4);
	*((short *) (sv + 2)) = 2;	// Message length in 32 bit words - 1
	revshort((short *) sv);
	revshort((short *) (sv + 2));
	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
						(LPARAM) (LPCSTR) rstring(IDS_T_LWLA_REQUEST));
	if (send(sock, sv, 12, 0) < 0) {
		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
		enable_ask_inputs(hDlg, TRUE);                	    
        return;
	}
	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
							(LPARAM) (LPCSTR) rstring(IDS_T_RECEIVE));
	if ((l = recv(sock, sv, sizeof sv, 0)) <= 0) {
		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
		enable_ask_inputs(hDlg, TRUE);                	    
        return;
	}
	closesocket(sock);			// Don't need socket any more
	
	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
	diasel = -1;
	freeLwlChain();
	cp = sv + 12;
	while (cp != NULL) {
		char *np = strchr(cp, '\n');
						
		if (np != NULL) {
			*np++ = 0;
		}
		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
							(LPARAM) (LPCSTR) cp);
		cp = np;
	}
	enable_ask_inputs(hDlg, TRUE);                	    
}

//	LWL_ASK_PROC  --  Look Who's Listening search dialogue procedure

static char *lwl_ask_target = NULL;
static HWND lwl_ask_dialogue = NULL;

BOOL CALLBACK lwl_ask_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static int echanged;
	int i;

    switch (message) {
        case WM_INITDIALOG:
        	{
        		lwl_ask_dialogue = hDlg;
				CheckDlgButton(hDlg, IDC_LWLA_EXACT, lwl_a_exact);
				/*	If no Ask server is specified, use the Tell server
					(or the default for it).  */ 
				if (lwl_a_server[0] == 0) {
					char as[82];
					
					if (lwl_s_server[0] == 0) {
						wsprintf(as, Format(61), (LPSTR) rstring(IDS_T_LWL_DEFAULT_SERVER));
					} else {
						wsprintf(as, Format(61), (LPSTR) lwl_s_server);
					}
					SetDlgItemText(hDlg, IDC_LWLA_SERVER, as);
				} else {
					SetDlgItemText(hDlg, IDC_LWLA_SERVER, lwl_a_server);
				}
				diasel = -1;
				
				//	Subclass edit controls to permit automatic update when they change

				lpfnOldEdit = (WNDPROC) GetWindowLong(GetDlgItem(hDlg, IDC_LWLA_SERVER),
											GWL_WNDPROC);
				SetWindowLong(GetDlgItem(hDlg, IDC_LWLA_SERVER), GWL_WNDPROC,
											(LONG) editReturn);
				SetWindowLong(GetDlgItem(hDlg, IDC_LWLA_QUERY), GWL_WNDPROC,
											(LONG) editReturn);

				EnableWindow(GetDlgItem(hDlg, IDC_LWLA_CONNECT), FALSE);
				conn = NULL;
				updateServerMessage(hDlg);
				
				/*	If the target for the search has been pre-specified (for
					example, by the answering machine), plug the target into
					the query box and post a message to start the search by
					faking a push on the Search button.  */
				
				if (lwl_ask_target != NULL) {
					SetDlgItemText(hDlg, IDC_LWLA_QUERY, lwl_ask_target);
					PostMessage(hDlg, WM_COMMAND, IDC_LWLA_SEARCH, 0L);
					GlobalFreePtr(lwl_ask_target);
					lwl_ask_target = NULL;
				}
			}
            break;
            
        case WM_DESTROY:
			lwl_ask_dialogue = NULL;
			break;

        case WM_COMMAND:
            switch ((short) WM_COMMAND_ID(wParam)) {
                case IDOK:
                	{
                		char *serv = lwl_a_server;
                	
	                	lwl_a_exact = IsDlgButtonChecked(hDlg, IDC_LWLA_EXACT);
						GetDlgItemText(hDlg, IDC_LWLA_SERVER, lwl_a_server, sizeof lwl_a_server);
	                    if (lwl_a_server[0] == '(') {
	                    	lwl_a_server[0] = 0;
	                    }
                		freeLwlChain();
		                EndDialog(hDlg, TRUE);
	                }
                    break;

                case IDCANCEL:
                	freeLwlChain();
                    EndDialog(hDlg, FALSE);
                    break;
                    
                case IDC_LWLA_SERVER:
                	if (WM_COMMAND_NOTIFY == EN_SETFOCUS) {
                		echanged = FALSE;
                	} else if (WM_COMMAND_NOTIFY == EN_CHANGE) {
                		echanged = TRUE;
                	} else if (((WM_COMMAND_NOTIFY == WM_EDITRETURN) ||
                			   ((WM_COMMAND_NOTIFY == EN_KILLFOCUS) && echanged))) {
                		echanged = FALSE;
                		//	Get server welcome message, if any, and display
						updateServerMessage(hDlg);
                	}
                	break;                    
                    
                case IDC_LWLA_QUERY:
                	if (WM_COMMAND_NOTIFY == EN_SETFOCUS) {
                		echanged = FALSE;
                	} else if (WM_COMMAND_NOTIFY == EN_CHANGE) {
                		echanged = TRUE;
                	} else if (((WM_COMMAND_NOTIFY == WM_EDITRETURN) ||
                			   ((WM_COMMAND_NOTIFY == EN_KILLFOCUS) && echanged))) {
                		char qs[256];
                		
	                	GetDlgItemText(hDlg, IDC_LWLA_SERVER, qs, sizeof qs);
	                	if (strlen(qs) > 0) {
	                		PostMessage(hDlg, WM_COMMAND, IDC_LWLA_SEARCH, 0L);
	                	}
                		echanged = FALSE;
                	}
                	break;                    
                    
                case IDC_LWLA_CONNECT:
                	if (diasel >= 0) {
                		struct lwl *l = lwlItem(diasel);
                		
                		if (l != NULL) {
                			struct sockaddr_in u;
                			char s[40];
                			
                			u.sin_addr.s_addr = l->naddr;
                			wsprintf(s, Format(48), (LPSTR) inet_ntoa(u.sin_addr), l->port); 
                			newConnection(hwndMDIFrame, NULL, s);
                			PostMessage(hDlg, WM_COMMAND, IDOK, 0L);
                		}
                	}
                	break;
                    
                case IDC_LWLA_RESULTS:
                	for (i = 0; i < nTextItems; i++) {
                		SetDlgItemText(hDlg, IDC_LWLA_LINE1 + i, "");
                	}
                	if (WM_COMMAND_NOTIFY == LBN_SELCHANGE) {
                		/*	Allow selection in results box only if it shows
                			result from a query as opposed to a server message. */
                		if (conn == NULL) {
                			diasel = LB_ERR;
                			SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS,
	                					LB_SETCURSEL, (WPARAM) -1, 0L);
                		} else {
	                		diasel = (int) SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS,
	                					LB_GETCURSEL, 0, 0L);
	                	}
                		if (diasel == LB_ERR) {
                			diasel = -1;
                		} 
                	} else if (WM_COMMAND_NOTIFY == LBN_SELCANCEL) {
                		diasel = -1;
                	}
                	EnableWindow(GetDlgItem(hDlg, IDC_LWLA_CONNECT), diasel >= 0);
                	if (diasel >= 0) {
                		struct lwl *l = lwlItem(diasel);
                		
                		if (l != NULL) {
                			char eb[40];
                			struct sockaddr_in u;
                			
                			i = 0;
                			if (l->name != NULL) {
                				SetDlgItemText(hDlg, IDC_LWLA_LINE1 + i++, l->name); 	
                			}
                			SetDlgItemText(hDlg, IDC_LWLA_LINE1 + i++, l->email ?
                				l->email : l->cname);
                			if (l->loc != NULL) {
                				SetDlgItemText(hDlg, IDC_LWLA_LINE1 + i++, l->loc); 	
                			}
                			if (l->phone != NULL) {
                				SetDlgItemText(hDlg, IDC_LWLA_LINE1 + i++, l->phone); 	
                			}
                			u.sin_addr.s_addr = l->naddr;
                			strcpy(eb, inet_ntoa(u.sin_addr));
                			wsprintf(eb + strlen(eb), Format(64), l->port);
                			SetDlgItemText(hDlg, IDC_LWLA_LINE1 + i++, eb);  	
                		}
                	} 
                	break;
                    
                case IDC_LWLA_SEARCH:
                	{
                		struct sockaddr_in askhost;
                		char sv[512];
                		char *serv = sv, *cp;
                		SOCKET sock;
                		int l, nitems;
                	    
                	    SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
						SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
							(LPARAM) (LPCSTR) rstring(IDS_T_LWLA_LOOKUP));
                	    GetDlgItemText(hDlg, IDC_LWLA_SERVER, sv, sizeof sv);
                	    if (sv[0] == '(') {
					    	serv++;
					    	if ((cp = strchr(serv, ')')) != NULL) {
					    		*cp = 0;
					    	}
                	    }
						askhost.sin_family = AF_INET;
						askhost.sin_port = htons(NETFONE_COMMAND_PORT + 2);
						askhost.sin_addr.s_addr = inet_addr(serv);
						enable_ask_inputs(hDlg, FALSE);
						if (askhost.sin_addr.s_addr == INADDR_NONE) {
							LPHOSTENT h = gethostbyname(serv);
											
							if (h == NULL) {
					            int serr = WSAGetLastError();
								
								if (serr != WSAEINTR) {		            
							        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(41),
							                (LPSTR) serv,
							                serr, SockerrToString(serr));
							    }
                	    		SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
                	    		enable_ask_inputs(hDlg, TRUE);
						        break;
							} else {
								memcpy(&askhost.sin_addr.s_addr, (h->h_addr),
									sizeof askhost.sin_addr.s_addr);
							}
						}

						// Create the socket and connect to host
				
						SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
							(LPARAM) (LPCSTR) rstring(IDS_T_LWLA_CONNECT));
						sock = socket(AF_INET, SOCK_STREAM, 0);
						if (sock == INVALID_SOCKET) {
					        int serr = WSAGetLastError();
											            
					        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(54),
					                serr, SockerrToString(serr));
                	    	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
                	    	enable_ask_inputs(hDlg, TRUE);
							break;
						}
				
						if (connect(sock, (struct sockaddr *) &askhost, sizeof askhost) < 0) {
					        int serr = WSAGetLastError();
													            
					        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(57),
					                serr, SockerrToString(serr));
					        closesocket(sock);
                	    	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
                	    	enable_ask_inputs(hDlg, TRUE);
					        break;
						}
						*((short *) sv) = (short) ((RTP_VERSION << 14) | RTCP_APP | (1 << 8));
						*((long *) (sv + 4)) = 0;
						memcpy(sv + 8, rstring(IDS_T_LWL_QUERY), 4);
						cp = sv + 12;
						if (IsDlgButtonChecked(hDlg, IDC_LWLA_EXACT)) {
							*cp++ = '*';
						}
						GetDlgItemText(hDlg, IDC_LWLA_QUERY, cp, (sizeof sv) - (cp - sv));
						cp += strlen(cp) + 1;
						while ((cp - sv) & 3) {
							*cp++ = 0;
						}
						*((short *) (sv + 2)) = ((cp - sv) / 4) - 1;
						revshort((short *) sv);
						revshort((short *) (sv + 2));
						SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
							(LPARAM) (LPCSTR) rstring(IDS_T_LWLA_QUERY));
						if (send(sock, sv, 13 + strlen(sv + 12), 0) < 0) {
					        int serr = WSAGetLastError();
													            
					        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(62),
					                serr, SockerrToString(serr));
					        closesocket(sock);
                	    	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
                	    	enable_ask_inputs(hDlg, TRUE);
					        break;
						}
						SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
							(LPARAM) (LPCSTR) rstring(IDS_T_LWLA_RESULTS));
						if ((l = recv(sock, sv, sizeof sv, 0)) <= 0) {
					        int serr = WSAGetLastError();
													            
					        MsgBox(hDlg, MB_ICONSTOP | MB_OK, Format(63),
					                serr, SockerrToString(serr));
					        closesocket(sock);
                	    	SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
                	    	enable_ask_inputs(hDlg, TRUE);
					        break;
						}
						closesocket(sock);			// Don't need socket any more
						
						enable_ask_inputs(hDlg, TRUE);
						nitems = sv[0] & 0x1F;
						SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_RESETCONTENT, 0, 0L);
						freeLwlChain();				// Release any previous results
						diasel = -1;
	                	for (i = 0; i < nTextItems; i++) {
	                		SetDlgItemText(hDlg, IDC_LWLA_LINE1 + i, "");
	                	}
						EnableWindow(GetDlgItem(hDlg, IDC_LWLA_CONNECT), FALSE);
						cp = sv + 4;
						while (nitems-- > 0) {
							struct lwl *lw;
			
							lw = (struct lwl *) GlobalAllocPtr(GPTR, sizeof(struct lwl));
							if (lw != NULL) {
								int parsing = TRUE;
								struct sockaddr_in u;
			
								memcpy(&(lw->ssrc), cp, 4);
								cp += 4;
			
								while (parsing) {
									switch (*cp) {
			
										case RTCP_SDES_CNAME:		// Canonical (talk, finger) name
											lw->cname = dupSdesItem(&cp);
											break;
			
										case RTCP_SDES_NAME:		// Full name
											lw->name = dupSdesItem(&cp);
											break;
			
										case RTCP_SDES_EMAIL:		// E-mail address
											lw->email = dupSdesItem(&cp);
											break;
			
										case RTCP_SDES_PHONE:		// Telephone number
											lw->phone = dupSdesItem(&cp);
											break;
			
										case RTCP_SDES_LOC:			// Geographical location
											lw->loc = dupSdesItem(&cp);
											break;
			
										case RTCP_SDES_TOOL:		// Tool (client) name
											lw->tool = dupSdesItem(&cp);
											break;
			
										case RTCP_SDES_PRIV:		// Private SDES extensions
											{
												LPSTR zp = dupSdesItem(&cp);
			
												if (*zp != 0) {
													char hawx[20];
													
													//	P:	Port user is listening on
													if (zp[0] == 1 &&
			                                            zp[1] == 'P') {
			                                            strcpy(hawx, zp + 2);
														lw->port = atoi(hawx);
														
													//	I:	IP address of user (as long)
													} else if (zp[0] == 1 &&
			                                                   zp[1] == 'I') {
														lw->naddr = inet_addr(zp + 2);
														
													//	T:	Time and date of last status update
													}  else if (zp[0] == 1 &&
			                                                    zp[1] == 'T') {
			                                            strcpy(hawx, zp + 2);
														lw->ltime = atol(hawx);
													}
													GlobalFreePtr(zp);
												}
											}
											break;
			
										case RTCP_SDES_END:
											cp++;
											while ((cp - sv) & 3) {
												cp++;
											}
											parsing = FALSE;
											break;
			
										default:
											{
												LPSTR zp = dupSdesItem(&cp);
			
												if (zp != NULL) {
													GlobalFreePtr(zp);
												}
											}
											break;
									}
								}
								u.sin_addr.s_addr = lw->naddr;

								if (lw->cname != NULL || lw->email != NULL) {
									char s[256];
									
									strcpy(s, lw->email != NULL ? lw->email : lw->cname);
									if (lw->name != NULL) {
										wsprintf(s + strlen(s), Format(34), lw->name);
									}
									if (lw->loc != NULL) {
										strcat(s, " ");
										strcat(s, lw->loc);
									} 								
									SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
										(LPARAM) (LPCSTR) s);
									lw->next = NULL;
									if (conn == NULL) {
										conn = ctail = lw;
									} else {
										ctail->next = lw;
										ctail = lw;
									}
								} else {								
									destroyLwl(lw);
								}
							}
						}

						/* If one or more items have been placed into the results box,
						   set focus to the first item found and post a message to the
						   results box which will cause it to be selected and the
						   information describing it painted in the IDC_LWLA_LINE1...
						   fields. */
						if (conn != NULL) {
							SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_SETCURSEL, 0, 0L);
							SetFocus(GetDlgItem(hDlg, IDC_LWLA_RESULTS));
							PostMessage(hDlg, WM_COMMAND, MAKELONG(IDC_LWLA_RESULTS, LBN_SELCHANGE), 0L);
						} else {
							/* If the query found nothing, however, plug the "no match"
							   message in the results box, set the focus back to the
							   query edit field, and select the entire field to make it
							   easy to replace it entirely.  Note that since conn is
							   NULL, the user won't be able to select our "no match"
							   item in the results box. */
							SendDlgItemMessage(hDlg, IDC_LWLA_RESULTS, LB_ADDSTRING, 0,
								(LPARAM) rstring(IDS_T_LWLA_NOMATCH));
							SetFocus(GetDlgItem(hDlg, IDC_LWLA_QUERY));
							SendDlgItemMessage(hDlg, IDC_LWLA_QUERY, EM_SETSEL, 0, -1);
						}
               	}
                	break;
		        	
                case ID_HELP:
					displayHelpTopic(IDS_HELP_LWL_ASK);
                	break;

                default:
                    break;
            }
            break;
        	
        default:
        	break;	    	
    }
    return FALSE;
}

//	LWL_ASK  --  Search Look Who's Listening directory

VOID lwl_ask(HWND hwnd)
{
    DialogBox(hInst, MAKEINTRESOURCE(IDD_LWL_ASK), hwnd, lwl_ask_proc);
    return;
}

//	LWL_ASK_SET_TARGET  --  Pre-specify the target of a LWL search

void lwl_ask_set_target(const char *target)
{
	if (lwl_ask_target != NULL) {
		GlobalFreePtr(lwl_ask_target);
		lwl_ask_target = NULL;
	}
	if (lwl_ask_dialogue == NULL) {
		lwl_ask_target = GlobalAllocPtr(GPTR, strlen(target) + 1);
		if (lwl_ask_target != NULL) {
			strcpy(lwl_ask_target, target);
		}
		PostMessage(hwndMDIFrame, WM_COMMAND, IDM_DIR_SEARCH, 0);
	} else {
		SetDlgItemText(lwl_ask_dialogue, IDC_LWLA_QUERY, target);
		PostMessage(lwl_ask_dialogue, WM_COMMAND, IDC_LWLA_SEARCH, 0L);
	}
}
