2
0

varutils.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2001 by the Free Pascal development team
  4. Variant routines for non-windows oses.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { ---------------------------------------------------------------------
  12. Some general stuff: Error handling and so on.
  13. ---------------------------------------------------------------------}
  14. { we so ugly things with tvararray here }
  15. {$RANGECHECKS OFF}
  16. Procedure SetUnlockResult (P : PVarArray; Res : HResult);
  17. begin
  18. If Res=VAR_OK then
  19. Res:=SafeArrayUnlock(P)
  20. else
  21. SafeArrayUnlock(P);
  22. end;
  23. Procedure MakeWideString (Var P : PWideChar; W : WideString);
  24. begin
  25. P:=PWideChar(W);
  26. end;
  27. Procedure CopyAsWideString (Var PDest : PWideChar; PSource : PWideChar);
  28. begin
  29. WideString(Pointer(PDest)):=WideString(Pointer(PSource));
  30. end;
  31. { ---------------------------------------------------------------------
  32. Basic variant handling.
  33. ---------------------------------------------------------------------}
  34. function VariantInit(var Varg: TVarData): HRESULT;stdcall;
  35. begin
  36. With Varg do
  37. begin
  38. FillChar(VBytes, SizeOf(VBytes), 0);
  39. VType:=varEmpty;
  40. end;
  41. Result:=VAR_OK;
  42. end;
  43. function VariantClear(var Varg: TVarData): HRESULT;stdcall;
  44. begin
  45. With Varg do
  46. if (VType and varArray)=varArray then
  47. begin
  48. Result:=SafeArrayDestroy(VArray);
  49. if Result<>VAR_OK then
  50. exit;
  51. end
  52. else
  53. begin
  54. if (VType and varByRef) = 0 then
  55. case VType of
  56. varEmpty, varNull, varSmallint, varInteger, varSingle, varDouble, varWord,
  57. varCurrency, varDate, varError, varBoolean, varByte,VarShortInt,
  58. varInt64, VarLongWord,VarQWord:
  59. ;
  60. varOleStr:
  61. WideString(Pointer(VOleStr)):='';
  62. varDispatch,
  63. varUnknown:
  64. iinterface(vunknown):=nil;
  65. else
  66. exit(VAR_BADVARTYPE)
  67. end;
  68. end;
  69. Result:=VariantInit(Varg);
  70. end;
  71. function VariantCopy(var VargDest: TVarData; const VargSrc: TVarData): HRESULT;stdcall;
  72. begin
  73. if @VargSrc = @VargDest then
  74. Exit(VAR_OK);
  75. Result:=VariantClear(VargDest);
  76. if Result<>VAR_OK then
  77. exit;
  78. With VargSrc do
  79. begin
  80. if (VType and varArray) <> 0 then
  81. Result:=SafeArrayCopy(VArray,VargDest.VArray)
  82. else
  83. begin
  84. if (VType and varByRef) <> 0 then
  85. VArgDest.VPointer:=VPointer
  86. else
  87. case (VType and varTypeMask) of
  88. varEmpty, varNull:;
  89. varSmallint, varInteger, varSingle, varDouble, varCurrency, varWord,
  90. varDate, varError, varBoolean, varByte,VarShortInt,
  91. varInt64, VarLongWord,VarQWord:
  92. Move(VBytes, VargDest.VBytes, SizeOf(VargDest.VBytes));
  93. varOleStr:
  94. CopyAsWideString(VargDest.VOleStr,VOleStr);
  95. varDispatch:
  96. IUnknown(VargDest.vdispatch):=IUnknown(VargSrc.vdispatch);
  97. varUnknown:
  98. IUnknown(VargDest.vunknown):=IUnknown(VargSrc.vunknown);
  99. else
  100. Exit(VAR_BADVARTYPE);
  101. end;
  102. end;
  103. VargDest.VType:=VType;
  104. end;
  105. end;
  106. function VariantCopyInd(var VargDest: TVarData; const VargSrc: TVarData): HRESULT;stdcall;
  107. begin
  108. if (VargSrc.VType and varByRef) = 0 then
  109. Exit(VariantCopy(VargDest, VargSrc));
  110. With VargSrc do
  111. begin
  112. if (VType and varArray) <> 0 then
  113. Exit(VAR_INVALIDARG);
  114. case (VType and varTypeMask) of
  115. varEmpty, varNull:;
  116. varSmallint : VargDest.VSmallInt:=PSmallInt(VPointer)^;
  117. varInteger : VargDest.VInteger:=PLongint(VPointer)^;
  118. varSingle : VargDest.VSingle:=PSingle(VPointer)^;
  119. varDouble : VargDest.VDouble:=PDouble(VPointer)^;
  120. varCurrency : VargDest.VCurrency:=PCurrency(VPointer)^;
  121. varDate : VargDest.VDate:=PDate(VPointer)^;
  122. varBoolean : VargDest.VBoolean:=PWordBool(VPointer)^;
  123. varError : VargDest.VError:=PError(VPointer)^;
  124. varByte : VargDest.VByte:=PByte(VPointer)^;
  125. varWord : VargDest.VWord:=PWord(VPointer)^;
  126. VarShortInt : VargDest.VShortInt:=PShortInt(VPointer)^;
  127. VarInt64 : VargDest.VInt64:=PInt64(VPointer)^;
  128. VarLongWord : VargDest.VLongWord:=PCardinal(VPointer)^;
  129. VarQWord : VargDest.VQWord:=PQWord(VPointer)^;
  130. varVariant : Variant(VargDest):=Variant(PVarData(VPointer)^);
  131. varOleStr : CopyAsWideString(VargDest.VOleStr,PVarData(VPointer)^.VoleStr);
  132. varDispatch,
  133. varUnknown : NoInterfaces;
  134. else
  135. Exit(VAR_BADVARTYPE);
  136. end;
  137. VargDest.VType:=VType and VarTypeMask;
  138. end;
  139. Result:=VAR_OK;
  140. end;
  141. Function VariantChangeTypeEx(var VargDest: TVarData; const VargSrc: TVarData;
  142. LCID: Integer; Flags: Word; VarType: Word): HRESULT; stdcall;
  143. var
  144. Tmp : TVarData;
  145. begin
  146. if ((VarType and varArray) <> 0) or
  147. ((VargSrc.VType and varArray) <> 0) or
  148. ((VarType and varByRef) <> 0) then
  149. Exit(VAR_INVALIDARG);
  150. Result:=VariantCopyInd(Tmp, VargSrc);
  151. if Result = VAR_OK then
  152. try
  153. Result:=VariantClear(VargDest);
  154. {$RANGECHECKS ON}
  155. if Result = VAR_OK then
  156. try
  157. case Vartype of
  158. varSmallInt : VargDest.VSmallInt:=VariantToSmallInt(Tmp);
  159. varInteger : VargDest.VInteger:=VariantToLongint(Tmp);
  160. varSingle : VargDest.VSingle:=VariantToSingle(Tmp);
  161. varDouble : VargDest.VDouble:=VariantToDouble(Tmp);
  162. varCurrency : VargDest.VCurrency:=VariantToCurrency(Tmp);
  163. varDate : VargDest.VDate:=VariantToDate(tmp);
  164. varOleStr : MakeWideString(VargDest.VoleStr, VariantToWideString(tmp));
  165. varDispatch : Result:=VAR_TYPEMISMATCH;
  166. varUnknown : Result:=VAR_TYPEMISMATCH;
  167. varBoolean : VargDest.VBoolean:=VariantToBoolean(Tmp);
  168. varByte : VargDest.VByte:=VariantToByte(Tmp);
  169. VarShortInt : VargDest.VShortInt:=VariantToShortInt(Tmp);
  170. VarInt64 : VargDest.Vint64:=VariantToInt64(Tmp);
  171. VarLongWord : VargDest.VLongWord:=VariantToCardinal(Tmp);
  172. VarQWord : VargDest.VQWord:=VariantToQword(tmp);
  173. else
  174. Result:=VAR_BADVARTYPE;
  175. end;
  176. If Result = VAR_OK then
  177. VargDest.VType:=VarType;
  178. except
  179. On E : EVariantError do
  180. Result:=E.ErrCode;
  181. else
  182. Result:=VAR_INVALIDARG;
  183. end;
  184. finally
  185. VariantClear(Tmp);
  186. end;
  187. {$RANGECHECKS OFF}
  188. end;
  189. { ---------------------------------------------------------------------
  190. Variant array support
  191. ---------------------------------------------------------------------}
  192. Function CheckArrayUnlocked (psa : PVarArray) : HResult;
  193. begin
  194. If psa^.LockCount = 0 Then
  195. Result:=VAR_OK
  196. else
  197. Result:=VAR_ARRAYISLOCKED;
  198. end;
  199. Function CheckVarArray(psa: PVarArray ): HRESULT;
  200. begin
  201. If psa=nil then
  202. Result:=VAR_INVALIDARG
  203. else
  204. Result:=VAR_OK;
  205. end;
  206. Function SafeArrayCalculateElementAddress(psa: PVarArray; aElement: SizeInt): Pointer;
  207. begin
  208. Result:=Pointer(psa^.Data)+(aElement*psa^.ElementSize);
  209. end;
  210. Function CheckVarArrayAndCalculateAddress(psa: PVarArray;
  211. Indices: PVarArrayCoorArray; var Address: Pointer; Lockit: Boolean): HRESULT;
  212. var
  213. I,D,Count,Idx : LongInt;
  214. begin
  215. Result:=CheckVarArray(psa);
  216. Address:=nil;
  217. Count:=0;
  218. If Result<>VAR_OK then
  219. exit;
  220. D:=0;
  221. for I:=0 to psa^.DimCount-1 do
  222. begin
  223. Idx:=Indices^[psa^.DimCount-I-1] - psa^.Bounds[I].LowBound;
  224. if (Idx<0) or (Idx>=psa^.Bounds[I].ElementCount) then
  225. Exit(VAR_BADINDEX);
  226. if I=0 then
  227. Count:=Idx
  228. else
  229. Inc(Count,Idx*D);
  230. Inc(D,psa^.Bounds[I].ElementCount);
  231. end;
  232. Address:=SafeArrayCalculateElementAddress(psa, Count);
  233. if LockIt then
  234. Result:=SafeArrayLock(psa);
  235. end;
  236. Function SafeArrayElementTotal(psa: PVarArray): Integer;
  237. var
  238. I: Integer;
  239. begin
  240. Result:=1;
  241. With psa^ do
  242. for I:=0 to DimCount - 1 do
  243. Result:=Result*Bounds[I].ElementCount;
  244. end;
  245. type
  246. TVariantArrayType = (vatNormal, vatInterface, vatWideString, vatVariant);
  247. Function VariantArrayType(psa: PVarArray): TVariantArrayType;
  248. begin
  249. if ((psa^.Flags and ARR_DISPATCH) <> 0) or
  250. ((psa^.Flags and ARR_UNKNOWN) <> 0) then
  251. Result:=vatInterface
  252. else if (psa^.Flags AND ARR_OLESTR) <> 0 then
  253. Result:=vatWideString
  254. else if (psa^.Flags and ARR_VARIANT) <> 0 then
  255. Result := vatVariant
  256. else
  257. Result:=vatNormal;
  258. end;
  259. Function SafeArrayClearDataSpace(psa: PVarArray; WipeBytes: Boolean {= True}): HRESULT;
  260. var
  261. vat: TVariantArrayType;
  262. P : Pointer;
  263. J,Count : Integer;
  264. begin
  265. try
  266. count:=SafeArrayElementTotal(psa);
  267. vat:=VariantArrayType(psa);
  268. case vat of
  269. vatNormal : FillChar(psa^.Data^,Count*psa^.ElementSize,0);
  270. vatInterface :
  271. for j := 0 to Count - 1 do
  272. begin
  273. P := SafeArrayCalculateElementAddress(psa,j);
  274. IUnknown(PUnknown(P)^):=Nil
  275. end;
  276. vatWideString :
  277. for j := 0 to Count - 1 do
  278. begin
  279. P := SafeArrayCalculateElementAddress(psa,j);
  280. WideString(PPointer(P)^):='';
  281. end;
  282. vatVariant :
  283. for j := 0 to Count - 1 do
  284. begin
  285. P := SafeArrayCalculateElementAddress(psa,j);
  286. VariantClear(PVarData(P)^);
  287. end;
  288. end;
  289. Result:=VAR_OK;
  290. except
  291. On E : Exception do
  292. Result:=ExceptionToVariantError (E);
  293. end;
  294. end;
  295. Function SafeArrayCopyDataSpace(psa, psaOut: PVarArray): HRESULT;
  296. var
  297. vat: TVariantArrayType;
  298. P1,P2 : Pointer;
  299. J,Count : Integer;
  300. begin
  301. try
  302. Count:=SafeArrayElementTotal(psa);
  303. vat:=VariantArrayType(psa);
  304. case vat of
  305. vatNormal: Move(psa^.Data^,psaOut^.Data^,Count*psa^.ElementSize);
  306. vatInterface :
  307. for j := 0 to Count - 1 do
  308. begin
  309. P1 := SafeArrayCalculateElementAddress(psa,j);
  310. P2 := SafeArrayCalculateElementAddress(psaout,j);
  311. IUnknown(PUnknown(P2)^):=IUnknown(PUnknown(P1)^);
  312. end;
  313. vatWideString :
  314. for j := 0 to Count - 1 do
  315. begin
  316. P1 := SafeArrayCalculateElementAddress(psa,j);
  317. P2 := SafeArrayCalculateElementAddress(psaOut,j);
  318. WideString(PPointer(P2)^):=WideString(PPointer(P1)^);
  319. end;
  320. vatVariant :
  321. for j := 0 to Count - 1 do
  322. begin
  323. P1 := SafeArrayCalculateElementAddress(psa,j);
  324. P2 := SafeArrayCalculateElementAddress(psaOut,j);
  325. VariantCopy(PVarData(P2)^,PVarData(P2)^);
  326. end;
  327. end;
  328. Result:=VAR_OK;
  329. except
  330. On E : Exception do
  331. Result:=ExceptionToVariantError(E);
  332. end;
  333. end;
  334. Type
  335. TVartypes = varEmpty..varByte;
  336. Const
  337. Supportedpsas : set of TVarTypes =
  338. [varSmallint,varInteger,varSingle,varDouble,varCurrency,varDate,varOleStr,
  339. varDispatch,varError,varBoolean,varVariant,varUnknown,varByte];
  340. psaElementSizes : Array [varEmpty..varByte] of Byte =
  341. (0,0,2,4,4,8,8,8,4,4,4,2,16,4,0,0,0,1);
  342. psaElementFlags : Array [varEmpty..varByte] of Longint =
  343. (ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,
  344. ARR_OLESTR,ARR_DISPATCH,ARR_NONE,ARR_NONE,ARR_VARIANT,ARR_UNKNOWN,
  345. ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE);
  346. Function SafeArrayCreate(VarType, Dim: DWord; const Bounds: TVarArrayBoundArray): PVarArray;stdcall;
  347. var
  348. res : HRESULT;
  349. I : DWord;
  350. begin
  351. Result:=nil;
  352. if Not (VarType in Supportedpsas) Then
  353. exit;
  354. Res:=SafeArrayAllocDescriptor(Dim, Result);
  355. if Res<>VAR_OK then
  356. exit;
  357. Result^.DimCount:=Dim;
  358. Result^.Flags:=psaElementFlags[VarType];
  359. Result^.ElementSize:=psaElementSizes[VarType];
  360. Result^.LockCount := 0;
  361. for i:=0 to Dim-1 do
  362. begin
  363. Result^.Bounds[i].LowBound:=Bounds[Dim-I-1].LowBound;
  364. Result^.Bounds[I].ElementCount:=Bounds[Dim-I-1].ElementCount;
  365. end;
  366. res:=SafeArrayAllocData(Result);
  367. if res<>VAR_OK then
  368. begin
  369. SafeArrayDestroyDescriptor(Result);
  370. Result:=nil;
  371. end;
  372. end;
  373. Function SafeArrayAllocDescriptor(DimCount: Dword; var psa: PVarArray): HRESULT;stdcall;
  374. begin
  375. try
  376. { one bound item is included in TVarArray }
  377. psa:=GetMem(SizeOf(TVarArray) + SizeOf(TVarArrayBound)*(DimCount-1));
  378. Result:=VAR_OK;
  379. except
  380. On E : Exception do
  381. Result:=ExceptionToVariantError(E);
  382. end;
  383. end;
  384. Function SafeArrayAllocData(psa: PVarArray): HRESULT;stdcall;
  385. begin
  386. try
  387. With psa^ do
  388. begin
  389. Data:=GetMem(SafeArrayElementTotal(psa)*ElementSize);
  390. fillchar(Data^,SafeArrayElementTotal(psa)*ElementSize,0);
  391. end;
  392. Result:=VAR_OK;
  393. except
  394. On E : Exception do
  395. Result:=ExceptionToVariantError(E);
  396. end;
  397. end;
  398. Function SafeArrayDestroy(psa: PVarArray): HRESULT;stdcall;
  399. begin
  400. Result:=CheckVarArray(psa);
  401. if Result<> VAR_OK then
  402. exit;
  403. Result:=CheckArrayUnlocked(psa);
  404. if Result<> VAR_OK then
  405. exit;
  406. Result:=SafeArrayDestroyData(psa);
  407. if Result<>VAR_OK then
  408. exit;
  409. Result:=SafeArrayDestroyDescriptor(psa);
  410. end;
  411. Function SafeArrayDestroyDescriptor(psa: PVarArray): HRESULT;stdcall;
  412. begin
  413. Result:=CheckVarArray(psa);
  414. if Result<>VAR_OK then
  415. exit;
  416. Result:=CheckArrayUnlocked(psa);
  417. if Result<> VAR_OK then
  418. exit;
  419. try
  420. FreeMem(psa);
  421. except
  422. On E : Exception do
  423. Result:=ExceptionToVariantError(E);
  424. end;
  425. end;
  426. Function SafeArrayDestroyData(psa: PVarArray): HRESULT;stdcall;
  427. begin
  428. Result:=CheckVarArray(psa);
  429. if Result<>VAR_OK then
  430. exit;
  431. Result:=CheckArrayUnlocked(psa);
  432. if Result<> VAR_OK then
  433. exit;
  434. try
  435. Result:=SafeArrayClearDataSpace(psa, False);
  436. if (Result=VAR_OK) and ((psa^.Flags and ARR_FIXEDSIZE)=0) then
  437. begin
  438. FreeMem(psa^.Data);
  439. psa^.Data:=nil;
  440. end;
  441. except
  442. On E : Exception do
  443. Result:=ExceptionToVariantError(E);
  444. end;
  445. end;
  446. Function SafeArrayRedim(psa: PVarArray; const NewBound: TVarArrayBound): HRESULT;stdcall;
  447. var
  448. vat: TVariantArrayType;
  449. i, D,j,count : Integer;
  450. P : Pointer;
  451. begin
  452. Result:=CheckVarArray(psa);
  453. if Result <> VAR_OK then
  454. exit;
  455. if (psa^.Flags and ARR_FIXEDSIZE) <> 0 then
  456. Exit(VAR_INVALIDARG);
  457. Result:=SafeArrayLock(psa);
  458. if Result<>VAR_OK then
  459. exit;
  460. try
  461. D:=NewBound.ElementCount - psa^.Bounds[0].ElementCount;
  462. for i:=1 to psa^.DimCount - 1 do
  463. D:=D*psa^.Bounds[i].ElementCount;
  464. if D<>0 then
  465. begin
  466. Count:=SafeArrayElementTotal(psa);
  467. if D<0 then
  468. begin
  469. vat:=VariantArrayType(psa);
  470. for j:=Count-1 downto Count+D do
  471. begin
  472. P:=SafeArrayCalculateElementAddress(psa,j);
  473. if vat = vatInterface then
  474. IUnknown(PPointer(P)^):=Nil
  475. else if vat=vatWideString then
  476. WideString(PPointer(P)^):=''
  477. else if vat=vatVariant then
  478. VariantClear(PVarData(P)^);
  479. end;
  480. end;
  481. ReAllocMem(psa^.Data,(Count+D)*psa^.ElementSize);
  482. if D>0 then
  483. fillchar((PChar(psa^.Data)+Count*psa^.ElementSize)^,D*psa^.ElementSize,0);
  484. end;
  485. psa^.Bounds[0].ElementCount:=NewBound.ElementCount;
  486. psa^.Bounds[0].LowBound:=NewBound.LowBound;
  487. except
  488. On E : Exception do
  489. Result:=ExceptionToVariantError(E);
  490. end;
  491. SetUnlockResult(psa,Result);
  492. end;
  493. Function SafeArrayCopy(psa: PVarArray; var psaOut: PVarArray): HRESULT;stdcall;
  494. var
  495. i : Integer;
  496. begin
  497. Result:=CheckVarArray(psa);
  498. if Result<>VAR_OK then
  499. exit;
  500. Result:=SafeArrayLock(psa);
  501. if Result<>VAR_OK then
  502. exit;
  503. try
  504. Result:=SafeArrayAllocDescriptor(psa^.DimCount,psaOut);
  505. if Result<>VAR_OK then
  506. Exit;
  507. try
  508. With psaOut^ do
  509. begin
  510. Flags:=psa^.Flags;
  511. ElementSize:=psa^.ElementSize;
  512. LockCount := 0;
  513. DimCount:=psa^.DimCount;
  514. for i:=0 to DimCount-1 do
  515. begin
  516. Bounds[i].ElementCount:=psa^.Bounds[i].ElementCount;
  517. Bounds[i].LowBound:=psa^.Bounds[i].LowBound;
  518. end;
  519. end;
  520. Result:=SafeArrayAllocData(psaOut);
  521. if Result<>VAR_OK then
  522. exit;
  523. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  524. finally
  525. if Result<>VAR_OK then
  526. begin
  527. SafeArrayDestroyDescriptor(psaOut);
  528. psaOut:=nil;
  529. end;
  530. end;
  531. except
  532. On E : Exception do
  533. Result:=ExceptionToVariantError(E)
  534. end;
  535. SetUnlockResult(psa,Result);
  536. end;
  537. Function SafeArrayCopyData(psa, psaOut: PVarArray): HRESULT;stdcall;
  538. var
  539. i : Integer;
  540. begin
  541. Result:=CheckVarArray(psa);
  542. if Result<>VAR_OK then
  543. exit;
  544. Result:=CheckVarArray(psaOut);
  545. if Result<>VAR_OK then
  546. exit;
  547. Result:=SafeArrayLock(psaOut);
  548. if Result<>VAR_OK then
  549. exit;
  550. try
  551. Result:=SafeArrayLock(psa);
  552. if Result<>VAR_OK then
  553. exit;
  554. try
  555. With psaOut^ do
  556. begin
  557. if (psa^.Flags<>Flags) or
  558. (psa^.ElementSize<>ElementSize) or
  559. (psa^.DimCount<>DimCount) then
  560. Exit(VAR_INVALIDARG);
  561. for i:=0 to psa^.DimCount - 1 do
  562. if (psa^.Bounds[i].LowBound<>Bounds[i].LowBound) or
  563. (psa^.Bounds[i].ElementCount<>Bounds[i].ElementCount) then
  564. exit(VAR_INVALIDARG);
  565. end;
  566. Result:=SafeArrayClearDataSpace(psaOut,True);
  567. if Result<> VAR_OK then
  568. exit;
  569. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  570. finally
  571. SetUnlockResult(psa,Result);
  572. end;
  573. finally
  574. SetUnlockResult(psaOut,Result);
  575. end;
  576. end;
  577. Function SafeArrayGetLBound(psa: PVarArray; Dim: DWord; var LBound: LongInt): HRESULT;stdcall;
  578. begin
  579. Result:=CheckVarArray(psa);
  580. if Result<>VAR_OK then
  581. exit;
  582. if (Dim>0) and (Dim<=psa^.DimCount) then
  583. LBound:=psa^.Bounds[psa^.dimcount-Dim].LowBound
  584. else
  585. Result:=VAR_BADINDEX;
  586. end;
  587. Function SafeArrayGetUBound(psa: PVarArray; Dim : DWord; var UBound: LongInt): HRESULT;stdcall;
  588. begin
  589. Result:=CheckVarArray(psa);
  590. if Result<>VAR_OK then
  591. exit;
  592. if (Dim>0) and (Dim<=psa^.DimCount) then
  593. UBound:=psa^.Bounds[psa^.dimcount-Dim].LowBound +
  594. psa^.Bounds[psa^.dimcount-Dim].ElementCount-1
  595. else
  596. Result:=VAR_BADINDEX
  597. end;
  598. Function SafeArrayGetDim(psa: PVarArray): HRESULT;stdcall;
  599. begin
  600. if CheckVarArray(psa)<>VAR_OK then
  601. Result:=0
  602. else
  603. Result:=psa^.DimCount;
  604. end;
  605. Function SafeArrayAccessData(psa: PVarArray; var ppvData: Pointer): HRESULT;stdcall;
  606. begin
  607. Result:=SafeArrayLock(psa);
  608. if Result<>VAR_OK then
  609. ppvData:=nil
  610. else
  611. ppvData:=psa^.Data;
  612. end;
  613. Function SafeArrayUnaccessData(psa: PVarArray): HRESULT;stdcall;
  614. begin
  615. Result:=SafeArrayUnlock(psa);
  616. end;
  617. Function SafeArrayLock(psa: PVarArray): HRESULT;stdcall;
  618. begin
  619. Result:=CheckVarArray(psa);
  620. if Result<>VAR_OK then
  621. exit;
  622. InterlockedIncrement(psa^.LockCount);
  623. end;
  624. Function SafeArrayUnlock(psa: PVarArray): HRESULT;stdcall;
  625. begin
  626. Result:=CheckVarArray(psa);
  627. if (Result<>VAR_OK) then
  628. exit;
  629. if InterlockedDecrement(psa^.LockCount)<0 then
  630. begin
  631. InterlockedIncrement(psa^.LockCount);
  632. result:=VAR_UNEXPECTED;
  633. end;
  634. end;
  635. Function SafeArrayGetElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  636. Data: Pointer): HRESULT;stdcall;
  637. var
  638. P: Pointer;
  639. begin
  640. Result:=CheckVarArrayAndCalculateAddress(psa, Indices, P, True);
  641. if Result<>VAR_OK then
  642. exit;
  643. try
  644. case VariantArrayType(psa) of
  645. vatNormal:
  646. Move(P^, Data^, psa^.ElementSize);
  647. vatInterface:
  648. NoInterfaces; // Just assign...
  649. vatWideString:
  650. NoWideStrings; // Just assign...
  651. end;
  652. except
  653. On E : Exception do
  654. Result:=ExceptionToVariantError(E);
  655. end;
  656. SetUnlockResult(psa,Result);
  657. end;
  658. Function SafeArrayPutElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  659. const Data: Pointer): HRESULT;stdcall;
  660. var
  661. P: Pointer;
  662. begin
  663. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,P,True);
  664. if Result<>VAR_OK then
  665. exit;
  666. try
  667. case VariantArrayType(psa) of
  668. vatNormal:
  669. Move(Data^,P^,psa^.ElementSize);
  670. vatInterface:
  671. NoInterfaces;
  672. vatWideString:
  673. NoWideStrings;
  674. end;
  675. except
  676. On E : Exception do
  677. Result:=ExceptionToVariantError(E);
  678. end;
  679. SetUnlockResult(psa,Result);
  680. end;
  681. Function SafeArrayPtrOfIndex(psa: PVarArray; Indices: PVarArrayCoorArray;
  682. var Address: Pointer): HRESULT;stdcall;
  683. begin
  684. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,Address,False);
  685. end;
  686. Function SafeArrayGetElemSize(psa: PVarArray): LongWord;stdcall;
  687. begin
  688. if CheckVarArray(psa)<>VAR_OK then
  689. Result:=0
  690. else
  691. Result:=psa^.ElementSize;
  692. end;