/*
 *  Aladdin Stuffit Plugin (32-bit version)
 *
 *  Filename: AttachTran.cpp
 *
 *  Last edited: Monday, August 25, 1997
 *
 *  Author: Scott Manjourides
 *
 *  Copyright 1997 QUALCOMM Inc.
 Copyright (c) 2016, Computer History Museum 
All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to 
the limitations in the disclaimer below) provided that the following conditions are met: 
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
   disclaimer in the documentation and/or other materials provided with the distribution. 
 * Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products 
   derived from this software without specific prior written permission. 
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE 
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
DAMAGE. 


 *
 *  Send comments and questions to <emsapi-info@qualcomm.com>
 */

/*
This is an automatic response to return unique ID numbers for plugins
created for Eudora using the EMSAPI. If you want more information about
creating plugins you can write to <mailto:emsapi-info@qualcomm.com> or 
visit our EMS API web site at <http://www.eudora.com/developers/emsapi/>.

Here are your IDs, as requested.  There are five so you have some extra just
in case.  If you lose track of the five here, you can always get a few more.
The sole purpose of these ID's is to make sure each plugin has a unique 
identifier.

Plugin IDs:

     1330
     1331
     1332
     1333
     1334
*/

#ifdef _DEBUG
#include <ctype.h>
#endif // _DEBUG

#include <afxwin.h> // MFC & Windows master header
#include <afxdlgs.h>
#include <cderr.h> // Common dialog error returns
#include <windows.h>

#include <malloc.h> // malloc, free
#include <string.h> // strdup

#include <stdio.h>
#include <string.h>

#include "resource.h" // Resource IDs for dialogs and icons

#include "ems-win.h" // The EMS API
#include "Stuff32.h" 

#include "AladdinProgDlg.h" /* Progress dialog that does Aladdin Engine stuff */

/* The keyword 'bool' is used throughout the Stuffit engine, so let's ignore the warning. */
#pragma warning(disable:4237) /* warning C4237: nonstandard extension used : 'bool' keyword is reserved for future use */

#include "Engine.h"

using namespace StuffItEngine;

/*****************************************************************************/
/* CONSTANTS */

#ifdef _COMMERCIAL_VER
	static const int kPluginID = 1330;
	#define _COMPRESS_
	#define _EXPAND_
#else // _FREE_VER
	#ifdef _FREE_VER
		static const int kPluginID = 1331;
		#define _EXPAND_
	#else // _OEM_VER
		static const int kPluginID = 1332;
		#define _COMPRESS_
	#endif
#endif

static const unsigned long kPluginIconID = IDI_MAIN;

/*****************************************************************************/
/* GLOBALS */

// This externs into Stuff32.cpp
extern CStuffDLL theDLL;

/*	We don't know what formats the Stuffit engine will support, so we test
	at runtime for each format. The ones that work, we add to the menu.

    This applies to compression only, as the engine decides for itself
	what it can uncompress. Could list all types from EngineType.h, but
	we only check the main ones we are interested in.
*/
static struct gArchiveInfo_tag {
	UINT menuTextID;
	UINT fileTitleID;
	engineFormat engVal;
} gArchiveInfo[] = {
	{ IDS_STUFFIT_MENU_STR, IDS_STUFFIT_TITLE_STR, engineFormatStuffIt },
	{ IDS_ZIP_MENU_STR, IDS_ZIP_TITLE_STR, engineFormatZip },
	{ IDS_ARC_MENU_STR, IDS_ARC_TITLE_STR, engineFormatArc }
};

static const int gMaxEngCount = 3; /* Number of types we have listed above */

static int gValidCount = 0; /* This will increase at runtime if any compression types are supported */
static int gValidArr[gMaxEngCount] = { -1 };

/*****************************************************************************/
/* MACROS */

#define safefree(p) { if (p) { free(p); p=NULL; } }

/*****************************************************************************/
/* LOCAL FUNCTION PROTOTYPES */

// Generalized functions
void DoIconInit(long trans_id, HICON FAR*FAR* trans_icon);

/*****************************************************************************/

/*
   We need a dialog to prompt the user for a directory when decompressing. There is no
   common control or dialog which does this, so roll your own. We take the standard
   non-explorer file selection dialog, play around with the controls and use it
   as a directory-only selection.

   This is done via subclassing CFileDialog to provide a clean, usable interface to
   our exotic dialog.
*/

// Needed to get the control IDs for the the controls to hide
#include <dlgs.h>

class CDirDialog : public CFileDialog
{
// Construction
public:
	/* Pass in a path to indicate the initial selection */
	CDirDialog(const char *pStartDir, CWnd* pParentWnd);

// Attributes
public:
		
// Operations
public:
	BOOL OnInitDialog();
	CString GetDirStr();

// Implementation
protected:
	/* These methods are used to muck around with the existing controls */
	void StretchControl(int nID1, int nID2);
	void HideControl(int nID);

	/* These are here in case someone needs them */
	CString m_Title;
	CString m_StartDir;
	CString m_Filter;
};

CDirDialog::CDirDialog(const char *pStartDir, CWnd* pParentWnd = NULL) :
	CFileDialog(FALSE, NULL, "A", OFN_HIDEREADONLY, NULL, pParentWnd)
{
#ifdef WIN32
	m_ofn.Flags &= ~ ( OFN_SHOWHELP | OFN_EXPLORER );
#else
	m_ofn.Flags &= ~OFN_SHOWHELP;
#endif
	
	m_Title.LoadString(IDS_FILE_DIR_TITLE);
	m_ofn.lpstrTitle = m_Title;
		
	m_StartDir = CString(pStartDir);
	m_ofn.lpstrInitialDir = m_StartDir;
	
	m_Filter.LoadString(IDS_ALL_FILES_FILTER);
	for (char* s = m_Filter.GetBuffer(1); *s; s++)
	{
		if (*s == '|')
			*s = 0;
	}
	m_ofn.lpstrFilter = m_Filter;
}

void CDirDialog::StretchControl(int nID1, int nID2)
{
	// nID2 will be stretched left to cover nID1

	// What this means is the left edge of nID2 will be moved to be the the
	// left edge of ID1.

	CWnd* pWnd = NULL;
	RECT rect1, rect2;

	pWnd = GetDlgItem(nID1);
	pWnd->GetWindowRect(&rect1);
	ScreenToClient(&rect1);

	pWnd = GetDlgItem(nID2);
	pWnd->GetWindowRect(&rect2);
	ScreenToClient(&rect2);

	pWnd->SetWindowPos(NULL,
						rect1.left,
						rect2.top,
						rect2.right - rect1.left,
						rect2.bottom - rect2.top,
						SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER );
}

void CDirDialog::HideControl(int nID)
{
	// Hide the control, if possible
	CWnd* pWnd = NULL;

	pWnd = GetDlgItem(nID);
	if (pWnd)
		pWnd->ShowWindow(SW_HIDE);
}

/* Return the selected directory after user is done. */
CString CDirDialog::GetDirStr()
{
	return (GetPathName().GetBufferSetLength(m_ofn.nFileOffset - 1));
}

BOOL CDirDialog::OnInitDialog()
{
	if (!CFileDialog::OnInitDialog())
		return (FALSE);

	/* !! NOTE: Microsoft screwed up, the "Folders" text has an ID of 0xFFFF !! */

	// Stretch the useful controls over the useless ones
	StretchControl(stc3, 0xFFFF); // Move the "Folders" text
	StretchControl(edt1, stc1);   // Move the selected directory text
	StretchControl(lst1, lst2);   // Move the directory list box
	StretchControl(stc2, stc4);   // Move the "Drives" text
	StretchControl(cmb1, cmb2);   // Move the drives combo box

	// Hide all the controls we don't need
	HideControl(stc3);
	HideControl(edt1);
	HideControl(lst1);
	HideControl(stc2);
	HideControl(cmb1);

	CString tmp;

	// Change text of OK button
	tmp.LoadString(IDS_EXTRACT_HERE);
	SetDlgItemText(IDOK, tmp);

	// Change the static text above the selection display
	tmp.LoadString(IDS_FOLDER_TXT); // Replace "Folders" with "Destination"
	SetDlgItemText(0xFFFF, tmp);

#ifdef NEVER_DO_THIS
	{
		// This code was used to walk through all the controls and get their IDs. This
		// is how I found 0xFFFF to be the mystery "Folders" text.
		CWnd *pWnd = GetTopWindow();
		int nID;

		while (pWnd)
		{
			nID = pWnd->GetDlgCtrlID();
			pWnd = pWnd->GetNextWindow();
		}
	}
#endif

	return (TRUE);
}

/*****************************************************************************/
/* TRANSLATER API FUNCTIONS */

/*****\
*
* ems_plugin_version: Get the version of the API used for this plugin
*
\*****/

extern "C" long WINAPI ems_plugin_version(
    short FAR* api_version      /* Place to return api version */
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	*api_version = EMS_VERSION;
	return (EMSR_OK);
}

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

/*****\
*
* ems_plugin_init: Initialize plugin and get its basic info
*
\*****/

extern "C" long WINAPI ems_plugin_init(
    void FAR*FAR* globals,          /* Out: Return for allocated instance structure */
    short eudAPIVersion,        /* In: The API version eudora is using */
    emsMailConfigP mailConfig,  /* In: Eudoras mail configuration */
    emsPluginInfoP pluginInfo   /* Out: Return Plugin Information */
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

#ifdef _COMPRESS_

	if (gValidCount < 1)
	{
		gValidCount = 0;
		
		for (int i = 0; i < gMaxEngCount; i++)
		{
			archiveWriter writer = newArchiveWriter();

			if (canWrite(gArchiveInfo[i].engVal, writer))
			{
				gValidArr[gValidCount++] = i;
			}

		    deleteArchiveWriter(writer);
		}
	}
#endif // _COMPRESS_

	if (pluginInfo)
	{
		pluginInfo->numTrans = 0;
#ifdef _EXPAND_
		pluginInfo->numSpecials = 1;
#else
		pluginInfo->numSpecials = 0;
#endif // _EXPAND_

		pluginInfo->numAttachers = gValidCount;

		CString sTitle;
		CString sVer;

		sTitle.LoadString(AFX_IDS_APP_TITLE);
		sVer.LoadString(IDS_VERSION_STR);

#ifdef _FREE_VER
		{
			CString sAppendix;
			sAppendix.LoadString(IDS_FREEWARE_APPENDIX);
			sTitle = sTitle + " " + sAppendix;
		}
#endif

		pluginInfo->desc = strdup(((const char *)CString(sTitle + ", " + sVer)));

		DoIconInit(-1, &(pluginInfo->icon));

		pluginInfo->id = kPluginID;
	}

	return (EMSR_OK);
}

/* ----- Info about special menu items hooks ------------------------------- */
extern "C" long WINAPI ems_special_info(
    void FAR* globals,          /* Out: Return for allocated instance structure */
    emsMenuP specialMenu         /* Out: The menu */
)
{
#ifdef _EXPAND_
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if (specialMenu->id != 1)
		return (EMSR_INVALID_TRANS);

	CString str;
	str.LoadString(IDS_DECOMPRESS_MENU_TXT);

	specialMenu->desc = strdup((const char *) str);
#endif // _EXPAND_

	return (EMSR_OK);
}

/* ----- Call a special menu item hook ------------------------------------- */
extern "C" long WINAPI ems_special_hook(
    void FAR* globals,          /* Out: Return for allocated instance structure */
    emsMenuP specialMenu        /* In: The menu */
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

#ifdef _EXPAND_

	if ((!specialMenu) || (specialMenu->id != 1))
		return (EMSR_UNKNOWN_FAIL);

	const DWORD dwFlags = OFN_HIDEREADONLY | OFN_SHAREAWARE | OFN_FILEMUSTEXIST | OFN_EXPLORER;
//	const LPCTSTR lpszFilter = "Compressed Files (*.sit;*.zip)|*.sit;*.zip|Stuffit Files (*.sit)|*.sit|Zip Files (*.zip)|*.zip|All Files (*.*)|*.*||";

	CString sFilter;
	sFilter.LoadString(IDS_EXPAND_FILTER);

	CString sTitle;
	sTitle.LoadString(IDS_FILE_OPEN_TITLE);

	CFileDialog opendlg(TRUE, NULL, NULL, dwFlags, (LPCTSTR) sFilter, NULL);
	opendlg.m_ofn.lpstrTitle = (LPCSTR) sTitle;

	// Add copyright to bottom of file select dialog
		LPCSTR DlgName;
		opendlg.m_ofn.Flags |= OFN_ENABLETEMPLATE;
		DlgName = MAKEINTRESOURCE(IDD_OPENDLG_EXT);
		opendlg.m_ofn.lpTemplateName = DlgName;
		opendlg.m_ofn.hInstance = AfxFindResourceHandle( MAKEINTRESOURCE(IDD_OPENDLG_EXT), RT_DIALOG);

	CString archive_filename;
	if (opendlg.DoModal() == IDOK)
	{
		archive_filename = opendlg.GetPathName();

		CDirDialog savedlg((const char *)archive_filename, AfxGetMainWnd());
		if (savedlg.DoModal() == IDOK)
		{
			CString archive_destdir = savedlg.GetDirStr(); // returns "C:\blah\blah" (no trailing slash)

			// Create the archive
			archiveReader reader = newArchiveReader();
			if (!openArchive((const char *) archive_filename, reader))
			{
				CString engineErr = getEngineErrorString(getReaderError(reader));
				
				if ((engineErr.Left(11)) == CString("engineError"))
					engineErr = engineErr.Right(engineErr.GetLength() - 11);

				CString displayErr;
				AfxFormatString1(displayErr, IDS_ERR_OPENING, engineErr);
				AfxMessageBox((const char *)displayErr, MB_OK | MB_ICONEXCLAMATION);

				return (EMSR_OK);
			}

			setReaderDestination((const char *) archive_destdir, reader);

			// Setup the progress dialog to do the expanding
			CAladdinProgDlg	progDlg;
			progDlg.Create(IDD_ALADDIN_PROGRESS_DLG);
			progDlg.ShowWindow(SW_SHOW);
			progDlg.UpdateWindow();
			bool bSuccess = progDlg.DoExpandArchive(reader);
			progDlg.DestroyWindow();

			if (!bSuccess)
			{
				CString engineErr = getEngineErrorString(getReaderError(reader));
				
				if ((engineErr.Left(11)) == CString("engineError"))
					engineErr = engineErr.Right(engineErr.GetLength() - 11);

				CString displayErr;
				AfxFormatString1(displayErr, IDS_ERR_DECODING, engineErr);
				AfxMessageBox((const char *)displayErr, MB_OK | MB_ICONEXCLAMATION);

				return (EMSR_OK);
			}
		}
	}

#endif // _EXPAND_

	return (EMSR_OK);
}

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

/*****\
*
* ems_attacher_info: Get details about a attacher in a plugin
*
\*****/

extern "C" long WINAPI ems_attacher_info(
    void FAR* globals,          /* Out: Return for allocated instance structure */
    emsMenuP attachMenu         /* Out: The menu */
)
{
#ifdef _COMPRESS_
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if ( (attachMenu->id <= 0) || (attachMenu->id > gValidCount) ) // IDs are 1-based, bleach!
		return (EMSR_INVALID_TRANS);

	CString sDesc;
	sDesc.LoadString(gArchiveInfo[gValidArr[(attachMenu->id - 1)]].menuTextID);

	attachMenu->desc = strdup(((const char *)sDesc));
#endif

	return (EMSR_OK);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*****\
*
* ems_attacher_hook: Get details about a attacher in a plugin
*
\*****/

extern "C" long WINAPI ems_attacher_hook(
    void FAR* globals,          /* Out: Return for allocated instance structure */
    emsMenuP attachMenu,        /* In: The menu */
    LPSTR attachDir,            /* In: Location to put attachments */
    long * numAttach,           /* Out: Number of files attached */
    emsDataFileP ** attachFiles /* Out: Name of files written */
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

#ifdef _COMPRESS_

	long id = attachMenu->id;
	unsigned int idx;

	if ( (id <= 0) || (id > gValidCount) ) // IDs are 1-based, bleach!
		return (EMSR_INVALID_TRANS);

	if ((!attachFiles) || (!attachMenu))
		return (EMSR_UNKNOWN_FAIL);

	int ret = 0;
	CFileDialog *pFileDlg = NULL;

	const DWORD dwFlags = OFN_ALLOWMULTISELECT
							| OFN_HIDEREADONLY
							// | OFN_SHAREAWARE
							| OFN_FILEMUSTEXIST
							| OFN_EXPLORER;

	const LPCTSTR lpszFilter = "All Files (*.*)|*.*||";

	CString sTitle;
	sTitle.LoadString(gArchiveInfo[gValidArr[(id - 1)]].fileTitleID);

	const DWORD nBufSize = 4096;
	char pTheBuf[nBufSize] = {0};

	do
	{
		if (pFileDlg)
		{
			delete (pFileDlg);
			pFileDlg = NULL;
		}

		// Create the COpenMultiFileDlg object, initialized
		pFileDlg = new CFileDialog(FALSE, NULL, NULL, dwFlags, lpszFilter, NULL);
		ASSERT(pFileDlg);

		pFileDlg->m_ofn.lpstrTitle = (LPCSTR) sTitle;

		pFileDlg->m_ofn.lpstrFile = (LPTSTR) pTheBuf;
		pFileDlg->m_ofn.nMaxFile = (DWORD) nBufSize;

		LPCSTR DlgName;
		
		pFileDlg->m_ofn.Flags |= OFN_ENABLETEMPLATE;
		DlgName = MAKEINTRESOURCE(IDD_OPENDLG_EXT);
		pFileDlg->m_ofn.lpTemplateName = DlgName;
		pFileDlg->m_ofn.hInstance = AfxFindResourceHandle( MAKEINTRESOURCE(IDD_OPENDLG_EXT), RT_DIALOG);

		ret = pFileDlg->DoModal();

		if (ret != IDOK)
		{
			DWORD err = CommDlgExtendedError();

			if (err == 0)
			{
				return (EMSR_UNKNOWN_FAIL); // CLICKED 'CANCEL'
			}
			else // (err > 0)
			{
				UINT nErrID = 0;

				/* Check all the errors, just to be safe. Display some appropriate text */
				switch (err)
				{
					// MEMORY ERRORS
					case CDERR_INITIALIZATION: // The common dialog box function failed during initialization. This error often occurs when sufficient memory is not available.
					case CDERR_MEMALLOCFAILURE: // The common dialog box function was unable to allocate memory for internal structures.
					case CDERR_MEMLOCKFAILURE: // The common dialog box function was unable to lock the memory associated with a handle.
					{
						nErrID = IDS_MEMORYERR_STR;
					}
					break;

					// RESOURCE ERRORS
					case CDERR_FINDRESFAILURE: // The common dialog box function failed to find a specified resource.
					case CDERR_LOADRESFAILURE: // The common dialog box function failed to load a specified resource.
					case CDERR_LOADSTRFAILURE: // The common dialog box function failed to load a specified string.
					case CDERR_LOCKRESFAILURE: // The common dialog box function failed to lock a specified resource.
					{
						nErrID = IDS_RESOURCEERR_STR;
					}
					break;

					case FNERR_BUFFERTOOSMALL:
					{
						// The buffer pointed to by the lpstrFile member of the OPENFILENAME
						// structure is too small for the filename specified by the user. The
						// first two bytes of the lpstrFile buffer contain an integer value
						// specifying the size, in bytes (ANSI version) or characters
						// (Unicode version), required to receive the full name. 
						nErrID = IDS_TOOMANYFILESERR_STR;				
					}
					break;
					
					case FNERR_INVALIDFILENAME: // A filename is invalid.
					{
						nErrID = IDS_INVALIDFILEERR_STR;
					}
					break;

					// GENERAL INTERNAL ERRORS
					case CDERR_DIALOGFAILURE: // The dialog box could not be created. The common dialog box function's call to the DialogBox function failed. For example, this error occurs if the common dialog box call specifies an invalid window handle.
					case CDERR_NOHINSTANCE: // The ENABLETEMPLATE flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a corresponding instance handle.
					case CDERR_NOHOOK: // The ENABLEHOOK flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a pointer to a corresponding hook procedure.
					case CDERR_NOTEMPLATE: // The ENABLETEMPLATE flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a corresponding template.
					case CDERR_REGISTERMSGFAIL: // The RegisterWindowMessage function returned an error code when it was called by the common dialog box function.
					case CDERR_STRUCTSIZE: // The lStructSize member of the initialization structure for the corresponding common dialog box is invalid.
					case FNERR_SUBCLASSFAILURE: // An attempt to subclass a list box failed because sufficient memory was not available.
					
					default:
					{
						nErrID = IDS_INTERNALERR_STR;				
					}
					break;
				}

				if (AfxMessageBox( nErrID, MB_ICONEXCLAMATION | MB_RETRYCANCEL ) == IDCANCEL)
					return (EMSR_UNKNOWN_FAIL);
			}
		}
	} while (ret != IDOK);

	// ----- Process the request

	CWaitCursor waiting;

	// Count the files
	UINT nFileCount = 0;
	POSITION pos = pFileDlg->GetStartPosition();
	while (pos)
	{
		pFileDlg->GetNextPathName(pos);
		(nFileCount)++;
	}

	// Allocate room for the list
    const char** fileList;
    fileList = (const char**)malloc((nFileCount + 1) * sizeof(const char*));
	ASSERT(fileList);

	// Build the list
	pos = pFileDlg->GetStartPosition();
	for (idx = 0; idx < nFileCount; idx++)
		fileList[idx] = strdup(pFileDlg->GetNextPathName(pos));

    fileList[nFileCount] = engineFileListEnd;

	if (pFileDlg)
	{
		delete (pFileDlg);
		pFileDlg = NULL;
	}

	// Create the archive
	archiveWriter writer = newArchiveWriter();

	//	setWriterArchiveName("C:\\BLAH.SIT", writer);
    setWriterArchiveFormat(gArchiveInfo[gValidArr[(id - 1)]].engVal, writer);

	CAladdinProgDlg	progDlg;
	
	//progDlg.DoModal();
	progDlg.Create(IDD_ALADDIN_PROGRESS_DLG);
	progDlg.ShowWindow(SW_SHOW);
	progDlg.UpdateWindow();
	progDlg.DoCreateArchive(fileList, writer);
	progDlg.DestroyWindow();

	// -- Don't need this, the dialog does all the work --
	//
	// bSuccess = createArchive(fileList, writer); // Do the work
    // ASSERT(bSuccess);


	const char *pWriterName = getWriterArchiveName(writer);
	ASSERT(pWriterName);

	*numAttach = 1;

	// Allocate the number of pointers
	*attachFiles = (emsDataFileP *) malloc( sizeof(emsDataFileP) * (*numAttach));
	ASSERT(*attachFiles);

	(*attachFiles)[0] = (emsDataFileP) malloc(sizeof(emsDataFile));
	ASSERT((*attachFiles)[0]);

	(*attachFiles)[0]->size = sizeof(emsDataFile);
	(*attachFiles)[0]->fileName = strdup(pWriterName);
	ASSERT((*attachFiles)[0]->fileName);

    deleteArchiveWriter(writer);

	for (idx = 0; idx < nFileCount; idx++)
		free((char *)fileList[idx]);
	free(fileList);

#endif // _COMPRESS_

	return (EMSR_OK);
}

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

/*****\
*
* ems_plugin_finish: End use of a plugin and clean up
*
\*****/

extern "C" long WINAPI ems_plugin_finish(
    void FAR* globals           /* Pointer to translator instance structure */
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// We don't use 'globals'
	return (EMSR_OK); 
}

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

/*****\
*
* ems_free: Free memory allocated by EMS plug-in
*
\*****/

extern "C" long WINAPI ems_free(
    void FAR* mem               /* Memory to free */
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if (mem)
		safefree(mem);

	return (EMSR_OK);
}

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

static void DoIconInit(
    long trans_id,         /* ID of translator to get info for */
    HICON FAR*FAR* icon   /* Return for icon data */
)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if (!icon)
		return;

	if (trans_id < 0) /* Main plugin icon, not specific translator */
	{
		*icon = (HICON *)malloc(sizeof(HICON));
		**icon = theDLL.LoadIcon(kPluginIconID); /* 32x32 */
	}
	else
		*icon = NULL;
}
