äžæ¹ã§ããããã¯å®éã«éåžžã«äŸ¿å©ãªæ å ±ã®ã¹ãã¬ãŒãžã§ããããã®å Žã§ããŒã¿ãå€æŽã§ããŸããä»æ¹ã§ã¯ããã®å©äŸ¿æ§ã¯ããŒã¿ãžã®ã¢ã¯ã»ã¹é床ã«ãã£ãŠéšåçã«å¹³æºåãããŸãã
äžè¬çã«ãéåžžã¯è€åãã¡ã€ã«ã¯äœã«äœ¿çšãããŸããïŒ
ç¹å®ã®ã³ã³ããïŒNoSQLãµãã»ããïŒã«ä¿åããå¿ èŠããããã¹ãŠã®ãã®ã
ããšãã°ã97ã2003ã®å€ãããŒãžã§ã³ã®Microsoft Officeã®ãã¡ã€ã«ïŒå®éã«ã¯æ°ååã®ãã¡ã€ã«ã§æ§æãããŠããŸãïŒã¯ãè€åãã¡ã€ã«ã«ä¿åãããŠããŸããã ããã§ãããããä¿åãããZIPã®ã¿ãã³ã³ãããšããŠäœ¿çšãããŸãã
MSIã€ã³ã¹ããŒã«ããã±ãŒãžãè€åãã¡ã€ã«ã§ãããThumbs.dbãã©ã«ããŒã®ãµã ãã€ã«ãã£ãã·ã¥ãã¡ã€ã«ããã®åœ¢åŒã䜿çšããŸãã
確ãã«ãåãWordã«ã¯ãç Žæããããã¥ã¡ã³ããå埩ããããŸãã¯å°ãªããšãå埩ããããšãããŠãŒãã£ãªãã£ïŒWordã®å埩ãWordå埩ããŒã«ããã¯ã¹ãMunsoft Easy Wordå埩ïŒããããŸãã ç¬èªã®çµè«ãåŒãåºãããšãã§ããŸãã
ãã ããè€åãã¡ã€ã«ãé©åã«åŠçããã°ããããã®æå·ã®åé¡ã解決ã§ããŸãïŒãããŠããã®æ¹æ³ã瀺ããŸãïŒã
ãããŠããã¡ããããã®åœ¢åŒã®ééããªãå©ç¹ã¯ããã¡ã€ã«ãšãã©ã«ããŒãåããæ¬æ Œçãªãã¡ã€ã«ã·ã¹ãã ãã¹ãã¬ãŒãžå ã§ãšãã¥ã¬ãŒããããããšã§ãã
ãšããã§ããã¥ã¢ã³ã¹ã èšäºãå§ããåã«ãããã€ãã®ãã©ãŒã©ã ã§èª¿æ»ãå®æœããŸããããã»ãšãã©ã®éçºè ã¯è€åãã¡ã€ã«ã䜿çšãããåçŽãªçç±ã§ããããäœã§ããããèããŸããã§ããã
ä»ããã®ã®ã£ãããåããŸãã
1.è€åãã¡ã€ã«ãšãã®äœæã«é¢ããäžè¬æ å ±
è€åãã¡ã€ã«ã®æ§é ãšå éšåœ¢åŒã«ã€ããŠã¯ããã«èª¬æããŸããããããã¯äžèŠã§ãã
æåã«ãããªãã¯ããããæãããå¿ èŠããããŸã-圌ãäœã«ã€ããŠãªã®ãã
ããã§ã¯ãStgCreateDocfileãåŒã³åºããŠæ°ããè€åãã¡ã€ã«ãäœæããããšããå§ããŸãããã
çšéã§ã¯ããã®ActiveXãšAxCtrlsã®ã«ããã«ãæ¥ç¶ããŸãïŒäŸ¿å©ã«ãªããŸãïŒã
ãããŠä»ãç§ãã¡ã¯æžããŸãïŒ
procedure CheckHResult(Code: HRESULT); begin if not Succeeded(Code) then RaiseLastOSError; end; var TestFilePath: string; WideBuff: WideString; Root: IStorage; begin TestFilePath := ExtractFilePath(ParamStr(0)) + '..\data\simple.bin'; ForceDirectories(ExtractFilePath(TestFilePath)); WideBuff := TestFilePath; CheckHResult(StgCreateDocfile(@WideBuff[1], STGM_CREATE or STGM_WRITE or STGM_SHARE_EXCLUSIVE, 0, Root));
ãŸããæã«æ³šæãæããŸãã
STGM_CREATEããã³STGM_WRITE-ããã2ã€ã®ãã©ã°ã¯æ°ããè€åãã¡ã€ã«ãäœæããããã«äœ¿çšããããã®å Žåã®STGM_WRITEãã©ã°ã®ååšã¯å¿ é ã§ãïŒããã§ãªãå Žåããã©ãŒã«ã¹ã¯æ©èœããŸããïŒã
éèŠïŒ
ãããã3çªç®ã®ãã©ã°STGM_SHARE_EXCLUSIVEã䜿çšãããšããã¹ãŠãéåžžã«è€éã«ãªããŸãã 2çªç®ã®ç« ã§èª¬æãããŠããããã«ãèªã¿åãå°çšã¢ãŒãã§ãã¡ã€ã«ãéãå Žåãé€ãããã®ååšã¯åžžã«å¿ èŠã§ãã
IDA Pro Freewareã§èªåã§ç¢ºèªã§ããŸãã
StgCreateDocfileã¯ãVerifyPermsãåŒã³åºãããDfOpenDocfileé¢æ°ãåŒã³åºããŸãããã®é¢æ°ã§ã¯ã次ã®ãããªãã§ãã¯ãè¡ãããŸãã

ã¢ãã¬ã¹72554E62ã§ã¯ããã®ãã©ã°ã®ååšããã§ãã¯ãããçªç¶æ€åºãããªãå Žåã¯ããšã©ãŒãéãããŸãã ãããã£ãŠãè€æ°åèšé²ããããã«è€åãã¡ã€ã«ãåæã«éãããšã¯çŠæ¢ãããŠããŸãã
3çªç®ã®ãªã³ã°ã§ãã®ãããªãã§ãã¯ãèŠãã®ã¯å°ãé©ãã§ãïŒå®éšçã«ïŒãããäžããåŸãåæã«2åé²é³ããããã«ãã¡ã€ã«ãéãããšãã§ããŸããã ããã-ãã¡ãããäž¡æ¹ã®ãã¡ã€ã«ã«æ£ããæžã蟌ãããšã¯ã§ããŸããã§ããã :)
å®éãããã¯ããŒã¿ã¹ãã¬ãŒãžåœ¢åŒãã®ãã®ã®ãããããªãæèœãªæ±ºå®ã§ãããèšäºã®çµããè¿ãã§ãå°ãåŸã§èª¬æããŸãã
ãã¹ãŠã®ãã§ãã¯ãæåããæ»ãã³ãŒãStgCreateDocfileãS_OKã§ããå Žåããã®é¢æ°ã®4çªç®ã®ãã©ã¡ãŒã¿ãŒã§ãIStorageã€ã³ã¿ãŒãã§ã€ã¹ã¯ãè€åãã¡ã€ã«ã®ã«ãŒãèŠçŽ ãæã瀺ããŠæ»ããŸãã
次ã«äœãã§ããŸããïŒ
ããšãã°ãã«ãŒãã«æ°ãããã¡ã€ã«ãäœæãïŒãŸã ãã¡ã€ã«ã·ã¹ãã ããããŸãïŒãããŒã¿ãããã¯ãæžã蟌ã¿ãŸãã
ãã®é¢æ°ãæžããŸãïŒ
procedure WriteFile(Storage: IStorage; AName: WideString; Data: AnsiString); var Stream: IStream; OS: TOleStream; begin CheckHResult(Storage.CreateStream(@AName[1], STGM_WRITE or STGM_SHARE_EXCLUSIVE, 0, 0, Stream)); OS := TOleStream.Create(Stream); try OS.WriteBuffer(Data[1], Length(Data)); finally OS.Free; end; end;
æåã«ãStorage.CreateStreamé¢æ°ãåŒã³åºããŠæ°ããããã¡ã€ã«ããäœæããŸãã ããã¯ã以åã«æ€èšããStgCreateDocfileãšã»ãŒåãã§ãããçµæãšããŠããã¡ã€ã«ã®ã³ã³ãã³ããåŠçãããIStreamã€ã³ã¿ãŒãã§ã€ã¹ãè¿ããŸã ã
ãã©ã°ã«æ³šæããŠãã ããïŒSTGM_SHARE_EXCLUSIVEãæå®ããå¿ èŠãããã2çªç®ïŒäœæããå ŽåïŒã¯STGM_WRITEãŸãã¯STGM_READWRITEã®ããããã§ãªããã°ãªããŸãããã è€åãã¡ã€ã«ã¯STGM_WRITEãã©ã°ã䜿çšããŠäœæãããŸãã-䜿çšãããŠããŸãã
䟿å®äžãIStreamã®åŠçã¯ãããŒã¿ãèšé²ããTOleStreamã¬ã€ã€ãŒã¯ã©ã¹ãä»ããŠå®è¡ãããŸãã
ãã¡ãããããã¯åççãªåé¡ã§ã¯ãªããISequentialStreamã€ã³ã¿ãŒãã§ã€ã¹ã®Writeé¢æ°ã®åŒã³åºãã䜿çšã§ããŸããISequentialStreamã€ã³ã¿ãŒãã§ã€ã¹ã®åå«ã¯IStreamã§ãããTOleStreamã¯ã©ã¹ã®æäœã¯ç°¡åã§ãã
åã«å®è£ ããé¢æ°ãåŒã³åºããŸãïŒ
WriteFile(Root, 'RootFile', 'First file data');
ãã®çµæãRootFileãšããååãšãæåã®ãã¡ã€ã«ããŒã¿ãã®å 容ãæã€ãã¡ã€ã«ãã«ãŒãã«è¡šç€ºãããŸãã
éèŠïŒ
ããã§1ã€ã®æ³šæç¹ããããŸãïŒè€åãã¡ã€ã«å ã®ãã¡ã€ã«ãšãã©ã«ããŒã®ååã¯ã31 Unicodeæåã®é·ããè¶ ããããšã¯ã§ããŸããïŒå®éã32æå以äžã§ããããŒãã®çµäºãå¿ããŠã¯ãªããŸããïŒã
ã¯ãããã®ããã«ããã©ã«ããŸãã¯ãã¡ã€ã«ãã123ããšåŒã¶ããšãã§ããŸããããç§ã®é·ããã¡ã€ã«åãšãã以äžã®æ°åããåŒã³åºãããšã¯ã§ããŸããã ããã«ãä»æ§äžãååã«äœ¿çšã§ããªãæåã®ã»ããããããŸãïŒ0ã0x1FïŒã
ããããããªãã¯èšãã ãã-ãªããã®ãããªå¶éãããã®ãââããããŠãã¹ãã®å·šå€§ãªæ·±ããæã€å·šå€§ãªåå²ãã¡ã€ã«ã·ã¹ãã ãå±éãããå Žåã¯ã©ãããã®ãïŒ
ãããã£ãŠãæšæºã®ãã¡ã€ã«å¶éãšã¯ç°ãªããMAX_PATHå®æ°ã¯åœ±é¿ããŸããã
ããã€ããã°ããŒã ããšããååã®500åã®ãµããã©ã«ããŒ
ç°¡åã§ãããä»®æ³ãã¡ã€ã«ã·ã¹ãã ã䜿çšããŠäœæ¥ããŸã-å¿ èŠãªããšãè¡ããŸãã :)
ã©ã ã«æ»ããŸããããã«ãŒãã«ãã©ã«ããŒãäœæããŸãã
CheckHResult(Root.CreateStorage('SubFolder', STGM_WRITE or STGM_SHARE_EXCLUSIVE, 0, 0, Folder));
ã³ãŒãã¯Storage.CreateStreamã®åŒã³åºããšã»ãšãã©åãã§ãããä»åã¯æ°ããäœæããããã©ã«ããŒãæãå¥ã®IStorageã€ã³ã¿ãŒãã§ã€ã¹ãååŸããŸãã
ããã«æ°ãããã¡ã€ã«ãäœæã§ããŸãïŒ
WriteFile(Folder, 'SubFolderFile', 'Second file data');
ãããè¡ãããã«ãæåã®ãã©ã¡ãŒã¿ãŒã¯ã«ãŒãã§ã¯ãªããã«ãŒããåç §ããŸãããäœæãããã°ããã®Forderã§ãã
éèŠïŒ
ãããŠä»ããã¥ã¢ã³ã¹ã¯ãä»ããã¢ããªã±ãŒã·ã§ã³ãéãããšãããŒã¿ãä¿åãããªãå ŽåããããŸãã
ããã§ã¯ãå®éããã¹ãŠãããã»ã©åçŽã§ã¯ãããŸãããããšãã°ãèªå® ã®ãã·ã³ã§ã¯ãã®åäœãåçŸãããããšãä¿èšŒãããŠããŸãããåäœããŠãããã·ã³ã§ã¯ãŸã£ããéã§ãã
ããŒã¿ã®ä¿åãä¿èšŒããã«ã¯ã次ã®ã³ãŒããå®è¡ããå¿ èŠããããŸãã
CheckHResult(Root.Commit(STGC_DEFAULT));
ãã®ã³ãŒããå®è¡ãããšããã¹ãŠã®ããŒã¿ããã£ã¹ã¯äžã®ãã¡ã€ã«ã«ä¿åãããããšãä¿èšŒãããŸãã ããŠãçªç¶ "çªç¶"æ°ãå€ãã£ãå Žåã¯ã次ã®ã³ãŒããåŒã³åºãããšã§ãååã®ã³ããã以éã«çºçãããã¹ãŠã®å€æŽãåãæ¶ãããšãã§ããŸãã
CheckHResult(Root.Revert);
ãšããã§ããã¡ã€ã«ãéããããšã«ã€ããŠã
ããã¯ãã«ãŒãã®éåžžã®ãããã¯è§£é€ã«ãã£ãŠè¡ãããŸãããã®åŸã@ IntfClearãã«ãŒãå€æ°ã®ã€ã³ã¿ãŒãã§ã€ã¹ã«å¯ŸããŠåŒã³åºããããšãä»ã®ãã¹ãŠã®ã€ã³ã¿ãŒãã§ã€ã¹ãéå±€é ã«ç Žæ£ãããŸãã
ä»ã«äœãæ®ã£ãŠããŸããïŒ
ããããã£ãšCopyTo / MoveElementTo / EnumElementsã¡ãœãããªã©...
ãããã«ã€ããŠã¯å°ãåŸã§èª¬æããŸãããä»ã®ãšããã¯ãèšäºã«æ·»ä»ãããã¢ãŒã«ã€ããéãããã¡ã€ã« ".. \ simple \ StorageCreateDemo.dpr"ã§äžèšã®ã³ãŒãã®å®è£ ã確èªã§ããŸãã
ä»ãç§ãã¡ã¯ãã®ãã¹ãŠã®åé¡ãèªã¿èŸŒãããšããŠããŸãã
2.è€åãã¡ã€ã«ã®èªã¿åã
æ°ãããããžã§ã¯ããäœæããActiveXãšAxCtrlsãå床æ¥ç¶ããŠãéå§ã³ãŒããèšè¿°ããŸãããã
var TestFilePath: string; WideBuff: WideString; Root: IStorage; begin TestFilePath := ExtractFilePath(ParamStr(0)) + '..\data\simple.bin'; WideBuff := TestFilePath; CheckHResult(StgOpenStorage(@WideBuff[1], nil, STGM_READ or STGM_SHARE_DENY_WRITE, nil, 0, Root));
æžã蟌ã¿ã¢ã¯ã»ã¹ãå¿ èŠãªããããSTGM_READãã©ã°ã䜿çšããŸããããã§ã¯ãSTGM_SHARE_DENY_WRITEã䜿çšããããSTGM_SHARE_EXCLUSIVEã®ãŸãŸã«ããããéžæã§ããŸãïŒ2ã€ã®ãã©ã°ã®ãããããå¿ èŠã§ãïŒã
ã³ãŒãå®è¡ã®çµæã¯ãã«ãŒããæãIStorageã¯ã©ã¹ã®ã«ãŒãå€æ°ã§ãã
ãã£ã¹ã¯äžã®æå®ããããã©ã«ããŒå ã®ãã¡ã€ã«ãã©ã®ããã«æ€çŽ¢ããŸããïŒ
åœç¶ãFindFirstFileã䜿çšããååž°çãªãã£ã¬ã¯ããªãã©ããŒãµã«ã
ãã®å Žåã䌌ããããªãã®ããããŸããããã¯IStorageã€ã³ã¿ãŒãã§ã€ã¹ã®EnumElementsã¡ãœããã§ãåŒã³åºãã¯æ¬¡ã®ããã«ãªããŸãã
var Enum: IEnumStatStg; begin CheckHResult(Storage.EnumElements(0, nil, 0, Enum));
倧ãŸãã«èšããšãããã¯FindFirstFileåŒã³åºãã«é¡äŒŒããŠããŸãããããã§ã¯ããã«åŠçããããã®ãã³ãã«ã§ã¯ãªããIEnumStatStgã€ã³ã¿ãŒãã§ã€ã¹ãååŸããŸãã
泚ç®ãã䟡å€ãããèå³æ·±ãç¹ã1ã€ãããŸãã
ãã®ã€ã³ã¿ãŒãã§ã€ã¹ïŒäœ¿çšããå ŽåïŒã¯TStatStgæ§é ãè¿ããŸãããã®ãã£ãŒã«ãã®1ã€ã¯ãã¿ã€ããPOleStrã§ããpwcsNameãã©ã¡ãŒã¿ãŒã«ãªããŸãã
ã·ã ã¹ã®ç¶æ³ãç解ããŠããŸããïŒ
ãã¡ãããOLEã¯ãã€ãã£ãã¡ã¢ãªãããŒãžã£ãŒã®ååšãèªèãããIMallocã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠç¬èªã®æ段ã§ãã®è¡ãæ ŒçŽããããã®ãããã¯ãå²ãåœãŠããããããã¯æœåšçãªã¡ã¢ãªã§ãã
ãã®ç¶æ³ãåŠçããªãå Žåãã¢ããªã±ãŒã·ã§ã³ã¡ã¢ãªã¯ãã¯ããªã¢ãã©ãŒã«ãºã®ããã«æµããŸãããã¡ã¢ãªæ¶è²»ã«ãŠã³ã¿ãèŠãã®ã¯æ¥œããã§ãããã :)
ãããã£ãŠãæåã«ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãžã®ãªã³ã¯ãååŸããå¿ èŠããããŸãïŒ
if (CoGetMalloc(1, ShellMalloc) <> S_OK) or (ShellMalloc = nil) then raise Exception.Create('CoGetMalloc failed.');
å²ãåœãŠãããã¡ã¢ãªã解æŸããããã«å¿ èŠã§ã¯ãããŸããã
ãã®ãããªãã®ïŒ
ShellMalloc.Free(TmpElement.pwcsName);
ããã«ããã1ã€ã®ãã¥ã¢ã³ã¹ïŒ
è¿ãããTStatStgã®ããŒã¿åã¯ã次ã®å€ãåãããšãã§ããŸãã
- STGTY_STORAGEã¯ãã©ã«ããŒã§ã
- STGTY_STREAMã¯ãã¡ã€ã«ã§ã
ä»ã®ãªãã·ã§ã³ã¯ãã¹ãŠçŽç²ã«ãµãŒãã¹ã§ãããèå³ã¯ãããŸããã
ãããã©ã®ããã«èµ·ããããèŠãŠã¿ãŸãããã
procedure Enumerate(const Root: string; Storage: IStorage); var Enum: IEnumStatStg; TmpElement: TStatStg; ShellMalloc: IMalloc; Fetched: Int64; Folder: IStorage; AFile: IStream; begin // .. OLE, IMalloc if (CoGetMalloc(1, ShellMalloc) <> S_OK) or (ShellMalloc = nil) then raise Exception.Create('CoGetMalloc failed.'); // CheckHResult(Storage.EnumElements(0, nil, 0, Enum)); // Fetched := 1; while Fetched > 0 do if Enum.Next(1, TmpElement, @Fetched) = S_OK then // ( ) if ShellMalloc.DidAlloc(TmpElement.pwcsName) = 1 then begin // Write('Found: ', Root, '\', AnsiString(TmpElement.pwcsName)); // case TmpElement.dwType of // - STGTY_STREAM: begin Writeln(' - file: ', sLineBreak); CheckHResult(Storage.OpenStream(TmpElement.pwcsName, nil, STGM_READ or STGM_SHARE_EXCLUSIVE, 0, AFile)); ShowFileData(AFile); Writeln; end; // - STGTY_STORAGE: begin Writeln(' - folder'); CheckHResult(Storage.OpenStorage(TmpElement.pwcsName, nil, STGM_READ or STGM_SHARE_EXCLUSIVE, nil, 0, Folder)); Enumerate(Root + '\' + string(TmpElement.pwcsName), Folder); end; else Writeln('Unsupported type: ', TmpElement.dwType); end; // , - ShellMalloc.Free(TmpElement.pwcsName); end; end;
ãããŠãæåã®ç« ã§äœæããããã¡ã€ã«ãèªãã ãšãã«äœãèµ·ãããèŠãŠã¿ãŸãããïŒ

å®éãããã¯ãŸãã«æåã®ç« ã§èšé²ããããŒã¿ã§ãã
ãã®äŸã®ã³ãŒãã¯èšäºã®ã¢ãŒã«ã€ãã«ããããã¹ã.. \ simple \ StorageReadDemo.dprãã«åŸã£ãŠããŸãã
次ã«ããããããå°ã䟿å©ã«äœ¿çšããæ¹æ³ãèŠãŠã¿ãŸãããã
3.ã©ãããŒã¯ã©ã¹
ãã€ãŠãç§ã¯å°ããªã¢ãžã¥ãŒã«ïŒã³ã¡ã³ãä»ãã®1000è¡ïŒãéçºããŸããããã®ã¢ãžã¥ãŒã«ã¯ãè€åãã¡ã€ã«ãæäœããéã®ãã¹ãŠã®ãã¥ã¢ã³ã¹ãèæ ®ãããã䟿å©ãªäœæ¥ã¡ã«ããºã ãæäŸããããã€ãã®ã¯ã©ã¹ãå®è£ ããŸãã
ã¢ãŒã«ã€ãã®ã.. \ StorageReader \ FWStorage.pasããã©ã«ãã«ãããŸã ã
ããã€ãã®æ¬ é¥ããããŸãã å®éãç§ã¯ãã®éçºãããªãåã«æŸæ£ãããããDelphiã®ãŠãã³ãŒãããŒãžã§ã³ã§ã¯ãæååã®æäœã«é¢é£ããäžæºãçºè¡ããŸãã
[dcc32èŠå] FWStorage.pasïŒ860ïŒïŒW1057ãAnsiStringããããstringããžã®æé»çãªæååãã£ã¹ã
[dcc32èŠå] uStgReader.pasïŒ102ïŒïŒW1057ãShortStringããããstringããžã®æé»çãªæååãã£ã¹ã
ãããåæã«ãããã¯éåžžã«æ©èœçã§ããããããã®å€åã¯ããã©ãŒãã³ã¹ã«åœ±é¿ãäžããŸããã ïŒæ£çŽã«èšããšããããããšããã«ã¯é¢åã§ãïŒã
ãã®ã¢ãžã¥ãŒã«ã¯ã次ã®äºçŽã§èªç±è£éã§äœ¿çšã§ããŸãã
ã¯ã©ã¹ã³ãŒããçªç¶å€æŽãïŒãã®ãè¿œå ããèŠã€ãã£ãå Žåã¯ãšã©ãŒãä¿®æ£ããŠïŒããããã€ã³ã¿ãŒãããã«ã¢ããããŒããããšãã¢ãžã¥ãŒã«ã®äœæè ã®ååãããããŒã«ä¿åãããŸãã
ç§ã¯ãããã®ã¢ãžã¥ãŒã«ã«åè¡ããŠããŸããïŒç§ã«ãšã£ãŠã¯æ代é ãã§ãïŒã®ã§ãããã«å®äºããããã®ãªã¯ãšã¹ããæåŠããŸãã
ãããã£ãŠããã®ã¢ãžã¥ãŒã«ã§ã¯ãè€åãã¡ã€ã«ãæäœããTFWStorageã¯ã©ã¹ãšãIStorageã®ã©ãããŒã§ããTFWStorageCursorã¯ã©ã¹ã«èå³ããããŸãã
æåã«ããããã®ã¯ã©ã¹ã®ã¡ãœããããªã¹ããã次ã«ããããæäœããäŸã瀺ããŸãã
ãããã£ãŠãTFWStorageã¯ã©ã¹ã¯ããã¡ã€ã«ã®æäœã®ã¿ãç®çãšããŠãããããã€ãã®å®çšçãªã¡ãœãããæäŸããŸãã
- OpenFileãOpenFileReadOnly-ãŸãããã¹ãŠãæ確ã§ãåã«è€åãã¡ã€ã«ãéããŸãã ã©ã¡ãã®ã¡ãœãããããã¡ã€ã«ã®ã«ãŒããã£ã¬ã¯ããªãæãTFWStorageCursorã¯ã©ã¹ãäœæããŠè¿ããŸãã
- CloseFile-ãããã£ãŠã以åã«éãããã¡ã€ã«ãéããŸãã
- åæ¥ç¶-以åã«éãããã¡ã€ã«ãåæ€åºããŸãã TFWStorageCursorãè¿ããŸãã
- å§çž®-æå®ãããã¡ã€ã«ãå§çž®ããæçåãããããã¯ãåé€ããŸãã å§çž®ãã¡ã€ã«ã¯éããªãã§ãã ããã
- IsStgValidBinaryFmt-æå®ãããã¡ã€ã«ã§ãã¹ãŠãæ£åžžã§ããããã®æ§é ãç Žå£ãããŠããªããã©ããã確èªããŸãã æå®ããããã¡ã€ã«ã¯éããªãã§ãã ããã
- ForceStorage-æå®ããããã¹ã«ããè€åãã¡ã€ã«å ã«ãã©ã«ããŒãäœæãŸãã¯éããŸãã ãã¹ã¯ã«ãŒãããæå®ããå¿ èŠããããã\ããã»ãã¬ãŒã¿ãšããŠäœ¿çšãããŸãã äŸïŒããã¡ã€ã«\ Subfolder1 \ subfolder2 \ subsubfolderãžã®ãã¹ãã TFWStorageCursorãè¿ããŸãã
ã€ãŸã ååãšããŠããã®äž»ãªã¿ã¹ã¯ã¯ãTFWStorageCursorã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãæäŸããããšã§ããããã«ãããè€åãã¡ã€ã«ã®äž»ãªäœæ¥ãè¡ãããŸãã
圌ã®æ¹æ³ã¯æ¬¡ã®ãšããã§ãã
- CreateStorage-çŸåšã®ãã©ã«ããŒå ã«æ°ãããã©ã«ããŒãäœæããæ°ããäœæããããã©ã«ããŒãæãTFWStorageCursorãè¿ããŸãã
- OpenStorage-çŸåšã®ãã©ã«ããŒå ã®ãã©ã«ããŒãéããŸãã éããŠãããã©ã«ããŒãæãTFWStorageCursorãè¿ããŸãã
- DeleteStorage-çŸåšã®ãã©ã«ããŒå ã®æå®ããããã©ã«ããŒãåé€ããŸãã
- ã³ããŒ-æå®ãããã¡ã€ã«ãŸãã¯ãã©ã«ããŒãçŸåšã®ãã©ã«ããŒããå¥ã®ãã©ã«ããŒã«ã³ããŒããŸãã ã³ããŒå ã®ãã©ã«ããŒã¯ãTFWStorageCursorã¯ã©ã¹ã®åœ¢åŒã§è»¢éãããŸãã
- MoveTo-Copyã¡ãœãããšåæ§ã«ãã³ããŒãããã¢ã€ãã ã®ã¿ãçŸåšã®ãã©ã«ããŒããåé€ãããŸãã
- CreateStream-çŸåšã®ãã©ã«ããŒã«ç©ºã®ãã¡ã€ã«ãäœæããŸãã
- ReadStream-æå®ããããã¡ã€ã«ã®å 容ãèªã¿åããŸãã
- WriteStream-æ°ããããŒã¿ããã¡ã€ã«ã«æžã蟌ã¿ãŸãã ãã®ååã®ãã¡ã€ã«ãååšããªãå Žåã¯ãäœæããŸãã
- DeleteStream-çŸåšã®ãã©ã«ããŒå ã®ãã¡ã€ã«ãåé€ããŸãã
- FlushBuffer-å€æŽãä¿åããŸãã
- ååã®å€æŽ-çŸåšã®ãã©ã«ããŒå ã®æå®ããããã¡ã€ã«ãŸãã¯ãã©ã«ããŒã®ååãå€æŽããŸãã
- åæ-çŸåšã®ãã©ã«ããŒã®å 容ããªã¹ãããTFWStorageEnumã®é åãšããŠçµæãè¿ããŸã
- åŸæ¹-芪ãã©ã«ããŒãžã®ãªã³ã¯ãè¿ããããèªäœãç Žæ£ãããŸãïŒã«ãŒãã§ãªãéãïŒã
- ãªãªãŒã¹-çŸåšã®ã¯ã©ã¹ãç Žæ£ããŸãã
- IsRoot-çŸåšã®ã¯ã©ã¹ãè€åãã¡ã€ã«ã®ã«ãŒããã©ã«ããŒãæããŠãããã©ããã瀺ããŸãã
- GetName-çŸåšã®ãã©ã«ããŒã®ååãè¿ããŸãã
- ãã¹-çŸåšã®ãã©ã«ããŒãžã®ãã¹ãè¿ããŸãã
- ã¹ãã¬ãŒãž-ãã¹ãŠã®åãµããã©ã«ããŒã®ãªã¹ãã
ã芧ã®ãšãããIStreamã«ã¯ã©ãããŒã¯ãããŸããããã®ã€ã³ã¿ãŒãã§ã€ã¹ã§ã®äœæ¥ã¯ãCreateStreamãReadStreamãWriteStreamã¡ãœããã«å§ä»»ãããŸãã
Enumerateã¡ãœãããè¿ãTFWStorageEnumé åã§ã¯ãpacsNameã«å²ãåœãŠãããã¡ã¢ãªã解æŸããå¿ èŠã¯ãããŸãããããã¯æ¢ã«å®äºããŠããããã€ãã£ãã¡ã¢ãªãããŒãžã£ã«ãã£ãŠå²ãåœãŠãããã¡ã¢ãªã«æ ŒçŽãããŠããããŒã¿ã®ã³ããŒã䜿çšããŠããŸãã
Backwardã¡ãœããã§çºçããå¯èœæ§ãããå¯äžã®è³ªåã¯ããããã©ã®ããã«çºçããããšããããšã§ãã
ãããŠä»ãç§ã¯ãããæ¬åœã«äŸ¿å©ã§ããããšã瀺ããŸãã
ããã§ãããšãã°ããã®ãããªãã¹ãéãå¿ èŠãããå ŽåïŒããã¡ã€ã«\ Subfolder1 \ subfolder2 \ subsubfolderãžã®ãã¹ããããã¯ã第2ç« ã®éåžžã®ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠå®è¡ããå¿ èŠããããŸãã
ãã¡ã€ã«èªäœãéããã«ãŒããæãIStorageã€ã³ã¿ãŒãã§ãŒã¹ãååŸããŠãããæåã®ãã©ã«ããŒã®IStorageãååŸãã次ã«2çªç®ãš3çªç®ã®ãã©ã«ããŒïŒããµããµããã©ã«ããŒãïŒã®IStorageãååŸããŸãã
ãããã¯ã©ããã«æ ŒçŽããå¿ èŠãããæ倧4ã€ã®èŠçŽ ã§ãã
TFWStorageã䜿çšãããšãç©äºããã£ãšç°¡åã«ãªããŸãã
procedure TForm1.Button1Click(Sender: TObject); var Path: string; Storage: TFWStorage; Root, Folder: TFWStorageCursor; Data: TStringStream; begin Storage := TFWStorage.Create; try // Path := ExpandFileName(ExtractFilePath(ParamStr(0)) + '..\data\test.bin'); // Storage.OpenFile(Path, True, Root); // Storage.ForceStorage(Path + '\Subfolder1\subloder2\subsubfolder', Folder); Data := TStringStream.Create; try // Data.WriteString('new file data.'); // while Folder <> Root do begin Folder.WriteStream(Folder.GetName + '_new_file.txt', Data); // Folder.Backward(Folder); end; // Root.FlushBuffer; finally Data.Free; end; finally Storage.Free; end; end;
ããã°ã©ãã³ã°ã®èŠ³ç¹ããèŠããšãéåžžã«äŸ¿å©ã§ããã
ããã§ã¯ããã£ãšæ·±å»ãªãã®ãã€ãŸãè€åãã¡ã€ã«ã®å 容ã®ãšãã£ã¿ãŒãäœæããŸãããã
æ°ãããããžã§ã¯ããéãããã®äžã«æ¬¡ã®ãããªãã®ãäœæããŸãã

ãã©ã€ããŒãã§ã¯ã3ã€ã®å€æ°ãè¿œå ããŸãã
private FCurrentFileName: string; FStorage: TFWStorage; FRoot: TFWStorageCursor;
ãã©ãŒã ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã次ã®ã³ãŒããèšè¿°ããŸãã
procedure TForm1.FormCreate(Sender: TObject); begin // FCurrentFileName := ExpandFileName(ExtractFilePath(ParamStr(0)) + '..\data\simple.bin'); // FStorage := TFWStorage.Create; // OpenFile(False); end;
次ã«ããã¡ã€ã«èªäœãéãæé ãèšè¿°ããŸããããã¯ç°¡åã§ãã
procedure TForm1.OpenFile(CreateNew: Boolean); begin // , FStorage.CloseFile; // FStorage.OpenFile(FCurrentFileName, CreateNew or not FileExists(FCurrentFileName), FRoot); Caption := FCurrentFileName; // ShowStorageData(FRoot); end;
ãããŸã§ã®ãšãããšãŠãç°¡åã§ãããïŒ ååãšããŠãæ®ãã®ã³ãŒãã¯åçŽã§ãã
次ã«ãç»é¢ã«ãã©ã«ãã®å 容ã衚瀺ããæé ãèšè¿°ããŸãã
procedure TForm1.ShowStorageData(AStorage: TFWStorageCursor); procedure AddItem(const ACaption: string; AIndex: Integer); begin with ListView1.Items.Add do begin Caption := ACaption; case AIndex of -1: ImageIndex := -1; 1: begin ImageIndex := 0; SubItems.Add('Folder'); end else ImageIndex := 1; SubItems.Add('File'); end; // Data, : // -1 - // 0 - // 1 - // Data := Pointer(AIndex); end; end; var AData: TFWStorageEnum; I: Integer; begin ListView1.Items.BeginUpdate; try ListView1.Items.Clear; // , // ( - ) if not AStorage.IsRoot then AddItem('..', -1); // AStorage.Enumerate(AData); // ListView for I := 0 to AData.Count - 1 do AddItem( string(AData.ElementEnum[I].pacsName), Byte(AData.ElementEnum[I].dwType = STGTY_STORAGE)); finally ListView1.Items.EndUpdate; end; end;
ãã¹ãŠãæ£åžžã«å®äºãããããããžã§ã¯ããéå§ãããšãæåã®ç« ã§äœæãããã¡ã€ã«ã.. \ data \ simple.binããéãããã¹ãŠã次ã®ããã«ãªããŸãã

ããã§ã¯ããªããžããªãããã²ãŒãããŸãããã
ãã®ããžãã¯ã¯ç°¡åã§ãïŒ
- ãã©ã«ããããã«ã¯ãªãã¯ããŸã-ãã©ã«ããéããŠããã®å 容ã衚瀺ããŸãã
- ãã¡ã€ã«ãããã«ã¯ãªãã¯ããŸã-ãã¡ã€ã«å 容ãšãã£ã¿ãŒãéããŸãã
- èŠçŽ ã..ããããã«ã¯ãªãã¯ããŸã-次ã®ã¬ãã«ã«é²ã¿ãŸãã
ãããè¡ãã«ã¯ãListViewã®OnDblClickã€ãã³ããã³ãã©ãŒã§æ¬¡ã®ã³ãŒããèšè¿°ããŸãã
procedure TForm1.ListView1DblClick(Sender: TObject); begin // - if ListView1.Selected = nil then Exit; // Data case Integer(ListView1.Selected.Data) of -1: // begin // FRoot.Backward(FRoot); // ShowStorageData(FRoot); end; 0: // EditFile; 1: // begin // FRoot.OpenStorage(AnsiString(ListView1.Selected.Caption), FRoot); // ShowStorageData(FRoot); end; end; end;
ããã§ãããã«ã¯ãªãã¯ã§ã¹ãã¢ãæ©ãåãããšãã§ããŸãã :)
次ã®ããã«ãã¡ã€ã«ãç·šéããŸãã æ°ãããã©ãŒã ããããžã§ã¯ãã«æ¥ç¶ããä¿åãã¿ã³ãšãã£ã³ã»ã«ãã¿ã³ãè¿œå ããŸããããã«ããã¡ã€ã«ã®å 容ã衚瀺ãããTMemoãè¿œå ãããã®åŸã次ã®ã³ãŒããèšè¿°ããŸãã
procedure TForm1.EditFile; var Buff: TMemoryStream; Data: AnsiString; begin Buff := TMemoryStream.Create; try // FRoot.ReadStream(AnsiString(ListView1.Selected.Caption), Buff); // if Buff.Size > 0 then begin SetLength(Data, Buff.Size); Buff.Read(Data[1], Buff.Size); end; // frmEdit := TfrmEdit.Create(Self); try // Memo frmEdit.Memo1.Text := string(Data); // if frmEdit.ShowModal <> mrOk then Exit; // Memo Buff.Clear; Data := AnsiString(frmEdit.Memo1.Text); if Length(Data) > 0 then Buff.Write(Data[1], Length(Data)); // FRoot.WriteStream(AnsiString(ListView1.Selected.Caption), Buff); // FRoot.FlushBuffer; finally frmEdit.Release; end; finally Buff.Free; end; end;
ããŠãããã«ã¯ã»ãŒæ¬æ Œçãªãšãã£ã¿ãŒããããŸããããã©ãŒã ã®äžéšã«ãããã¿ã³ã®æ©èœãè¿œå ããããšã¯æ®ã£ãŠããŸãã
æ°ããè€åãã¡ã€ã«ãäœæããæ¢åã®ãã¡ã€ã«ãéãããã®ãã³ãã©ãŒã¯æ¬¡ã®ããã«ãªããŸãã
procedure TForm1.btnCreateDFaseClick(Sender: TObject); begin if SaveDialog1.Execute then begin FCurrentFileName := SaveDialog1.FileName; OpenFile(True); end; end; procedure TForm1.btnOpenDBaseClick(Sender: TObject); begin if OpenDialog1.Execute then begin FCurrentFileName := OpenDialog1.FileName; OpenFile(False); end; end;
ããã¯ãæ°ãããã©ã«ããŒãäœæããæ¢åã®ãã©ã«ããŒãåé€ããããã®ãã¿ã³ã³ãŒãã«ãªããŸãã
procedure TForm1.btnAddFolderClick(Sender: TObject); var NewFolderName: string; Tmp: TFWStorageCursor; begin if InputQuery('New folder', 'Enter folder name', NewFolderName) then begin FRoot.CreateStorage(AnsiString(NewFolderName), Tmp); FRoot.FlushBuffer; end; ShowStorageData(FRoot); end; procedure TForm1.btnDelFolderClick(Sender: TObject); begin if Application.MessageBox( PChar(Format('Delete folder: "%s"?', [ListView1.Selected.Caption])), 'Delete folder', MB_ICONQUESTION or MB_YESNO) = ID_YES then begin FRoot.DeleteStorage(AnsiString(ListView1.Selected.Caption)); FRoot.FlushBuffer; ShowStorageData(FRoot); end; end;
åãããšããã¡ã€ã«ãéããŠåé€ãããã¿ã³ã®ã¿
procedure TForm1.btnAddFileClick(Sender: TObject); var NewFileName: string; begin if InputQuery('New file', 'Enter file name', NewFileName) then begin FRoot.CreateStream(AnsiString(NewFileName)); FRoot.FlushBuffer; end; ShowStorageData(FRoot); end; procedure TForm1.btnDelFileClick(Sender: TObject); begin if Application.MessageBox( PChar(Format('Delete file: "%s"?', [ListView1.Selected.Caption])), 'Delete file', MB_ICONQUESTION or MB_YESNO) = ID_YES then begin FRoot.DeleteStream(AnsiString(ListView1.Selected.Caption)); FRoot.FlushBuffer; ShowStorageData(FRoot); end; end;
ããã ãã§ããç§ã®æèŠã§ã¯ç°¡å
ã§ã:) ããã§èŠãããšãã§ããŸãããDOCãã¡ã€ã«å ã«ä¿åãããŠãããã®ã¯äœã§ããïŒ :)

ããããããã§åæ¢ããè€åãã¡ã€ã«ãåŒãèµ·ããããŸããŸãªãã©ãã«ã®èª¬æã«ç§»ãã§ãããããããŠãã¢ãŒã«ã€ãå ã®ãã®ãµã³ãã«ã®ãœãŒã¹ã³ãŒãããã¹ã«åŸã£ãŠååŸã§ããŸãïŒ ".. \ StorageReader \"
4.è€åãã¡ã€ã«ã®çæ
, , , .
â .
.
â .
, . :)ïŒ
, , .
, , :
- â â
- â â â
- 建èšã°ã«ãŒãâ建èšâãã¥ãŒâãªããžã§ã¯ãâèŠç©
å®éããããã®ãã¹ãŠã®å»ºèšãããžã§ã¯ãããªããžã§ã¯ããªã©ïŒæšå®ãé€ãïŒã¯éå±€ãªããžã§ã¯ãã«ãããŸãã-åºæ¬çã«ãã©ã«ããŒã§ããããããã®ãã©ã«ããŒã¯å³å¯ã«å®çŸ©ãããé åºã§ç§»åããå¿ èŠããããŸãã
ãã¡ã€ã«ã·ã¹ãã ããŒã«ã䜿çšããŠãã®éå±€ãäœæãããã©ã«ããŒã®çš®é¡ïŒéå±€ã®ã¬ãã«ãããã«ã/ãªããžã§ã¯ã/ãã¥ãŒããå±ããïŒãå®è£ ããããšãæ³åãããšãããšãã°ãã«ãŒãïŒla thumbs.dbã«ããïŒ ãããããææ®è ã®äžã§ãã®æ§é å šäœãå°ç¡ãã«ããããšãã§ããé床ã«éã³å¿ã®ãããã³ãæã£ãŠãããŠãŒã¶ãŒã§äœããã¹ãã§ããããïŒ
ãããã®èæ ®äºé ãããäœå¹Žãåã«ãããŒã¿ãŠã§ã¢ããŠã¹ãšããŠè€åãã¡ã€ã«ãéžæããã®ã¯ããŠãŒã¶ãŒãããã«äŸµå ¥ããŠãã¹ãŠãå£ãããšãã§ããªãããã§ãã
ãã®ã¹ãã¬ãŒãžåœ¢åŒã䜿çšããŠããã©ã«ãäœæã®ç®çã®éå±€ãå¶åŸ¡ãããŠãŒã¶ãŒã足ã§æ®åœ±ããã®ãé²ãããšãã§ããŸãã
ãããããã¥ã¢ã³ã¹ãåºãŠããŸãããåœç€Ÿã®ãœãããŠã§ã¢ã§æ°ããèŠç©ãããäœæãããšããäœããã®çç±ã§ããŠãŒã¶ãŒã¯ãèŠç©ããã®ââååã§èŠ³å¯ããããšã«é¢ããå®å šãªæ å ±ã衚瀺ããããšããŸãã
äŸïŒãæ§çŽ æã®ãã©ãã¯ã®ãªãŒããŒããŒã«ã Selegvozh-Chimã»ã¯ã·ã§ã³ãçéã142 pc1-163 pc10ãé·ã22.0 kmâã
ç§ãã¡ã¯æãåºããŸã-ãã¡ã€ã«åã®é·ãã®å¶éã¯ããã31æåã§ãããããã¯æ¥µç«¯ãªå Žåã§ãïŒãå€ããã¹ãžã®ãªãŒããŒããŒã«ãã
ããããããŠã§ã€ã®ä¿®çããšåä»ããŸãã
ãããŠãã¡ããããã¹ã«æ²¿ã£ãŠãã¡ã€ã«åãè殺ãããšããŠãŒã¶ãŒã¯ã²ã©ãæ°åã害ããã®ã§ãããã«ã€ããŠäœãããªããã°ãªããŸããã§ããã
:
, ( â ), . «Properties», ( , , ) ( 1024 â , , ).
â â «Data», .
:

, ?
GUID «» 31 . :)
31 , - .
, 5 ?
-, , 5 , . , , â . :)
ããã¶ã€ã³ç 究æããšåŒã°ãããã®ãããªã¯ã©ã€ã¢ã³ãããããŸã-ãã·ã¢äžã«ã¯ãããã®å€ãããããããã§ã¯èšå€§ãªæ°ã®èŠç©ãè ãåããŠããŸãã圌ãã¯ãã¹ãŠããã§ããããããã£ãŠãåã«ã巚倧ãªãäžé£ã®æšå®å€ã§åžžã«åäœããŸã-ãããä»äºã§ãã
ãããŠããæ¥ã次ã®ãããªãã°ã¬ããŒããå¯ããããŸããããçããããœãããŠã§ã¢ã®èµ·åãåŸ ã€ã®ã«ããããããŠããŸãããæ¯æ¥äœãããŠããã®ã§ããïŒã
ãŸãããããã®ãªãã£ã¹ã®äžéšã¯ããµã€ãã«æäŸã§ããªãããŒã¿ãåŠçããŠããããïŒäžéšã®æ¿åºæ©é¢ã¯èŠ³å¯ããŠããŸãïŒããŸã£ããç解ã§ããŸããã§ãã-éçã®ãã¬ãŒãã¯ã©ãããæ¥ãã®ã§ããïŒ!!!
ãããã幞éãªããšã«ãããŒã¿ã¯æ©å¯ã§ã¯ãªããç§ãã¡ã«æäŸãããŸããã
ãããŠä»ãç§ã®ãã©ã«ãã«ã¯ã»ãŒ2ã®ã¬ãã€ãã®ãã¡ã€ã«ããããŸãçŽ20äžä»¶ã®èŠç©ãããè¹å ã§ïŒéšéïŒãã¡ãããç§ã¯ãã®ãããªããªã¥ãŒã ã«å€¢äžã§ããã...
ããããæ¬åœã«-å¿ èŠãã©ããã«ãããããããã®ãµã€ãºã®ãã¡ã€ã«ã¯5å以äžéãããŸããã§ããïŒæ¬¡ã®ç« ã§ãã®çç±ãç解ããŸãïŒã
圌ãã¯é床ã®ãã¹ããéå§ããå®éšçã«ç¢ºç«ãããŸããïŒãã§ã«50ã¡ã¬ãã€ãã®ãµã€ãºã®è€åãã¡ã€ã«ã®ããªã¥ãŒã ã§äœæ¥ããã®ã¯æ°ã«å ¥ããªãã§ãããã
ãã¹ãã¯ãã¡ãããã¹ãã§ãããäœãããå¿ èŠããããŸãã
ã§ããã ãæ©ããè€åãã¡ã€ã«ã§ã¯ãªãããŒã¿ããŒã¹ã«ä¿åãããããŒã¿ãåŠçãããããã¯ãŒã¯ãµãŒãã¹ãå®è£ ãããŸãããããã«ã圌ãã¯ããã«ãéåžžã®Firebird / Interbaseãšããæ·±å»ãªããŒã¿ããŒã¹ã®äž¡æ¹ïŒMS SQL / Olracleãããã³ADOãããŒãã«ãã蟌ãŸããïŒã®ãµããŒããè¿œå ããŸãããè€åãã¡ã€ã«ããããŒã¿ããŒã¹ã«ããŒã¿ãå€æããå°ããªãŠãŒãã£ãªãã£ãäœæãããŸããã
ç§ãã¡ã¯ãã¹ãããŸã-ããã¯é£ã¶ãç§ã®æ¯ã¯å¿é ããŸãããããã¥ã¢ã³ã¹ããããŸãã
2ã®ã¬ãã¡ã€ã«ãããã¹ãŠã®ããŒã¿ãååŸããŠããŒã¿ããŒã¹ã«è»¢éããããšã¯ã§ããŸããã
ããæç¹ã§ãOpenStorageãä»ããŠæ¬¡ã®ãã©ã«ããŒãéããšãéããšã©ãŒãçºçããå¯èœæ§ããããŸãããã®å Žåããã以äžå¿é ããå¿ èŠã¯ãããŸãããåŒã³åºãã¯ãšã©ãŒã«ãªããŸãã
ããã¯ãŸãã«ãã®ç®çã®ããã§ãããTFWStorageã«2ã€ã®ã¡ãœãããè¿œå ãããŸãããReConnect-è€åãã¡ã€ã«ãåæ€åºã§ããæ¹æ³ãšããšã©ãŒãçºçãããã©ã«ããŒãããã«éãForceStorageã¡ãœããã§ãã
ãã ãããã®æç¹ã§ã¯ããŸã ååãªã³ãŒã³ãåŸããããå¥ã®è£œåã§è€åãã¡ã€ã«ã䜿çšããŠããŸããããã®ãããžã§ã¯ãã¯ãæ å ±ç §äŒã·ã¹ãã ïŒISSïŒã§ãããæšå®è ã«åœŒã«å¿ èŠãªããã¥ã¡ã³ãïŒMSDNã®åçãªé¡äŒŒç©ïŒãžã®ã¢ã¯ã»ã¹ãæäŸããŸãã
ãããŠä»ãããŠãããŒã¹ãåãã責任ã®ããæè¡è ããã£ãŠæ¥ãŠããããŒã¹ãéããªãã®ã§ã次ã®ã¢ããããŒãããªãªãŒã¹ã§ããŸããããšèšããŸãã
ç§ã¯ãã§ãã¯ãå§ããŠããŸãã
, , StgOpenStorage.
âŠ
â - 4 , .
, . .
, â , ( ) â MSDN , . , .
, :
ããšãã°ããã¡ã€ã«ïŒã¹ããªãŒã ïŒã«äœããæžã蟌ã¿ãEnumElementsãåŒã³åºããŠããã¡ã€ã«ãååšãããã©ããã確èªããããšããŸãããŸãããã®åŒã³åºãã«ãã£ãŠè¿ãããIEnumStatStgã¯ããã®ãããªã¹ããªãŒã ãèªèããŸããã次ã«ãCreateStreamãåŒã³åºããŠäœæããŸããããšã©ãŒãçºçããŸãã
ãã®å Žåããã®ãã€ã³ããåé¿ããã®ã¯éåžžã«ç°¡åã§ããæå®ãããã¹ããªãŒã ã«å¯ŸããŠDestroyElementãåŒã³åºããCreateStreamãåŒã³åºããŠåäœæããã ãã§ååã§ãããããã¯éåžžã«çŽ æŽãããåŒã³åºãã§ãããè€åãã¡ã€ã«ã®åé¡ã¯æ¬åœã«åé¡ã§ããã
ãããŠã圌ã«ãšã£ãŠã¯æ¬åœã«æªãã®ã§ãç§ãã¡ã¯åœŒãããŸã å©çšå¯èœãªããŒã¿ãååŸããæ¹æ³ãåŠã¶å¿ èŠããããŸãã
5. RAWã¢ãŒãã§ã®ããŒã¿ã®èªã¿åã
ããªãã¯ä»ããã®æèŠãæã£ãŠãããšæãïŒãŸããããªãèªèº«ãnifigaãè€åãã¡ã€ã«ã䜿çšãããšããããã€ã®åé¡ãããã§ããããïŒãªãèè ã¯ãããã«ã€ããŠè©±ãã®ã§ããããïŒ
ããã¯æ£ããæèŠã§ã¯ãããŸãããçŸåšäœ¿çšãããŠããããŸããŸãªãã¯ãããžãŒã«å€§éã®ãšã©ãŒãæããããšãã§ããŸãããããã¯ããããæåã«å€±æããããšãæå³ãããã®ã§ã¯ãããŸããã
ããšãã°ã察å¿ããAPIãåŒã³åºãããã«èª€ã£ããã©ã¡ãŒã¿ãŒã䜿çšããã ãã§ã3çªç®ã®ãªã³ã°ããçŽæ¥ãNTFSãã¡ã€ã«ã·ã¹ãã ã«åºæ¬çã«åé€ã§ããªããã©ã«ããŒãçŽæ¥äœæã§ããããšãããã£ãŠããå Žåããã¡ã€ã«ã·ã¹ãã ã®äœ¿çšãæåŠããŸãããïŒ :)
è€åãã¡ã€ã«ã¯æ¬åœã«åªããŠããŸãããæ£ãã調çããæ¹æ³ãåŠã¶å¿ èŠããããŸãã
äžè¬çã«ã¯ãMS ã¯æè¡ã®èª¬æãå ¬é圢åŒã§å ¬éããŠããããã®åœ¢åŒã§äœæ¥ãéå§ãããšããJava POIFSããã®åœ¢åŒã®èª¬æãWikiããã®çãæç²ãããã³POIFSã®æ§é ã®è©³çŽ°ãªèª¬æãå«ãå¥ã®ãã¡ã€ã«ããååŸã§ããŸããã§ããïŒç¹ã«çåºã«ãããšïŒïŒããããç§ã¯ä»ãããèŠã€ããããšãã§ããŸããïŒäœå¹Žãçµã¡ãŸããïŒã
ã ãããç§ãå¿ èŠãªãšãã«ãã©ãŒããããéããªãã£ãã®ã§ãã :)
ãããã£ãŠãç§ã¯èªåã§ãã¹ãŠãéžæããå¿ èŠããããŸããã
è€åãã¡ã€ã«ãæ§æãããã®ãã€ãŸãããããŒã調ã¹ãŸãã
TPoifsFileHeader = packed record // . (0 x E011CFD0, 0 x E11AB1A1) _abSig: array [0..7] of Byte; // Class ID. WriteClassStg, GetClassFile/ReadClassStg. // Excel = 0 _clid: TGUID; // . _uMinorVersion: USHORT; // Dll/ _uDllVersion: USHORT; // 0 x FFFE , Intel _uByteOrder: USHORT; // . 9, 512 (2 ^ 9) _uSectorShift: USHORT; // -. 6, 64 (2 ^ 6) _uMiniSectorShift: USHORT; // , 0 _usReserved: USHORT; // , 0 _ulReserved1: ULONG; // , 0 _ulReserved2: ULONG; // , FAT. // 7, 1, , 1 DIF . _csectFat: ULONG; // , Property Set Storage // ( FAT Directory Root Directory Entry) _sectDirStart: ULONG; // . _signature: ULONG; // -. 4096 _ulMiniSectorCutoff: ULONG; // -FAT. // (-2), - . _sectMiniFatStart: ULONG; // -FAT. 0, - _csectMiniFat: ULONG; // DIF . // 7, DIF (-2) _sectDifStart: ULONG; // DIF .0, < 7 _csectDif: ULONG; // 109 , FAT. // 7, , (-1). _sectFat: array [0..108] of ULONG; end;
ããŠãããã§ã¯ãã¹ãŠãæ確ã§ããã¹ãŠã®kamentyãæ·»ä»ãããŠãããšæããŸã-æåã«ãã®æ§é ãæ€èšããå¿ èŠããããŸãã
_uSectorShiftãã£ãŒã«ããš_uMiniSectorShiftãã£ãŒã«ãã®å¯äžã®ãã®ã¯2ã®çŽ¯ä¹ã§ãããããããããéåžžã«æ»ãå¿ èŠããããŸãã
procedure TPoifsFile.InitHeader; begin FStream.ReadBuffer(FHeader, SizeOf(TPoifsFileHeader)); FHeader._uSectorShift := Round(IntPower(2, FHeader._uSectorShift)); FHeader._uMiniSectorShift := Round(IntPower(2, FHeader._uMiniSectorShift)); end;
次ã«ãFATãèªã¿åãå¿
èŠããããŸããFATã¯ãããããŒã®_ulMiniSectorCutoffãã£ãŒã«ãã®å€ä»¥äžã®ãµã€ãºã®ãã¡ã€ã«ã«é¢ããããŒã¿ãæ ŒçŽããŸãã
procedure TPoifsFile.ComposeFAT; var I, J, X, FatLength: Integer; FatBlock: TPoifsFatBlock; CurrentFat, Offset: Integer; XFat: array of Integer; begin // - FAT ( 128 ) // DIF , _csectFat FatLength := FHeader._csectFat * 128; // FAT SetLength(FFat, FatLength); // SetLength(FFatOffset, FatLength); // DIF , FAT 109 // DIF for I := 0 to IfThen(FHeader._csectDif > 0, 108, FHeader._csectFat - 1) do begin // FAT 128 FatBlock := TPoifsFatBlock(GetBlock(FHeader._sectFat[I])); for J := 0 to 127 do begin FFat[I * 128 + J] := FatBlock[J]; // , FFatOffset[I * 128 + J] := FStream.Position - SizeOf(TPoifsBlock); end; end; // , DIF if FHeader._sectDifStart = 0 then Exit; // , FAT Offset := FHeader._sectDifStart; // XFAT FAT SetLength(XFat, 128); // FAT CurrentFat := 13951; //109 * 128 - 1 BAT for X := 0 to FHeader._csectDif - 1 do begin // ( _uSectorShift ) // FStream.Position := GetBlockOffset(Offset); // FAT FStream.ReadBuffer(XFat[0], 128 * SizeOf(DWORD)); // // // for I := 0 to 126 do begin // , , // FAT if XFat[I] < 0 then Exit; // FAT 128 FatBlock := TPoifsFatBlock(GetBlock(XFat[I])); for J := 0 to 127 do begin Inc(CurrentFat); FFat[CurrentFat] := FatBlock[J]; FFatOffset[CurrentFat] := FStream.Position - SizeOf(TPoifsBlock); end; end; // Offset := XFat[127]; end; end;
ããã§ã¯TPoifsFatBlockæ§é ã䜿çšãããŸããããã¯ã128åã®æŽæ°ã®é åã§ãã
GetBlockOffsetããã³GetBlocké¢æ°ãšåæ§ã«ã
ãããã¯æ¬è³ªçã«åçŽã§ãã
function TPoifsFile.GetBlockOffset(BlockIndex: Integer): Int64; begin Result := HEADER_SIZE + FHeader._uSectorShift * BlockIndex; end; function TPoifsFile.GetBlock(Adress: Integer): TPoifsBlock; begin FStream.Position := GetBlockOffset(Adress); FStream.ReadBuffer(Result, SizeOf(TPoifsBlock)); end;
次ã®æé ã§ã¯ããµã€ãºã_ulMiniSectorCutoffãã£ãŒã«ãã®å€ããå°ãããã¡ã€ã«ã«é¢ããããŒã¿ãä¿åãããããã¡ãããæ€èšããŸãã
procedure TPoifsFile.ComposeMiniFat; var I, CurrChain: Integer; TmpPosition: int64; begin // CurrChain := FHeader._sectMiniFatStart; // (- 128 ) SetLength(FMiniFat, FHeader._csectMiniFat * 128); I := 0; while Integer(CurrChain) >= 0 do begin // TmpPosition := GetBlockOffset(CurrChain); // , if TmpPosition < 0 then Exit; //if TmpPosition > FStream.Size then Exit; FStream.Position := TmpPosition; // FStream.ReadBuffer(FMiniFat[I], 512 {128 * SizeOf(DWORD)}); Inc(I, 128); // FAT CurrChain := FFat[CurrChain]; end; end;
æåŸã®æé ã¯ããã¹ãŠã®ãã¡ã€ã«ãšãã©ã«ããŒã®ããããã£ãèªã¿åãããšã§ãã
ãããã¯ããããã®æ§é ã®é åã«ä¿åãããŸãã
TPoifsProperty = packed record // 128 length // / Caption: array[0..31] of WChar; // CaptionSize: Word; // STGTY_ PropertyType: Byte; // ( TPoifsProperty Red-Black-Tree) NodeColor: Byte; // 0 (red) or 1 (black) // PreviousProp: Integer; // NextProp: Integer; // ChildProp: Integer; Reserved1: TGUID; UserFlags: DWORD; // ATime: array [0..1] of Int64; // FAT StartBlock: Integer; // Size: Integer; Reserved2: DWORD; end; TPoifsPropsBlock = array[0..3] of TPoifsProperty;
ãããŠã次ã®ã³ãŒãã§ããããèªã¿ãŸãã
function TPoifsFile.ReadPropsArray: Boolean; var I, J, Len: Integer; PropsBlock: TPoifsPropsBlock; begin Result := True; // Len := 0; // , Property Set Storage J := FHeader._sectDirStart; repeat // 4 Inc(Len, 4); SetLength(FPropsArray, Len); PropsBlock := TPoifsPropsBlock(GetBlock(J)); for I := 0 to 3 do FPropsArray[Len - 4 + I] := PropsBlock[I]; // FAT J := FFat[J]; until J = ENDOFCHAIN; end;
ãã®åŸãæå ã«ãããŸãïŒ
- FATå€ã®é åãåå€ã«ã¯ããŒã¿ä»ãã®ã»ã¯ã·ã§ã³çªå·ãå«ãŸããŸãã
- ãã¡ã€ã«å ã®ããŒã¿ãžã®ãªãã»ããã®é å
- MiniFATå€ã®é å
- ãã¹ãŠã®ãã¡ã€ã«ã®ããããã£ã®é å
FATããã³MiniFATãšã¯äœã§ããïŒ
倧ãŸãã«èšããšãè€åãã¡ã€ã«ã¯ããããŒã§ãããä»ã®ãã¹ãŠãååšããFHeader._uSectorShiftã®ãµã€ãºã®ããŒã¿ââã»ã¯ã¿ãŒã®é åã§ãã
FATã«ã¯ããããã®ã»ã¯ã¿ãŒã«ããŒã¿ãä¿åããæé ãå«ãŸããŠããŸãïŒãã¡ã€ã«ã®å 容ãšããŠãŒã¶ãŒãã¢ã¯ã»ã¹ã§ããªãå³å¯ãªãµãŒãã¹ãããã¯ã®äž¡æ¹ïŒã
ããšãã°ããµã€ãºã1ã¡ã¬ãã€ãã®ãã¡ã€ã«ããããæ£ç¢ºã«2048ã»ã¯ã¿ãŒãå²ãåœãŠãããŸããåã»ã¯ã¿ãŒã®ãµã€ãºã¯512ãã€ãã§ãïŒããã©ã«ãïŒã
æçåã«ããããã®ãã¡ã€ã«ã®ããŒã¿ã¯åžžã«é£ç¶ããŠéä¿¡ããããšã¯éãããæåã®10ã»ã¯ã¿ãŒã«ãã¡ã€ã«ã®çµãããå«ãŸããæ®ãããã®å§ãŸãã«ãªãå¯èœæ§ããããŸãã
, ( ) FAT StartBlock TPoifsProperty, , , ( FAT).
, , .
, .
. , TPoifsProperty, PreviousProp, NextProp ChildProp, NodeColor. Red-Black-Tree.
, .
, .
, :

: ( TreeView), .
, Extract:
begin FileStream := TFileStream.Create(edSrc.Text, fmOpenReadWrite); try AFile := TPoifsFile.Create(FileStream); try // AFile.LoadFromStream; ATree := TStorageTree.Create; try // for I := 0 to AFile.PropertiesCount - 1 do ATree.AddNode(I).Data := AFile[I]; // FillAllChilds(0, ATree.GetNode(0).Data.ChildProp); // TreeView1.Items.Clear; FillTree(nil, 0); // DebugLog := TStringList.Create; try Extract(IncludeTrailingPathDelimiter(edDst.Text), 0); if DebugLog.Count > 0 then DebugLog.SaveToFile(IncludeTrailingPathDelimiter(edDst.Text) + 'cannotread.log'); finally DebugLog.Free; end; finally ATree.Free; end; finally AFile.Free; end; finally FileStream.Free; end; end;
æåã®æ®µéïŒãã¡ã€ã«ããã®ããŒã¿ã®èªã¿åãïŒã¯æ¢ã«å®è£ ãããŠããŸãã
2çªç®ãš3çªç®ã«é²ã¿ãŸãããã
èããããªãã£ãã®ã§ãããªãŒã®æ§é ã埩å ããããã«ããœãªã¥ãŒã·ã§ã³ã®åºç€ãšããŠã°ã©ãã䜿çšããŸããã
èãæ¹ã¯ç°¡åã§ãããŸããã°ã©ãã«Nåã®ããŒããè¿œå ããŸããåããŒãã¯TPoifsPropertyé åã®èŠçŽ ã®1ã€ãæ åœããŸãïŒããã¯å®éã«ã³ãŒãã§è¡šç€ºããããããŒããåããããããã¯ã§ãïŒã
ãããŠæ¬¡ã®ã¹ãããã¯ãããŒãã誰ããäœãåç §ãããã®éã®ã¯ãã¹ãªã³ã¯ãæ§ç¯ããããšã§ãã
äžè¬ã«ãããªãŒèªäœã¯éåžžã«åçŽã«æ§ç¯ãããŸããäž»ãªããšã¯ãããã€ãã®åçŽãªã«ãŒã«ã«åŸãããšã§ãã
- TPoifsProperty.ChildProp-åžžã«ãã©ã«ããŒå ã®æåã®åãæããŸãïŒãã©ã«ããŒã®ã¿ã§æºããããŸãïŒ
- TPoifsProperty.PreviousProp-çŸåšã®ãã©ã«ããŒå ã®åã®ã¢ã€ãã ã瀺ããŸãã
- TPoifsProperty.NextProp-çŸåšã®ãã©ã«ããŒå ã®æ¬¡ã®ã¢ã€ãã ã瀺ããŸãã
ããæ確ã«ããããã«ãããã«ããªãã®ããã®åçããããŸãïŒ

äžç¢å°ã¯ChildPropãå³ã¯NextPropãå·Šã¯PreviousPropã§ãã
ãã®çµæãè€åãã¡ã€ã«ã®ã«ãŒãå ã«2ã€ã®ãã¡ã€ã«ãš1ã€ã®ãã©ã«ããŒãããããã®äžã«ããã«3ã€ã®ãã¡ã€ã«ãããããšãããã«æããã«ãªããŸãã
ãã ãã第3段éãã©ã®ããã«èŠããããã€ãŸããã°ã©ãããŒãéã®ãªã³ã¯ã®æ§ç¯ãèŠãŠã¿ãŸãããã
var ATree: TStorageTree; ... procedure FillAllChilds(RootIndex, CurrentIndex: Integer); var SubChildIndex: Integer; RootNode, CurrNode, ChildNode: TStorageElement; begin if CurrentIndex < 0 then Exit; // RootNode := ATree.GetNode(RootIndex); // CurrNode := ATree.GetNode(CurrentIndex); if CurrNode = nil then Exit; // - if CurrNode.Added then Exit; CurrNode.Added := True; // ATree.AddVector(RootNode, CurrNode); // FillAllChilds(CurrNode.ID, CurrNode.Data.ChildProp); // SubChildIndex := CurrNode.Data.PreviousProp; while SubChildIndex >= 0 do begin // , FillAllChilds(RootIndex, SubChildIndex); ChildNode := ATree.GetNode(SubChildIndex); if ChildNode <> nil then SubChildIndex := ChildNode.Data.PreviousProp else SubChildIndex := -1; end; // , SubChildIndex := CurrNode.Data.NextProp; while SubChildIndex >= 0 do begin FillAllChilds(RootIndex, SubChildIndex); ChildNode := ATree.GetNode(SubChildIndex); if ChildNode <> nil then SubChildIndex := ChildNode.Data.NextProp else SubChildIndex := -1; end; end;
TStorageTreeã¯ã©ã¹ã§è¡šãããã°ã©ãã¯ã©ã¹ã®å®è£ ã¯ãèšäºã®ãããã¯ãšã¯é¢ä¿ããªããããèæ ®ããŸããããã®ã¯ã©ã¹ã®ã³ãŒãã¯sourceã«è¡šç€ºãããŸãã
çŸæç¹ã§ã¯ãã€ã³ããã¯ã¹ã«ãã£ãŠã°ã©ãããŒããè¿ãGetNodeã¡ãœããïŒDataããããã£ãä»ããŠå¶åŸ¡ãããTPoifsPropertyé åèŠçŽ ãžã®åç §ãå«ãïŒãšãã°ã©ãã®2ã€ã®ããŒãéã®ãªã³ã¯ãäœæããAddVectorã¡ãœãããç¥ã£ãŠããã ãã§ååã§ãã
次ã«ã第4段é-ã°ã©ãã«åºã¥ããŠããã©ã«ããŒãšãã¡ã€ã«ã®ããªãŒãäœæããŸãã
procedure FillTree(Node: TTreeNode; RootNodeIndex: Integer); var W: WideString; TreeNode: TTreeNode; I: Integer; RootStorageNode, ChildStorageNode: TStorageElement; begin // RootStorageNode := ATree.GetNode(RootNodeIndex); // ( ) W := RootStorageNode.Data.Caption; TreeNode := TreeView1.Items.AddChildFirst(Node, W); case RootStorageNode.Data.PropertyType of STGTY_STORAGE: TreeNode.ImageIndex := 0; STGTY_STREAM: TreeNode.ImageIndex := 1; end; // for I := 0 to RootStorageNode.VectorCount - 1 do begin // , ( ?) ChildStorageNode := TStorageElement(RootStorageNode.GetVector(I).SlaveNode); if ChildStorageNode = nil then Continue; // , , if ChildStorageNode.ID <> RootNodeIndex then FillTree(TreeNode, ChildStorageNode.ID); end; end;
äžè¬çãªååž°ã
ã«ãŒãããéå§ããŠã°ã©ãã®ããŒãã倧ãŸãã«å®è¡ããåŸå±ããŒããžã®ãªã³ã¯ïŒã°ã©ãã®ãšããžGetVectorïŒIïŒãSlaveNodeããååŸïŒãçŸåšã®ãã©ã«ããŒã«æ ŒçŽãããŸãã
NodeColorãã£ãŒã«ããèæ ®ããŠããRed-Black-Treeãã«æ§é ããªãŒãæ§ç¯ããªãã£ãçç±ãå°ããŸããïŒ
ããããéååž«ã¯åœŒãç¥ã£ãŠããŸããç§ã¯ãã®ã¢ã«ãŽãªãºã ãåæ°å¹Žåã«æžããŸãããããããŸããããŸã-äœã觊ããªãã§ãã ããããšããé»éã®ã«ãŒã«ããããŸãã :)
次ã«ã5çªç®ã®æ®µéã«é²ã¿ãŸã-ããŒã¿ãå€éšãã©ã«ããŒã«æœåºããŸãã
ãã ãããã®ããã«ã¯ããã¡ã€ã«ã«é¢é£ä»ããããããŒã¿ã»ããå šäœãååŸããæ¹æ³ãæ£ç¢ºã«ææ¡ããå¿ èŠããããŸãã
FATã»ã¯ã·ã§ã³ã«ã€ããŠè¿°ã¹ãããšãæãåºããŠãã ãã-ããŒã¿ã¯åžžã«é£ç¶ããŠéä¿¡ããããšã¯éãããFATã§èšè¿°ãããã»ã¯ã·ã§ã³ã®ã€ã³ããã¯ã¹ã«çŠç¹ãåœãŠãŠååŸããå¿ èŠããããŸãã
ã倧ããªãã¡ã€ã«ãïŒããããŒã®_ulMiniSectorCutoffãã£ãŒã«ãã«ä¿åãããŠããå€ä»¥äžã®ãµã€ãºïŒã®ããŒã¿ãååŸããæ¹æ³ãåç §ããŠãã ããã
procedure TPoifsFile.GetDataFromStream(ChainStart: ULONG; NeedLength: DWORD; const Stream: TStream); begin Stream.Size := 0; while (Integer(ChainStart) >= 0) and (Stream.Size < NeedLength) do begin // FStream.Position := GetBlockOffset(ChainStart); // ChainStart := FFat[ChainStart]; // Stream.CopyFrom(FStream, FHeader._uSectorShift); end; // if Stream.Size > NeedLength then Stream.Size := NeedLength; end;
ã»ã¯ã¿ãŒå ã®ããŒã¿ã¯ãããã¯åäœã§ä¿åãããå®éã®ãã¡ã€ã«ãµã€ãºã¯åžžã«ãã®ãµã€ãºã®åæ°ã§ã¯ãªããããæçµç·šéãå¿ èŠã§ãã
åæããŸããæçµæ¹èšçãåé€ããã«ã¯ãå°ãæžãçŽã䟡å€ããããŸãããå¿ èŠã§ããïŒ :)
ãã ãããã©ã¡ãŒã¿ãŒã®ç¹ã§ã¯ãç§å¯ãäœããªãChainStartã«èå³ããããŸããããã¯ãTPoifsPropertyæ§é äœã®StartBlockãã£ãŒã«ãã®å€ã§ãã
ãããŠã_ulMiniSectorCutoffãããå°ããªãã¡ã€ã«ã®ããŒã¿ãååŸããŸãã
procedure TPoifsFile.GetDataFromMiniStream(ChainStart: ULONG; NeedLength: DWORD; const Stream: TStream); var MiniStreamOffset: DWORD; RealMiniStreamSector, TmpChain: Integer; begin Stream.Size := 0; while (Integer(ChainStart) >= 0) and (Stream.Size < NeedLength) do begin // Ministream TmpChain := ChainStart; RealMiniStreamSector := Properties[0].StartBlock; while TmpChain >= 8 do begin Dec(TmpChain, 8); RealMiniStreamSector := FFat[RealMiniStreamSector]; end; // MiniStreamOffset := GetBlockOffset(RealMiniStreamSector); // FStream.Position := MiniStreamOffset + (ChainStart mod 8) * FHeader._uMiniSectorShift; // ChainStart := FMiniFat[ChainStart]; // Stream.CopyFrom(FStream, FHeader._uMiniSectorShift); end; // if Stream.Size > NeedLength then Stream.Size := NeedLength; end;
å°ãããªãããŒã§ãããïŒ
確ãã«ãããèŠããšãããã§ã®å€æŽã¯ãTmpChainãšåãFATãä»ãããªãã»ããã®èšç®ã®ã¿ã§ããã»ã¯ã¿ãŒã蚱容å€ïŒ8ïŒãè¶ ããŠããã¯ã¢ãŠããããå Žåããããã¡ãããžã®ãªã³ã¯ãã«ãŒãã«ãããããTmpChainã蚱容å€ããå°ãããªããŸã§ãã«ãŒãããFATãã§ãŒã³ã«æ²¿ã£ãŠé²ã¿ãŸãã
ããã§ãæå®ãããã¡ã€ã«ããããŒã¿ãæœåºããæé ãäœæã§ããŸãã
procedure GetStorageData(ANode: TStorageElement; const Stream: TStream); begin if ANode.Data.Size < Integer(AFile.Header._ulMiniSectorCutoff) then AFile.GetDataFromMiniStream(ANode.Data.StartBlock, ANode.Data.Size, Stream) else AFile.GetDataFromStream(ANode.Data.StartBlock, ANode.Data.Size, Stream); end;
ãã®æé ã§ã¯ãè€åãã¡ã€ã«ãããã©ã«ããŒã«æœåºãããã°ã©ãã®ããŒãã転éãããã®ãµã€ãºã«åºã¥ããŠãäžèšã§å®è£ ããã¡ãœããã®1ã€ãåŒã³åºããŸãã
ã»ãšãã©ãã¹ãŠã®ããã«èŠããŸãããæåŸã®5çªç®ã®ã¹ããŒãžã¯æ®ããŸã-è€åãã¡ã€ã«ã®å
容å
šäœããã©ã«ããŒã«è§£åããŸãã
procedure Extract(Path: string; RootNodeIndex: Integer); var W: WideString; I: Integer; RootStorageNode, ChildStorageNode: TStorageElement; F: TFileStream; begin RootStorageNode := ATree.GetNode(RootNodeIndex); W := RootStorageNode.Data.Caption; case RootStorageNode.Data.PropertyType of STGTY_STORAGE: Path := Path + W + '\'; STGTY_STREAM: begin try ForceDirectories(Path); F := TFileStream.Create(Path + W, fmCreate); try GetStorageData(RootStorageNode, F); finally F.Free; end; except DebugLog.Add(Path + W); end; end; end; for I := 0 to RootStorageNode.VectorCount - 1 do begin ChildStorageNode := TStorageElement(RootStorageNode.GetVector(I).SlaveNode); if ChildStorageNode = nil then Continue; if ChildStorageNode.ID <> RootNodeIndex then Extract(Path, ChildStorageNode.ID); end; end;
ããŠãããã§ã³ã¡ã³ããªãã§ãã§ã«ãç§ãã¡ã¯ãã¹ãŠä»¥åã«èŠãŸãã-éåžžã®ã¢ã«ãŽãªãºã ã
äœæãããããžã§ã¯ããèµ·åããŠãWordããã¥ã¡ã³ãã«èšå®ãããšã次ã®ããã«ãªããŸãã

ãããŠãç§ãã¡å šå¡ããããæã«å ¥ããããã«ã¯ãããããããŸãïŒ

ãã¹ãŠã®ãã¡ã€ã«ã§ã¯ãããŸãããïŒ
ãšãŠãç°¡åã§ããããªãŒã®ååãèŠããšãã|ãã®åœ¢ã§ããã·ã¥ã衚瀺ãããŸãã ãCompObjãã®åã®ãã¡ã€ã«åãŸãã¯ç解ã§ããªãã¹ããŒã¹ã®åã
ãããã¯ãæåã®ç« ã§èšåããOLEçšã«äºçŽãããŠããæåã§ãïŒ0ã0x1FïŒãååã«ãã®ãããªæåãå«ããã¡ã€ã«ãäœæã§ããªããããã¹ããããããŸããããããã®ããŒã¿ã¯ãcannotread.logããšãããã°ã«æžã蟌ãŸããŸãã
ãã¡ãããããã¯ç°¡åã«åŠçã§ããŸããããã¢ã§ãåæ§ã§ãã
ãã®äŸã®ã³ãŒãã¯ããã©ã«ããŒã.. \ RawStorageReader \ã ã®ã¢ãŒã«ã€ãã«ãããŸãã
ãããããªãããããã¹ãŠæžããã®ã§ããïŒ
åã®ç« ã§æžããã¢ããªã±ãŒã·ã§ã³ã䜿çšããŠããã®ãã¡ã€ã«ãéããŸãããïŒ ".. \ç Žæãã\ corrupted_storage.bin"
次ã®ãããªãã®ã«ãªããŸãã

ããã§ã¯ãAPIããçŽæ¥ã第2ç« ã®èªè ãèªãã§ã¿ãŸãããã

æ²ãã¿ããã®åŸãã©ã®ãããªãã©ãã«ãçºçããããèŠãŠããã®ãã¡ã€ã«ãæ¢ã«RAWã¢ãŒãã§éããŸãã

ããããšã©ãŒãèªãã§ãã¹ã¿ãã¯ãèŠãŠãã ããïŒ

ãã¡ã€ã«ããããã£ã®èªã¿åã段éã§ãšã©ãŒãçºçããŸãããGetBlocké¢æ°ã§ReadBufferãå®è¡ã§ããŸããã§ããã
決å®ããŸãã
6.ããŒã¿ã®ãšã©ãŒãä¿®æ£ããå©çšå¯èœãªãã®ãã¹ãŠãèªã¿èŸŒãããšããŸãã
èšäºã®åé ã§ãWordã®ããã¥ã¡ã³ãã®ããŸããŸãªã埩å è ãã®ã³ããŒãå šäœã«ã€ããŠã話ããŸãããä»ãç§ãã¡ã¯ãããã®ãããªãã®ãæžããŸãã :)
ãããã®ãŠãŒãã£ãªãã£ã¯ãã¹ãŠ2ã€ã®ã¢ãŒãã§åäœããŸãã
- è€åãã¡ã€ã«ã®åœ¢åŒã«ã€ããŠç¥ã£ãŠããŸãã
- Wordãã¹ããªãŒã ã«ä¿åããããŒã¿åœ¢åŒã«ã€ããŠç¥ã£ãŠããŸãã
ãã¡ããã2çªç®ã®æ®µèœã«é¢ããæ å ±ã¯ãããŸããããå¿ èŠãããŸããããæåã®æ®µèœã«ã€ããŠã¯ã5çªç®ã®ç« ãèªãã åŸããåãã®ãšããã§ãã :)
:
- ( , )
- FAT
- TPoifsProperty
æåã®ãã®ã¯åŠçãããŸããããããããŸããå€åãFATãæ§ç¯ããæåã®ã»ã¯ã¿ãŒã®å€ãèšç®ããããšãããã¡ã³ãããã§ãããããç§ã¯ãã®ãããªãã®ãèŠãããšã¯ãããŸããã
2çªç®ã¯å®è³ªçã«æªåŠçã§ãã
FATã«ã»ã¯ã¿ãŒçªå·ãå«ãŸããŠããããšãããã£ãŠããããã次ã®æ¡ä»¶ã«ãã£ãŠç Žå£ãå€æã§ããŸãã次ã®å€ã¯ãENDOFCHAINå®æ°ïŒ-2ïŒããå°ããããFATé åã®ãµã€ãºãã倧ãããªããŸãã
倱æãããããã¯ã®å€ãENDOFCHAINå®æ°ã«å€æŽããããšã§ä¿®æ£ã§ããŸãããååãšããŠããã®ãããªä»å ¥ã®åŸã§ãããããã¡ããã»ã¯ã¿ãŒã¯éšåçã«èæ ®ããããã¡ã€ã«ããããã£ã®é åã¯æå°éã«ã¢ã¯ã»ã¹ã§ããŸãïŒå¹žéãªå Žåã§ãïŒã
3çªç®ã®ãªãã·ã§ã³ã¯åŠçäžã§ãã
倧ãŸãã«ãã»ã¯ã¿ãŒèªã¿åããšã©ãŒãçºçããFATã»ã«ã®ã¢ãã¬ã¹ã調ã¹ãŠãENDOFCHAINã«èšå®ããŸãããã¡ãããããã¯ããŒã¿ã®äžéšãåãåããŸãïŒ99ïŒ ã®ã±ãŒã¹ã殺ãããŸããïŒããå®éã«å©çšã§ãããã®ãèªã¿ãŸãã
4çªç®ã®ãªãã·ã§ã³ã¯åŠçãããŸããããã®ããŒã¿ã¯è€åãã¡ã€ã«ã«å±ããªããããåã«ä¿åããã ãã§ãå¶åŸ¡ã¯ããŸããïŒãµã€ãºã ãããªããªããŸãïŒã
åæãéå§ããŸãïŒ
è¯ãããšã«ã¯ã3çªç®ã®åé¡ã«ãã察åŠã§ããŸãããã€ãŸãã倱æããFATã€ã³ããã¯ã¹ã®æ°ãç¹å®ããä¿®æ£ããŸãã
RAWã¢ãŒãã§ããŒã¿ãæäœããæ¹æ³ãç¥ã£ãŠããã°ãããã¯é£ãããããŸããã
æåã«ãããŒã¿ãããã¯ã®èªã¿åãæé ãå€æŽããŸãã
function TPoifsFile.GetBlock(Adress: Integer): TPoifsBlock; var BlockOffset: Integer; begin BlockOffset := GetBlockOffset(Adress); if BlockOffset < FStream.Size then begin FStream.Position := BlockOffset; FStream.ReadBuffer(Result, SizeOf(TPoifsBlock)); end else raise Exception.Create('Wrong block offset at addres: ' + IntToStr(Adress)); end;
çªç¶äœããäžç·ã«æé·ããªãã£ãå Žåã圌女ã¯ãªãã»ããããã§ãã¯ããäŸå€ãçºçãããŸãããã
ReadPropsArrayããã·ãŒãžã£ã§2çªç®ã®å€æŽãè¡ããFATé åã®ç¶æ ãããå³å¯ã«å¶åŸ¡ããŸãã
function TPoifsFile.ReadPropsArray: Boolean; var I, J, Len, LastGood: Integer; PropsBlock: TPoifsPropsBlock; begin Result := True; // Len := 0; // , Property Set Storage J := FHeader._sectDirStart; LastGood := J; repeat if J = FREESECT then begin FixFatEntry(LastGood, ENDOFCHAIN); Break; end; // 4 Inc(Len, 4); SetLength(FPropsArray, Len); // try PropsBlock := TPoifsPropsBlock(GetBlock(J)); except FixFatEntry(LastGood, ENDOFCHAIN); Break; end; for I := 0 to 3 do FPropsArray[Len - 4 + I] := PropsBlock[I]; LastGood := J; // FAT J := FFat[J]; if J < ENDOFCHAIN then begin FixFatEntry(LastGood, ENDOFCHAIN); Break; end; until J = ENDOFCHAIN; end;
ããã§ã¯ãFixFatEntryããã·ãŒãžã£ãèšè¿°ããå¿ èŠããããŸãã
procedure TPoifsFile.FixFatEntry(FatIndex, NewValue: Integer); var J, Offset: Integer; begin // FAT J := FatIndex mod 128; Offset := FFatOffset[FatIndex] + J * 4; // FStream.Position := Offset; FStream.WriteBuffer(NewValue, SizeOf(Integer)); end;
å ã®ãã¡ã€ã«ã®FATãã§ãŒã³ã«å€æŽãå ããã®ã¯ã圌女ã®å©ããåããŠã§ãã
ã§ã¯ãäœãèµ·ãã£ãã®ãèŠãŠã¿ãŸãããã

⊠:)
, , , .
, , FixFatEntry FStream.WriteBuffer.
, , , , , , .
:)
: "..\RawStorageReader\PoifsWithRepair.pas" .
, .
7.
â , .
, , â , , , ( , ) .
â , .
, , ?
, , â , , :)
, , :
, , , , .
() .
, , , .
:
8 (, RAW ) 473 , .
, â 150 , .
24 , 12 .
ã«ãŠã³ãïŒ1æ¥150,000åã®æã¡äžã* 24æ¥* 12ãæ* 8幎= 345ãæ°çŸäžåã®æã¡äžãïŒå¹³åïŒã
å®éãç§ã®æå ã«ã¯ã¡ããã©473åã®ãåã°çŒãããã¡ã€ã«ããããŸãïŒæã«1ã2åçºçããããšããããŸãããæ°ãæã«ããã£ãŠèœã¡çãããšããããŸãïŒããããã®ãã¡ïŒãã®ç¹ãèæ ®ããå¿ èŠããããŸãïŒãçŽ100人ãbeatãããFATã䜿çšããŠããŸããïŒãããŠãç§ãèšã£ãããã«ãbeatãããããŒã«ãããã¯éåžžã«æªãã§ãïŒã
ãã®ãããFATã¬ãã«ã§ç Žãããæ°çŸã®ãã¡ã€ã«ã®ã»ãšãã©ãã¹ãŠãè€åãã¡ã€ã«ãåé€ããUnEraseãªã©ã®ãŠãŒãã£ãªãã£ã§åŸ©å ãããå°ããããŸããã
ãããŠãããããšã¯äœã®é¢ä¿ããããŸãã-åé€ããŸããã§ããã埩å ããããšã¯ã§ããŸããã
ãããã£ãŠããã®100åãè¿ããŠãèŠãŠã¿ãŸãããïŒè€åãã¡ã€ã«ãå£ãå¯èœæ§ã¯äœã§ããïŒ
ã¯ãã100äžåã®1-èšé²é床ã®éãCDã¯ãã®æ°ãããé »ç¹ã«å€±æããŸã:)
ä¿¡ããããªãïŒ
( , ) ?
?
â : .
«» â :)
, , â , ( , ).
, :
- , â , .
- AddVectoredExceptionHandler. â SEH. , , â . ( , False Alarm :)
, .
, " " .
: , ( 1024 ). , , NTFS? :)
é 匵ã£ãŠã:)
â (Rouse_)
, 2015