⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsdvol.c

📁 Win9x下文件系统驱动的例子(EXT2)源代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (!ior)
		return Ioreq->ir_error = ERROR_NOT_ENOUGH_MEMORY;

	// macro to simplify grossly long field name access:
	#define ioctl(f) ior->_ureq.sdeffsd_req_usage._IOR_ioctl_##f
	
	pRegs = (CLIENT_STRUCT*) Ioreq->ir_cregptr;	
	ioctl(client_params) = (ULONG) pRegs;
	ioctl(function) = _ClientAX;
	//ASSERT(_ClientBL-1 == m_drive);
	ioctl(drive) = SUPER(Ioreq)->DosDrive;
	ioctl(control_param) = _ClientCX;

	if (Ioreq->ir_options & IOCTL_PKT_LINEAR_ADDRESS)
		ioctl(buffer_ptr) = (ULONG) Ioreq->ir_data; // flat buffer address
	else
		{						// 16-bit IOCTL
		ior->IOR_flags |= IORF_16BIT_IOCTL;
		ioctl(buffer_ptr) = (ULONG) Client_Ptr_Flat(DS, DX);
		}						// 16-bit IOCTL

	//IOS_SendCommand(ior, (PDCB) Vrp->VRP_device_handle);
	IOS_SendCommand(ior, SUPER(Ioreq)->Device);
	
	status = ior->IOR_status;
	_ClientAX = (USHORT) ioctl(return);
	DestroyIOR(ior);

	if (status >= IORS_ERROR_DESIGNTR)	
		status = (USHORT) IOSMapIORSToI21(status);
	else
		status = 0;				// success after error is still success

	Ioreq->ir_error = (int) status;

	VxdDebugPrint(D_VOLUME, "IOCTL16, done, error=%i", Ioreq->ir_error);

	return Ioreq->ir_error;
#endif		/* NYI */
}


int __cdecl FsdVolDelete(pioreq Ioreq)
{
	VxdDebugPrint(D_VOLUME,  "DEL");
	Ioreq->ir_error = 5;
	VxdDebugFlush();
	return Ioreq->ir_error;
}











int __cdecl FsdVolDir(pioreq Ioreq)
{
	char			bcsdirname[MAX_PATH];
	TInode			*inode;

	VxdDebugPrint(D_VOLUME, "DIR (%s), dir=%U", sDirActions[Ioreq->ir_flags], Ioreq->ir_upath);

	switch (Ioreq->ir_flags)
	{
		case CREATE_DIR:
		case DELETE_DIR:
		case QUERY83_DIR:
			Ioreq->ir_error = ERROR_INVALID_FUNCTION;
			break;

		case CHECK_DIR:
			Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
			if (GetBcsPath(SUPER(Ioreq)->DosDrive, Ioreq->ir_upath, bcsdirname))
			{
				if ((inode = DirName2Inode(SUPER(Ioreq), bcsdirname)))
				{
					if (S_ISDIR(inode->Mode))
						Ioreq->ir_error = 0;
					InodeRelease(inode);
				}
			}
			break;

		case QUERYLONG_DIR:
			Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
			if (GetBcsPath(SUPER(Ioreq)->DosDrive, Ioreq->ir_upath, bcsdirname))
			{
				if ((inode = DirName2Inode(SUPER(Ioreq), bcsdirname)))
				{
					if (S_ISDIR(inode->Mode))
					{
						Ioreq->ir_error = 0;
						BcsToUniParsed(bcsdirname, (PUSHORT) Ioreq->ir_ppath2);
					}
					InodeRelease(inode);
				}
			}
			break;

		default:
			Ioreq->ir_error = ERROR_INVALID_FUNCTION;
			break;
	}

	VxdDebugPrint(D_VOLUME, "DIR: done, error=%i", Ioreq->ir_error);
	VxdDebugFlush();

	return Ioreq->ir_error;
}








int __cdecl FsdVolAttrib(pioreq Ioreq)
{
	TInode			*inode;
	ext2_inode		*ext2inode;
	char			bcspathname[MAX_PATH];

	VxdDebugPrint(D_VOLUME, "ATTRIB(%s), path=%U, attrib=%X", sAttribActions[Ioreq->ir_flags], Ioreq->ir_upath, Ioreq->ir_uFName, (Ioreq->ir_attr & 0xFFFF));

		/*
		 * First get the bcs_pathname of the directory in which
		 * the lookup is to be performed
		 */
	if (GetBcsPath(SUPER(Ioreq)->DosDrive, Ioreq->ir_upath, bcspathname))
	{

			/*
			 * Get the inode belonging to the object name
			 */
		if ( (inode = DirName2Inode(SUPER(Ioreq), bcspathname)))
		{
			ext2inode = InodeLock(inode);

			switch(Ioreq->ir_flags)
			{
				case GET_ATTRIBUTES:
					Ioreq->ir_attr = inode->DosAttrib;
					Ioreq->ir_error = 0;
					break;

				case GET_ATTRIB_MODIFY_DATETIME:
					Ioreq->ir_dostime = dateUnix2Dos(ext2inode->i_mtime);
					Ioreq->ir_error = 0;
					break;

				case GET_ATTRIB_LAST_ACCESS_DATETIME:
					Ioreq->ir_dostime = dateUnix2Dos(ext2inode->i_atime);
					Ioreq->ir_error = 0;
					break;

				case GET_ATTRIB_CREATION_DATETIME:
					Ioreq->ir_dostime = dateUnix2Dos(ext2inode->i_ctime);
					Ioreq->ir_error = 0;
					break;

				case GET_ATTRIB_COMP_FILESIZE:
					Ioreq->ir_size = ext2inode->i_size;
					break;

					/*
					 * Don't fail these, just ignore them...
					 */
				case SET_ATTRIB_LAST_ACCESS_DATETIME:
				case SET_ATTRIB_MODIFY_DATETIME:
				case SET_ATTRIB_CREATION_DATETIME:
					Ioreq->ir_error = 0;
					break;

				case SET_ATTRIBUTES:
				default:
					Ioreq->ir_error = ERROR_ACCESS_DENIED;
					break;
			}
			InodeUnlock(inode);	
		}
		else
			Ioreq->ir_error = ERROR_FILE_NOT_FOUND;
	}
	else
		Ioreq->ir_error = ERROR_FILE_NOT_FOUND;

	VxdDebugPrint(D_VOLUME, "ATTRIB: done, error=%lu", (ULONG) Ioreq->ir_error);
	VxdDebugFlush();

	return Ioreq->ir_error;
}








int __cdecl FsdVolFlush(pioreq Ioreq) 
{
	VxdDebugPrint(D_VOLUME,  "flush");
	VxdDebugFlush();
	return (Ioreq->ir_error=0);
}


/*
	IOREQ Structure:
	Entry
		ir_rh -- Supplies handle to disk volume or network resource to get info on.
		ir_flags -- Supplies special flags for this function.
			GetDiskInfo Flags:
			GDF_NO_DISK_HIT -- This flag is a hint flag to the FSD. It specifies that the FSD should, if possible, return a close approximation to the freespace on the disk without accessing the disk in any fashion. This is an optimization that is used by some components in the system. It is not mandatory to implement this except in certain special cases. Look in the notes below for more details.
		ir_user -- User id for this request.
		ir_pid -- Process id for this request.
	Returns
		ir_error -- Returns status of the operation ( 0 if no error, errorcode otherwise ).
		ir_length -- Returns number of bytes per sector.
		ir_size -- Returns total number of allocation units.
		ir_data -- Returns an optional pointer to the file allocation table (FAT) identification byte.  This is only required for local FAT file systems.
		ir_sectors -- Returns number of sectors per allocation unit.
		ir_numfree -- Returns number of free allocation units.
*/

int __cdecl FsdVolInfo(pioreq Ioreq)
{
	ext2_super_block	*ext2_super;

	VxdDebugPrint(D_VOLUME,  "info");

	ext2_super = SuperLock(SUPER(Ioreq));

		/*
		 * Eventhough the ir_size and ir_numfree are 32 bit numbers,
		 * most applications (also the explorer) treat these as
		 * 16 bits numbers.
		 * Workaround: we always return allocation unit of 32KB
		 */
	//Ioreq->ir_data = 0;
	//Ioreq->ir_length = 512;
	//Ioreq->ir_sectors = 1 << DevGetLogBlockSize(SUPER(Ioreq)->Device);
	//Ioreq->ir_size = ext2_super->s_blocks_count; 
	//Ioreq->ir_numfree = ext2_super->s_free_blocks_count;

	Ioreq->ir_data = 0;
	Ioreq->ir_length = 512;
	Ioreq->ir_sectors = 64; // 64 == 1 << 6
	Ioreq->ir_size = ext2_super->s_blocks_count >> (6 - DevGetLogBlockSize(SUPER(Ioreq)->Device)); 
	Ioreq->ir_numfree = ext2_super->s_free_blocks_count >> (6 - DevGetLogBlockSize(SUPER(Ioreq)->Device)); 

	VxdDebugPrint(D_VOLUME,  "sector=%lu, size=%lu, numfree=%lu", (ULONG) Ioreq->ir_sectors, (ULONG) Ioreq->ir_size, (ULONG) Ioreq->ir_numfree);
	
	SuperUnlock(SUPER(Ioreq));

	VxdDebugFlush();

	return (Ioreq->ir_error=0);
}










int __cdecl FsdVolRename(pioreq Ioreq)
{
	VxdDebugPrint(D_VOLUME,  "rename");
	return (Ioreq->ir_error=5);
}







int __cdecl FsdVolSearch(pioreq Ioreq)
{
	TFindContext	*findcontext;
	srch_entry		*search_entry;
	char			*pc;
	int				error;
	int				attr;

	if (Ioreq->ir_flags == SEARCH_FIRST)
	{
		attr = Ioreq->ir_attr & 0xFFFF;
		Ioreq->ir_error = 0;

		VxdDebugPrint(D_VOLUME, "FFIRST(short), path=%U, attrib=%X", Ioreq->ir_upath, attr);

			/*
			 * If we are asked for a dir label, we return
			 * the device name
			 */
		if (attr == FILE_ATTRIBUTE_LABEL)
		{
			search_entry = (srch_entry *) Ioreq->ir_data;
			search_entry->se_attrib = FILE_ATTRIBUTE_LABEL;
			strcpy(search_entry->se_name, SUPER(Ioreq)->DeviceName + 5);
			VxdDebugPrint(D_VOLUME, "FFIRST(short), done, returned label");
			VxdDebugFlush();

			return Ioreq->ir_error;
		}


			/*
			 * Setup a findcontext
			 */
		if ((findcontext = FsdPrepareFindNext(Ioreq)))
		{

				/*
				 * Update the ioreq for future findnext calls
				 */
			search_entry = (srch_entry *) Ioreq->ir_data;
			memcpy(search_entry->se_key.sk_localFSD, &findcontext, 4);
			Ioreq->ir_firstclus = 0;

				/*
				 * 8.3 searches with capitals
				 */
			pc = findcontext->SearchName;
			while(*pc)
				*pc++ = toupper(*pc);


			
				/*
				 * Now simple issue an findnext
				 */
			error = FsdShortFindNext(Ioreq);
				
				/*
				 * Adjust the error code for a findfirst
				 */
			if (error == ERROR_NO_MORE_FILES)
				Ioreq->ir_error = ERROR_FILE_NOT_FOUND;
		}
		VxdDebugPrint(D_VOLUME, "FFIRST(short), done, %s",
			Ioreq->ir_error ? "no more files or error" : "entry found");
	}
	else
		FsdShortFindNext(Ioreq);
		
	VxdDebugFlush();
	return Ioreq->ir_error;
}



int __cdecl FsdVolQuery(pioreq Ioreq)
{

	VxdDebugPrint(D_VOLUME, "QUERY level %i", Ioreq->ir_options);

	switch(Ioreq->ir_options)
	{
		case 0:
		case 1:
			Ioreq->ir_error = ERROR_INVALID_FUNCTION;
			break;
		case 2:
			//BCSToUni(Ioreq->ir_data, gFileSystem, strlen(gFileSystem), BCS_OEM, &qword);
			//((PUSHORT) Ioreq->ir_data)[qword.ddLower >> 1] = 0;
			Ioreq->ir_length = EXT2_NAME_LEN | (EXT2_NAME_LEN << 16);
			Ioreq->ir_options = FS_CASE_IS_PRESERVED | FS_VOL_SUPPORTS_LONG_NAMES;
			//Ioreq->ir_options = FS_VOL_SUPPORTS_LONG_NAMES;
			Ioreq->ir_error = 0;
			break;
	}
	VxdDebugPrint(D_VOLUME, "QUERY: done");
	VxdDebugFlush();

	return Ioreq->ir_error;
}

int __cdecl FsdVolDisconnect(pioreq Ioreq)
{
	VxdDebugPrint(D_VOLUME,  "disconnect");
	VxdDebugFlush();
	return (Ioreq->ir_error=5);
}

int __cdecl FsdVolUNCPipe(pioreq Ioreq)
{
	VxdDebugPrint(D_VOLUME,  "UNCPipe");
	VxdDebugFlush();
	return (Ioreq->ir_error=5);
}

int __cdecl FsdVolParams(pioreq Ioreq)
{
		/*
		 * We do maintain DPDs
		 */
	VxdDebugPrint(D_VOLUME,  "Params");
	VxdDebugFlush();
	return (Ioreq->ir_error = ERROR_INVALID_FUNCTION);
}


int __cdecl FsdVolFindOpen	(pioreq Ioreq)
{
	_QWORD				Result;
	_WIN32_FIND_DATA	*FindData;
	TFindContext		*findcontext;
	char				*devicename;
	int					error;
	int					attr;

	attr = (Ioreq->ir_attr & 0xFFFF);
	Ioreq->ir_error = 0;
	VxdDebugPrint(D_VOLUME, "FFIRST(lfn), path=%U, attrib=%X", Ioreq->ir_upath, attr);

	if (attr == FILE_ATTRIBUTE_LABEL)
	{
			/*
			 * return the device name on a label request
			 */
		devicename = SUPER(Ioreq)->DeviceName + 5;
		FindData = Ioreq->ir_data;
			
			/*
			 * Set long name
			 */
		BCSToUni(FindData->cFileName, devicename, strlen(devicename), BCS_OEM, &Result);
		FindData->cFileName[Result.ddLower >> 1] = 0;

			/*
			 * Set short name
			 */
		BCSToUni(FindData->cAlternateFileName, devicename, strlen(devicename), BCS_OEM, &Result);
		FindData->cAlternateFileName[Result.ddLower >> 1] = 0;

		FindData->dwFileAttributes = FILE_ATTRIBUTE_LABEL;
		Ioreq->ir_pos = 0;
		Ioreq->ir_fh = 0;
		SetHandleFunc(Ioreq, FsdLfnFindNext, FsdFileEmptyFunc, &gFsdFindFunctions);	

		VxdDebugPrint(D_VOLUME, "FFIRST(lfn), done, returned label");
		
		return 0;
	}

		/*
		 * Setup a findcontext
		 */
	if ((findcontext = FsdPrepareFindNext(Ioreq)))
	{

			/*
			 * Update the ioreq for future findnext calls
			 */
		Ioreq->ir_fh = findcontext;
		SetHandleFunc(Ioreq, FsdLfnFindNext, FsdFileEmptyFunc, &gFsdFindFunctions);
		
			/*
			 * Now simply issue an findnext
			 */
		error = FsdLfnFindNext(Ioreq);
			
			/*
			 * Adjust the error code for a findfirst
			 */
		if (error == ERROR_NO_MORE_FILES)
			Ioreq->ir_error = ERROR_FILE_NOT_FOUND;

		if (error)
			DirDestroyFindContext(findcontext);
	}
	VxdDebugPrint(D_VOLUME, "FFIRST(lfn), done, %s",
		Ioreq->ir_error ? "no more files or error" : "entry found");
	
	VxdDebugFlush();

	return Ioreq->ir_error;
}



int __cdecl FsdVolDasdio(pioreq Ioreq)
{
	VxdDebugPrint(D_VOLUME, "DASDIO");

	VxdDebugFlush();

	return (Ioreq->ir_error = ERROR_INVALID_FUNCTION);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -