streams.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {****************************************************************************}
  11. {* TStream *}
  12. {****************************************************************************}
  13. procedure TStream.ReadNotImplemented;
  14. begin
  15. raise EStreamError.CreateFmt(SStreamNoReading, [ClassName]) at get_caller_addr(get_frame);
  16. end;
  17. procedure TStream.WriteNotImplemented;
  18. begin
  19. raise EStreamError.CreateFmt(SStreamNoWriting, [ClassName]) at get_caller_addr(get_frame);
  20. end;
  21. function TStream.Read(var Buffer; Count: Longint): Longint;
  22. begin
  23. ReadNotImplemented;
  24. Result := 0;
  25. end;
  26. function TStream.Write(const Buffer; Count: Longint): Longint;
  27. begin
  28. WriteNotImplemented;
  29. Result := 0;
  30. end;
  31. function TStream.GetPosition: Int64;
  32. begin
  33. Result:=Seek(0,soCurrent);
  34. end;
  35. procedure TStream.SetPosition(const Pos: Int64);
  36. begin
  37. Seek(pos,soBeginning);
  38. end;
  39. procedure TStream.SetSize64(const NewSize: Int64);
  40. begin
  41. // Required because can't use overloaded functions in properties
  42. SetSize(NewSize);
  43. end;
  44. function TStream.GetSize: Int64;
  45. var
  46. p : int64;
  47. begin
  48. p:=Seek(0,soCurrent);
  49. GetSize:=Seek(0,soEnd);
  50. Seek(p,soBeginning);
  51. end;
  52. procedure TStream.SetSize(NewSize: Longint);
  53. begin
  54. // We do nothing. Pipe streams don't support this
  55. // As wel as possible read-ony streams !!
  56. end;
  57. procedure TStream.SetSize(const NewSize: Int64);
  58. begin
  59. // Backwards compatibility that calls the longint SetSize
  60. if (NewSize<Low(longint)) or
  61. (NewSize>High(longint)) then
  62. raise ERangeError.Create(SRangeError);
  63. SetSize(longint(NewSize));
  64. end;
  65. function TStream.Seek(Offset: Longint; Origin: Word): Longint;
  66. type
  67. TSeek64 = function(const offset:Int64;Origin:TSeekorigin):Int64 of object;
  68. var
  69. CurrSeek,
  70. TStreamSeek : TSeek64;
  71. CurrClass : TClass;
  72. begin
  73. // Redirect calls to 64bit Seek, but we can't call the 64bit Seek
  74. // from TStream, because then we end up in an infinite loop
  75. CurrSeek:=nil;
  76. CurrClass:=Classtype;
  77. while (CurrClass<>nil) and
  78. (CurrClass<>TStream) do
  79. CurrClass:=CurrClass.Classparent;
  80. if CurrClass<>nil then
  81. begin
  82. CurrSeek:[email protected];
  83. TStreamSeek:=@TStream(@CurrClass).Seek;
  84. if TMethod(TStreamSeek).Code=TMethod(CurrSeek).Code then
  85. CurrSeek:=nil;
  86. end;
  87. if CurrSeek<>nil then
  88. Result:=Seek(Int64(offset),TSeekOrigin(origin))
  89. else
  90. raise EStreamError.CreateFmt(SSeekNotImplemented,[ClassName]);
  91. end;
  92. function TStream.Seek(const Offset: Int64; Origin: TSeekorigin): Int64;
  93. begin
  94. // Backwards compatibility that calls the longint Seek
  95. if (Offset<Low(longint)) or
  96. (Offset>High(longint)) then
  97. raise ERangeError.Create(SRangeError);
  98. Result:=Seek(longint(Offset),ord(Origin));
  99. end;
  100. procedure TStream.ReadBuffer(var Buffer; Count: Longint);
  101. begin
  102. if Read(Buffer,Count)<Count then
  103. Raise EReadError.Create(SReadError);
  104. end;
  105. procedure TStream.WriteBuffer(const Buffer; Count: Longint);
  106. begin
  107. if Write(Buffer,Count)<Count then
  108. Raise EWriteError.Create(SWriteError);
  109. end;
  110. function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
  111. var
  112. i : Int64;
  113. buffer : array[0..1023] of byte;
  114. begin
  115. CopyFrom:=0;
  116. If (Count=0) then
  117. begin
  118. // This WILL fail for non-seekable streams...
  119. Source.Position:=0;
  120. Count:=Source.Size;
  121. end;
  122. while Count>0 do
  123. begin
  124. if (Count>sizeof(buffer)) then
  125. i:=sizeof(Buffer)
  126. else
  127. i:=Count;
  128. i:=Source.Read(buffer,i);
  129. i:=Write(buffer,i);
  130. if i=0 then break;
  131. dec(count,i);
  132. CopyFrom:=CopyFrom+i;
  133. end;
  134. end;
  135. function TStream.ReadComponent(Instance: TComponent): TComponent;
  136. var
  137. Reader: TReader;
  138. begin
  139. Reader := TReader.Create(Self, 4096);
  140. try
  141. Result := Reader.ReadRootComponent(Instance);
  142. finally
  143. Reader.Free;
  144. end;
  145. end;
  146. function TStream.ReadComponentRes(Instance: TComponent): TComponent;
  147. begin
  148. ReadResHeader;
  149. Result := ReadComponent(Instance);
  150. end;
  151. procedure TStream.WriteComponent(Instance: TComponent);
  152. begin
  153. WriteDescendent(Instance, nil);
  154. end;
  155. procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
  156. begin
  157. WriteDescendentRes(ResName, Instance, nil);
  158. end;
  159. procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
  160. var
  161. Driver : TAbstractObjectWriter;
  162. Writer : TWriter;
  163. begin
  164. Driver := TBinaryObjectWriter.Create(Self, 4096);
  165. Try
  166. Writer := TWriter.Create(Driver);
  167. Try
  168. Writer.WriteDescendent(Instance, Ancestor);
  169. Finally
  170. Writer.Destroy;
  171. end;
  172. Finally
  173. Driver.Free;
  174. end;
  175. end;
  176. procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  177. var
  178. FixupInfo: Integer;
  179. begin
  180. { Write a resource header }
  181. WriteResourceHeader(ResName, FixupInfo);
  182. { Write the instance itself }
  183. WriteDescendent(Instance, Ancestor);
  184. { Insert the correct resource size into the resource header }
  185. FixupResourceHeader(FixupInfo);
  186. end;
  187. procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
  188. var
  189. ResType, Flags : word;
  190. begin
  191. ResType:=NtoLE(word($000A));
  192. Flags:=NtoLE(word($1030));
  193. { Note: This is a Windows 16 bit resource }
  194. { Numeric resource type }
  195. WriteByte($ff);
  196. { Application defined data }
  197. WriteWord(ResType);
  198. { write the name as asciiz }
  199. WriteBuffer(ResName[1],length(ResName));
  200. WriteByte(0);
  201. { Movable, Pure and Discardable }
  202. WriteWord(Flags);
  203. { Placeholder for the resource size }
  204. WriteDWord(0);
  205. { Return current stream position so that the resource size can be
  206. inserted later }
  207. FixupInfo := Position;
  208. end;
  209. procedure TStream.FixupResourceHeader(FixupInfo: Integer);
  210. var
  211. ResSize,TmpResSize : Integer;
  212. begin
  213. ResSize := Position - FixupInfo;
  214. TmpResSize := NtoLE(longword(ResSize));
  215. { Insert the correct resource size into the placeholder written by
  216. WriteResourceHeader }
  217. Position := FixupInfo - 4;
  218. WriteDWord(TmpResSize);
  219. { Seek back to the end of the resource }
  220. Position := FixupInfo + ResSize;
  221. end;
  222. procedure TStream.ReadResHeader;
  223. var
  224. ResType, Flags : word;
  225. begin
  226. try
  227. { Note: This is a Windows 16 bit resource }
  228. { application specific resource ? }
  229. if ReadByte<>$ff then
  230. raise EInvalidImage.Create(SInvalidImage);
  231. ResType:=LEtoN(ReadWord);
  232. if ResType<>$000a then
  233. raise EInvalidImage.Create(SInvalidImage);
  234. { read name }
  235. while ReadByte<>0 do
  236. ;
  237. { check the access specifier }
  238. Flags:=LEtoN(ReadWord);
  239. if Flags<>$1030 then
  240. raise EInvalidImage.Create(SInvalidImage);
  241. { ignore the size }
  242. ReadDWord;
  243. except
  244. on EInvalidImage do
  245. raise;
  246. else
  247. raise EInvalidImage.create(SInvalidImage);
  248. end;
  249. end;
  250. function TStream.ReadByte : Byte;
  251. var
  252. b : Byte;
  253. begin
  254. ReadBuffer(b,1);
  255. ReadByte:=b;
  256. end;
  257. function TStream.ReadWord : Word;
  258. var
  259. w : Word;
  260. begin
  261. ReadBuffer(w,2);
  262. ReadWord:=w;
  263. end;
  264. function TStream.ReadDWord : Cardinal;
  265. var
  266. d : Cardinal;
  267. begin
  268. ReadBuffer(d,4);
  269. ReadDWord:=d;
  270. end;
  271. function TStream.ReadQWord: QWord;
  272. var
  273. q: QWord;
  274. begin
  275. ReadBuffer(q,8);
  276. ReadQWord:=q;
  277. end;
  278. Function TStream.ReadAnsiString : String;
  279. Var
  280. TheSize : Longint;
  281. P : PByte ;
  282. begin
  283. ReadBuffer (TheSize,SizeOf(TheSize));
  284. SetLength(Result,TheSize);
  285. // Illegal typecast if no AnsiStrings defined.
  286. if TheSize>0 then
  287. begin
  288. ReadBuffer (Pointer(Result)^,TheSize);
  289. P:=Pointer(Result)+TheSize;
  290. p^:=0;
  291. end;
  292. end;
  293. Procedure TStream.WriteAnsiString (const S : String);
  294. Var L : Longint;
  295. begin
  296. L:=Length(S);
  297. WriteBuffer (L,SizeOf(L));
  298. WriteBuffer (Pointer(S)^,L);
  299. end;
  300. procedure TStream.WriteByte(b : Byte);
  301. begin
  302. WriteBuffer(b,1);
  303. end;
  304. procedure TStream.WriteWord(w : Word);
  305. begin
  306. WriteBuffer(w,2);
  307. end;
  308. procedure TStream.WriteDWord(d : Cardinal);
  309. begin
  310. WriteBuffer(d,4);
  311. end;
  312. procedure TStream.WriteQWord(q: QWord);
  313. begin
  314. WriteBuffer(q,8);
  315. end;
  316. {****************************************************************************}
  317. {* THandleStream *}
  318. {****************************************************************************}
  319. Constructor THandleStream.Create(AHandle: Integer);
  320. begin
  321. FHandle:=AHandle;
  322. end;
  323. function THandleStream.Read(var Buffer; Count: Longint): Longint;
  324. begin
  325. Result:=FileRead(FHandle,Buffer,Count);
  326. If Result=-1 then Result:=0;
  327. end;
  328. function THandleStream.Write(const Buffer; Count: Longint): Longint;
  329. begin
  330. Result:=FileWrite (FHandle,Buffer,Count);
  331. If Result=-1 then Result:=0;
  332. end;
  333. Procedure THandleStream.SetSize(NewSize: Longint);
  334. begin
  335. SetSize(Int64(NewSize));
  336. end;
  337. Procedure THandleStream.SetSize(const NewSize: Int64);
  338. begin
  339. FileTruncate(FHandle,NewSize);
  340. end;
  341. function THandleStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  342. begin
  343. Result:=FileSeek(FHandle,Offset,ord(Origin));
  344. end;
  345. {****************************************************************************}
  346. {* TFileStream *}
  347. {****************************************************************************}
  348. constructor TFileStream.Create(const AFileName: string; Mode: Word);
  349. begin
  350. FFileName:=AFileName;
  351. If Mode=fmcreate then
  352. FHandle:=FileCreate(AFileName)
  353. else
  354. FHAndle:=FileOpen(AFileName,Mode);
  355. If (THandle(FHandle)=feInvalidHandle) then
  356. If Mode=fmcreate then
  357. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  358. else
  359. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  360. end;
  361. constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  362. begin
  363. FFileName:=AFileName;
  364. If Mode=fmcreate then
  365. FHandle:=FileCreate(AFileName,Rights)
  366. else
  367. FHAndle:=FileOpen(AFileName,Mode);
  368. If (THandle(FHandle)=feInvalidHandle) then
  369. If Mode=fmcreate then
  370. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  371. else
  372. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  373. end;
  374. destructor TFileStream.Destroy;
  375. begin
  376. FileClose(FHandle);
  377. end;
  378. {****************************************************************************}
  379. {* TCustomMemoryStream *}
  380. {****************************************************************************}
  381. procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: PtrInt);
  382. begin
  383. FMemory:=Ptr;
  384. FSize:=ASize;
  385. end;
  386. function TCustomMemoryStream.GetSize: Int64;
  387. begin
  388. Result:=FSize;
  389. end;
  390. function TCustomMemoryStream.Read(var Buffer; Count: LongInt): LongInt;
  391. begin
  392. Result:=0;
  393. If (FSize>0) and (FPosition<Fsize) and (FPosition>=0) then
  394. begin
  395. Result:=FSize-FPosition;
  396. If Result>Count then Result:=Count;
  397. Move ((FMemory+FPosition)^,Buffer,Result);
  398. FPosition:=Fposition+Result;
  399. end;
  400. end;
  401. function TCustomMemoryStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  402. begin
  403. Case Word(Origin) of
  404. soFromBeginning : FPosition:=Offset;
  405. soFromEnd : FPosition:=FSize+Offset;
  406. soFromCurrent : FPosition:=FPosition+Offset;
  407. end;
  408. Result:=FPosition;
  409. {$IFDEF DEBUG}
  410. if Result < 0 then
  411. raise Exception.Create('TCustomMemoryStream');
  412. {$ENDIF}
  413. end;
  414. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  415. begin
  416. if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
  417. end;
  418. procedure TCustomMemoryStream.SaveToFile(const FileName: string);
  419. Var S : TFileStream;
  420. begin
  421. S:=TFileStream.Create (FileName,fmCreate);
  422. Try
  423. SaveToStream(S);
  424. finally
  425. S.free;
  426. end;
  427. end;
  428. {****************************************************************************}
  429. {* TMemoryStream *}
  430. {****************************************************************************}
  431. Const TMSGrow = 4096; { Use 4k blocks. }
  432. procedure TMemoryStream.SetCapacity(NewCapacity: PtrInt);
  433. begin
  434. SetPointer (Realloc(NewCapacity),Fsize);
  435. FCapacity:=NewCapacity;
  436. end;
  437. function TMemoryStream.Realloc(var NewCapacity: PtrInt): Pointer;
  438. begin
  439. If NewCapacity<0 Then
  440. NewCapacity:=0
  441. else
  442. begin
  443. // if growing, grow at least a quarter
  444. if (NewCapacity>FCapacity) and (NewCapacity < (5*FCapacity) div 4) then
  445. NewCapacity := (5*FCapacity) div 4;
  446. // round off to block size.
  447. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  448. end;
  449. // Only now check !
  450. If NewCapacity=FCapacity then
  451. Result:=FMemory
  452. else
  453. begin
  454. Result:=Reallocmem(FMemory,Newcapacity);
  455. If (Result=Nil) and (Newcapacity>0) then
  456. Raise EStreamError.Create(SMemoryStreamError);
  457. end;
  458. end;
  459. destructor TMemoryStream.Destroy;
  460. begin
  461. Clear;
  462. Inherited Destroy;
  463. end;
  464. procedure TMemoryStream.Clear;
  465. begin
  466. FSize:=0;
  467. FPosition:=0;
  468. SetCapacity (0);
  469. end;
  470. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  471. begin
  472. Stream.Position:=0;
  473. SetSize(Stream.Size);
  474. If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
  475. end;
  476. procedure TMemoryStream.LoadFromFile(const FileName: string);
  477. Var S : TFileStream;
  478. begin
  479. S:=TFileStream.Create (FileName,fmOpenRead or fmShareDenyWrite);
  480. Try
  481. LoadFromStream(S);
  482. finally
  483. S.free;
  484. end;
  485. end;
  486. procedure TMemoryStream.SetSize({$ifdef CPU64}const{$endif CPU64} NewSize: PtrInt);
  487. begin
  488. SetCapacity (NewSize);
  489. FSize:=NewSize;
  490. IF FPosition>FSize then
  491. FPosition:=FSize;
  492. end;
  493. function TMemoryStream.Write(const Buffer; Count: LongInt): LongInt;
  494. Var NewPos : PtrInt;
  495. begin
  496. If (Count=0) or (FPosition<0) then
  497. exit(0);
  498. NewPos:=FPosition+Count;
  499. If NewPos>Fsize then
  500. begin
  501. IF NewPos>FCapacity then
  502. SetCapacity (NewPos);
  503. FSize:=Newpos;
  504. end;
  505. System.Move (Buffer,(FMemory+FPosition)^,Count);
  506. FPosition:=NewPos;
  507. Result:=Count;
  508. end;
  509. {****************************************************************************}
  510. {* TStringStream *}
  511. {****************************************************************************}
  512. procedure TStringStream.SetSize(NewSize: Longint);
  513. begin
  514. Setlength(FDataString,NewSize);
  515. If FPosition>NewSize then FPosition:=NewSize;
  516. end;
  517. constructor TStringStream.Create(const AString: string);
  518. begin
  519. Inherited create;
  520. FDataString:=AString;
  521. end;
  522. function TStringStream.Read(var Buffer; Count: Longint): Longint;
  523. begin
  524. Result:=Length(FDataString)-FPosition;
  525. If Result>Count then Result:=Count;
  526. // This supposes FDataString to be of type AnsiString !
  527. Move (Pchar(FDataString)[FPosition],Buffer,Result);
  528. FPosition:=FPosition+Result;
  529. end;
  530. function TStringStream.ReadString(Count: Longint): string;
  531. Var NewLen : Longint;
  532. begin
  533. NewLen:=Length(FDataString)-FPosition;
  534. If NewLen>Count then NewLen:=Count;
  535. SetLength(Result,NewLen);
  536. Read (Pointer(Result)^,NewLen);
  537. end;
  538. function TStringStream.Seek(Offset: Longint; Origin: Word): Longint;
  539. begin
  540. Case Origin of
  541. soFromBeginning : FPosition:=Offset;
  542. soFromEnd : FPosition:=Length(FDataString)+Offset;
  543. soFromCurrent : FpoSition:=FPosition+Offset;
  544. end;
  545. If FPosition>Length(FDataString) then FPosition:=Length(FDataString);
  546. If FPosition<0 then FPosition:=0;
  547. Result:=FPosition;
  548. end;
  549. function TStringStream.Write(const Buffer; Count: Longint): Longint;
  550. begin
  551. Result:=Count;
  552. SetSize(FPosition+Count);
  553. // This supposes that FDataString is of type AnsiString)
  554. Move (Buffer,PChar(FDataString)[Fposition],Count);
  555. FPosition:=FPosition+Count;
  556. end;
  557. procedure TStringStream.WriteString(const AString: string);
  558. begin
  559. Write (PChar(Astring)[0],Length(AString));
  560. end;
  561. {****************************************************************************}
  562. {* TResourceStream *}
  563. {****************************************************************************}
  564. {$ifdef UNICODE}
  565. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PWideChar);
  566. begin
  567. Res:=FindResource(Instance, Name, ResType);
  568. if Res=0 then
  569. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  570. Handle:=LoadResource(Instance,Res);
  571. if Handle=0 then
  572. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  573. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  574. end;
  575. constructor TResourceStream.Create(Instance: THandle; const ResName: WideString; ResType: PWideChar);
  576. begin
  577. inherited create;
  578. Initialize(Instance,PWideChar(ResName),ResType);
  579. end;
  580. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PWideChar);
  581. begin
  582. inherited create;
  583. Initialize(Instance,PWideChar(ResID),ResType);
  584. end;
  585. {$else UNICODE}
  586. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar);
  587. begin
  588. Res:=FindResource(Instance, Name, ResType);
  589. if Res=0 then
  590. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  591. Handle:=LoadResource(Instance,Res);
  592. if Handle=0 then
  593. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  594. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  595. end;
  596. constructor TResourceStream.Create(Instance: THandle; const ResName: string; ResType: PChar);
  597. begin
  598. inherited create;
  599. Initialize(Instance,pchar(ResName),ResType);
  600. end;
  601. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
  602. begin
  603. inherited create;
  604. Initialize(Instance,pchar(PtrInt(ResID)),ResType);
  605. end;
  606. {$endif UNICODE}
  607. destructor TResourceStream.Destroy;
  608. begin
  609. UnlockResource(Handle);
  610. FreeResource(Handle);
  611. inherited destroy;
  612. end;
  613. {****************************************************************************}
  614. {* TOwnerStream *}
  615. {****************************************************************************}
  616. constructor TOwnerStream.Create(ASource: TStream);
  617. begin
  618. FSource:=ASource;
  619. end;
  620. destructor TOwnerStream.Destroy;
  621. begin
  622. If FOwner then
  623. FreeAndNil(FSource);
  624. inherited Destroy;
  625. end;
  626. {****************************************************************************}
  627. {* TStreamAdapter *}
  628. {****************************************************************************}
  629. constructor TStreamAdapter.Create(Stream: TStream; Ownership: TStreamOwnership = soReference);
  630. begin
  631. inherited Create;
  632. FStream:=Stream;
  633. FOwnership:=Ownership;
  634. m_bReverted:=false; // mantis 15003
  635. // http://www.tech-archive.net/Archive/German/microsoft.public.de.vc/2005-08/msg00791.html
  636. // http://code.google.com/p/ddab-lib/wiki/TPJIStreamWrapper
  637. end;
  638. destructor TStreamAdapter.Destroy;
  639. begin
  640. if StreamOwnership=soOwned then
  641. FreeAndNil(FStream);
  642. inherited Destroy;
  643. end;
  644. {$warnings off}
  645. function TStreamAdapter.Read(pv: Pointer; cb: DWORD; pcbRead: PDWORD): HResult; stdcall;
  646. var
  647. readcount: Longint;
  648. begin
  649. if m_bReverted then
  650. begin
  651. Result := STG_E_REVERTED;
  652. Exit;
  653. end;
  654. if pv = nil then
  655. begin
  656. Result := E_INVALIDARG;
  657. Exit;
  658. end;
  659. readcount := FStream.Read(pv^, cb);
  660. if pcbRead <> nil then pcbRead^ := readcount;
  661. Result := S_OK;
  662. end;
  663. function TStreamAdapter.Write(pv: Pointer; cb: DWORD; pcbWritten: PDWORD): HResult; stdcall;
  664. var
  665. writecount: Longint;
  666. begin
  667. if m_bReverted then
  668. begin
  669. Result := STG_E_REVERTED;
  670. Exit;
  671. end;
  672. if pv = nil then
  673. begin
  674. Result := E_INVALIDARG;
  675. Exit;
  676. end;
  677. writecount := FStream.Write(pv^, cb);
  678. if pcbWritten <> nil then pcbWritten^ := writecount;
  679. Result := S_OK;
  680. end;
  681. function TStreamAdapter.Seek(dlibMove: Largeint; dwOrigin: Longint; out libNewPosition: Largeint): HResult; stdcall;
  682. var
  683. newpos: Int64;
  684. begin
  685. if m_bReverted then
  686. begin
  687. Result := STG_E_REVERTED;
  688. Exit;
  689. end;
  690. case dwOrigin of
  691. STREAM_SEEK_SET: newpos := FStream.Seek(dlibMove, soBeginning);
  692. STREAM_SEEK_CUR: newpos := FStream.Seek(dlibMove, soCurrent);
  693. STREAM_SEEK_END: newpos := FStream.Seek(dlibMove, soEnd);
  694. else begin Result := E_INVALIDARG; exit; end;
  695. end;
  696. if @libNewPosition <> nil then
  697. libNewPosition := newpos;
  698. Result := S_OK;
  699. end;
  700. function TStreamAdapter.SetSize(libNewSize: Largeint): HResult; stdcall;
  701. begin
  702. if m_bReverted then
  703. begin
  704. Result := STG_E_REVERTED;
  705. Exit;
  706. end;
  707. runerror(217);
  708. end;
  709. function TStreamAdapter.CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint; out cbWritten: Largeint): HResult; stdcall;
  710. begin
  711. if m_bReverted then
  712. begin
  713. Result := STG_E_REVERTED;
  714. Exit;
  715. end;
  716. runerror(217);
  717. end;
  718. function TStreamAdapter.Commit(grfCommitFlags: Longint): HResult; stdcall;
  719. begin
  720. if m_bReverted then
  721. Result := STG_E_REVERTED
  722. else
  723. Result := S_OK;
  724. end;
  725. function TStreamAdapter.Revert: HResult; stdcall;
  726. begin
  727. m_bReverted := True;
  728. Result := S_OK;
  729. end;
  730. function TStreamAdapter.LockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
  731. begin
  732. Result := STG_E_INVALIDFUNCTION;
  733. end;
  734. function TStreamAdapter.UnlockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
  735. begin
  736. Result := STG_E_INVALIDFUNCTION;
  737. end;
  738. function TStreamAdapter.Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult; stdcall;
  739. begin
  740. if m_bReverted then
  741. begin
  742. Result := STG_E_REVERTED;
  743. Exit;
  744. end;
  745. if grfStatFlag in [STATFLAG_DEFAULT,STATFLAG_NOOPEN,STATFLAG_NONAME] then
  746. begin
  747. if @statstg <> nil then
  748. begin
  749. fillchar(statstg, sizeof(TStatStg),#0);
  750. { //TODO handle pwcsName
  751. if grfStatFlag = STATFLAG_DEFAULT then
  752. runerror(217) //Result :={$ifdef windows} STG_E_INVALIDFLAG{$else}E_INVALID_FLAG{$endif}
  753. }
  754. statstg.dwType := STGTY_STREAM;
  755. statstg.cbSize := FStream.Size;
  756. statstg.grfLocksSupported := LOCK_WRITE;
  757. end;
  758. Result := S_OK;
  759. end else
  760. Result := STG_E_INVALIDFLAG
  761. end;
  762. function TStreamAdapter.Clone(out stm: IStream): HResult; stdcall;
  763. begin
  764. if m_bReverted then
  765. begin
  766. Result := STG_E_REVERTED;
  767. Exit;
  768. end;
  769. runerror(217);
  770. end;
  771. constructor TProxyStream.Create(const Stream: IStream);
  772. begin
  773. FStream := Stream;
  774. end;
  775. function TProxyStream.Read(var Buffer; Count: Longint): Longint;
  776. begin
  777. Check(FStream.Read(@Buffer, Count, @Result));
  778. end;
  779. function TProxyStream.Seek(Offset: Longint; Origin: Word): Longint;
  780. var
  781. Pos: Int64;
  782. begin
  783. Check(FStream.Seek(Offset, Origin, Pos));
  784. Result := Pos;
  785. end;
  786. function TProxyStream.Write(const Buffer; Count: Longint): Longint;
  787. begin
  788. Check(FStream.Write(@Buffer, Count, @Result));
  789. end;
  790. function TProxyStream.GetIStream: IStream;
  791. begin
  792. Result := FStream;
  793. end;
  794. procedure TProxyStream.Check(err:integer);
  795. var e : EInOutError;
  796. begin
  797. e:= EInOutError.Create('Proxystream.Check');
  798. e.Errorcode:=err;
  799. raise e;
  800. end;
  801. {$warnings on}