📄 fghook.cpp
字号:
ShellPostError(FG_ERR_WARNING, FG_WARN_PT_DELETE); //Send a warning.
return pir->ir_error;
}
}
//go on to find next file
R0_FindNextFile(hFind, &bcsFindData, &error);
} //while(error==ERROR_SUCCESS)
} //if(pir->ir_attr&FILE_FLAG_WILDCARDS || pir->ir_attr&FILE_FLAG_HAS_STAR)
else if((pProtFile=protFileList.IsUnderProtection(Drive, pir->ir_ppath, PT_DELETE|PT_HIDE))!=NULL)
{
//Deal with file name without wildcards:
if(pProtFile->PF_type&PT_HIDE)
pir->ir_error=ERROR_FILE_NOT_FOUND; //Protect hidden file.
if(!protFileList.bDelBak)
{
//Deny delete
pir->ir_error=ERROR_ACCESS_DENIED;
ShellPostError(FG_ERR_WARNING, FG_WARN_PT_DELETE); //Send a warning.
}
else
{
//Back up on delete.
UniToBCSPathEx((PUCHAR)pBCSPath,pir->ir_ppath->pp_elements,Drive,MAX_PATH,CodePage,&res);
pir->ir_error=FileRename(pBCSPath);
}
return pir->ir_error;
}
return ERROR_SUCCESS;
}
//Append a extension like ".BAK0" or ".BAK1" to the file name.
//(the maximum number appended at the tail depends on MAX_BAK_NUM)
//If every optional back up file name have been used, return FALSE,
//else return TRUE.
//No checking for the parameters. pBCSNewName must be long enough.
BOOL AppendBakExtension(const char *pBCSOldName, char *pBCSNewName)
{
strcpy(pBCSNewName,pBCSOldName);
strcat(pBCSNewName,".BAK1"); //Rename the file.
WORD error;
_WIN32_FIND_DATA_BCS findData;
char i;
for(i='2'; i<='1'+maxBakNum-1; i++)
{
R0_FindFirstFile(pBCSNewName, NULL, &findData, &error);
if(error==ERROR_FILE_NOT_FOUND)
return TRUE;
else
//if the file name has already been used, make some change.
pBCSNewName[strlen(pBCSNewName)-1]=i;
}
return FALSE;
}
//Backup a file by renaming it:
//e.g. "A.txt" to "A.txt.BAK".
WORD FileRename(char *pBCSOldName)
{
char pBCSNewName[MAX_PATH+1];
WORD error;
//Name the bak file.
AppendBakExtension(pBCSOldName, pBCSNewName);
R0_RenameFile(pBCSOldName,pBCSNewName,&error);
return error;
}
// Function name : FileBackupByHandle
// Backup a file identified by pir->ir_fh & pBCSName.
// Using pir->ir_fh to read from the file.
// if the handle is open with out Generic_Read, this function will fail.
// Only call this function in HookProc.
WORD FileBackupByHandle(pioreq pir,int Drive, int ResType, int CodePage,const char *pBCSName)
{
char pBCSNewName[MAX_PATH+1];
HANDLE hNewFile;
BYTE action;
WORD error, retVal=ERROR_SUCCESS;
ifsreq ifsr;
//Name the bak file.
AppendBakExtension(pBCSName, pBCSNewName);
hNewFile=R0_OpenCreateFile(FALSE, pBCSNewName,OPEN_ACCESS_WRITEONLY | OPEN_SHARE_COMPATIBLE,
ATTR_NORMAL, ACTION_IFEXISTS_TRUNCATE | ACTION_IFNOTEXISTS_CREATE,0 ,&error,&action);
if(error!=ERROR_SUCCESS) return error;
char buf[BUF_LEN+1];
DWORD nBytesRead=0,nBytesWrite=0,offset=0;
memcpy(&ifsr,pir,sizeof(ifsreq));
pIFSFunc readFunc = ifsr.ifs_hndl->hf_read;
while(1)
{
ifsr.ifsir.ir_length=BUF_LEN;
ifsr.ifsir.ir_options=R0_NO_CACHE;
ifsr.ifsir.ir_data=buf;
ifsr.ifsir.ir_pos=offset;
if((*PrevHookProc)(readFunc, IFSFN_READ,Drive, ResType, CodePage,(pioreq) &ifsr)==STATUS_PENDING)
IFSMgr_CompleteAsync((pioreq) &ifsr);
nBytesRead=ifsr.ifsir.ir_length;
if(ifsr.ifsir.ir_error!=ERROR_SUCCESS || !nBytesRead)
{
retVal=ifsr.ifsir.ir_error;
break;
}
nBytesWrite=R0_WriteFile(FALSE,hNewFile,buf,nBytesRead,offset,&error);
if(error!=ERROR_SUCCESS)
{
retVal=error;
break;
}
offset+=nBytesRead;
}
R0_CloseFile(hNewFile,&error);
return retVal;
}
// Function name : FileBackup
// Back up a file identify by pBCSName.
// If the file is currently open by other user with DENY_READ, this function will fail.
WORD FileBackup(char *pBCSName)
{
char pBCSNewName[MAX_PATH+1];
HANDLE hOldFile, hNewFile;
BYTE action;
WORD error, retVal=ERROR_SUCCESS;
//Name the bak file.
AppendBakExtension(pBCSName, pBCSNewName);
hOldFile=R0_OpenCreateFile(FALSE, pBCSName,OPEN_ACCESS_READONLY | OPEN_SHARE_COMPATIBLE,
ATTR_NORMAL, ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_FAIL ,0 ,&error,&action);
if(error!=ERROR_SUCCESS)
{
return error;
}
hNewFile=R0_OpenCreateFile(FALSE, pBCSNewName,OPEN_ACCESS_WRITEONLY | OPEN_SHARE_COMPATIBLE,
ATTR_NORMAL, ACTION_IFEXISTS_TRUNCATE | ACTION_IFNOTEXISTS_CREATE,0 ,&error,&action);
if(error!=ERROR_SUCCESS) return error;
char buf[BUF_LEN+1];
DWORD nBytesRead=0,nBytesWrite=0,offset=0;
while(1)
{
nBytesRead=R0_ReadFile(FALSE, hOldFile, buf, BUF_LEN, offset, &error);
if(error!=ERROR_SUCCESS || !nBytesRead)
{
retVal=error;
break;
}
nBytesWrite=R0_WriteFile(FALSE,hNewFile,buf,nBytesRead,offset,&error);
if(error!=ERROR_SUCCESS)
{
retVal=error;
break;
}
offset+=nBytesRead;
}
R0_CloseFile(hOldFile, &error);
R0_CloseFile(hNewFile,&error);
return retVal;
}
//Similar to UniToBCSPath(...)
void UniToBCSPathEx(PUCHAR pBCSPath, PathElement* pUniPath, int Drive, DWORD maxLength, int charSet, _QWORD* pResult)
{
//Get driver volume:
pBCSPath[0]=(char)Drive-1+'A';
pBCSPath[1]=':';
UniToBCSPath(pBCSPath+2,pUniPath,maxLength,charSet,pResult);
pBCSPath[pResult->ddLower+2]=NULL;
}
//Get full Canonicalized Path from pir->ir_fh.
BOOL GetFullNameByHandle(pioreq pir,int &Drive, int ResType, int CodePage,path_t pPPath, BOOL bFindHandle)
{
//Search in handle table first.
if((bFindHandle && findHTable.Find(pir->ir_fh, Drive, pPPath, MAX_PATH)) || openHTable.Find(pir->ir_fh, Drive, pPPath, MAX_PATH))
return TRUE;
//if not found in handle table, call FS_EnumerateHandle to get file path.
ifsreq ifsr;
memcpy( &ifsr, pir, sizeof(ifsreq));
ifsr.ifsir.ir_flags = bFindHandle ? ENUMH_GETFINDINFO : ENUMH_GETFILENAME;
ifsr.ifsir.ir_ppath = pPPath;
pIFSFunc enumFunc = ifsr.ifs_hndl->hf_misc->hm_func[HM_ENUMHANDLE]; //get address of FS_EnumerateHandle from struct hndlfunc.
if((*PrevHookProc)(enumFunc, IFSFN_ENUMHANDLE, Drive, ResType, CodePage,(pioreq) &ifsr)!= ERROR_SUCCESS) return FALSE;
return TRUE;
}
void SetLastError(WORD errorCode)
{
lastError=errorCode;
}
WORD GetLastError()
{
return lastError;
}
UINT refData;
SHELLMessage_THUNK thunk;
//Gobal error handler for device:
//err: error code. severity: 0 means a fatal error, 1 a minor one.
//return value: 0 ---the moduel where the error occurs must stop processing.
// 1 ---processing can go on.
int ErrorHandler(unsigned int err, int severity/*=1*/)
{
ShellPostError(err,severity);
return 1;
}
//Callback function for user's response of shell_message.
void __stdcall MsgCallBack(DWORD ResponseCode,PVOID Refdata)
{
switch(*((UINT *)Refdata))
{
case ON_MSG_FILE_NOT_FOUND:
if(ResponseCode==IDNO)
ShellUnloadDevice(); //call on FileGuard win32 GUI to stop protection.
break;
}
}
//Read protected file information:
//DO NOT call this function from within HookProc.
BOOL ReadProtectedFileInfo(char *pFileName)
{
//Prevent reentry:
bBusy=TRUE;
HANDLE hIniFile;
WORD error;
BYTE action;
hIniFile=R0_OpenCreateFile(TRUE,pFileName,OPEN_ACCESS_READONLY|OPEN_SHARE_COMPATIBLE|OPEN_FLAGS_COMMIT,ATTR_NORMAL,ACTION_IFEXISTS_OPEN|ACTION_IFNOTEXISTS_FAIL,R0_NO_CACHE,&error,&action);
if(error!=ERROR_SUCCESS)
{
ErrorHandler(FG_ERR_INI_FILE_NOT_FOUND);
return FALSE;
}
//INI file format: each record consist of a '@' followed by length of the path
//(4 char, including a whitespace),a '#' followed by protection type(3 char,
//including a whitespace) and anther '#' followed
//by the path of a file under protection.
const UINT BYTES_TO_READ=MAX_PATH*5;
char buf[BYTES_TO_READ+1];
char path[MAX_PATH+1];
UINT offset=0;
do
{
BYTE nBytesRead=0;
for(int i=0;i<=BYTES_TO_READ;i++) buf[i]=0;
nBytesRead=R0_ReadFile(FALSE,hIniFile,buf,BYTES_TO_READ,offset,&error);
if(nBytesRead==0) break;
if(error!=ERROR_SUCCESS)
continue;
UINT pos=0;
//find first '@':
while(*(buf+pos)!='@' && pos<=BYTES_TO_READ-1)
pos++;
offset+=pos;
do
{
PROTECTED_FILE protFile;
if(StringToFileInfo(buf+pos, &protFile,path)!=1)
break; //not more record in the string. Go on to read next.
else
{
pos+=(strlen(path)+RECORD_LEN);
offset+=(strlen(path)+RECORD_LEN); //make sure offset is always pointing to the beginning of a new record.
#ifdef DEBUG
dout <<path<<endl;
#endif
protFileList.Add(&protFile);
}
}
while(1);
}
while(1);
R0_CloseFile(hIniFile,&error);
bBusy=FALSE;
return TRUE;
}
//save protected file information.
//DO NOT call this function from within HookProc.
BOOL SaveProtectedFileInfo(char *pFileName) //debug: unreferrence function.
{
//Prevent reentry:
bBusy=TRUE;
HANDLE hIniFile;
WORD error;
BYTE action;
hIniFile=R0_OpenCreateFile(TRUE,pFileName,OPEN_ACCESS_WRITEONLY|OPEN_SHARE_COMPATIBLE|OPEN_FLAGS_COMMIT,ATTR_NORMAL,ACTION_IFNOTEXISTS_CREATE|ACTION_IFEXISTS_TRUNCATE,R0_NO_CACHE,&error,&action);
if(error!=ERROR_SUCCESS)
{
ErrorHandler(FG_ERR_CANNOT_MAKE);
#ifdef DEBUG
dout << "Save file list: can't open file." << endl;
#endif
return FALSE;
}
//INI file format: each record consist of a '@' followed by length of the path
//(4 char, including a whitespace),a '#' followed by protection type(3 char,
//including a whitespace) and anther '#' followed
//by the path of a file under protection.
PROTECTED_FILE *pProtFile;
char *buf=(char *)malloc(MAX_PATH+15);
UINT offset=0;
if((pProtFile=protFileList.FindFirst())!=NULL)
{
UINT stringLen=sprintf(buf,"@ %3u, %2u,%s\0\n",strlen(pProtFile->PF_pPath),pProtFile->PF_type,pProtFile->PF_pPath);
stringLen++; //add the final char '\0'.
if((stringLen>R0_WriteFile(FALSE, hIniFile, buf, stringLen, offset, &error)) || error!=ERROR_SUCCESS)
{
ErrorHandler(FG_ERR_CANNOT_WRITE_RECORD);
#ifdef DEBUG
dout << "Save file list: can't write an record." << endl;
#endif
}
else offset+=stringLen; //writing success.
}
else //if not item found
{
R0_CloseFile(hIniFile, &error);
free(buf);
return TRUE;
}
while((pProtFile=protFileList.FindNext())!=NULL)
{
UINT stringLen=sprintf(buf,"@ %3u, %2u,%s\0\n",strlen(pProtFile->PF_pPath),pProtFile->PF_type,pProtFile->PF_pPath);
stringLen++; //add the final char '\0'.
if((stringLen>R0_WriteFile(FALSE, hIniFile, buf, stringLen, offset, &error)) || error!=ERROR_SUCCESS)
{
ErrorHandler(FG_ERR_CANNOT_WRITE_RECORD);
#ifdef DEBUG
dout << "Save file list: can't write an record." << endl;
#endif
}
else offset+=stringLen; //writing success.
}
R0_CloseFile(hIniFile, &error);
free(buf);
bBusy=FALSE;
return TRUE; //end of list.
}
//call for win32 GUI to stop protection.
BOOL ShellUnloadDevice()
{
if(!hAppWnd)
return FALSE;
return SHELL_PostMessage(hAppWnd, SM_DEVICE_FATAL_ERROR, 0, 0, 0, 0);
}
//Post errer code to win32 app.
BOOL ShellPostError(DWORD err, int severity)
{
if(!hAppWnd)
return FALSE;
return SHELL_PostMessage(hAppWnd, SM_DEVICE_ERROR, (WORD)severity, err, 0, 0); //Error message sended to win32 app.
//wParam is severity, lParam is error code.
}
int wstrlen(unsigned short *uniString)
{
int i = 0;
int len = 0;
while( uniString[i++] != 0 ) len+=2;
return len;
}
//Make characters in a wide character string to upper case.
//Return Value: string length.
int StringUpper(WCHAR *s, int len)
{
int i=-1;
while(++i<=len)
if(s[i]>='a' && s[i]<='z')
s[i]-=32;
return i;
}
//Convert BCS path to file system device's Canonicalized Path.
BOOL BCSToFSDPath(FSD_PATH *fp, const char *pBCSPath)
{
fp->ppath=(struct ParsedPath *)malloc((strlen(pBCSPath)+1)*sizeof(WCHAR));
if(!fp->ppath) return FALSE;
fp->flag=0;
fp->drive=pBCSPath[0]-'A'+1; //used first character as drive volume.
//i: index; prefix: prefix in parsed element(pe_length); elemLength: length of an element;
unsigned int i=3,prefix=4, elemLength=0, totalLenghth=0;
_QWORD res;
do
{
if(*(pBCSPath+i)=='\\')
{
BCSToUni((WCHAR *)((char *)fp->ppath+prefix+sizeof(WCHAR)), (PUCHAR)pBCSPath+i-elemLength, elemLength, BCS_OEM, &res);
*(short *)((char*)fp->ppath+prefix)=sizeof(WCHAR)+res.ddLower; //set pe_length.
totalLenghth+=*((char*)fp->ppath+prefix);
prefix+=*((char*)fp->ppath+prefix); //pointing to current '\' (pe_length).
elemLength=0;
i++;
continue;
}
else if(*(pBCSPath+i)=='*')
fp->flag|=FG_FILE_FLAG_HAS_STAR;
else if(*(pBCSPath+i)=='?')
fp->flag|=FG_FILE_FLAG_HAS_QUERYMARK;
elemLength++;
i++;
}
while(*(pBCSPath+i));
BCSToUni((WCHAR *)((char *)fp->ppath+prefix+sizeof(WCHAR)), (PUCHAR)pBCSPath+i-elemLength, elemLength, BCS_OEM, &res);
*(short *)((char*)fp->ppath+prefix)=sizeof(WCHAR)+res.ddLower; //set pe_length for last element.
totalLenghth+=*((char*)fp->ppath+prefix);
fp->ppath->pp_totalLength=2*sizeof(WCHAR)+totalLenghth; //set total length.
fp->ppath->pp_prefixLength=prefix; //pointing to last path element.
*(short *)((char *)fp->ppath+fp->ppath->pp_totalLength)=NULL;
return TRUE;
}
//Compare two parsed element.
BOOL _inline ElementMatch(PathElement *pPattern, PathElement *pMatcher, int flag)
{
if(!(flag&FG_FILE_FLAG_HAS_STAR) && pPattern->pe_length!=pMatcher->pe_length) //if pattern has not stars, and lengths don't equal, then match fail.
return FALSE;
return PatternMatch((WCHAR *)pPattern->pe_unichars, (WCHAR *)pMatcher->pe_unichars, pPattern->pe_length/sizeof(WCHAR)-1, pMatcher->pe_length/sizeof(WCHAR)-1);
}
//Compare two FSD_PATH struct.
BOOL _inline FSDPathMatch(FSD_PATH *pPattern, FSD_PATH *pMatcher)
{
//compare path.
if((pPattern->drive!=pMatcher->drive) || (!(pPattern->flag&FG_FILE_FLAG_HAS_STAR) && pPattern->ppath->pp_totalLength!=pMatcher->ppath->pp_totalLength))
return FALSE;
PathElement *ppe, *mpe;
ppe=pPattern->ppath->pp_elements;
mpe=pMatcher->ppath->pp_elements;
while(ppe->pe_length)
{
//compare each parsed element.
if(!ElementMatch(ppe, mpe, pPattern->flag))
return FALSE;
ppe=IFSNextElement(ppe);
mpe=IFSNextElement(mpe);
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -