/*
Auto:		smake	ForceIcon
*/

/* $Revision Header built automatically *************** (do not edit) ************
**
** © Copyright by GuntherSoft
**
** File             : SnakeSYS:CPrgs/Utils/ForceIcon.c
** Created on       : Wednesday, 20.10.93 15:55:50
** Created by       : Kai Iske
** Current revision : V1.0
**
**
** Purpose
** -------
**   - Forces Disk Icons to a specified position.
**     Usefull for CD-Rom users
**
** Revision V1.0
** --------------
** created on Wednesday, 20.10.93 15:55:50  by  Kai Iske.   LogMessage :
**     --- Initial release ---
**
*********************************************************************************/


/**********************************************************************/
/*                      Routines for this module                      */
/**********************************************************************/
static struct	FIconSema	*FindFIconSema(void);
static void			RemoveFIconSema(struct FIconSema *FIconSema);
static ULONG	__saveds __asm	MyGetIcon(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a2 struct FreeList *FList, register __a6 struct Library *IconBase);
static ULONG	__saveds __asm	MyPutIcon(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a6 struct Library *IconBase);
static ULONG	__asm		DoForce(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a2 struct FreeList *FList, register __a6 struct Library *IconBase);
static BOOL			StoreIconPos(struct DiskObject *Icon);
static ULONG	__saveds __asm	MyLock(register __d1 UBYTE *Name, register __d2 ULONG Mode, register __a6 struct DosLibrary *DOSBase);
static BOOL			OpenAll(void);
static void			CloseAll(void);




/**********************************************************************/
/*                    Functions of files included                     */
/**********************************************************************/
	// LoadPrefs.h

static void			LoadPrefs(struct FIconSema *FIconSema);

	// VolList.h

static BOOL			GetDevVolList(struct List *VolList);
static BOOL			GetDosEntries(struct List *VolList, ULONG Mode);
static void			FreeDevVolList(struct List *VolList);
static void			SortList(struct List *VolList, BOOL DisplayType);
static void			SortPartialList(struct List *VolList, UWORD Left, UWORD Right);
static APTR			GetListEntry(struct List *List, WORD EntryNum);
static BOOL			MyStrCmp(char *FromName, char *ToName);

	// Error.h

static void	__stdargs	DisplayError(LONG ErrCode, ULONG Arg1, ...);

	// PoolVec.h

static APTR			AllocVecPool(struct FIconSema *FIconSema, ULONG Size);
static void			FreeVecPool(struct FIconSema *FIconSema, APTR Addr);

	// CheckToolTypes.h

static void			CheckToolTypes(struct WBStartup *WBenchMsg);




/**********************************************************************/
/*                           Library bases                            */
/**********************************************************************/
struct	ExecBase		*SysBase;
struct	IntuitionBase		*IntuitionBase	= NULL;
struct	DosLibrary		*DOSBase	= NULL;
struct	Library			*IconBase	= NULL;
struct	Library			*UtilityBase	= NULL;
struct	Library			*IFFParseBase	= NULL;






/**********************************************************************/
/*                         "No-StartUp vars"                          */
/**********************************************************************/
static const char		_VER[]		= "\0$VER: ForceIcon "REVISION" ("REVDATE")\0";
char				_ProgramName[]	= "ForceIcon";
LONG				_OSERR		= 0;





/**********************************************************************/
/*                           Our variables                            */
/**********************************************************************/
static	ULONG	__asm		(*OldGetIcon)(register __a0 UBYTE *, register __a1 struct DiskObject *, register __a2 struct FreeList *, register __a6 struct Library *);
static	ULONG	__asm		(*OldPutIcon)(register __a0 UBYTE *, register __a1 struct DiskObject *, register __a6 struct Library *);
static	ULONG	__asm		(*OldLock)(register __d1 UBYTE *, register __d2 ULONG, register __a6 struct DosLibrary *);
static	ULONG	__asm		(*CheckGetIcon)(register __a0 UBYTE *, register __a1 struct DiskObject *, register __a2 struct FreeList *, register __a6 struct Library *);
static	ULONG	__asm		(*CheckPutIcon)(register __a0 UBYTE *, register __a1 struct DiskObject *, register __a6 struct Library *);
static	ULONG	__asm		(*CheckLock)(register __d1 UBYTE *, register __d2 ULONG, register __a6 struct DosLibrary *);

static	struct	FIconSema	*FIconSema	= NULL;		// Pointer to our rendezvous semaphore

static	LONG			SnapNotify	= 2;		// How to notify a snap






/**********************************************************************/
/*                      This is our main program                      */
/**********************************************************************/
ULONG __saveds main(void)
{
	struct	Process		*MyProc;
	struct	WBStartup	*WBenchMsg	= NULL;
	BOOL			QuitIT		= FALSE;



		// Get SysBase

	SysBase	= *((struct ExecBase **)0x4L);


		// Get address of our process

	MyProc = (struct Process *)FindTask(NULL);



		// Determine where we were started from

	if(!MyProc->pr_CLI)
	{
		WaitPort(&MyProc->pr_MsgPort);
		WBenchMsg = (struct WBStartup *)GetMsg(&MyProc->pr_MsgPort);
	}



		// Don`t run under OS < 37

	if(((struct Library *)SysBase)->lib_Version >= 37)
	{
			// Open libraries

		if(OpenAll())
		{
				// Prefs Program there ???

			if((FIconSema = FindFIconSema()))
			{

					// Check ToolTypes

				CheckToolTypes(WBenchMsg);


				Disable();
					// Patch icon.library functions

				OldGetIcon		= (ULONG *)SetFunction(IconBase, -0x0000002a, &MyGetIcon);
				OldPutIcon		= (ULONG *)SetFunction(IconBase, -0x00000030, &MyPutIcon);

					// Patch dos.library functions

				OldLock			= (ULONG *)SetFunction(DOSBase, -0x00000054, &MyLock);
				Enable();



					// Ok, patches placed.
					// Make all connected drives diskchange

				{
					struct	List	ChangeList;

					ObtainSemaphore(&FIconSema->FIconSema);

					NewList(&ChangeList);

						// Create list of connected devices

					if(GetDosEntries(&ChangeList, LDF_VOLUMES))
					{
						struct	DosList		*DList;
						struct	VolEntry	*ThisEntry,
									*ListEntry;
						struct	DevProc		*DevProc;
						char			DevName[130];
						BOOL			FoundDev,
									DoDskCh;

						while((ThisEntry = (struct VolEntry *)RemHead(&ChangeList)))
						{
							FoundDev	= FALSE;
							DoDskCh		= FALSE;

								// Find name of device this volume resides in

							if((DList = LockDosList(LDF_DEVICES|LDF_READ)))
							{
								while((DList = NextDosEntry(DList, LDF_DEVICES|LDF_READ)))
								{
									if(ThisEntry->DriverTask == DList->dol_Task && !FoundDev)
									{
										setmem(DevName, 130, 0);
										strncpy(DevName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));
										FoundDev	= TRUE;
									}
								}
								UnLockDosList(LDF_DEVICES|LDF_READ);
							}

								// Found corresponding device ???

							if(FoundDev)
							{
									// Check whether to diskchange

								ListEntry	= (struct VolEntry *)FIconSema->VolumeList.lh_Head;
								while(ListEntry->Link.ln_Succ && !DoDskCh)
								{
									if(ListEntry->Link.ln_Type == LDF_DEVICES)
										DoDskCh	= (MyStrCmp(ListEntry->VolName, DevName) == 0);
									else
										DoDskCh	= (MyStrCmp(ListEntry->VolName, ThisEntry->VolName) == 0);

									ListEntry = (struct VolEntry *)ListEntry->Link.ln_Succ;
								}

								if(DoDskCh)
								{
									strcat(DevName, ":");

									if(ThisEntry->DriverTask && (DevProc = GetDeviceProc(DevName, NULL)))
									{
										if(TypeOfMem(DevProc->dvp_Port))
										{
											if(DoPkt(DevProc->dvp_Port, ACTION_INHIBIT, DOSTRUE, NULL, NULL, NULL, NULL))
												DoPkt(DevProc->dvp_Port, ACTION_INHIBIT, DOSFALSE, NULL, NULL, NULL, NULL);
										}
										FreeDeviceProc(DevProc);
									}
								}
							}

							FreeVecPool(FIconSema, ThisEntry);
						}
					}

					ReleaseSemaphore(&FIconSema->FIconSema);
				}

					// Wait for termination

				while(!QuitIT)
				{
					ULONG	MySig;

					MySig	= Wait(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D);

						// User snapped icon?

					if(MySig & SIGBREAKF_CTRL_D)
					{
						if(FIconSema->PrefsTask)
							Signal(FIconSema->PrefsTask, SIGBREAKF_CTRL_F);

						if(SnapNotify == 2)
							DisplayError(ERR_SNAPEDICON, NULL);
						else if(SnapNotify == 1)
							DisplayBeep(NULL);
					}
					else
					{
							// Ok, we are to quit

						QuitIT	= TRUE;


						Disable();

							// Try to re-install old vectors

						CheckGetIcon		= SetFunction(IconBase, -0x0000002a, OldGetIcon);
						CheckPutIcon		= SetFunction(IconBase, -0x00000030, OldPutIcon);
						CheckLock		= SetFunction(DOSBase, -0x00000054, OldLock);

						if((CheckGetIcon != &MyGetIcon) || (CheckPutIcon != &MyPutIcon) || (CheckLock != &MyLock))
						{
							QuitIT = FALSE;

								// Re-install patches created by someone else

							SetFunction(IconBase, -0x0000002a, CheckGetIcon);
							SetFunction(IconBase, -0x00000030, CheckPutIcon);
							SetFunction(DOSBase, -0x00000054, CheckLock);
						}

						Enable();

						if(!QuitIT)
						{
							if(CheckGetIcon != &MyGetIcon)
								DisplayError(ERR_PATCH, (ULONG)"GetIcon()", NULL);
							else if(CheckPutIcon != &MyPutIcon)
								DisplayError(ERR_PATCH, (ULONG)"PutIcon()", NULL);
							else if(CheckLock != &MyLock)
								DisplayError(ERR_PATCH, (ULONG)"Lock()", NULL);
						}
					}
				}
			}
			RemoveFIconSema(FIconSema);
		}
	}


		// Close libs

	CloseAll();


		// Send back WBStartUp Message

	if(WBenchMsg)
	{
		Forbid();
		ReplyMsg((struct Message *)WBenchMsg);
	}
	return(0);
}




/**********************************************************************/
/*                        Functionreplacements                        */
/**********************************************************************/
void chkabort(void){;}
void __stdargs _XCEXIT(LONG Val){;}





/**********************************************************************/
/*                      My new GetIcon function                       */
/**********************************************************************/
static ULONG __saveds __asm MyGetIcon(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a2 struct FreeList *FList, register __a6 struct Library *IconBase)
{
	struct	Process		*MyProc = (struct Process *)FindTask(NULL);
	ULONG	RetVal;

		// Calling process a real process and is it Workbench ?

	if((MyProc->pr_Task.tc_Node.ln_Type == NT_PROCESS) && !strcmp(MyProc->pr_Task.tc_Node.ln_Name, "Workbench"))
	{
			if(!stricmp(Name, "Disk"))
				RetVal = DoForce(Name, DObj, FList, IconBase);
			else
				RetVal = OldGetIcon(Name, DObj, FList, IconBase);
	}
	else
		RetVal = OldGetIcon(Name, DObj, FList, IconBase);

	return(RetVal);
}




/**********************************************************************/
/*                      My new PutIcon function                       */
/**********************************************************************/
static ULONG __saveds __asm MyPutIcon(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a6 struct Library *IconBase)
{
	struct	Process		*MyProc = (struct Process *)FindTask(NULL);
	ULONG	RetVal;

		// Calling process a real process and is it Workbench ?

	if((MyProc->pr_Task.tc_Node.ln_Type == NT_PROCESS) && !strcmp(MyProc->pr_Task.tc_Node.ln_Name, "Workbench"))
	{
			if(!stricmp(Name, "Disk"))
			{
				if(!StoreIconPos(DObj))
					RetVal	= OldPutIcon(Name, DObj, IconBase);
				else
				{
					Signal(FIconSema->ServerTask, SIGBREAKF_CTRL_D);
					RetVal	= TRUE;
				}
			}
			else
				RetVal = OldPutIcon(Name, DObj, IconBase);
	}
	else
		RetVal = OldPutIcon(Name, DObj, IconBase);

	return(RetVal);
}





/**********************************************************************/
/*                       Main forcement routine                       */
/**********************************************************************/
static ULONG __asm DoForce(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a2 struct FreeList *FList, register __a6 struct Library *IconBase)
{
	struct	FileLock	*Dir;
	struct	DosList		*DList;
	char			*VolName,
				*DevName	= NULL,
				*IconName;
	BPTR			MyLock,
				CheckLock;
	LONG			Left,
				Top,
				WinWidth,
				WinHeight,
				WinFlags;
	WORD			WinX,
				WinY;
	ULONG			RetVal		= 0;
	BOOL			Found		= FALSE,
				UseAltIcon,
				UseIconPos,
				UseWindow,
				UseFlags;





		// Get our semaphore

	ObtainSemaphore(&FIconSema->FIconSema);


		// Get buffers

	if((VolName = AllocMem(130, MEMF_CLEAR)) && (DevName = AllocMem(130, MEMF_CLEAR)))
	{
			// Switch to current dir

		MyLock	= CurrentDir(NULL);
		Dir	= (struct FileLock *)BADDR(MyLock);
		DList	= (struct DosList *)BADDR(Dir->fl_Volume);

			// Get name of volume inserted

		strncpy(VolName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));

			// Reset current dir

		CurrentDir(MyLock);

			// Get Name of Device

		if((DList = LockDosList(LDF_DEVICES|LDF_READ)))
		{
			while((DList = NextDosEntry(DList, LDF_DEVICES|LDF_READ)))
			{
				if(Dir->fl_Task == DList->dol_Task)
					strncpy(DevName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));
			}
			UnLockDosList(LDF_DEVICES|LDF_READ);
		}

			// Really to load from ROOT ???

		if(!(CheckLock = ParentDir(MyLock)))
		{
				// Do we have patches waiting ???

			if(!IsListEmpty(&FIconSema->VolumeList))
			{
				struct	VolEntry	*ThisEntry = (struct VolEntry *)FIconSema->VolumeList.lh_Head;

				do
				{
						// This one to patch ???

					if(ThisEntry->Link.ln_Type == LDF_DEVICES && !MyStrCmp(ThisEntry->VolName, DevName))
						Found = TRUE;

					else if(ThisEntry->Link.ln_Type == LDF_VOLUMES && !MyStrCmp(ThisEntry->VolName, VolName))
						Found = TRUE;

					else
						ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;

				} while(!Found && ThisEntry->Link.ln_Succ);

					// Object to be patched ?

				if(Found)
				{
						// Set vars for icon substitution

					UseAltIcon	= (ThisEntry->UseAlt == MODE_USE);
					IconName	= ThisEntry->IconName;

						// Set vars for icon placement

					UseIconPos	= (ThisEntry->IconPos == MODE_USE);
					Left		= ThisEntry->Left;
					Top		= ThisEntry->Top;

						// Set vars for window settings

					UseWindow	= (ThisEntry->UseWin == MODE_USE);
					WinX		= ThisEntry->WinX;
					WinY		= ThisEntry->WinY;
					WinWidth	= ThisEntry->WinWidth;
					WinHeight	= ThisEntry->WinHeight;

						// Set vars for window flags

					UseFlags	= (ThisEntry->UseFlags == MODE_USE);
					WinFlags	= ThisEntry->WinFlags;


						// This entry a volume and are we allowed to obtain settings from device ???

					if(ThisEntry->Link.ln_Type == LDF_VOLUMES)
					{
						struct	VolEntry	*DevEntry	= (struct VolEntry *)FIconSema->VolumeList.lh_Head;
						BOOL			FoundMyDev	= FALSE;

							// Search for device-entry corresponding to volume

						while(DevEntry->Link.ln_Succ && !FoundMyDev)
						{
							if(DevEntry->Link.ln_Type == LDF_DEVICES && !MyStrCmp(DevEntry->VolName, DevName))
								FoundMyDev	= TRUE;
							else
								DevEntry	= (struct VolEntry *)DevEntry->Link.ln_Succ;
						}

							// Got a device entry for this volume ???

						if(FoundMyDev)
						{
								// Use alternative icon for volume ???

							if(ThisEntry->UseAlt == MODE_INHERIT)
							{
									// no, use one for device entry ???
									// If so, set pointer to new iconname

								if(DevEntry->UseAlt == MODE_USE)
								{
									UseAltIcon	= TRUE;
									IconName	= DevEntry->IconName;
								}
							}

								// Use alternative position for volume ???

							if(ThisEntry->IconPos == MODE_INHERIT)
							{
									// no, use one for device entry ???
									// if so, set vars

								if(DevEntry->IconPos == MODE_USE)
								{
									UseIconPos	= TRUE;
									Left		= DevEntry->Left;
									Top		= DevEntry->Top;
								}
							}

								// Use settings of window ???

							if(ThisEntry->UseWin == MODE_INHERIT)
							{
									// no, use one for device entry ???
									// if so, set vars

								if(DevEntry->UseWin == MODE_USE)
								{
									UseWindow	= TRUE;
									WinX		= DevEntry->WinX;
									WinY		= DevEntry->WinY;
									WinWidth	= DevEntry->WinWidth;
									WinHeight	= DevEntry->WinHeight;
								}
							}

								// Use settings of flags

							if(ThisEntry->UseFlags == MODE_INHERIT)
							{
									// no, use one for device entry ???
									// if so, set vars

								if(DevEntry->UseFlags == MODE_USE)
								{
									UseFlags	= TRUE;
									WinFlags	= DevEntry->WinFlags;
								}
							}
						}
					}


						// Alternative icon ???

					if(UseAltIcon)
					{
						char	*EndPtr;

							// Check for name and remove extension

						strcpy(VolName, IconName);
						strlwr(VolName);
						if((EndPtr = strstr(VolName, ".info")))
						{
							BPTR	TestLock;

							setmem(VolName, 130, 0);
							strncpy(VolName, IconName, (EndPtr - VolName));

								// Try to get supplied name

							if((TestLock = Lock(IconName, ACCESS_READ)))
							{
								UnLock(TestLock);

									// Try to read in this icon

								if(!(RetVal = OldGetIcon(VolName, DObj, FList, IconBase)))
									RetVal = OldGetIcon(Name, DObj, FList, IconBase);
								else
								{
									BOOL	GotData	= FALSE;

										// Ok, we`ve loaded a new icon, so set appropriate flags ;)

									if(DObj->do_Type == WBTOOL || DObj->do_Type == WBPROJECT)
									{
											// Try to set drawerdata for tool and project icons

										if((DObj->do_DrawerData = AllocMem(sizeof(struct DrawerData), MEMF_CLEAR|MEMF_PUBLIC)))
											GotData	= TRUE;
									}
									else
										GotData = TRUE;

									if(GotData)
									{
										struct	DrawerData	*DDat = DObj->do_DrawerData;

											// Fill in structure

										DDat->dd_NewWindow.LeftEdge	= ThisEntry->LeftEdge;
										DDat->dd_NewWindow.TopEdge	= ThisEntry->TopEdge;
										DDat->dd_NewWindow.Width	= ThisEntry->Width;
										DDat->dd_NewWindow.Height	= ThisEntry->Height;
										DDat->dd_NewWindow.DetailPen	= 255;
										DDat->dd_NewWindow.BlockPen	= 255;
										DDat->dd_NewWindow.Flags	= WFLG_HASZOOM|WFLG_WINDOWTICKED|WFLG_REPORTMOUSE|WFLG_SIMPLE_REFRESH|WFLG_SIZEBRIGHT|WFLG_SIZEBBOTTOM|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_SIZEGADGET;
										DDat->dd_NewWindow.MinWidth	= 90;
										DDat->dd_NewWindow.MinHeight	= 40;
										DDat->dd_NewWindow.MaxWidth	= 0xffff;
										DDat->dd_NewWindow.MaxHeight	= 0xffff;
										DDat->dd_NewWindow.Type		= WBENCHSCREEN;
										DDat->dd_CurrentX		= ThisEntry->CurrentX;
										DDat->dd_CurrentY		= ThisEntry->CurrentY;
										DDat->dd_Flags			= ThisEntry->Flags;
										DDat->dd_ViewModes		= ThisEntry->ViewMode;

											// A Ok, set new type of icon

										DObj->do_Type = WBDISK;
									}
								}
							}
							else
								RetVal = OldGetIcon(Name, DObj, FList, IconBase);
						}
						else
							RetVal = OldGetIcon(Name, DObj, FList, IconBase);
					}
					else
						RetVal = OldGetIcon(Name, DObj, FList, IconBase);

					if(RetVal)
					{
						struct	Screen	*WBScreen	= LockPubScreen("Workbench");

							// Patch position ???

						if(WBScreen)
						{
								// Do so

							DObj->do_CurrentX = ((UseIconPos) ? (Left < 0 ? WBScreen->Width + Left : Left) : NO_ICON_POSITION);
							DObj->do_CurrentY = ((UseIconPos) ? (Top < 0 ? WBScreen->Height + Top - WBScreen->BarHeight - 1 : Top - WBScreen->BarHeight - 1) : NO_ICON_POSITION);

							UnlockPubScreen(NULL, WBScreen);
						}

							// Use window ???

						if(UseWindow)
						{
							DObj->do_DrawerData->dd_NewWindow.LeftEdge	= WinX;
							DObj->do_DrawerData->dd_NewWindow.TopEdge	= WinY;
							DObj->do_DrawerData->dd_NewWindow.Width		= WinWidth;
							DObj->do_DrawerData->dd_NewWindow.Height	= WinHeight;
						}

							// Set Flags ???

						if(UseFlags)
						{
							DObj->do_DrawerData->dd_Flags			= (WinFlags > 3 ? 2 : 0);
							DObj->do_DrawerData->dd_ViewModes		= (WinFlags > 3 ? WinFlags - 3 : WinFlags + 1);
						}
					}
				}
			}
		}
		else
			UnLock(CheckLock);
	}

	if(VolName)
		FreeMem(VolName, 130);

	if(DevName)
		FreeMem(DevName, 130);


		// No entry found and not the orig. icon read -> use supplied name

	if(!Found && !RetVal)
		RetVal = OldGetIcon(Name, DObj, FList, IconBase);

		// Release that fine semaphore

	ReleaseSemaphore(&FIconSema->FIconSema);

	return(RetVal);
}





/**********************************************************************/
/*                        My new Lock routine                         */
/**********************************************************************/
static ULONG __saveds __asm MyLock(register __d1 UBYTE *Name, register __d2 ULONG Mode, register __a6 struct DosLibrary *DOSBase)
{
	struct	Process		*MyProc		= (struct Process *)FindTask(NULL);
	struct	FileLock	*Dir;
	struct	DosList		*DList;
	char			*VolName,
				*DevName	= NULL,
				*IconName;
	BPTR			MyLock,
				CheckLock;
	ULONG			RetVal		= NULL;
	BOOL			Found		= FALSE,
				UseAltIcon;



		// Get buffers

	if((VolName = AllocMem(130, MEMF_CLEAR|MEMF_PUBLIC)) && (DevName = AllocMem(130, MEMF_CLEAR|MEMF_PUBLIC)))
	{
			// Calling process a real process and is it Workbench ?

		if((MyProc->pr_Task.tc_Node.ln_Type == NT_PROCESS) && TypeOfMem(MyProc->pr_Task.tc_Node.ln_Name) && !strcmp(MyProc->pr_Task.tc_Node.ln_Name, "Workbench"))
		{

				// Trying to load a Disk.info ???

			if(TypeOfMem(Name) && !stricmp(Name, "Disk.info"))
			{
					// Get my semaphore

				ObtainSemaphore(&FIconSema->FIconSema);

					// Switch to current dir

				MyLock	= CurrentDir(NULL);
				Dir	= (struct FileLock *)BADDR(MyLock);
				DList	= (struct DosList *)BADDR(Dir->fl_Volume);

					// Get name of volume inserted

				strncpy(VolName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));

					// Reset current dir

				CurrentDir(MyLock);

					// Get Name of Device

				if((DList = LockDosList(LDF_DEVICES|LDF_READ)))
				{
					while((DList = NextDosEntry(DList, LDF_DEVICES|LDF_READ)))
					{
						if(Dir->fl_Task == DList->dol_Task)
							strncpy(DevName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));
					}
					UnLockDosList(LDF_DEVICES|LDF_READ);
				}

					// Really load from ROOT ?

				if(!(CheckLock = ParentDir(MyLock)))
				{
						// Do we have patches waiting ???

					if(!IsListEmpty(&FIconSema->VolumeList))
					{
						struct	VolEntry	*ThisEntry = (struct VolEntry *)FIconSema->VolumeList.lh_Head;

						do
						{
								// This one to patch ???

							if(ThisEntry->Link.ln_Type == LDF_DEVICES && !MyStrCmp(ThisEntry->VolName, DevName))
								Found = TRUE;

							else if(ThisEntry->Link.ln_Type == LDF_VOLUMES && !MyStrCmp(ThisEntry->VolName, VolName))
								Found = TRUE;

							else
								ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;

						} while(!Found && ThisEntry->Link.ln_Succ);

							// Object to be patched ?

						if(Found)
						{
								// Set vars for icon substitution

							UseAltIcon	= (ThisEntry->UseAlt == MODE_USE);
							IconName	= ThisEntry->IconName;

								// This entry a volume and are we allowed to obtain settings from a device ???

							if(ThisEntry->Link.ln_Type == LDF_VOLUMES)
							{
								struct	VolEntry	*DevEntry	= (struct VolEntry *)FIconSema->VolumeList.lh_Head;
								BOOL			FoundMyDev	= FALSE;

									// Search for device-entry corresponding to volume

								while(DevEntry->Link.ln_Succ && !FoundMyDev)
								{
									if(DevEntry->Link.ln_Type == LDF_DEVICES && !MyStrCmp(DevEntry->VolName, DevName))
										FoundMyDev	= TRUE;
									else
										DevEntry	= (struct VolEntry *)DevEntry->Link.ln_Succ;
								}

									// Got a device entry for this volume ???

								if(FoundMyDev)
								{
										// Use alternative icon for volume ???

									if(ThisEntry->UseAlt == MODE_INHERIT)
									{
											// no, use one for device entry ???
											// If so, set pointer to new iconname

										if(DevEntry->UseAlt == MODE_USE)
										{
											UseAltIcon	= TRUE;
											IconName	= DevEntry->IconName;
										}
									}
								}
							}

								// If an alternative icon is to be used
								// lock this one, otherwise lock Disk.info

							if(UseAltIcon)
							{
								struct	DiskObject	*OldDiskObject;
								WORD	OldLeft		= 50,
									OldTop		= 50,
									OldWidth 	= 400,
									OldHeight	= 100;
								LONG	OldCurrentX	= 0,
									OldCurrentY	= 0;
								ULONG	OldFlags	= 0x0;
								UWORD	OldViewMode	= 1;

								if(!(RetVal = OldLock(IconName, Mode, DOSBase)))
									RetVal = OldLock(Name, Mode, DOSBase);
								else
								{
										// Get original Disk.info file, in order to obtain
										// the correct window position and size

									strcat(DevName, ":Disk");
									if(!(OldDiskObject = GetDiskObject(DevName)))
									{
										strcat(VolName, ":Disk");
										OldDiskObject = GetDiskObject(VolName);
									}

									if(OldDiskObject)
									{
										OldLeft		= OldDiskObject->do_DrawerData->dd_NewWindow.LeftEdge;
										OldTop		= OldDiskObject->do_DrawerData->dd_NewWindow.TopEdge;
										OldWidth	= OldDiskObject->do_DrawerData->dd_NewWindow.Width;
										OldHeight	= OldDiskObject->do_DrawerData->dd_NewWindow.Height;
										OldCurrentX	= OldDiskObject->do_DrawerData->dd_CurrentX;
										OldCurrentY	= OldDiskObject->do_DrawerData->dd_CurrentY;
										OldFlags	= OldDiskObject->do_DrawerData->dd_Flags;
										OldViewMode	= OldDiskObject->do_DrawerData->dd_ViewModes;

										FreeDiskObject(OldDiskObject);
									}

									ThisEntry->LeftEdge	= OldLeft;
									ThisEntry->TopEdge	= OldTop;
									ThisEntry->Width	= OldWidth;
									ThisEntry->Height	= OldHeight;
									ThisEntry->CurrentX	= OldCurrentX;
									ThisEntry->CurrentY	= OldCurrentY;
									ThisEntry->Flags	= OldFlags;
									ThisEntry->ViewMode	= OldViewMode;
								}
							}
							else
								Found = FALSE;
						}
					}
				}
				else
					UnLock(CheckLock);

				ReleaseSemaphore(&FIconSema->FIconSema);
			}
		}
	}

	if(VolName)
		FreeMem(VolName, 130);

	if(DevName)
		FreeMem(DevName, 130);


	if(!Found)
		RetVal = OldLock(Name, Mode, DOSBase);

	return(RetVal);
}






/**********************************************************************/
/*               Store icons position of the info file                */
/**********************************************************************/
static BOOL StoreIconPos(struct DiskObject *Icon)
{
	struct	FileLock	*Dir;
	struct	DosList		*DList;
	struct	VolEntry	*ThisEntry;
	char			*VolName;
	BPTR			MyLock,
				CheckLock;
	BOOL			Found		= FALSE,
				RetVal		= FALSE,
				Created		= FALSE,
				IsReadOnly	= FALSE;



		// Get our semaphore

	ObtainSemaphore(&FIconSema->FIconSema);


		// Get buffers

	if((VolName = AllocMem(130, MEMF_CLEAR)))
	{
			// Switch to current dir

		MyLock	= CurrentDir(NULL);
		Dir	= (struct FileLock *)BADDR(MyLock);
		DList	= (struct DosList *)BADDR(Dir->fl_Volume);

			// Get name of volume inserted

		strncpy(VolName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));

			// Reset current dir

		CurrentDir(MyLock);

			// Get Name of Device

		if((DList = LockDosList(LDF_DEVICES|LDF_READ)))
		{
			while((DList = NextDosEntry(DList, LDF_DEVICES|LDF_READ)))
			{
				if(Dir->fl_Task == DList->dol_Task)
				{
					struct	InfoData	__aligned	InfoData;

						// Get information about drive

					if(DoPkt(Dir->fl_Task, ACTION_DISK_INFO, MKBADDR(&InfoData), NULL, NULL, NULL, NULL))
					{
							// Is drive write protected?

						if(InfoData.id_DiskState == ID_WRITE_PROTECTED)
							IsReadOnly	= TRUE;
					}
				}
			}
			UnLockDosList(LDF_DEVICES|LDF_READ);
		}



			// Really to load from ROOT ???

		if(!(CheckLock = ParentDir(MyLock)))
		{
				// Do we have patches waiting ???

			if(!IsListEmpty(&FIconSema->VolumeList))
			{
				ThisEntry = (struct VolEntry *)FIconSema->VolumeList.lh_Head;

				do
				{
						// This one to patch ???

					if(ThisEntry->Link.ln_Type == LDF_VOLUMES && !MyStrCmp(ThisEntry->VolName, VolName))
						Found = TRUE;

					else
						ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;

				} while(!Found && ThisEntry->Link.ln_Succ);
			}


				// Object to be patched found? If not, create new entry (VOLUME)

			if(!Found)
			{
					// Clear pointer

				ThisEntry	= NULL;

					// Device really is READONLY?

				if(IsReadOnly)
				{
						// Try to create new entry

					if((ThisEntry = AllocVecPool(FIconSema, sizeof(struct VolEntry))))
					{
							// Fill in structure and set flag

						ThisEntry->Link.ln_Name	= ThisEntry->VolName;
						ThisEntry->Link.ln_Type	= LDF_VOLUMES;
						strcpy(ThisEntry->VolName, VolName);
						Created		= TRUE;
					}
				}
			}

				// Got an entry?

			if(ThisEntry)
			{
				struct	Screen	*WBScreen	= LockPubScreen("Workbench");

					// Got screen?

				if(WBScreen)
				{
						// Created new entry? Add to list

					if(Created)
						AddHead(&FIconSema->VolumeList, (struct Node *)ThisEntry);

						// Set vars for icon placement

					ThisEntry->Left		= Icon->do_CurrentX;
					ThisEntry->Top		= Icon->do_CurrentY + WBScreen->BarHeight + 1;
					ThisEntry->IconPos	= MODE_USE;
					RetVal			= TRUE;

						// Unlock screen

					UnlockPubScreen(NULL, WBScreen);
				}
				else
				{
						// Failure and created entry?
						// Free memory associated

					if(Created)
						FreeVecPool(FIconSema, ThisEntry);
				}
			}
		}
		else
			UnLock(CheckLock);
	}

	if(VolName)
		FreeMem(VolName, 130);

		// Release that fine semaphore

	ReleaseSemaphore(&FIconSema->FIconSema);

	return(RetVal);
}









/**********************************************************************/
/*                           Open libraries                           */
/**********************************************************************/
static BOOL OpenAll(void)
{
	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"intuition.library", 37);
		return(FALSE);
	}

	if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"dos.library", 37);
		return(FALSE);
	}

	if(!(IconBase = OpenLibrary("icon.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"icon.library", 37);
		return(FALSE);
	}

	if(!(UtilityBase = OpenLibrary("utility.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"utility.library", 37);
		return(FALSE);
	}

	if(!(IFFParseBase = OpenLibrary("iffparse.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"iffparse.library", 37);
		return(FALSE);
	}

	if(!(AslBase = OpenLibrary("asl.library", 36)))
	{
		DisplayError(ERR_OPEN, (ULONG)"asl.library", 36);
		return(FALSE);
	}

	return(TRUE);
}








/**********************************************************************/
/*                          Close libraries                           */
/**********************************************************************/
static void CloseAll(void)
{
	if(AslBase)
		CloseLibrary(AslBase);

	if(IFFParseBase)
		CloseLibrary(IFFParseBase);

	if(UtilityBase)
		CloseLibrary(UtilityBase);

	if(IconBase)
		CloseLibrary(IconBase);

	if(DOSBase)
		CloseLibrary((struct Library *)DOSBase);

	if(IntuitionBase)
		CloseLibrary((struct Library *)IntuitionBase);
}




/**********************************************************************/
/*       Now include the LoadRoutine and the VolumeList routine       */
/**********************************************************************/
#include	"LoadPrefs.h"
#include	"VolList.h"
#include	"Error.h"
#include	"Rendezvous.h"
#include	"CheckToolTypes.h"
#include	"PoolVec.h"
