📄 fsdvol.c
字号:
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 + -