streams.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  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. Buffer: Pointer;
  113. BufferSize, i: LongInt;
  114. const
  115. MaxSize = $20000;
  116. begin
  117. Result:=0;
  118. if Count=0 then
  119. Source.Position:=0; // This WILL fail for non-seekable streams...
  120. BufferSize:=MaxSize;
  121. if (Count>0) and (Count<BufferSize) then
  122. BufferSize:=Count; // do not allocate more than needed
  123. GetMem(Buffer,BufferSize);
  124. try
  125. if Count=0 then
  126. repeat
  127. i:=Source.Read(buffer^,BufferSize);
  128. if i>0 then
  129. WriteBuffer(buffer^,i);
  130. Inc(Result,i);
  131. until i<BufferSize
  132. else
  133. while Count>0 do
  134. begin
  135. if Count>BufferSize then
  136. i:=BufferSize
  137. else
  138. i:=Count;
  139. Source.ReadBuffer(buffer^,i);
  140. WriteBuffer(buffer^,i);
  141. Dec(count,i);
  142. Inc(Result,i);
  143. end;
  144. finally
  145. FreeMem(Buffer);
  146. end;
  147. end;
  148. function TStream.ReadComponent(Instance: TComponent): TComponent;
  149. var
  150. Reader: TReader;
  151. begin
  152. Reader := TReader.Create(Self, 4096);
  153. try
  154. Result := Reader.ReadRootComponent(Instance);
  155. finally
  156. Reader.Free;
  157. end;
  158. end;
  159. function TStream.ReadComponentRes(Instance: TComponent): TComponent;
  160. begin
  161. ReadResHeader;
  162. Result := ReadComponent(Instance);
  163. end;
  164. procedure TStream.WriteComponent(Instance: TComponent);
  165. begin
  166. WriteDescendent(Instance, nil);
  167. end;
  168. procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
  169. begin
  170. WriteDescendentRes(ResName, Instance, nil);
  171. end;
  172. procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
  173. var
  174. Driver : TAbstractObjectWriter;
  175. Writer : TWriter;
  176. begin
  177. Driver := TBinaryObjectWriter.Create(Self, 4096);
  178. Try
  179. Writer := TWriter.Create(Driver);
  180. Try
  181. Writer.WriteDescendent(Instance, Ancestor);
  182. Finally
  183. Writer.Destroy;
  184. end;
  185. Finally
  186. Driver.Free;
  187. end;
  188. end;
  189. procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  190. var
  191. FixupInfo: Integer;
  192. begin
  193. { Write a resource header }
  194. WriteResourceHeader(ResName, FixupInfo);
  195. { Write the instance itself }
  196. WriteDescendent(Instance, Ancestor);
  197. { Insert the correct resource size into the resource header }
  198. FixupResourceHeader(FixupInfo);
  199. end;
  200. procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
  201. var
  202. ResType, Flags : word;
  203. begin
  204. ResType:=NtoLE(word($000A));
  205. Flags:=NtoLE(word($1030));
  206. { Note: This is a Windows 16 bit resource }
  207. { Numeric resource type }
  208. WriteByte($ff);
  209. { Application defined data }
  210. WriteWord(ResType);
  211. { write the name as asciiz }
  212. WriteBuffer(ResName[1],length(ResName));
  213. WriteByte(0);
  214. { Movable, Pure and Discardable }
  215. WriteWord(Flags);
  216. { Placeholder for the resource size }
  217. WriteDWord(0);
  218. { Return current stream position so that the resource size can be
  219. inserted later }
  220. FixupInfo := Position;
  221. end;
  222. procedure TStream.FixupResourceHeader(FixupInfo: Integer);
  223. var
  224. ResSize,TmpResSize : Integer;
  225. begin
  226. ResSize := Position - FixupInfo;
  227. TmpResSize := NtoLE(longword(ResSize));
  228. { Insert the correct resource size into the placeholder written by
  229. WriteResourceHeader }
  230. Position := FixupInfo - 4;
  231. WriteDWord(TmpResSize);
  232. { Seek back to the end of the resource }
  233. Position := FixupInfo + ResSize;
  234. end;
  235. procedure TStream.ReadResHeader;
  236. var
  237. ResType, Flags : word;
  238. begin
  239. try
  240. { Note: This is a Windows 16 bit resource }
  241. { application specific resource ? }
  242. if ReadByte<>$ff then
  243. raise EInvalidImage.Create(SInvalidImage);
  244. ResType:=LEtoN(ReadWord);
  245. if ResType<>$000a then
  246. raise EInvalidImage.Create(SInvalidImage);
  247. { read name }
  248. while ReadByte<>0 do
  249. ;
  250. { check the access specifier }
  251. Flags:=LEtoN(ReadWord);
  252. if Flags<>$1030 then
  253. raise EInvalidImage.Create(SInvalidImage);
  254. { ignore the size }
  255. ReadDWord;
  256. except
  257. on EInvalidImage do
  258. raise;
  259. else
  260. raise EInvalidImage.create(SInvalidImage);
  261. end;
  262. end;
  263. function TStream.ReadByte : Byte;
  264. var
  265. b : Byte;
  266. begin
  267. ReadBuffer(b,1);
  268. ReadByte:=b;
  269. end;
  270. function TStream.ReadWord : Word;
  271. var
  272. w : Word;
  273. begin
  274. ReadBuffer(w,2);
  275. ReadWord:=w;
  276. end;
  277. function TStream.ReadDWord : Cardinal;
  278. var
  279. d : Cardinal;
  280. begin
  281. ReadBuffer(d,4);
  282. ReadDWord:=d;
  283. end;
  284. function TStream.ReadQWord: QWord;
  285. var
  286. q: QWord;
  287. begin
  288. ReadBuffer(q,8);
  289. ReadQWord:=q;
  290. end;
  291. Function TStream.ReadAnsiString : String;
  292. Var
  293. TheSize : Longint;
  294. P : PByte ;
  295. begin
  296. ReadBuffer (TheSize,SizeOf(TheSize));
  297. SetLength(Result,TheSize);
  298. // Illegal typecast if no AnsiStrings defined.
  299. if TheSize>0 then
  300. begin
  301. ReadBuffer (Pointer(Result)^,TheSize);
  302. P:=Pointer(Result)+TheSize;
  303. p^:=0;
  304. end;
  305. end;
  306. Procedure TStream.WriteAnsiString (const S : String);
  307. Var L : Longint;
  308. begin
  309. L:=Length(S);
  310. WriteBuffer (L,SizeOf(L));
  311. WriteBuffer (Pointer(S)^,L);
  312. end;
  313. procedure TStream.WriteByte(b : Byte);
  314. begin
  315. WriteBuffer(b,1);
  316. end;
  317. procedure TStream.WriteWord(w : Word);
  318. begin
  319. WriteBuffer(w,2);
  320. end;
  321. procedure TStream.WriteDWord(d : Cardinal);
  322. begin
  323. WriteBuffer(d,4);
  324. end;
  325. procedure TStream.WriteQWord(q: QWord);
  326. begin
  327. WriteBuffer(q,8);
  328. end;
  329. {****************************************************************************}
  330. {* THandleStream *}
  331. {****************************************************************************}
  332. Constructor THandleStream.Create(AHandle: THandle);
  333. begin
  334. FHandle:=AHandle;
  335. end;
  336. function THandleStream.Read(var Buffer; Count: Longint): Longint;
  337. begin
  338. Result:=FileRead(FHandle,Buffer,Count);
  339. If Result=-1 then Result:=0;
  340. end;
  341. function THandleStream.Write(const Buffer; Count: Longint): Longint;
  342. begin
  343. Result:=FileWrite (FHandle,Buffer,Count);
  344. If Result=-1 then Result:=0;
  345. end;
  346. Procedure THandleStream.SetSize(NewSize: Longint);
  347. begin
  348. SetSize(Int64(NewSize));
  349. end;
  350. Procedure THandleStream.SetSize(const NewSize: Int64);
  351. begin
  352. FileTruncate(FHandle,NewSize);
  353. end;
  354. function THandleStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  355. begin
  356. Result:=FileSeek(FHandle,Offset,ord(Origin));
  357. end;
  358. {****************************************************************************}
  359. {* TFileStream *}
  360. {****************************************************************************}
  361. constructor TFileStream.Create(const AFileName: string; Mode: Word);
  362. begin
  363. FFileName:=AFileName;
  364. If Mode=fmcreate then
  365. FHandle:=FileCreate(AFileName)
  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. constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  375. begin
  376. FFileName:=AFileName;
  377. If Mode=fmcreate then
  378. FHandle:=FileCreate(AFileName,Rights)
  379. else
  380. FHAndle:=FileOpen(AFileName,Mode);
  381. If (THandle(FHandle)=feInvalidHandle) then
  382. If Mode=fmcreate then
  383. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  384. else
  385. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  386. end;
  387. destructor TFileStream.Destroy;
  388. begin
  389. FileClose(FHandle);
  390. end;
  391. {****************************************************************************}
  392. {* TCustomMemoryStream *}
  393. {****************************************************************************}
  394. procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: PtrInt);
  395. begin
  396. FMemory:=Ptr;
  397. FSize:=ASize;
  398. end;
  399. function TCustomMemoryStream.GetSize: Int64;
  400. begin
  401. Result:=FSize;
  402. end;
  403. function TCustomMemoryStream.Read(var Buffer; Count: LongInt): LongInt;
  404. begin
  405. Result:=0;
  406. If (FSize>0) and (FPosition<Fsize) and (FPosition>=0) then
  407. begin
  408. Result:=FSize-FPosition;
  409. If Result>Count then Result:=Count;
  410. Move ((FMemory+FPosition)^,Buffer,Result);
  411. FPosition:=Fposition+Result;
  412. end;
  413. end;
  414. function TCustomMemoryStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  415. begin
  416. Case Word(Origin) of
  417. soFromBeginning : FPosition:=Offset;
  418. soFromEnd : FPosition:=FSize+Offset;
  419. soFromCurrent : FPosition:=FPosition+Offset;
  420. end;
  421. Result:=FPosition;
  422. {$IFDEF DEBUG}
  423. if Result < 0 then
  424. raise Exception.Create('TCustomMemoryStream');
  425. {$ENDIF}
  426. end;
  427. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  428. begin
  429. if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
  430. end;
  431. procedure TCustomMemoryStream.SaveToFile(const FileName: string);
  432. Var S : TFileStream;
  433. begin
  434. S:=TFileStream.Create (FileName,fmCreate);
  435. Try
  436. SaveToStream(S);
  437. finally
  438. S.free;
  439. end;
  440. end;
  441. {****************************************************************************}
  442. {* TMemoryStream *}
  443. {****************************************************************************}
  444. Const TMSGrow = 4096; { Use 4k blocks. }
  445. procedure TMemoryStream.SetCapacity(NewCapacity: PtrInt);
  446. begin
  447. SetPointer (Realloc(NewCapacity),Fsize);
  448. FCapacity:=NewCapacity;
  449. end;
  450. function TMemoryStream.Realloc(var NewCapacity: PtrInt): Pointer;
  451. begin
  452. If NewCapacity<0 Then
  453. NewCapacity:=0
  454. else
  455. begin
  456. // if growing, grow at least a quarter
  457. if (NewCapacity>FCapacity) and (NewCapacity < (5*FCapacity) div 4) then
  458. NewCapacity := (5*FCapacity) div 4;
  459. // round off to block size.
  460. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  461. end;
  462. // Only now check !
  463. If NewCapacity=FCapacity then
  464. Result:=FMemory
  465. else
  466. begin
  467. Result:=Reallocmem(FMemory,Newcapacity);
  468. If (Result=Nil) and (Newcapacity>0) then
  469. Raise EStreamError.Create(SMemoryStreamError);
  470. end;
  471. end;
  472. destructor TMemoryStream.Destroy;
  473. begin
  474. Clear;
  475. Inherited Destroy;
  476. end;
  477. procedure TMemoryStream.Clear;
  478. begin
  479. FSize:=0;
  480. FPosition:=0;
  481. SetCapacity (0);
  482. end;
  483. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  484. begin
  485. Stream.Position:=0;
  486. SetSize(Stream.Size);
  487. If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
  488. end;
  489. procedure TMemoryStream.LoadFromFile(const FileName: string);
  490. Var S : TFileStream;
  491. begin
  492. S:=TFileStream.Create (FileName,fmOpenRead or fmShareDenyWrite);
  493. Try
  494. LoadFromStream(S);
  495. finally
  496. S.free;
  497. end;
  498. end;
  499. procedure TMemoryStream.SetSize({$ifdef CPU64}const{$endif CPU64} NewSize: PtrInt);
  500. begin
  501. SetCapacity (NewSize);
  502. FSize:=NewSize;
  503. IF FPosition>FSize then
  504. FPosition:=FSize;
  505. end;
  506. function TMemoryStream.Write(const Buffer; Count: LongInt): LongInt;
  507. Var NewPos : PtrInt;
  508. begin
  509. If (Count=0) or (FPosition<0) then
  510. exit(0);
  511. NewPos:=FPosition+Count;
  512. If NewPos>Fsize then
  513. begin
  514. IF NewPos>FCapacity then
  515. SetCapacity (NewPos);
  516. FSize:=Newpos;
  517. end;
  518. System.Move (Buffer,(FMemory+FPosition)^,Count);
  519. FPosition:=NewPos;
  520. Result:=Count;
  521. end;
  522. {****************************************************************************}
  523. {* TStringStream *}
  524. {****************************************************************************}
  525. procedure TStringStream.SetSize(NewSize: Longint);
  526. begin
  527. Setlength(FDataString,NewSize);
  528. If FPosition>NewSize then FPosition:=NewSize;
  529. end;
  530. constructor TStringStream.Create(const AString: string);
  531. begin
  532. Inherited create;
  533. FDataString:=AString;
  534. end;
  535. function TStringStream.Read(var Buffer; Count: Longint): Longint;
  536. begin
  537. Result:=Length(FDataString)-FPosition;
  538. If Result>Count then Result:=Count;
  539. // This supposes FDataString to be of type AnsiString !
  540. Move (Pchar(FDataString)[FPosition],Buffer,Result);
  541. FPosition:=FPosition+Result;
  542. end;
  543. function TStringStream.ReadString(Count: Longint): string;
  544. Var NewLen : Longint;
  545. begin
  546. NewLen:=Length(FDataString)-FPosition;
  547. If NewLen>Count then NewLen:=Count;
  548. SetLength(Result,NewLen);
  549. Read (Pointer(Result)^,NewLen);
  550. end;
  551. function TStringStream.Seek(Offset: Longint; Origin: Word): Longint;
  552. begin
  553. Case Origin of
  554. soFromBeginning : FPosition:=Offset;
  555. soFromEnd : FPosition:=Length(FDataString)+Offset;
  556. soFromCurrent : FpoSition:=FPosition+Offset;
  557. end;
  558. If FPosition>Length(FDataString) then FPosition:=Length(FDataString);
  559. If FPosition<0 then FPosition:=0;
  560. Result:=FPosition;
  561. end;
  562. function TStringStream.Write(const Buffer; Count: Longint): Longint;
  563. begin
  564. Result:=Count;
  565. SetSize(FPosition+Count);
  566. // This supposes that FDataString is of type AnsiString)
  567. Move (Buffer,PChar(FDataString)[Fposition],Count);
  568. FPosition:=FPosition+Count;
  569. end;
  570. procedure TStringStream.WriteString(const AString: string);
  571. begin
  572. Write (PChar(Astring)[0],Length(AString));
  573. end;
  574. {****************************************************************************}
  575. {* TResourceStream *}
  576. {****************************************************************************}
  577. {$ifdef UNICODE}
  578. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PWideChar; NameIsID: Boolean);
  579. begin
  580. Res:=FindResource(Instance, Name, ResType);
  581. if Res=0 then
  582. if NameIsID then
  583. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  584. else
  585. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  586. Handle:=LoadResource(Instance,Res);
  587. if Handle=0 then
  588. if NameIsID then
  589. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  590. else
  591. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  592. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  593. end;
  594. constructor TResourceStream.Create(Instance: THandle; const ResName: WideString; ResType: PWideChar);
  595. begin
  596. inherited create;
  597. Initialize(Instance,PWideChar(ResName),ResType,False);
  598. end;
  599. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PWideChar);
  600. begin
  601. inherited create;
  602. Initialize(Instance,PWideChar(ResID),ResType,True);
  603. end;
  604. {$else UNICODE}
  605. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar; NameIsID: Boolean);
  606. begin
  607. Res:=FindResource(Instance, Name, ResType);
  608. if Res=0 then
  609. if NameIsID then
  610. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  611. else
  612. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  613. Handle:=LoadResource(Instance,Res);
  614. if Handle=0 then
  615. if NameIsID then
  616. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  617. else
  618. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  619. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  620. end;
  621. constructor TResourceStream.Create(Instance: THandle; const ResName: string; ResType: PChar);
  622. begin
  623. inherited create;
  624. Initialize(Instance,pchar(ResName),ResType,False);
  625. end;
  626. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
  627. begin
  628. inherited create;
  629. Initialize(Instance,pchar(PtrInt(ResID)),ResType,True);
  630. end;
  631. {$endif UNICODE}
  632. destructor TResourceStream.Destroy;
  633. begin
  634. UnlockResource(Handle);
  635. FreeResource(Handle);
  636. inherited destroy;
  637. end;
  638. {****************************************************************************}
  639. {* TOwnerStream *}
  640. {****************************************************************************}
  641. constructor TOwnerStream.Create(ASource: TStream);
  642. begin
  643. FSource:=ASource;
  644. end;
  645. destructor TOwnerStream.Destroy;
  646. begin
  647. If FOwner then
  648. FreeAndNil(FSource);
  649. inherited Destroy;
  650. end;
  651. {****************************************************************************}
  652. {* TStreamAdapter *}
  653. {****************************************************************************}
  654. constructor TStreamAdapter.Create(Stream: TStream; Ownership: TStreamOwnership = soReference);
  655. begin
  656. inherited Create;
  657. FStream:=Stream;
  658. FOwnership:=Ownership;
  659. m_bReverted:=false; // mantis 15003
  660. // http://www.tech-archive.net/Archive/German/microsoft.public.de.vc/2005-08/msg00791.html
  661. // http://code.google.com/p/ddab-lib/wiki/TPJIStreamWrapper
  662. end;
  663. destructor TStreamAdapter.Destroy;
  664. begin
  665. if StreamOwnership=soOwned then
  666. FreeAndNil(FStream);
  667. inherited Destroy;
  668. end;
  669. {$warnings off}
  670. function TStreamAdapter.Read(pv: Pointer; cb: DWORD; pcbRead: PDWORD): HResult; stdcall;
  671. var
  672. readcount: Longint;
  673. begin
  674. if m_bReverted then
  675. begin
  676. Result := STG_E_REVERTED;
  677. Exit;
  678. end;
  679. if pv = nil then
  680. begin
  681. Result := STG_E_INVALIDPOINTER;
  682. Exit;
  683. end;
  684. readcount := FStream.Read(pv^, cb);
  685. if pcbRead <> nil then pcbRead^ := readcount;
  686. Result := S_OK;
  687. end;
  688. function TStreamAdapter.Write(pv: Pointer; cb: DWORD; pcbWritten: PDWORD): HResult; stdcall;
  689. var
  690. writecount: Longint;
  691. begin
  692. if m_bReverted then
  693. begin
  694. Result := STG_E_REVERTED;
  695. Exit;
  696. end;
  697. if pv = nil then
  698. begin
  699. Result := STG_E_INVALIDPOINTER;
  700. Exit;
  701. end;
  702. writecount := FStream.Write(pv^, cb);
  703. if pcbWritten <> nil then pcbWritten^ := writecount;
  704. Result := S_OK;
  705. end;
  706. function TStreamAdapter.Seek(dlibMove: Largeint; dwOrigin: Longint; out libNewPosition: Largeint): HResult; stdcall;
  707. var
  708. newpos: Int64;
  709. begin
  710. if m_bReverted then
  711. begin
  712. Result := STG_E_REVERTED;
  713. Exit;
  714. end;
  715. case dwOrigin of
  716. STREAM_SEEK_SET: newpos := FStream.Seek(dlibMove, soBeginning);
  717. STREAM_SEEK_CUR: newpos := FStream.Seek(dlibMove, soCurrent);
  718. STREAM_SEEK_END: newpos := FStream.Seek(dlibMove, soEnd);
  719. else
  720. begin
  721. Result := STG_E_INVALIDFUNCTION;
  722. Exit;
  723. end;
  724. end;
  725. if @libNewPosition <> nil then
  726. libNewPosition := newpos;
  727. Result := S_OK;
  728. end;
  729. function TStreamAdapter.SetSize(libNewSize: Largeint): HResult; stdcall;
  730. begin
  731. if m_bReverted then
  732. begin
  733. Result := STG_E_REVERTED;
  734. Exit;
  735. end;
  736. if libNewSize<0 then
  737. begin
  738. Result := STG_E_INVALIDFUNCTION;
  739. Exit;
  740. end;
  741. try
  742. FStream.Size := libNewSize;
  743. Result := S_OK;
  744. except
  745. // TODO: return different error value according to exception like STG_E_MEDIUMFULL
  746. Result := E_FAIL;
  747. end;
  748. end;
  749. function TStreamAdapter.CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint; out cbWritten: Largeint): HResult; stdcall;
  750. var
  751. sz: dword;
  752. buffer : array[0..1023] of byte;
  753. begin
  754. if m_bReverted then
  755. begin
  756. Result := STG_E_REVERTED;
  757. Exit;
  758. end;
  759. // the method is similar to TStream.CopyFrom => use CopyFrom implementation
  760. cbWritten := 0;
  761. cbRead := 0;
  762. while cb > 0 do
  763. begin
  764. if (cb > sizeof(buffer)) then
  765. sz := sizeof(Buffer)
  766. else
  767. sz := cb;
  768. sz := FStream.Read(buffer, sz);
  769. inc(cbRead, sz);
  770. stm.Write(@buffer[0], sz, @sz);
  771. inc(cbWritten, sz);
  772. if sz = 0 then
  773. begin
  774. Result := E_FAIL;
  775. Exit;
  776. end;
  777. dec(cb, sz);
  778. end;
  779. Result := S_OK;
  780. end;
  781. function TStreamAdapter.Commit(grfCommitFlags: Longint): HResult; stdcall;
  782. begin
  783. if m_bReverted then
  784. Result := STG_E_REVERTED
  785. else
  786. Result := S_OK;
  787. end;
  788. function TStreamAdapter.Revert: HResult; stdcall;
  789. begin
  790. m_bReverted := True;
  791. Result := S_OK;
  792. end;
  793. function TStreamAdapter.LockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
  794. begin
  795. Result := STG_E_INVALIDFUNCTION;
  796. end;
  797. function TStreamAdapter.UnlockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
  798. begin
  799. Result := STG_E_INVALIDFUNCTION;
  800. end;
  801. function TStreamAdapter.Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult; stdcall;
  802. begin
  803. if m_bReverted then
  804. begin
  805. Result := STG_E_REVERTED;
  806. Exit;
  807. end;
  808. if grfStatFlag in [STATFLAG_DEFAULT,STATFLAG_NOOPEN,STATFLAG_NONAME] then
  809. begin
  810. if @statstg <> nil then
  811. begin
  812. fillchar(statstg, sizeof(TStatStg),#0);
  813. { //TODO handle pwcsName
  814. if grfStatFlag = STATFLAG_DEFAULT then
  815. runerror(217) //Result :={$ifdef windows} STG_E_INVALIDFLAG{$else}E_INVALID_FLAG{$endif}
  816. }
  817. statstg.dwType := STGTY_STREAM;
  818. statstg.cbSize := FStream.Size;
  819. statstg.grfLocksSupported := LOCK_WRITE;
  820. end;
  821. Result := S_OK;
  822. end else
  823. Result := STG_E_INVALIDFLAG
  824. end;
  825. function TStreamAdapter.Clone(out stm: IStream): HResult; stdcall;
  826. begin
  827. if m_bReverted then
  828. begin
  829. Result := STG_E_REVERTED;
  830. Exit;
  831. end;
  832. // don't raise an exception here return error value that function is not implemented
  833. // to implement this we need a clone method for TStream class
  834. Result := STG_E_UNIMPLEMENTEDFUNCTION;
  835. end;
  836. constructor TProxyStream.Create(const Stream: IStream);
  837. begin
  838. FStream := Stream;
  839. end;
  840. function TProxyStream.Read(var Buffer; Count: Longint): Longint;
  841. begin
  842. Check(FStream.Read(@Buffer, Count, @Result));
  843. end;
  844. function TProxyStream. Seek(const Offset: int64; Origin: TSeekOrigin): int64;
  845. begin
  846. Check(FStream.Seek(Offset, ord(Origin), result));
  847. end;
  848. function TProxyStream.Write(const Buffer; Count: Longint): Longint;
  849. begin
  850. Check(FStream.Write(@Buffer, Count, @Result));
  851. end;
  852. function TProxyStream.GetIStream: IStream;
  853. begin
  854. Result := FStream;
  855. end;
  856. procedure TProxyStream.Check(err:integer);
  857. var e : EInOutError;
  858. begin
  859. e:= EInOutError.Create('Proxystream.Check');
  860. e.Errorcode:=err;
  861. raise e;
  862. end;
  863. {$warnings on}