/*
**	termOldConfig.c
**
**	Old configuration processing routines
**
**	Copyright © 1990-1995 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"

struct OldSerialSettings
{
	ULONG	BaudRate;
	ULONG	BreakLength;
	ULONG	SerialBufferSize;

	UBYTE	SerialDevice[256];
	LONG	UnitNumber;

	BYTE	BitsPerChar;
	BYTE	Parity;
	BYTE	StopBits;
	BYTE	HandshakingProtocol;
	BYTE	Duplex;

	BYTE	xONxOFF;
	BYTE	HighSpeed;
	BYTE	Shared;
	BYTE	StripBit8;
	BYTE	CheckCarrier;
	BYTE	PassThrough;
};

struct OldModemSettings
{
	UBYTE	ModemInit[80];
	UBYTE 	ModemExit[80];
	UBYTE 	ModemHangup[80];
	UBYTE	DialPrefix[80];
	UBYTE	DialSuffix[80];

	UBYTE	NoCarrier[16];
	UBYTE	NoDialTone[16];
	UBYTE	Connect[16];
	UBYTE	Voice[16];
	UBYTE	Ring[16];
	UBYTE	Busy[16];

	LONG	RedialDelay;
	LONG	DialRetries;
	LONG	DialTimeout;
	BYTE	ConnectAutoBaud;
	BYTE	DropDTR;
};

struct OldCommandSettings
{
	UBYTE	StartupMacro[256];
	UBYTE	LogoffMacro[256];
	UBYTE	UploadMacro[256];
	UBYTE	DownloadMacro[256];
};

struct OldScreenSettings
{
	ULONG	DisplayMode;
	WORD	ColourMode;
	UWORD	Colours[16];
	UBYTE	FontName[256];
	WORD	FontHeight;

	BYTE	MakeScreenPublic;
	BYTE	ShanghaiWindows;

	BYTE	Blinking;
	BYTE	FasterLayout;
	BYTE	TitleBar;
	BYTE	StatusLine;
};

struct OldTerminalSettings
{
	BYTE	BellMode;
	BYTE	AlertMode;
	BYTE	EmulationMode;
	BYTE	FontMode;

	BYTE	SendCR;
	BYTE	SendLF;
	BYTE	ReceiveCR;
	BYTE	ReceiveLF;

	UWORD	NumColumns,
		NumLines;

	UBYTE	KeyMapFileName[256];
	UBYTE	EmulationFileName[256];
	UBYTE	BeepFileName[256];

	UBYTE	TextFontName[256];
	WORD	TextFontHeight;
};

struct OldPathSettings
{
	UBYTE	ASCIIUploadPath[256];
	UBYTE	ASCIIDownloadPath[256];

	UBYTE	TextUploadPath[256];
	UBYTE	TextDownloadPath[256];

	UBYTE	BinaryUploadPath[256];
	UBYTE	BinaryDownloadPath[256];

	UBYTE	DefaultStorage[256];

	UBYTE	Editor[256];
};

struct OldMiscSettings
{
	BYTE	Priority;
	BYTE	BackupConfig;

	BYTE	OpenFastMacroPanel;
	BYTE	ReleaseDevice;

	BYTE	TransferServer;
	BYTE	EmulationServer;

	BYTE	OverridePath;
	BYTE	AutoUpload;
	BYTE	SetArchivedBit;
	BYTE	IdentifyFiles;
};

struct OldClipSettings
{
	WORD	ClipboardUnit;

	WORD	LineDelay,
		CharDelay;

	UBYTE	InsertPrefix[80];
	UBYTE	InsertSuffix[80];
};

struct OldCaptureSettings
{
	BYTE	LogActions;
	BYTE	LogCall;
	UBYTE	LogFileName[256];

	LONG	MaxBufferSize;
	BYTE	BufferEnabled;

	BYTE	ConnectAutoCapture;
	BYTE	CaptureFilterMode;
	UBYTE	CapturePath[256];
};

struct OldFileSettings
{
	UBYTE	ProtocolFileName[256];
	UBYTE	TranslationFileName[256];
	UBYTE	MacroFileName[256];
	UBYTE	CursorFileName[256];
	UBYTE	FastMacroFileName[256];
};

struct OldEmulationSettings
{
	BYTE	CursorMode;
	BYTE	NumericMode;

	BYTE	CursorWrap;
	BYTE	LineWrap;

	BYTE	InsertMode;
	BYTE	NewLineMode;

	BYTE	FontScale;
	BYTE	ScrollMode;
	BYTE	DestructiveBackspace;
	BYTE	SwapBSDelete;
	BYTE	PrinterEnabled;
	BYTE	Pad;

	UBYTE	AnswerBack[80];
};

struct OldConfiguration
{
	struct OldSerialSettings	SerialConfig;
	struct OldModemSettings		ModemConfig;
	struct OldScreenSettings	ScreenConfig;
	struct OldTerminalSettings	TerminalConfig;
	struct OldEmulationSettings	EmulationConfig;
	struct OldClipSettings		ClipConfig;
	struct OldCaptureSettings	CaptureConfig;
	struct OldCommandSettings	CommandConfig;
	struct OldMiscSettings		MiscConfig;
	struct OldPathSettings		PathConfig;
	struct OldFileSettings		FileConfig;
};

struct OldPhoneHeader
{
	UBYTE	Name[40],		/* BBS name. */
		Number[60],		/* Phone number. */
		Comment[40];		/* Comment. */

	UBYTE	UserName[30],		/* User name for this BSS. */
		Password[30];		/* Password for user name. */
};

	/* ConvertHeader():
	 *
	 *	Convert old style phone book header to new style
	 *	phone book header.
	 */

STATIC VOID __regargs
ConvertHeader(struct OldPhoneHeader *OldHeader,struct PhoneHeader *NewHeader)
{
	strcpy(NewHeader -> Name,	OldHeader -> Name);
	strcpy(NewHeader -> Number,	OldHeader -> Number);
	strcpy(NewHeader -> Comment,	OldHeader -> Comment);

	strcpy(NewHeader -> UserName,	OldHeader -> UserName);
	strcpy(NewHeader -> Password,	OldHeader -> Password);
}

	/* ConvertConfig():
	 *
	 *	Convert old style configuration to new style configuration.
	 */

STATIC BYTE __regargs
ConvertConfig(struct OldConfiguration *OldConfig,struct Configuration *NewConfig,BOOLEAN IsPhonebook)
{
	if(CreateConfigEntry(NewConfig,PREF_SERIAL))
	{
		ResetConfigEntry(NewConfig,PREF_SERIAL,FALSE);

		memcpy(NewConfig -> SerialConfig,&OldConfig -> SerialConfig,MIN(sizeof(struct SerialSettings),sizeof(struct OldSerialSettings)));

		FixOldConfig(NewConfig,PREF_SERIAL,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_MODEM))
	{
		ResetConfigEntry(NewConfig,PREF_MODEM,FALSE);

		memcpy(NewConfig -> ModemConfig,&OldConfig -> ModemConfig,MIN(sizeof(struct ModemSettings),sizeof(struct OldModemSettings)));

		FixOldConfig(NewConfig,PREF_MODEM,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_COMMAND))
	{
		ResetConfigEntry(NewConfig,PREF_COMMAND,FALSE);

		memcpy(NewConfig -> CommandConfig,&OldConfig -> CommandConfig,MIN(sizeof(struct CommandSettings),sizeof(struct OldCommandSettings)));

		FixOldConfig(NewConfig,PREF_COMMAND,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_SCREEN))
	{
		ResetConfigEntry(NewConfig,PREF_SCREEN,FALSE);

		memcpy(NewConfig -> ScreenConfig,&OldConfig -> ScreenConfig,MIN(sizeof(struct ScreenSettings),sizeof(struct OldScreenSettings)));

		FixOldConfig(NewConfig,PREF_SCREEN,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_TERMINAL))
	{
		ResetConfigEntry(NewConfig,PREF_TERMINAL,FALSE);

		memcpy(NewConfig -> TerminalConfig,&OldConfig -> TerminalConfig,MIN(sizeof(struct TerminalSettings),sizeof(struct OldTerminalSettings)));

		FixOldConfig(NewConfig,PREF_TERMINAL,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_PATH))
	{
		ResetConfigEntry(NewConfig,PREF_PATH,FALSE);

		memcpy(NewConfig -> PathConfig,&OldConfig -> PathConfig,MIN(sizeof(struct PathSettings),sizeof(struct OldPathSettings)));

		FixOldConfig(NewConfig,PREF_PATH,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_MISC))
	{
		ResetConfigEntry(NewConfig,PREF_MISC,FALSE);

		memcpy(NewConfig -> MiscConfig,&OldConfig -> MiscConfig,MIN(sizeof(struct MiscSettings),sizeof(struct OldMiscSettings)));

		FixOldConfig(NewConfig,PREF_MISC,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_CLIP))
	{
		ResetConfigEntry(NewConfig,PREF_CLIP,FALSE);

		memcpy(NewConfig -> ClipConfig,&OldConfig -> ClipConfig,MIN(sizeof(struct ClipSettings),sizeof(struct OldClipSettings)));

		FixOldConfig(NewConfig,PREF_CLIP,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_CAPTURE))
	{
		ResetConfigEntry(NewConfig,PREF_CAPTURE,FALSE);

		memcpy(NewConfig -> CaptureConfig,&OldConfig -> CaptureConfig,MIN(sizeof(struct CaptureSettings),sizeof(struct OldCaptureSettings)));

		strcpy(NewConfig -> CaptureConfig -> CallLogFileName,NewConfig -> CaptureConfig -> LogFileName);

		AddPart(NewConfig -> CaptureConfig -> CallLogFileName,"term-call.log",MAX_FILENAME_LENGTH);

		FixOldConfig(NewConfig,PREF_CAPTURE,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_FILE))
	{
		LONG i,Error = 0;

		ResetConfigEntry(NewConfig,PREF_FILE,FALSE);

		memcpy(NewConfig -> FileConfig,&OldConfig -> FileConfig,MIN(sizeof(struct FileSettings),sizeof(struct OldFileSettings)));

		FixOldConfig(NewConfig,PREF_FILE,IsPhonebook,2,4);

		for(i = PREF_TRANSLATIONFILENAME ; i <= PREF_FASTMACROFILENAME ; i++)
		{
			if(!CreateConfigEntry(NewConfig,i))
			{
				Error = ERROR_NO_FREE_STORE;
				break;
			}
		}

		if(!Error)
		{
			strcpy(NewConfig -> TranslationFileName,	NewConfig -> FileConfig -> TranslationFileName);
			strcpy(NewConfig -> MacroFileName,		NewConfig -> FileConfig -> MacroFileName);
			strcpy(NewConfig -> CursorFileName,		NewConfig -> FileConfig -> CursorFileName);
			strcpy(NewConfig -> FastMacroFileName,		NewConfig -> FileConfig -> FastMacroFileName);

			DeleteConfigEntry(NewConfig,PREF_FILE);
		}
		else
		{
			SetIoErr(Error);
			return(FALSE);
		}
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_EMULATION))
	{
		ResetConfigEntry(NewConfig,PREF_EMULATION,FALSE);

		memcpy(NewConfig -> EmulationConfig,&OldConfig -> EmulationConfig,MIN(sizeof(struct EmulationSettings),sizeof(struct OldEmulationSettings)));

		FixOldConfig(NewConfig,PREF_EMULATION,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	FinalFix(NewConfig,IsPhonebook,2,4);

	return(TRUE);
}

	/* LoadOldPhonebook(STRPTR Name):
	 *
	 *	Restore a phone book from a disk file.
	 */

BYTE __regargs
LoadOldPhonebook(STRPTR Name,PhonebookHandle *BookHandle)
{
	STATIC ULONG Stops[6 * 2] =
	{
		ID_TERM,ID_VERS,
		ID_TERM,ID_DIAL,
		ID_TERM,ID_PREF,
		ID_TERM,ID_DATE,
		ID_TERM,ID_PHON,
		ID_TERM,ID_PSWD
	};

	struct PhoneEntry	**PrivatePhonebook;
	LONG			 PrivatePhoneSize = 0;
	LONG			 Size = 0,Count = 0,Last = -1;
	struct IFFHandle	*Handle;
	BYTE			 Success = FALSE;
	struct ContextNode	*Chunk;
	BYTE			 LastHadTime	= TRUE,
				 HadPassword	= FALSE;
	struct TimeDateNode	*TimeDateNode;
	struct OldConfiguration	*OldConfig;
	struct OldPhoneHeader	*OldHeader;
	LONG			 Error;

	if(OldConfig = (struct OldConfiguration *)AllocVecPooled(sizeof(struct OldConfiguration) + sizeof(struct OldPhoneHeader),MEMF_ANY))
	{
		OldHeader = (struct OldPhoneHeader *)(OldConfig + 1);

		if(Handle = AllocIFF())
		{
			if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
			{
				InitIFFasDOS(Handle);

				if(!(Error = OpenIFF(Handle,IFFF_READ)))
				{
					if(!(Error = StopChunks(Handle,(LONG *)Stops,6)))
					{
						while(!ParseIFF(Handle,IFFPARSE_SCAN))
						{
							Chunk = CurrentChunk(Handle);

							if(Chunk -> cn_ID == ID_VERS)
							{
								struct TermInfo TermInfo;

								if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
								{
									if(TermInfo . Version != 2 || TermInfo . Revision != 4)
									{
										Error = ERR_OUTDATED;

										break;
									}
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_PSWD)
							{
								UBYTE DummyBuffer[20];

								HadPassword = TRUE;

								if(ReadChunkBytes(Handle,DummyBuffer,20) == 20)
								{
									if(BookHandle)
									{
										if(BookHandle -> PhonePasswordUsed)
										{
											if(!memcmp(BookHandle -> PhonePassword,DummyBuffer,20))
												continue;
										}
									}
									else
									{
										if(PhonePasswordUsed)
										{
											if(!memcmp(PhonePassword,DummyBuffer,20))
												continue;
										}
									}

									memset(SharedBuffer,0,21);

									if(GetString(FALSE,TRUE,21,LocaleString(MSG_PHONEPANEL_PLEASE_ENTER_PASSWORD_TXT),SharedBuffer))
									{
										UBYTE AnotherBuffer[20];

										Encrypt(SharedBuffer,20,AnotherBuffer,SharedBuffer,strlen(SharedBuffer));

										if(!memcmp(DummyBuffer,AnotherBuffer,20))
										{
											if(BookHandle)
											{
												memcpy(BookHandle -> PhonePassword,DummyBuffer,20);

												BookHandle -> PhonePasswordUsed = TRUE;
											}
											else
											{
												memcpy(PhonePassword,DummyBuffer,20);

												PhonePasswordUsed = TRUE;
											}

											continue;
										}
										else
										{
											MyEasyRequest(Window,LocaleString(MSG_TERMPHONE_WRONG_PASSWORD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Name);

											break;
										}
									}
									else
										break;
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_DIAL)
							{
								if(ReadChunkBytes(Handle,&Size,sizeof(LONG)) == sizeof(LONG))
								{
									if(!(PrivatePhonebook = CreatePhonebook(Size,&PrivatePhoneSize,TRUE)))
										break;
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_PHON)
							{
								WORD Size = MIN(sizeof(struct OldPhoneHeader),Chunk -> cn_Size);

								if(ReadChunkBytes(Handle,OldHeader,Size) == Size)
								{
									if(BookHandle)
									{
										if(BookHandle -> PhonePasswordUsed)
											Decrypt((UBYTE *)OldHeader,Size,(UBYTE *)OldHeader,BookHandle -> PhonePassword,20);
									}
									else
									{
										if(PhonePasswordUsed)
											Decrypt((UBYTE *)OldHeader,Size,(UBYTE *)OldHeader,PhonePassword,20);
									}
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_PREF)
							{
								if(Last != -1)
								{
									if(!LastHadTime)
									{
										if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
											AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
									}
								}

								if(Size && Count < Size)
								{
									WORD LastSize = MIN(Chunk -> cn_Size,sizeof(struct OldConfiguration));

									if(BookHandle)
										BookHandle -> PhonePasswordUsed = HadPassword;
									else
										PhonePasswordUsed = HadPassword;

									if(ReadChunkBytes(Handle,OldConfig,LastSize) == LastSize)
									{
										if(BookHandle)
										{
											if(BookHandle -> PhonePasswordUsed)
												Decrypt((UBYTE *)OldConfig,LastSize,(UBYTE *)OldConfig,BookHandle -> PhonePassword,20);
										}
										else
										{
											if(PhonePasswordUsed)
												Decrypt((UBYTE *)OldConfig,LastSize,(UBYTE *)OldConfig,PhonePassword,20);
										}

										if(ConvertConfig(OldConfig,PrivatePhonebook[Count] -> Config,TRUE))
										{
											memset(PrivatePhonebook[Count] -> Header,0,sizeof(struct PhoneHeader));

											ConvertHeader(OldHeader,PrivatePhonebook[Count] -> Header);

											Last = Count;

											PrivatePhonebook[Count] -> Count = -1;

											Count++;

											LastHadTime = FALSE;
										}
										else
										{
											if(Count)
												Size = Count - 1;
											else
												Size = 0;

											break;
										}
									}
									else
									{
										Error = IoErr();

										if(Count)
											Size = Count - 1;
										else
											Size = 0;

										break;
									}
								}
							}

							if(Chunk -> cn_ID == ID_DATE)
							{
								if(Last != -1)
								{
									WORD Count = (Chunk -> cn_Size - sizeof(struct TimeDateHeader)) / sizeof(struct TimeDate);

									if(TimeDateNode = CreateTimeDateNode(-1,-1,"",Count))
									{
										if(ReadChunkBytes(Handle,&TimeDateNode -> Header,sizeof(struct TimeDateHeader)) == sizeof(struct TimeDateHeader))
										{
											if(ReadChunkBytes(Handle,TimeDateNode -> Table,sizeof(struct TimeDate) * Count) == sizeof(struct TimeDate) * Count)
											{
												AdaptTimeDateNode(TimeDateNode);

												AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);

												LastHadTime = TRUE;
											}
											else
											{
												Error = IoErr();

												FreeTimeDateNode(TimeDateNode);
											}
										}
										else
										{
											Error = IoErr();

											FreeTimeDateNode(TimeDateNode);
										}
									}
								}
							}
						}

						if(Size)
						{
							if(!LastHadTime && Last != -1)
							{
								if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
									AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
							}

							if(!BookHandle)
							{
								struct timeval Now;
								LONG i;

								GetSysTime(&Now);

								PhonebookID = Now . tv_secs;

								NewList((struct List *)&PhoneGroupList);

								if(Phonebook)
									DeletePhonebook(Phonebook,PhoneSize,TRUE);

								Phonebook = PrivatePhonebook;
								PhoneSize = PrivatePhoneSize;
								PhonebookAutoDial = FALSE;
								PhonebookAutoExit = FALSE;
								PhonebookDefaultGroup = 0;

								NumPhoneEntries = Size;

								for(i = 0 ; i < NumPhoneEntries ; i++)
									Phonebook[i] -> Header -> ID = PhonebookID++;
							}
							else
							{
								struct timeval Now;
								LONG i;

								GetSysTime(&Now);

								BookHandle -> PhonebookID = Now . tv_secs;

								if(BookHandle -> PhoneGroupList)
									NewList((struct List *)BookHandle -> PhoneGroupList);

								if(BookHandle -> Phonebook)
									DeletePhonebook(BookHandle -> Phonebook,BookHandle -> PhoneSize,TRUE);

								BookHandle -> Phonebook = PrivatePhonebook;
								BookHandle -> PhoneSize = PrivatePhoneSize;
								BookHandle -> DefaultGroup = 0;

								BookHandle -> NumPhoneEntries = Size;
								BookHandle -> AutoDial = FALSE;
								BookHandle -> AutoExit = FALSE;

								for(i = 0 ; i < BookHandle -> NumPhoneEntries ; i++)
									BookHandle -> Phonebook[i] -> Header -> ID = BookHandle -> PhonebookID++;
							}

							Success = TRUE;
						}
						else
						{
							if(PrivatePhoneSize)
							{
								DeletePhonebook(PrivatePhonebook,PrivatePhoneSize,TRUE);

								Success = FALSE;
							}
						}

						FreeDialList(TRUE);
					}

					CloseIFF(Handle);
				}

				Close(Handle -> iff_Stream);
			}
			else
				Error = IoErr();

			FreeIFF(Handle);
		}
		else
			Error = ERR_NO_MEM;

		FreeVecPooled(OldConfig);
	}
	else
		Error = ERR_NO_MEM;

	if(Error)
		SetIoErr(Error);

	return(Success);
}

	/* ReadConfig(STRPTR Name,struct Configuration *Config):
	 *
	 *	Read the configuration file, very much the same as ReadIFFData().
	 */

BYTE __regargs
ReadOldConfig(STRPTR Name,struct Configuration *Config)
{
	struct IFFHandle	*Handle;
	BYTE			 Success = FALSE;
	struct StoredProperty	*Prop;
	struct TermInfo		*TermInfo;
	struct OldConfiguration	*OldConfig;
	LONG			 Error;

	if(OldConfig = (struct OldConfiguration *)AllocVecPooled(sizeof(struct OldConfiguration),MEMF_ANY))
	{
		if(Handle = AllocIFF())
		{
			if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
			{
				InitIFFasDOS(Handle);

				if(!(Error = OpenIFF(Handle,IFFF_READ)))
				{
					if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
					{
						if(!(Error = StopChunk(Handle,ID_TERM,ID_PREF)))
						{
							if(!ParseIFF(Handle,IFFPARSE_SCAN))
							{
								if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
								{
									TermInfo = (struct TermInfo *)Prop -> sp_Data;

									if(TermInfo -> Version == 2 && TermInfo -> Revision == 4)
									{
										struct ContextNode *Chunk = CurrentChunk(Handle);

										if(ReadChunkRecords(Handle,OldConfig,MIN(Chunk -> cn_Size,sizeof(struct OldConfiguration)),1) == 1)
										{
											if(ConvertConfig(OldConfig,Config,FALSE))
												Success = TRUE;
										}
										else
											Error = IoErr();
									}
									else
										Error = ERR_OUTDATED;
								}
							}
						}
					}

					CloseIFF(Handle);
				}

				Close(Handle -> iff_Stream);
			}
			else
				Error = IoErr();

			FreeIFF(Handle);
		}
		else
			Error = ERR_NO_MEM;

		FreeVecPooled(OldConfig);
	}
	else
		Error = ERR_NO_MEM;

	if(Error)
		SetIoErr(Error);

	return(Success);
}
