/* ----------------------------------------------------------------------

	CNFTEST sample for Microsoft ActiveX Conferencing

	Copyright (c) 1996, Microsoft Corporation
	All rights reserved.

	MODULE: test.c

	PURPOSE: This file calls the Scrapi APIs to establish the 
	meeting connection and to perform other operations such as
	information exchange. Selecting function names from the menu 
	or using the toolbar buttons tests each function.
	
	COMMENTS: Following structures are used by the function.

		CONFADDR: Describes the meeting connection address.
		CONFINFO: Describes the meeting settings.
		CONFERECDIR: Describes the default receive directory
		             for transferred files.
		CONFNOTIFY: Describes the notification callback.
		CONFUSERINFO: Describes a user within a meeting.
	
	Log1, Log2, Log3, Log4 are all macros defined in global.h
	These functions call the Log function to print the messages
	to the message window.


	FUNCTIONS:
	LONG CALLBACK MyNotifyProc()- Callback function will take
		care of the meeting events	by the notification codes
	VOID CmdCancelTransfer()-  Cancel a file tranfer action.
		Calls ConferenceCancelTransfer
	VOID CmdConnect()-  Establishes the connection. Calls
		ConferenceConnect. 
	VOID CmdDisconnect()-  Disconnects the meeting. Calls
		ConferenceDisconnect. 
	VOID CmdGetInfo()- Calls ConferenceGetInfo
	VOID CmdLaunchRemote()- Calls ConferenceLaunchRemote
	VOID CmdListen()- Calls ConferenceListen
	VOID CmdRemoveNotify()- Calls ConferenceRemoveNotify
	VOID CmdSendData()- Calls ConferenceSetInfo
	VOID CmdSendFile()- Calls ConferenceSendFile
	VOID CmdSetInfo()- Calls ConferenceSetInfo
	VOID CmdSetNotify()- Calls ConferenceSetNotify
	VOID CmdShareWindow()- Calls ConferenceShareWindow
	VOID CmdUnShareWindow()- Calls ConferenceShareWindow
		with the CONF_WINDOW_UNSHARED code
	VOID CmdIsWindowShared()- Calls ConferenceShareWindow with
		the CONF_SW_IS_SHARED code

	VOID CmdEnumUser()- Calls ConferenceGetInfo
	VOID CmdEnumConf()- Calls ConferenceGetInfo
	VOID CmdSetGuid()- Calls ConferenceSetInfo
	VOID MyNotifyProc()- The notification procedure

----------------------------------------------------------------------- */

#include "main.h"

// Static Strings
static char _szCancelTransfer[] = "CancelTransfer";
static char _szConnect[]        = "Connect";
static char _szDisconnect[]     = "Disconnect";
static char _szGetInfo[]        = "GetInfo";
static char _szLaunchRemote[]   = "LaunchRemote";
static char _szListen[]         = "Listen";
static char _szRemoveNotify[]   = "RemoveNotify";
static char _szSetInfo[]        = "SetInfo";
static char _szSetNotify[]      = "SetNotify";
static char _szSendData[]       = "SendData";
static char _szSendFile[]       = "SendFile";
static char _szShareWindow[]    = "ShareWindow";

static char _szUnShareWindow[]  = "UnShareWindow";
static char _szIsWindowShared[] = "IsWindowShared";
static char _szSetGuid[]        = "SetGuid";
static char _szEnumUsers[]      = "EnumUsers";
static char _szEnumConfs[]      = "EnumConfs";

LONG CALLBACK MyNotifyProc(HCONF hConf, DWORD dwCode, DWORD dwParam, LPVOID lpv1, LPVOID lpv2, DWORD dwUser);

VOID DumpUserInfo(LPCONFUSERINFO lpUserInfo);
VOID DumpConfInfo(LPCONFINFO lpConfInfo);



/*  C M D  C A N C E L  T R A N S F E R */
/*----------------------------------------------------------------------------
	%%Function: CmdCancelTransfer

	CmdCancelTransfer function executes when the user selects 
	ConferenceCancelTransfer from the Test menu. 

	This function stops the current file transfer (if one is running)
	
----------------------------------------------------------------------------*/
VOID CmdCancelTransfer(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;

	LogTestStart(_szCancelTransfer);

	dwResult = ConferenceCancelTransfer(gPref.hConf, gdwFileId);
	LogResult(_szCancelTransfer, 1, dwResult);
	
	LogTestStop(_szCancelTransfer);
}



/*  C M D  C O N N E C T */
/*----------------------------------------------------------------------------
	%%Function: CmdConnect

	CmdConnect function executes when the user selects ConferenceConnect 
	from the Test menu. 

	This function reads the conference connection address from 
	the user and takes the initial conference settings information 
	and then calls the ConferenceConnect function to establish a 
	meeting between two systems.

----------------------------------------------------------------------------*/
VOID CmdConnect(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFADDR confAddr;
	CONFINFO confInfo;

	if (!DlgConferenceConnect())
	{
		LogTestCancel(_szConnect);
		return;
	}

	LogTestStart(_szConnect);

	InitStruct(&confAddr);

	confAddr.dwAddrType = gPref.iAddrType;
	confAddr.psz = gPref.szDefName;	// default name
	switch (gPref.iAddrType)
		{
	case CONF_ADDR_IP:
		confAddr.dwIp = DwIpAddrFromSz(gPref.szDefName);
		Log4(LOG_ALWAYS, "IPAddr=%d.%d.%d.%d",
				HIBYTE(HIWORD(confAddr.dwIp)),
				LOBYTE(HIWORD(confAddr.dwIp)),
				HIBYTE(LOWORD(confAddr.dwIp)),
				LOBYTE(LOWORD(confAddr.dwIp)) );
		break;
	case CONF_ADDR_MACHINENAME:
		Log1(LOG_ALWAYS, "Machine Name [%s]", confAddr.psz);
		break;
	case CONF_ADDR_PSTN:
		Log1(LOG_ALWAYS, "Telephone number [%s]", confAddr.psz);
		break;
	default:
		Log2(LOG_ALWAYS, "Unknown string [%s] (addrType=%d)", 
			(confAddr.psz == NULL) ? "<null>" : confAddr.psz, gPref.iAddrType);
		break;
		}

	InitStruct(&confInfo);
	confInfo.dwMediaType = gPref.dwMediaType;
	lstrcpy(confInfo.szConferenceName, gPref.szConferenceName);

	dwResult = ConferenceConnect(&gPref.hConf, &confAddr, &confInfo, NULL);
	LogResult(_szConnect, 1, dwResult);
	Log1(LOG_ALWAYS, "hConf = %08X", gPref.hConf);
	LogTestStop(_szConnect);
}



/*  C M D  D I S C O N N E C T */
/*----------------------------------------------------------------------------
	%%Function: CmdDisconnect

	This function executes when the user selects ConferenceDisconnect
	from the Test menu.

	Function disconnects the meeting by calling the 
	ConferenceDisconnect function.  

----------------------------------------------------------------------------*/
VOID CmdDisconnect(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;

	LogTestStart(_szDisconnect);

	dwResult = ConferenceDisconnect(gPref.hConf);
	LogResult(_szDisconnect, 1, dwResult);

	gPref.hConf = NULL;

	LogTestStop(_szDisconnect);
}



/*  C M D  G E T  I N F O */
/*----------------------------------------------------------------------------
	%%Function: CmdGetInfo

	Returns information about the specified meeting.

	This example calls the ConferenceGetInfo API twice to 
	display the current meeting name and number of users
	and to display the current receive directory for the local
	machine.

----------------------------------------------------------------------------*/
VOID CmdGetInfo(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFINFO confInfo;
	CONFRECDIR confRecDir;

	LogTestStart(_szGetInfo);

	InitStruct(&confInfo);
	dwResult = ConferenceGetInfo(gPref.hConf, CONF_ENUM_CONF, &confInfo);
	LogResult(_szGetInfo, 1, dwResult);
	if (CONFERR_SUCCESS == dwResult)
	{
		DumpConfInfo(&confInfo);
	}

	InitStruct(&confRecDir);
	dwResult = ConferenceGetInfo(gPref.hConf, CONF_GET_RECDIR, &confRecDir);
	LogResult(_szGetInfo, 2, dwResult);
	if (CONFERR_SUCCESS == dwResult)
	{
		Log1(LOG_ALWAYS, "  Receive Directory [%s]", confRecDir.szRecDir);
	}

	LogTestStop(_szGetInfo);
}


/*  C M D  L A U N C H  R E M O T E */
/*----------------------------------------------------------------------------
	%%Function: CmdLaunchRemote

----------------------------------------------------------------------------*/
VOID CmdLaunchRemote(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFDEST confDest;
	CONFUSERINFO confUserInfo;
	BOOL fFound = fFalse;
	CONFERR dwResult;

	LogTestStart(_szLaunchRemote);

	if (!DlgLaunchRemote())
	{
		LogTestCancel(_szLaunchRemote);
		return;
	}

	InitStruct(&confDest);
	InitStruct(&confUserInfo);

	if(0 == lstrcmp("<everyone>", gPref.szUserName))
		confDest.dwUserId = 0;
	else
	{
		// scan the array of users and match the name to a UserId 
		for( ; ; )
		{
			dwResult = ConferenceGetInfo(gPref.hConf, CONF_ENUM_USER, &confUserInfo);
			if(dwResult != CONFERR_SUCCESS)
			{
				if(dwResult != CONFERR_ENUM_COMPLETE)
				{
					Log1(LOG_ERROR, "ConferenceGetInfo returns %08x", dwResult);
					break;
				}
				break;
			}
			if(0 == lstrcmp(confUserInfo.szUserName, gPref.szUserName))
			{
				confDest.dwUserId = confUserInfo.dwUserId;
				fFound = fTrue;
				break;
			}
		}
	Assert(fFound);
	}

	confDest.guid = gPref.guidRemote;

	dwResult = ConferenceLaunchRemote(gPref.hConf, &confDest, 0);
	LogResult(_szLaunchRemote, 1, dwResult);

	LogTestStop(_szLaunchRemote);
}


/*  C M D  L I S T E N */
/*----------------------------------------------------------------------------
	%%Function: CmdListen

	Launchs NetMeeting in the background.
	
----------------------------------------------------------------------------*/
VOID CmdListen(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	
	LogTestStart(_szListen);

	dwResult = ConferenceListen(0);
	LogResult(_szListen, 1, dwResult);
	
	LogTestStop(_szListen);
}

/*  C M D  R E M O V E  N O T I F Y */
/*----------------------------------------------------------------------------
	%%Function: CmdRemoveNotify

	Removes the specified callback routine

----------------------------------------------------------------------------*/
VOID CmdRemoveNotify(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	int i;

	LogTestStart(_szRemoveNotify);
	
	if (!DlgRemoveNotify())
	{
		LogTestCancel(_szRemoveNotify);
		return;
	}
	
	dwResult = ConferenceRemoveNotify(gPref.hConf, gPref.hConfNotify);
	LogResult(_szRemoveNotify, 1, dwResult);
	
	if(dwResult == CONFERR_SUCCESS)
	{
		Log1(LOG_NORMAL, "Removed hConfNotify %d", gPref.hConfNotify);
		// Walk array & remove the one we just killed
		for( i = 0; i < giCount; i++)
		{
			if(gPref.hConfNotify == grhConfNotify[i])
			{
				grhConfNotify[i] = grhConfNotify[giCount-1];
				giCount--;
				break;
			}
		}
	}

	LogTestStop(_szRemoveNotify);
}


/*  C M D  S E N D  D A T A */
/*----------------------------------------------------------------------------
	%%Function: CmdSendData

	Sends data to other meeting participants.

	This example uses the ConferenceSendData API to transmit
	application specific data to all other meeting members.

	Note: currently all members of a meeting will receive
	any data transmitted by this API. 

----------------------------------------------------------------------------*/
VOID CmdSendData(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFDEST confDest;

	LogTestStart(_szSendData);

	if (!DlgSendData())
	{
		LogTestCancel(_szSendData);
		return;
	}

	InitStruct(&confDest);
	confDest.guid = gPref.guid;
	confDest.dwUserId = gPref.dwRemoteId;

	dwResult = ConferenceSendData(gPref.hConf, &confDest,
		gPref.szData, CbSz(gPref.szData), 0);

	LogResult(_szSendData, 1, dwResult);
	LogTestStop(_szSendData);
	return;
}


/*  C M D  S E N D  F I L E */
/*----------------------------------------------------------------------------
	%%Function: CmdSendFile

	Sends a file to other meeting participants.

	This example uses the ConferenceSendData API to transmit
	application specific data to all other meeting members.

	Note: currently all members of a meeting will receive
	any data transmitted by this API. 

----------------------------------------------------------------------------*/
VOID CmdSendFile(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFDEST confDest;
	CONFUSERINFO confUserInfo;
	
	LogTestStart(_szSendFile);

	if (!DlgSendFile())
	{
		LogTestCancel(_szSendFile);
		return;
	}

	InitStruct(&confDest);
	InitStruct(&confUserInfo);
	
	if(0== lstrcmp("<everyone>", gPref.szUserName))
		confDest.dwUserId = 0;
	else
	{
		// scan the array of users and match the name to a UserId 
		for( ; ; )
		{
			dwResult= ConferenceGetInfo(gPref.hConf, CONF_ENUM_USER, &confUserInfo);
			if(dwResult != CONFERR_SUCCESS)
			{
				if(dwResult != CONFERR_ENUM_COMPLETE)
				{
					Log1(LOG_ERROR, "ConferenceGetInfo result=%d -- could not find UserId", dwResult);
					break;
				}
				break;
			}
			if(0 == lstrcmp(confUserInfo.szUserName, gPref.szUserName))
			{
				confDest.dwUserId = confUserInfo.dwUserId;
				break;
			}
		}
	}
	
	dwResult = ConferenceSendFile(gPref.hConf, &confDest, gPref.szFileName, CONF_SF_NOWAIT);
	LogResult(_szSendFile, 1, dwResult);

	LogTestStop(_szSendFile);
}

/*  C M D  S E T  I N F O */
/*----------------------------------------------------------------------------
	%%Function: CmdSetInfo

	Set the file transfer receive directory on the local machine

----------------------------------------------------------------------------*/
VOID CmdSetInfo(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFRECDIR confRecDir;

	LogTestStart(_szSetInfo);

	InitStruct(&confRecDir);

	if (!FGetDirectory(confRecDir.szRecDir))
	{
		LogTestCancel(_szSetInfo);
		return;
	}

	dwResult = ConferenceSetInfo(gPref.hConf, CONF_SET_RECDIR, &confRecDir);
	LogResult(_szSetInfo, 1, dwResult);

	dwResult = ConferenceGetInfo(gPref.hConf, CONF_GET_RECDIR, &confRecDir);
	LogResult(_szSetInfo, 2, dwResult);

	Log1(LOG_ALWAYS, "Receive Directory [%s]", confRecDir.szRecDir);

	LogTestStop(_szSetInfo);
}

/*  C M D  S E T  N O T I F Y */
/*----------------------------------------------------------------------------
	%%Function: CmdSetNotify

	Sets the notification callback routine

----------------------------------------------------------------------------*/
VOID CmdSetNotify(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFNOTIFY confNotify;
	HCONFNOTIFY hConfNotify;

	LogTestStart(_szSetNotify);

	InitStruct(&confNotify);

	confNotify.pfnNotifyProc = MyNotifyProc;
	confNotify.guid = gPref.guid;

	dwResult = ConferenceSetNotify(gPref.hConf, &confNotify, &hConfNotify);
	
	if( giCount < 10 )
		grhConfNotify[giCount++] = hConfNotify;

	LogResult(_szSetNotify, 1, dwResult);
	Log1(LOG_NORMAL, "Set hConfNotify %d", hConfNotify);
	
	LogTestStop(_szSetNotify);
}



/*  C M D  S H A R E  W I N D O W */
/*----------------------------------------------------------------------------
	%%Function: CmdShareWindow

	Shares this test application with other meeting participants.

	The coolest API in the world!  This example uses the 
	ConferenceShareWindow API to share this test application 
	with all other meeting participants.

----------------------------------------------------------------------------*/
VOID CmdShareWindow(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;

	LogTestStart(_szShareWindow);

	dwResult = ConferenceShareWindow(gPref.hConf, hwnd, CONF_SW_SHARE);
	LogResult(_szShareWindow, 1, dwResult);

	LogTestStop(_szShareWindow);
}


/*  C M D  U N  S H A R E  W I N D O W */
/*----------------------------------------------------------------------------
	%%Function: CmdUnShareWindow

	Unshares this test application with other meeting participants.

	The 2nd coolest API in the world!  This example uses the 
	ConferenceShareWindow API to stop sharing this test application 
	with all other meeting participants.

----------------------------------------------------------------------------*/
VOID CmdUnShareWindow(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;

	LogTestStart(_szUnShareWindow);

	dwResult = ConferenceShareWindow(gPref.hConf, hwnd, CONF_SW_UNSHARE);
	LogResult(_szUnShareWindow, 1, dwResult);

	LogTestStop(_szUnShareWindow);
}

/*  C M D  I S  W I N D O W  S H A R E D */
/*----------------------------------------------------------------------------
	%%Function: CmdIsWindowShared

	Checks to see if the specified window has been shared successfully.

	This example uses the ConferenceIsWindowShared API to check the
	shared status of this test application.  The ConferenceIsWindowShared
	API returns TRUE if the window is currently shared, FALSE if not.

----------------------------------------------------------------------------*/
VOID CmdIsWindowShared(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;

	LogTestStart(_szIsWindowShared);

	dwResult = ConferenceShareWindow(gPref.hConf, hwnd, CONF_SW_IS_SHARED);
	LogResult(_szIsWindowShared, 1, dwResult);

	LogTestStop(_szIsWindowShared);
}




/*  C M D  E N U M  U S E R */
/*----------------------------------------------------------------------------
	%%Function: CmdEnumUser

	Walk the roster of meeting participants and display user info

	This example uses the ConferenceGetInfo API in a loop to display
	user information for all meeting attendees.

----------------------------------------------------------------------------*/
VOID CmdEnumUser(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFUSERINFO confUserInfo;

	LogTestStart(_szEnumUsers);

	InitStruct(&confUserInfo);

	for ( ; ; )
	{
		dwResult = ConferenceGetInfo(gPref.hConf, CONF_ENUM_USER, &confUserInfo);
		if (CONFERR_SUCCESS != dwResult)
		{
			if (CONFERR_ENUM_COMPLETE != dwResult)
				Log1(LOG_ALWAYS, "ConferenceGetInfo result=%d", dwResult);
			break;
		}
		DumpUserInfo(&confUserInfo);
	}
	LogTestStop(_szEnumUsers);
}


/*  C M D  E N U M  C O N F */
/*----------------------------------------------------------------------------
	%%Function: CmdEnumConf

	Enumerate all conferences on the current machine.

	Not a very interesting example since we only allow one conference
	at a time right now.  But this example shows how to list all
	conferences on the machine.

----------------------------------------------------------------------------*/
VOID CmdEnumConf(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	CONFERR dwResult;
	CONFINFO confInfo;

	LogTestStart(_szEnumConfs);

	InitStruct(&confInfo);

	for ( ; ; )
	{
		dwResult = ConferenceGetInfo(gPref.hConf, CONF_ENUM_CONF, &confInfo);
		if (CONFERR_SUCCESS != dwResult)
		{
			if (CONFERR_ENUM_COMPLETE != dwResult)
				Log1(LOG_ALWAYS, "ConferenceGetInfo result=%d", dwResult);
			break;
		}
		DumpConfInfo(&confInfo);
		if (0 == confInfo.hConf)
		{
			Log(LOG_ALWAYS, "Null hConf field!");
			break;
		}
	}
	LogTestStop(_szEnumConfs);
}


/*  C M D  S E T  G U I D */
/*----------------------------------------------------------------------------
	%%Function: CmdSetGuid

----------------------------------------------------------------------------*/
VOID CmdSetGuid(HWND hwnd, WORD wCmd, WORD wNotify, HWND hwndCtrl)
{
	DWORD dwResult;
	CONFGUID confGuid;

	LogTestStart(_szSetGuid);

	if (!DlgGuid())
		return;

	InitStruct(&confGuid);
	confGuid.guid = gPref.guid;
	confGuid.pszApplication  = gPref.szAppName;
	confGuid.pszCommandLine  = gPref.szCmdLine;
	confGuid.pszDirectory  = gPref.szCurrDir;

	dwResult = ConferenceSetInfo(gPref.hConf, CONF_SET_GUID, &confGuid);
	LogResult(_szSetGuid, 1, dwResult);

	LogTestStop(_szSetGuid);
}


/*  M Y  N O T I F Y  P R O C */
/*----------------------------------------------------------------------------
	%%Function: MyNotifyProc

	The conference notification handler.

	Currently this callback sinmply displays the notification messages
	and relevant information in the message window.  

----------------------------------------------------------------------------*/
LONG CALLBACK MyNotifyProc(HCONF hConf, DWORD dwCode, DWORD dwParam, LPVOID lpv1, LPVOID lpv2, DWORD dwUser)
{
	// print the text of the notification message
	Log4(LOG_ALWAYS, "[%s]     [%08X] (%08X, %08X)", GetConfnString(dwCode), dwParam, lpv1, lpv2);


	// display user or meeting information in the message box.
	switch (dwCode)
		{
	case CONFN_CONFERENCE_INIT:
	case CONFN_CONFERENCE_START:
	case CONFN_CONFERENCE_STOP:
	case CONFN_CONFERENCE_ERROR:
		DumpConfInfo(lpv2);
		break;

	case CONFN_USER_ADDED:
	case CONFN_USER_REMOVED:
		DumpUserInfo(lpv2);
		break;

	case CONFN_PEER_ADDED:
		Log2(LOG_NORMAL, "Peer Added: dwUserId=%X (%d)", dwParam, dwParam);
		break;
	case CONFN_PEER_REMOVED:
		Log2(LOG_NORMAL, "Peer Removed: dwUserId=%X (%d)", dwParam, dwParam);
		break;

	case CONFN_WINDOW_SHARED:
	case CONFN_WINDOW_UNSHARED:
		break;

	case CONFN_DATA_SENT:
		Log2(LOG_NORMAL, "Data Send: [%s] %d bytes", lpv2, dwParam);
		break;
	case CONFN_DATA_RECEIVED:
		Log2(LOG_NORMAL, "Data Recv: [%s] %d bytes", lpv2, dwParam);
		break;

	case CONFN_FILESEND_START:
		gdwFileId = dwParam;
		break;
	case CONFN_FILESEND_PROGRESS:
		{
			LPCONFFILEINFO lpFile = lpv2;
			Log2(LOG_NORMAL, "File transfer: sent %d of %d bytes", 
				lpFile->dwBytesTransferred, 
				lpFile->dwFileSize);
		break;
		}
	case CONFN_FILESEND_COMPLETE:
	case CONFN_FILESEND_ERROR:
		gdwFileId = FileIdNil;
		break;
	case CONFN_FILERECEIVE_START:
		gdwFileId = dwParam;
		break;
	case CONFN_FILERECEIVE_PROGRESS:
		{
			LPCONFFILEINFO lpFile = lpv2;
			Log2(LOG_NORMAL, "File transfer: received %d of %d bytes", 
				lpFile->dwBytesTransferred, 
				lpFile->dwFileSize);
		break;
		}
	case CONFN_FILERECEIVE_COMPLETE:
	case CONFN_FILERECEIVE_ERROR:
		gdwFileId = FileIdNil;
		break;

	default:
		break;
		} /* dwCode */

	return 0;
}
