varutils.inc 19 KB

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