/*

	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;
	} else {
		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 {
				_fmemcpy(&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:
                	WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY,
                				((DWORD) (Lrstring(IDS_HELP_LWL_TELL))));
                	holped = TRUE;
                	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 FAR *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 FAR *conn;			// Connection chain
static struct lwl FAR *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) {
		_fmemcpy(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 FAR *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 FAR *co = conn;
		
		conn = co->next;
		destroyLwl(co);
	}
}

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

static struct lwl FAR *lwlItem(int i)
{
	struct lwl FAR *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);                	    
	        return;
		} else {
			_fmemcpy(&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;
	_fmemcpy(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

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

    switch (message) {
        case WM_INITDIALOG:
        	{
				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);
			}
            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 FAR *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 FAR *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;
                			_fstrcpy(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 {
								_fmemcpy(&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;
						_fmemcpy(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 FAR *lw;
			
							lw = (struct lwl FAR *) GlobalAllocPtr(GPTR, sizeof(struct lwl));
							if (lw != NULL) {
								int parsing = TRUE;
								struct sockaddr_in u;
			
								_fmemcpy(&(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') {
			                                            _fstrcpy(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') {
			                                            _fstrcpy(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];
									
									_fstrcpy(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, " ");
										_fstrcat(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);
								}
							}
						}
                	}
                	break;
		        	
                case ID_HELP:
                	WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY,
                				((DWORD) (Lrstring(IDS_HELP_LWL_ASK))));
                	holped = TRUE;
                	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;
}
