static Partition *
UnmountIfMatchingID(Partition *_DEVICE_MAP_ONLY(partition),
	void *_DEVICE_MAP_ONLY(castToParams))
{
	UnmountDeviceParams *params = (UnmountDeviceParams *)castToParams;
	
	if (partition->VolumeDeviceID() == params->device) {

		TTracker *tracker = dynamic_cast<TTracker *>(be_app);
		if (tracker && tracker->QueryActiveForDevice(params->device)) {
			BString text;
			text << "To unmount " << partition->VolumeName() << " some query "
			"windows have to be closed. Would you like to close the query "
			"windows?";
			if ((new BAlert("", text.String(), "Cancel", "Close and unmount", NULL,
				B_WIDTH_FROM_LABEL))->Go() == 0)
				return partition;
			tracker->CloseActiveQueryWindows(params->device);
		}

		params->result = partition->Unmount();
		Device *device = partition->GetDevice();
		bool deviceHasMountedPartitions = false;

		if (params->result == B_OK && device->Removable()) {
			for (int32 sessionIndex = 0; ; sessionIndex++) {
				Session *session = device->SessionAt(sessionIndex);
				if (!session)
					break;

				for (int32 partitionIndex = 0; ; partitionIndex++) {
					Partition *partition = session->PartitionAt(partitionIndex);
					if (!partition)
						break;

					if (partition->Mounted() == kMounted) {
						deviceHasMountedPartitions = true;
						break;
					}
				}
			}

			if (!deviceHasMountedPartitions
				&& TrackerSettings().EjectWhenUnmounting())
				params->result = partition->GetDevice()->Eject();
		}

		return partition;
	}

	return NULL;
}
void
AutoMounter::MessageReceived(BMessage *message)
{
	switch (message->what) {
#if _INCLUDES_CLASS_DEVICE_MAP
		case kAutomounterRescan:
			RescanDevices();
			break;

		case kStartPolling:	
			// PRINT(("starting the automounter\n"));
			
			fScanThread = spawn_thread(AutoMounter::WatchVolumeBinder, 
#if DEBUG				
				"HiroshiLikesAtomountScan",	// long story
#else
				"AutomountScan",
#endif				
				B_LOW_PRIORITY, this);
			resume_thread(fScanThread);
			break;

		case kMountVolume:
			MountVolume(message);
			break;

		case kUnmountVolume:
			UnmountAndEjectVolume(message);
			break;

		case kSetAutomounterParams:
			{
				bool rescanNow = false;
				message->FindBool("rescanNow", &rescanNow);
				SetParams(message, rescanNow);
				WriteSettings();
				break;
			}

		case kMountAllNow:
			RescanDevices();
			MountAllNow();
			break;

		case kSuspendAutomounter:
			SuspendResume(true);
			break;

		case kResumeAutomounter:
			SuspendResume(false);
			break;

		case kTryMountingFloppy:
			TryMountingFloppy();
			break;

		case B_NODE_MONITOR:
			{
				int32 opcode;
				if (message->FindInt32("opcode", &opcode) != B_OK)
					break;
	
				switch (opcode) {
					case B_DEVICE_MOUNTED: {
						WRITELOG(("** Received Device Mounted Notification"));
						dev_t device;
						if (message->FindInt32("new device", &device) == B_OK) {
							Partition *partition =  FindPartition(device);
							if (partition == NULL || partition->Mounted() != kMounted) {
								WRITELOG(("Device %i not in device list.  Someone mounted it outside "
									"of Tracker", device));
		
								//
								// This is the worst case.  Someone has mounted
								// something from outside of tracker.  
								// Unfortunately, there's no easy way to tell which
								// partition was just mounted (or if we even know about the device),
								// so stop watching all nodes, rescan to see what is now mounted,
								// and start watching again.
								//
								RescanDevices();
							} else
								WRITELOG(("Found partition\n"));
						} else {
							WRITELOG(("ERROR: Could not find mounted device ID in message"));
							PRINT_OBJECT(*message);
						}
	
						break;
					}
	
	
					case B_DEVICE_UNMOUNTED: {
						WRITELOG(("*** Received Device Unmounted Notification"));
						dev_t device;
						if (message->FindInt32("device", &device) == B_OK) {
							Partition *partition = FindPartition(device);
	
							if (partition != 0) {
								WRITELOG(("Found device in device list. Updating state to unmounted."));
								partition->SetMountState(kNotMounted);
							} else
								WRITELOG(("Unmounted device %i was not in device list", device));
						} else {
							WRITELOG(("ERROR: Could not find unmounted device ID in message"));
							PRINT_OBJECT(*message);
						}
	
						break;
					}	
	
	
					//	The name of a mount point has changed
					case B_ENTRY_MOVED: {
						WRITELOG(("*** Received Mount Point Renamed Notification"));
					
						const char *newName;
						if (message->FindString("name", &newName) != B_OK) {
							WRITELOG(("ERROR: Couldn't find name field in update message"));
							PRINT_OBJECT(*message);
							break ;
						}
	
						//
						// When the node monitor reports a move, it gives the
						// parent device and inode that moved.  The problem is 
						// that  the inode is the inode of root *in* the filesystem,
						// which is generally always the same number for every 
						// filesystem of a type.
						//
						// What we'd really like is the device that the moved	
						// volume is mounted on.  Find this by using the 
						// *new* name and directory, and then stat()ing that to
						// find the device.
						//
						dev_t parentDevice;
						if (message->FindInt32("device", &parentDevice) != B_OK) {
							WRITELOG(("ERROR: Couldn't find 'device' field in update"
								" message"));
							PRINT_OBJECT(*message);
							break;
						}
		
						ino_t toDirectory;	
						if (message->FindInt64("to directory", &toDirectory)!=B_OK){
							WRITELOG(("ERROR: Couldn't find 'to directory' field in update"
							  "message"));
							PRINT_OBJECT(*message);
							break;
						}
		
						entry_ref root_entry(parentDevice, toDirectory, newName);
	
						BNode entryNode(&root_entry);
						if (entryNode.InitCheck() != B_OK) {
							WRITELOG(("ERROR: Couldn't create mount point entry node: %s/n", 
								strerror(entryNode.InitCheck())));
							break;
						}	
	
						node_ref mountPointNode;
						if (entryNode.GetNodeRef(&mountPointNode) != B_OK) {
							WRITELOG(("ERROR: Couldn't get node ref for new mount point"));
							break;
						}
				
	
						WRITELOG(("Attempt to rename device %li to %s", mountPointNode.device,
							newName));

						Partition *partition = FindPartition(mountPointNode.device);
						if (partition != NULL) {
							WRITELOG(("Found device, changing name."));

							BVolume mountVolume(partition->VolumeDeviceID());
							BDirectory mountDir;
							mountVolume.GetRootDirectory(&mountDir);
							BPath dirPath(&mountDir, 0);
					
							partition->SetMountedAt(dirPath.Path());
							partition->SetVolumeName(newName);					
							break;
						}
						else
							WRITELOG(("ERROR: Device %li does not appear to be present",
								mountPointNode.device));
					}
				}
			}
			break;


#endif
		default:
			BLooper::MessageReceived(message);
			break;
	}
}