打開被獨(dú)占的文件方法_第1頁
打開被獨(dú)占的文件方法_第2頁
打開被獨(dú)占的文件方法_第3頁
打開被獨(dú)占的文件方法_第4頁
打開被獨(dú)占的文件方法_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、打開被獨(dú)占的文件方法(一)-尋找打開文件的句柄打開被獨(dú)占的文件方法:被占用文件操作三法無疑我們中的很多人都會(huì)遇到需要讀寫被其它進(jìn)程占用的文件的情況,比如說在編寫backup程序或是trojan的時(shí)候。能從系統(tǒng)中抽出SAM文件,或是讀取其它某些用標(biāo)準(zhǔn)方法無法成功訪問的文件顯然是件不錯(cuò)的事情。比如說當(dāng)用標(biāo)志dwShareMode=0打開文件時(shí),其它進(jìn)程就不能對(duì)它進(jìn)行訪問了。一個(gè)很好的例子就是網(wǎng)絡(luò)尋呼機(jī)程序Miranda。這個(gè)程序在自己工作的時(shí)候不允許別人打開自己的數(shù)據(jù)庫。假設(shè)我們需要寫一個(gè)這樣的木馬,它在感染機(jī)器后從數(shù)據(jù)庫中竊走密碼,然后刪除自身,這個(gè)時(shí)候就需要解決這個(gè)問題。所以我決定寫下這篇文章

2、。文章篇幅不大,但里面的內(nèi)容可能會(huì)對(duì)某些人有益。那我們就開始吧。尋找打開文件的句柄如果文件由某個(gè)進(jìn)程打開,那么這個(gè)進(jìn)程就擁有了它的句柄。在我第二篇關(guān)于API攔截的文章里我講解了如何搜索需要的句柄并用它打開進(jìn)程,要訪問已打開的文件,我們也可以使用這種方法。我們需要使用ZwQuerySystemlnformation函數(shù)來枚舉句柄,將每一個(gè)句柄都用DuplicateHandle進(jìn)行復(fù)制,確定句柄屬于那個(gè)文件(ZwQueryInformationFile),女口果是要找的文件,就將句柄拷貝。這些在理論上都講得通,但在實(shí)踐中會(huì)遇到兩處難點(diǎn)。第一,在對(duì)打開的namedpipe(工作于blockmode)

3、的句柄調(diào)用ZwQueryInformationFile的時(shí)候,調(diào)用線程會(huì)等待pipe中的消息,而pipe中卻可能沒有消息,也就是說,調(diào)用ZwQueryInformationFile的線程實(shí)際上永久性地掛起了。所以命名文件的獲取不用在挑選句柄的主線程中進(jìn)行,可以啟動(dòng)獨(dú)立的線程并設(shè)置一個(gè)timeout值來避免掛起。第二,在拷貝句柄后,兩個(gè)句柄(我們進(jìn)程的和打開文件進(jìn)程的)將會(huì)指向同一個(gè)FileObject,從而當(dāng)前的輸入輸出模式、在文件中的位置以及其它與文件相關(guān)的信息就會(huì)由兩個(gè)進(jìn)程來共享。這時(shí),甚至只是讀取文件都會(huì)引起讀取位置的改變,從而破壞了打開文件程序的正常運(yùn)行。為了避免這種情形,我們需要需要

4、停止占用文件進(jìn)程的線程、保存當(dāng)前位置、拷貝文件、恢復(fù)當(dāng)前位置以及重新啟動(dòng)占用文件的進(jìn)程。這種方法不能用于許多情形,比如要在運(yùn)行的系統(tǒng)中拷貝注冊(cè)表文件,用這種方法就不會(huì)成功。我們先來試著實(shí)現(xiàn)對(duì)系統(tǒng)中所有已打開文件的句柄的枚舉。為枚舉句柄,每個(gè)句柄都由以下結(jié)構(gòu)體描述:typedefstruct_SYSTEM_HANDLEULONGuIdProcess;UCHARObjectType;UCHARFlags;USHORTHandle;POBJECTpObject;ACCESS_MASKGrantedAccess;SYSTEM_HANDLE,*PSYSTEM_HANDLE;這里的ObjectType域定

5、義了句柄所屬的對(duì)象類型。這里我們又遇到了問題一一File類型的ObjectType在Windows2000、XP和2003下的取值各不相同,所以我們不得不動(dòng)態(tài)的定義這個(gè)值。為此我們用CreateFile來打開NUL設(shè)備,找到它的句柄并記下它的類型:UCHARGetFileHandleType()HANDLEhFile;PSYSTEM_HANDLE_INFORMATIONInfo;ULONGr;UCHARResult=0;hFile=CreateFile(NUL,GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);if(hFile!=INVALID_HANDLE_VAL

6、UE)Info=GetInfoTable(SystemHandleInformation);if(Info)for(r=0;ruCount;r+)if(Info-aSHr.Handle=(USHORT)hFile&Info-aSHr.uldProcess=GetCurrentProcessld()Result=Info-aSHr.ObjectType;break;HeapFree(hHeap,0,Info);CloseHandle(hFile);returnResult;現(xiàn)在知道了句柄的類型我們就可以枚舉系統(tǒng)中打開的文件了。首先我們來用句柄獲取打開文件的文件名:typedefstruct_NM

7、_INFOHANDLEhFile;FILE_NAME_INFORMATIONInfo;WCHARNameMAX_PATH;NM_INFO,*PNM_INFO;DWORDWINAPIGetFileNameThread(PVOIDlpParameter)PNM_INFONmInfo=lpParameter;IO_STATUS_BLOCKIoStatus;intr;NtQueryInformationFile(Nmlnfo-hFile,&loStatus,&Nmlnfo-lnfo,sizeof(NM_INFO)-sizeof(HANDLE),FileNamelnformation);return0;

8、voidGetFileName(HANDLEhFile,PCHARTheName)HANDLEhThread;PNM_INFOInfo=HeapAlloc(hHeap,0,sizeof(NM_INFO);Info-hFile=hFile;hThread=CreateThread(NULL,0,GetFileNameThread,Info,0,NULL);if(WaitForSingleObject(hThread,INFINITE)=WAIT_TIMEOUT)TerminateThread(hThread,0);CloseHandle(hThread);memset(TheName,0,MAX

9、_PATH);WideCharToMultiByte(CP_ACP,0,Info-lnfo.FileName,Info-Info.FileNameLength1,TheName,MAX_PATH,NULL,NULL);HeapFree(hHeap,0,Info);現(xiàn)在來枚舉打開的文件:voidmain()PSYSTEM_HANDLE_INFORMATIONInfo;ULONGr;CHARNameMAX_PATH;HANDLEhProcess,hFile;hHeap=GetProcessHeap();ObFileType=GetFileHandleType();Info=GetInfoTable

10、(SystemHandleInformation);if(Info)for(r=0;ruCount;r+)if(Info-aSHr.ObjectType=ObFileType)hProcess=OpenProcess(PROCESS_DUP_HANDLE,FALSE,Info-aSHr.uldProcess);if(hProcess)if(DuplicateHandle(hProcess,(HANDLE)Info-aSHr.Handle,GetCurrentProcess(),&hFile,0,FALSE,DUPLICATE_SAME_ACCESS)GetFileName(hFile,Name

11、);printf(%sn,Name);CloseHandle(hFile);CloseHandle(hProcess);HeapFree(hHeap,0,Info);現(xiàn)在對(duì)于文件的拷貝我們剩下的工作只是找到所需句柄后用ReadFile讀取它。這里一定要使用前面提到的機(jī)制,不可疏忽。這種方法的優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單,但是其缺點(diǎn)更多,所以這個(gè)方法只適用于確定文件被那個(gè)進(jìn)程占用。打開被獨(dú)占的文件方法(二)-修改句柄訪問權(quán)限修改句柄訪問權(quán)限所有被占用的文件通常都可以用讀屬性(FILE_READ_ATTRIBUTES)打開,這樣就可以讀取文件的屬性,取得它的大小,枚舉NTSFstream,但遺憾的是,ReadF

12、ile就不能成功調(diào)用了。打開文件時(shí)各種訪問屬性的區(qū)別在哪里呢?顯然,打開文件時(shí),系統(tǒng)會(huì)記錄訪問屬性,之后會(huì)用這個(gè)屬性與請(qǐng)求的訪問作比較。如果找到了系統(tǒng)保存這個(gè)屬性的位置并修該掉它,那就不只可以讀取,甚至可以寫入任何已打開的文件。在用戶這一級(jí)別上我們并不是直接與文件打交道,而是通過它的句柄(這個(gè)句柄指向FileObject),而函數(shù)ReadFile/WriteFile調(diào)用ObReferenceObjectByHandle,并指明了相應(yīng)的訪問類型。由此我們可以得出結(jié)論,訪問權(quán)限保存在描述句柄的結(jié)構(gòu)體里。實(shí)際上,HANDLE_TABLE_ENTRY結(jié)構(gòu)體包含有一個(gè)GrantedAccess域,這個(gè)域

13、不是別的,就是句柄的訪問權(quán)限。遺憾的是,Microsoft的程序員們沒有提供修改句柄訪問權(quán)的API,所以我們不得不編寫驅(qū)動(dòng)自己來做這項(xiàng)工作。我在隱藏進(jìn)程檢測(cè)一文中講到過Windows2000和XP的句柄表結(jié)構(gòu)體,我想補(bǔ)充的只有一點(diǎn),就是Windows2003中的句柄表與XP的完全一樣。與那篇文章不同,我們這里不需要枚舉表中的句柄,而只需要找到某個(gè)具體的(已知的)句柄,我們不用管PspCidTable,而只操作自己進(jìn)程的句柄表,表的指針位于進(jìn)程的EPROCESS結(jié)構(gòu)體里(2000下的偏移為0 x128,XP下的為0 x0C4)。為了取得句柄結(jié)構(gòu)體指針需要調(diào)用未導(dǎo)出函數(shù)ExpLookupHandl

14、eTableEntry,但我們不會(huì)去搜索它,因?yàn)樵趯?dǎo)出函數(shù)中沒有對(duì)它的直接引用,搜索結(jié)果也很不可靠,除此之外我們此時(shí)還需要ExUnlockHandleTableEntry函數(shù)。最好的辦法就是編寫自己的句柄表lookup函數(shù)??紤]到Windows2000與XP下句柄表的差異,我們將編寫不同的函數(shù)。首先是Windows2000下的:PHANDLE_TABLE_ENTRYWin2kLookupHandleTableEntry(INPWIN2K_HANDLE_TABLEHandleTable,INEXHANDLEHandle)ULONGi,j,k;i=(Handle.lndex16)&255;j=(H

15、andle.lndex8)&255;k=(Handle.lndex)&255;if(HandleTable-Tablei)if(HandleTable-Tableij)return&(HandleTable-Tableijk);returnNULL;這段代碼簡(jiǎn)單易懂。因?yàn)榫浔闹当旧硎莻€(gè)三維表的三個(gè)索引,所以我們只需其中的各個(gè)部分并查看表中相應(yīng)的元素(當(dāng)然如果存在的話)。因?yàn)閃indowsXP中的句柄表可以有一到三個(gè)級(jí)別,所以相應(yīng)的lookup代碼就要更為復(fù)雜一些:PHANDLE_TABLE_ENTRYXpLookupHandleTableEntry(INPXP_HANDLE_TABLEHan

16、dleTable,INEXHANDLEHandle)ULONGi,j,k;PHANDLE_TABLE_ENTRYEntry=NULL;ULONGTableCode=HandleTable-TableCode&TABLE_LEVEL_MASK;p;i=(Handle.Index17)&0 x1FF;j=(Handle.lndex9)&0 x1FF;k=(Handle.Index)&0 x1FF;switch(HandleTable-TableCode&TABLE_LEVEL_MASK)case0:Entry=&(PHANDLE_TABLE_ENTRY)TableCode)k;break;case

17、1:if(PVOID*)TableCode)j)Entry=&(PHANDLE_TABLE_ENTRY*)TableCode)jk;break;case2:if(PVOID*)TableCode)i)if(PVOID*)TableCode)ij)Entry=&(PHANDLE_TABLE_ENTRY*)TableCode)ijk;break;returnEntry;我們看到,這段代碼中的句柄并不是ULONG型的值,而是EXHANDLE結(jié)構(gòu)體:typedefstruct_EXHANDLEunionstructULONGTagBits:02;ULONGIndex:30;HANDLEGenericH

18、andleOverlay;EXHANDLE,*PEXHANDLE;我們看到,句柄不知包含了表的索引,還包含了一個(gè)2bit的標(biāo)志。您可能已經(jīng)察覺到,一個(gè)句柄可以有著幾種不同的意義,這一點(diǎn)與這樣一個(gè)事實(shí)有關(guān),那就是并非句柄中所有的位都被使用到(依賴于在表中的級(jí)別)。這是WindowsXP最具個(gè)性的特點(diǎn)?,F(xiàn)在我們就可以獲取句柄表中所需的元素了,該編寫為句柄設(shè)置所需訪問屬性的函數(shù)了:BOOLEANSetHandleAccess(INHANDLEHandle,INACCESS_MASKGrantedAccess)PHANDLE_TABLEObjectTable=*(PHANDLE_TABLE*)RVAT

19、OVA(PsGetCurrentProcess(),ObjectTableOffset);PHANDLE_TABLE_ENTRYEntry;EXHANDLEExHandle;ExHandle.GenericHandleOverlay=Handle;Entry=ExLookupHandleTableEntry(ObjectTable,ExHandle);if(Entry)Entry-GrantedAccess=GrantedAccess;returnEntry0;現(xiàn)在編寫驅(qū)動(dòng),設(shè)置句柄的訪問屬性,通過DeviceIoControl向驅(qū)動(dòng)傳遞句柄。代碼如下:NTSTATUSDriverIoCont

20、rol(INPDEVICE_OBJECTDeviceObject,INPIRPIrp)PIO_STACK_LOCATIONpisl=loGetCurrentlrpStackLocation(Irp);NTSTATUSstatus=STATUS_UNSUCCESSFUL;ULONGBuffSize=pisl-Parameters.DeviceloControl.InputBufferLength;PUCHARpBuff=lrp-Associatedlrp.SystemBuffer;HANDLEHandle;ACCESS_MASKGrantedAccess;Irp-IoStatus.Informa

21、tion=0;switch(pisl-Parameters.DeviceloControl.IoControlCode)caseIOCTL1:if(pBuff&BuffSize=sizeof(HANDLE)+sizeof(ACCESS_MASK)Handle=*(HANDLE*)pBuff;GrantedAccess=*(ACCESS_MASK*)(pBuff+sizeof(HANDLE);if(Handle!=(HANDLE)-1&SetHandleAccess(Handle.GrantedAccess)status=STATUS_SUCCESS;break;Irp-IoStatus.Sta

22、tus=status;IoCompleteRequest(Irp,IO_NO_INCREMENT);returnstatus;NTSTATUSDriverCreateClose(INPDEVICE_OBJECTDeviceObject,INPIRPIrp)Irp-IoStatus.Information=0;Irp-IoStatus.Status=STATUS_SUCCESS;IoCompleteRequest(Irp,IO_NO_INCREMENT);returnSTATUS_SUCCESS;NTSTATUSDriverEntry(INPDRIVER_OBJECTDriverObject,I

23、NPUNICODE_STRINGRegistryPath)PCWSTRdDeviceName=LDevicefread;PCWSTRdSymbolicLinkName=LDosDevicesfread;NTSTATUSstatus;PDRIVER_DISPATCH*ppdd;RtllnitUnicodeString(&DeviceName,dDeviceName);RtllnitUnicodeString(&SymbolicLinkName,dSymbolicLinkName);switch(*NtBuildNumber)case2600:ObjectTableOffset=0 x0C4;Ex

24、LookupHandleTableEntry=XpLookupHandleTableEntry;break;case2195:ObjectTableOffset=0 x128;ExLookupHandleTableEntry=Win2kLookupHandleTableEntry;break;default:returnSTATUS_UNSUCCESSFUL;status=IoCreateDevice(DriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,0,TRUE,&deviceObject);if(NT_SUCCESS(status)status=

25、IoCreateSymbolicLink(&SymbolicLinkName,&DeviceName);if(!NT_SUCCESS(status)IoDeleteDevice(deviceObject);DriverObject-DriverUnload=DriverUnload;ppdd=DriverObject-MajorFunction;ppddIRP_MJ_CREATE=ppddIRP_MJ_CLOSE=DriverCreateClose;ppddIRP_MJ_DEVICE_CONTROL=DriverIoControl;returnstatus;遺憾的是句柄結(jié)構(gòu)體中的Granted

26、Access域并沒有和文件打開的屬性(GENERIC_READ、GENERIC_WRITE等)對(duì)應(yīng)起來,所以在設(shè)置新的屬性時(shí)我們需要以下constants:#defineAC_GENERIC_READ0 x120089#defineAC_GENERIC_WRITE0 x120196#defineAC_DELETE0 x110080#defineAC_READ_CONTROL0 x120080#defineAC_WRITE_DAC0 x140080#defineAC_WRITE_OWNER0 x180080#defineAC_GENERIC_ALL0 x1f01ff#defineAC_STAND

27、ARD_RIGHTS_ALL0 x1f0080為了使用這個(gè)驅(qū)動(dòng)將SAM文件拷貝到c盤根目錄,我們可以寫一個(gè)最簡(jiǎn)單的程序:#include#includehchange.hBOOLEANSetHandleAccess(HANDLEHandle,ACCESS_MASKGrantedAccess)HANDLEhDriver;ULONGBytes;ULONGBuff2;BOOLEANResult=FALSE;hDriver=CreateFile(.haccess,GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);if(hDriver!=INVALID_HANDLE_VALU

28、E)Buff0=(ULONG)Handle;Buff1=GrantedAccess;Result=DeviceIoControl(hDriver,IOCTL1,Buff,sizeof(Buff),NULL,0,&Bytes,NULL);CloseHandle(hDriver);voidmain()HANDLEhFile,hDest;ULONGSize,Bytes;PVOIDData;CHARNameMAX_PATH;GetSystemDirectory(Name,MAX_PATH);lstrcat(Name,WconfigSAM);hFile=CreateFile(Name,FILE_READ

29、_ATTRIBUTES,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,0,0);if(hFile!=INVALID_HANDLE_VALUE)if(SetHandleAccess(hFile,AC_GENERIC_READ)Size=GetFileSize(hFile,NULL);Data=VirtualAlloc(NULL,Size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);if(Data)ReadFile(hFile,Data,Size,&Bytes,NULL)

30、;hDest=CreateFile(c:SAM,GENERIC_WRITE,0,NULL,CREATE_NEW,0,0);if(hDest!=INVALID_HANDLE_VALUE)WriteFile(hDest,Data,Size,&Bytes,NULL);CloseHandle(hDest);VirtualFree(Data,0,MEM_RELEASE);CloseHandle(hFile);這個(gè)方法最大的缺陷就是強(qiáng)烈依賴于操作系統(tǒng),而且還需要加載驅(qū)動(dòng)程序,而這并不總是能實(shí)現(xiàn)的。但是從可靠性上來看,這種方法是最好的,所以我建議將其用在backup程序中(只是要經(jīng)過長(zhǎng)期的測(cè)試和調(diào)試!)。因

31、為這種方法有不能勝任的情形,我們轉(zhuǎn)入下一種方法。打開被獨(dú)占的文件方法(三)-使用直接硬盤訪問讀取文件使用直接硬盤訪問讀取文件直接訪問硬盤”這個(gè)想法當(dāng)然很酷,但很快DOS編程愛好者們就會(huì)失望,這里沒有硬件操作,因?yàn)槲④浐荜P(guān)心我們的疾苦,提供了方便簡(jiǎn)單的API,通過這些API可以幾乎直接地操作硬盤。這樣大家就明白了吧,實(shí)際上我們是想以RAW模式打開volume,并按cluster來讀取文件。希望大家沒有被嚇到:)如果直接入手解決這個(gè)問題,就需要手動(dòng)地分析文件系統(tǒng)結(jié)構(gòu),這樣我們就需要編寫很多多余的代碼,所以我們不會(huì)這樣去做,而是再一次參考微軟偉大的手冊(cè)一一MSDN。DefragmentingFile

32、s和DiskManagementControlCodes部分對(duì)于我們來說非常有用,那里面有文件系統(tǒng)驅(qū)動(dòng)的控制代碼,這些代碼可以用在各種磁盤整理程序中。打開MSDN,無疑會(huì)發(fā)現(xiàn),使用IOCTL代碼FSCTL_GET_RETRIEVAL_POINTERS可以獲取文件分配圖。也就是說我們只需要借助于這個(gè)IOCTL就可以獲取被占用文件的clusterlist并進(jìn)行讀取。用此代碼調(diào)用DeviceIoControl時(shí),InputBuffer應(yīng)該包含有STARTING_VCN_INPUT_BUFFER結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體描述了文件cluster鏈的首元素,函數(shù)成功執(zhí)行后,OutputBuffer將裝有RETR

33、IEVAL_POINTERS_BUFFER結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體描述了分配圖。我們來詳細(xì)地看一下這個(gè)結(jié)構(gòu)體:typedefstructLARGE_INTEGERStartingVcn;STARTING_VCN_INPUT_BUFFER,*PSTARTING_VCN_INPUT_BUFFER;typedefstructRETRIEVAL_POINTERS_BUFFERDWORDExtentCount;LARGE_INTEGERStartingVcn;structLARGE_INTEGERNextVcn;LARGE_INTEGERLcn;Extents1;RETRIEVAL_POINTERS_BUFF

34、ER,*PRETRIEVAL_POINTERS_BUFFER;第一個(gè)結(jié)構(gòu)體很容易懂,我們只需要向StartingVcn.QuadPart傳遞0,而第二個(gè)結(jié)構(gòu)體的格式需要好好研究一下。第一個(gè)域(ExtentCount)包含著結(jié)構(gòu)體中Extents元素的數(shù)目。StartingVcn文件第一個(gè)cluster鏈的鏈號(hào)。每一個(gè)Extents元素都包含有一個(gè)NextVcn,其含有鏈中cluser的數(shù)目,而Lcn其第一個(gè)cluster的cluster號(hào)。也就是說所返回的信息就是cluster鏈的描述符,其中每一個(gè)鏈都包含有某些個(gè)cluster?,F(xiàn)在返回信息的結(jié)構(gòu)體的含義就已經(jīng)明了了,到了編寫函數(shù)的時(shí)候了,這

35、個(gè)函數(shù)獲取文件完整的clusterlist并將其整理為數(shù)組形式。ULONGLONG*GetFileClusters(PCHARlpFileName,ULONGClusterSize,ULONG*ClCount,ULONG*FileSize)HANDLEhFile;ULONGOutSize;ULONGBytes,Cls,CnCount,r;ULONGLONG*Clusters=NULL;BOOLEANResult=FALSE;LARGE_INTEGERPrevVCN,Lcn;STARTING_VCN_INPUT_BUFFERInBuf;PRETRIEVAL_POINTERS_BUFFEROutB

36、uf;hFile=CreateFile(lpFileName,FILE_READ_ATTRIBUTES,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,0,0);if(hFile!=INVALID_HANDLE_VALUE)*FileSize=GetFileSize(hFile,NULL);OutSize=sizeof(RETRIEVAL_POINTERS_BUFFER)+(*FileSize/ClusterSize)*sizeof(OutBuf-Extents);OutBuf=malloc(OutSi

37、ze);InBuf.StartingVcn.QuadPart=0;if(DeviceIoControl(hFile,FSCTL_GET_RETRIEVAL_POINTERS,&lnBuf,sizeof(InBuf),OutBuf,OutSize,&Bytes,NULL)*ClCount=(*FileSize+ClusterSize-1)/ClusterSize;Clusters=malloc(*CICount*sizeof(ULONGLONG);PrevVCN=OutBuf-StartingVcn;for(r=0,Cls=0;rExtentCount;r+)Lcn=OutBuf-Extents

38、r.Lcn;for(CnCount=OutBuf-Extentsr.NextVcn.QuadPart-PrevVCN.QuadPart;CnCount;CnCount-,Cls+,Lcn.QuadPart+)ClustersCls=Lcn.QuadPart;PrevVCN=OutBuf-Extentsr.NextVcn;free(OutBuf);CloseHandle(hFile);returnClusters;函數(shù)完成后我們就得到了描述文件clusters的數(shù)組以及clusters的數(shù)目,現(xiàn)在可以很容易地拷貝文件了:voidFileCopy(PCHARlpSrcName,PCHARlpDstName)ULONGClusterSize,BlockSize;ULONGLONG*Clusters;ULONGClCount,FileSize,Bytes;HANDLEhDrive,hFile;ULONGSecPerCl,BtPer

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論