varutils.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  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. vat: TVariantArrayType;
  280. begin
  281. try
  282. vat:=VariantArrayType(psa);
  283. case vat of
  284. vatNormal: Move(psa^.Data^,
  285. psaOut^.Data^,
  286. SafeArrayElementTotal(psa)*psa^.ElementSize);
  287. vatInterface : NoInterfaces; // Copy element per element...
  288. vatWideString: NoWideStrings; // here also...
  289. end;
  290. Result:=VAR_OK;
  291. except
  292. On E : Exception do
  293. Result:=ExceptionToVariantError(E);
  294. end;
  295. end;
  296. Type
  297. TVartypes = varEmpty..varByte;
  298. Const
  299. Supportedpsas : set of TVarTypes =
  300. [varSmallint,varInteger,varSingle,varDouble,varCurrency,varDate,varOleStr,
  301. varDispatch,varError,varBoolean,varVariant,varUnknown,varByte];
  302. psaElementSizes : Array [varEmpty..varByte] of Byte =
  303. (0,0,2,4,4,8,8,8,4,4,4,2,16,4,0,0,0,1);
  304. psaElementFlags : Array [varEmpty..varByte] of Longint =
  305. (ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,
  306. ARR_OLESTR,ARR_DISPATCH,ARR_NONE,ARR_NONE,ARR_NONE,ARR_UNKNOWN,
  307. ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE);
  308. Function SafeArrayCreate(VarType, Dim: DWord; const Bounds: TVarArrayBoundArray): PVarArray;stdcall;
  309. var
  310. res : HRESULT;
  311. I : SizeInt;
  312. begin
  313. Result:=nil;
  314. if Not (VarType in Supportedpsas) Then
  315. exit;
  316. Res:=SafeArrayAllocDescriptor(Dim, Result);
  317. if Res<>VAR_OK then
  318. exit;
  319. Result^.DimCount:=Dim;
  320. Result^.Flags:=psaElementFlags[VarType];
  321. Result^.ElementSize:=psaElementSizes[VarType];
  322. Result^.LockCount := 0;
  323. for i:=0 to Dim-1 do
  324. begin
  325. Result^.Bounds[i].LowBound:=Bounds[Dim-I-1].LowBound;
  326. Result^.Bounds[I].ElementCount:=Bounds[Dim-I-1].ElementCount;
  327. end;
  328. res:=SafeArrayAllocData(Result);
  329. if res<>VAR_OK then
  330. begin
  331. SafeArrayDestroyDescriptor(Result);
  332. Result:=nil;
  333. end;
  334. end;
  335. Function SafeArrayAllocDescriptor(DimCount: Dword; var psa: PVarArray): HRESULT;stdcall;
  336. begin
  337. try
  338. { one bound item is included in TVarArray }
  339. psa:=GetMem(SizeOf(TVarArray) + SizeOf(TVarArrayBound)*(DimCount-1));
  340. Result:=VAR_OK;
  341. except
  342. On E : Exception do
  343. Result:=ExceptionToVariantError(E);
  344. end;
  345. end;
  346. Function SafeArrayAllocData(psa: PVarArray): HRESULT;stdcall;
  347. begin
  348. try
  349. With psa^ do
  350. begin
  351. Data:=GetMem(SafeArrayElementTotal(psa)*ElementSize);
  352. fillchar(Data^,SafeArrayElementTotal(psa)*ElementSize,0);
  353. end;
  354. Result:=VAR_OK;
  355. except
  356. On E : Exception do
  357. Result:=ExceptionToVariantError(E);
  358. end;
  359. end;
  360. Function SafeArrayDestroy(psa: PVarArray): HRESULT;stdcall;
  361. begin
  362. Result:=CheckVarArray(psa);
  363. if Result<> VAR_OK then
  364. exit;
  365. Result:=CheckArrayUnlocked(psa);
  366. if Result<> VAR_OK then
  367. exit;
  368. Result:=SafeArrayDestroyData(psa);
  369. if Result<>VAR_OK then
  370. exit;
  371. Result:=SafeArrayDestroyDescriptor(psa);
  372. end;
  373. Function SafeArrayDestroyDescriptor(psa: PVarArray): HRESULT;stdcall;
  374. begin
  375. Result:=CheckVarArray(psa);
  376. if Result<>VAR_OK then
  377. exit;
  378. Result:=CheckArrayUnlocked(psa);
  379. if Result<> VAR_OK then
  380. exit;
  381. try
  382. FreeMem(psa);
  383. except
  384. On E : Exception do
  385. Result:=ExceptionToVariantError(E);
  386. end;
  387. end;
  388. Function SafeArrayDestroyData(psa: PVarArray): HRESULT;stdcall;
  389. begin
  390. Result:=CheckVarArray(psa);
  391. if Result<>VAR_OK then
  392. exit;
  393. Result:=CheckArrayUnlocked(psa);
  394. if Result<> VAR_OK then
  395. exit;
  396. try
  397. Result:=SafeArrayClearDataSpace(psa, False);
  398. if (Result=VAR_OK) and ((psa^.Flags and ARR_FIXEDSIZE)=0) then
  399. begin
  400. FreeMem(psa^.Data);
  401. psa^.Data:=nil;
  402. end;
  403. except
  404. On E : Exception do
  405. Result:=ExceptionToVariantError(E);
  406. end;
  407. end;
  408. Function SafeArrayRedim(psa: PVarArray; const NewBound: TVarArrayBound): HRESULT;stdcall;
  409. var
  410. vat: TVariantArrayType;
  411. i, D,j,count : Integer;
  412. P : Pointer;
  413. begin
  414. Result:=CheckVarArray(psa);
  415. if Result <> VAR_OK then
  416. exit;
  417. if (psa^.Flags and ARR_FIXEDSIZE) <> 0 then
  418. Exit(VAR_INVALIDARG);
  419. Result:=SafeArrayLock(psa);
  420. if Result<>VAR_OK then
  421. exit;
  422. try
  423. D:=NewBound.ElementCount - psa^.Bounds[0].ElementCount;
  424. for i:=1 to psa^.DimCount - 1 do
  425. D:=D*psa^.Bounds[i].ElementCount;
  426. if D<>0 then
  427. begin
  428. Count:=SafeArrayElementTotal(psa);
  429. if D<0 then
  430. begin
  431. vat:=VariantArrayType(psa);
  432. for j:=Count-1 downto Count+D do
  433. begin
  434. P:=SafeArrayCalculateElementAddress(psa,j);
  435. if vat = vatInterface then
  436. NoInterfaces // Set to nil
  437. else
  438. NoWideStrings; // Set to empty...
  439. end;
  440. end;
  441. ReAllocMem(psa^.Data,Count+D);
  442. end;
  443. psa^.Bounds[0].ElementCount:=NewBound.ElementCount;
  444. psa^.Bounds[0].LowBound:=NewBound.LowBound;
  445. except
  446. On E : Exception do
  447. Result:=ExceptionToVariantError(E);
  448. end;
  449. SetUnlockResult(psa,Result);
  450. end;
  451. Function SafeArrayCopy(psa: PVarArray; var psaOut: PVarArray): HRESULT;stdcall;
  452. var
  453. i : Integer;
  454. begin
  455. Result:=CheckVarArray(psa);
  456. if Result<>VAR_OK then
  457. exit;
  458. Result:=SafeArrayLock(psa);
  459. if Result<>VAR_OK then
  460. exit;
  461. try
  462. Result:=SafeArrayAllocDescriptor(psa^.DimCount,psaOut);
  463. if Result<>VAR_OK then
  464. Exit;
  465. try
  466. With psaOut^ do
  467. begin
  468. Flags:=psa^.Flags;
  469. ElementSize:=psa^.ElementSize;
  470. LockCount := 0;
  471. DimCount:=psa^.DimCount;
  472. for i:=0 to DimCount-1 do
  473. begin
  474. Bounds[i].ElementCount:=psa^.Bounds[i].ElementCount;
  475. Bounds[i].LowBound:=psa^.Bounds[i].LowBound;
  476. end;
  477. end;
  478. Result:=SafeArrayAllocData(psaOut);
  479. if Result<>VAR_OK then
  480. exit;
  481. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  482. finally
  483. if Result<>VAR_OK then
  484. begin
  485. SafeArrayDestroyDescriptor(psaOut);
  486. psaOut:=nil;
  487. end;
  488. end;
  489. except
  490. On E : Exception do
  491. Result:=ExceptionToVariantError(E)
  492. end;
  493. SetUnlockResult(psa,Result);
  494. end;
  495. Function SafeArrayCopyData(psa, psaOut: PVarArray): HRESULT;stdcall;
  496. var
  497. i : Integer;
  498. begin
  499. Result:=CheckVarArray(psa);
  500. if Result<>VAR_OK then
  501. exit;
  502. Result:=CheckVarArray(psaOut);
  503. if Result<>VAR_OK then
  504. exit;
  505. Result:=SafeArrayLock(psaOut);
  506. if Result<>VAR_OK then
  507. exit;
  508. try
  509. Result:=SafeArrayLock(psa);
  510. if Result<>VAR_OK then
  511. exit;
  512. try
  513. With psaOut^ do
  514. begin
  515. if (psa^.Flags<>Flags) or
  516. (psa^.ElementSize<>ElementSize) or
  517. (psa^.DimCount<>DimCount) then
  518. Exit(VAR_INVALIDARG);
  519. for i:=0 to psa^.DimCount - 1 do
  520. if (psa^.Bounds[i].LowBound<>Bounds[i].LowBound) or
  521. (psa^.Bounds[i].ElementCount<>Bounds[i].ElementCount) then
  522. exit(VAR_INVALIDARG);
  523. end;
  524. Result:=SafeArrayClearDataSpace(psaOut,True);
  525. if Result<> VAR_OK then
  526. exit;
  527. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  528. finally
  529. SetUnlockResult(psa,Result);
  530. end;
  531. finally
  532. SetUnlockResult(psaOut,Result);
  533. end;
  534. end;
  535. Function SafeArrayGetLBound(psa: PVarArray; Dim: DWord; var LBound: LongInt): HRESULT;stdcall;
  536. begin
  537. Result:=CheckVarArray(psa);
  538. if Result<>VAR_OK then
  539. exit;
  540. if (Dim>0) and (Dim<=psa^.DimCount) then
  541. LBound:=psa^.Bounds[Dim-1].LowBound
  542. else
  543. Result:=VAR_BADINDEX;
  544. end;
  545. Function SafeArrayGetUBound(psa: PVarArray; Dim : DWord; var UBound: LongInt): HRESULT;stdcall;
  546. begin
  547. Result:=CheckVarArray(psa);
  548. if Result<>VAR_OK then
  549. exit;
  550. if (Dim>0) and (Dim<=psa^.DimCount) then
  551. UBound:=psa^.Bounds[Dim-1].LowBound +
  552. psa^.Bounds[Dim-1].ElementCount-1
  553. else
  554. Result:=VAR_BADINDEX
  555. end;
  556. Function SafeArrayGetDim(psa: PVarArray): HRESULT;stdcall;
  557. begin
  558. if CheckVarArray(psa)<>VAR_OK then
  559. Result:=0
  560. else
  561. Result:=psa^.DimCount;
  562. end;
  563. Function SafeArrayAccessData(psa: PVarArray; var ppvData: Pointer): HRESULT;stdcall;
  564. begin
  565. Result:=SafeArrayLock(psa);
  566. if Result<>VAR_OK then
  567. ppvData:=nil
  568. else
  569. ppvData:=psa^.Data;
  570. end;
  571. Function SafeArrayUnaccessData(psa: PVarArray): HRESULT;stdcall;
  572. begin
  573. Result:=SafeArrayUnlock(psa);
  574. end;
  575. Function SafeArrayLock(psa: PVarArray): HRESULT;stdcall;
  576. begin
  577. Result:=CheckVarArray(psa);
  578. if Result<>VAR_OK then
  579. exit;
  580. InterlockedIncrement(psa^.LockCount);
  581. end;
  582. Function SafeArrayUnlock(psa: PVarArray): HRESULT;stdcall;
  583. begin
  584. Result:=CheckVarArray(psa);
  585. if (Result<>VAR_OK) then
  586. exit;
  587. if InterlockedDecrement(psa^.LockCount)<0 then
  588. begin
  589. InterlockedIncrement(psa^.LockCount);
  590. result:=VAR_UNEXPECTED;
  591. end;
  592. end;
  593. Function SafeArrayGetElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  594. Data: Pointer): HRESULT;stdcall;
  595. var
  596. P: Pointer;
  597. begin
  598. Result:=CheckVarArrayAndCalculateAddress(psa, Indices, P, True);
  599. if Result<>VAR_OK then
  600. exit;
  601. try
  602. case VariantArrayType(psa) of
  603. vatNormal:
  604. Move(P^, Data^, psa^.ElementSize);
  605. vatInterface:
  606. NoInterfaces; // Just assign...
  607. vatWideString:
  608. NoWideStrings; // Just assign...
  609. end;
  610. except
  611. On E : Exception do
  612. Result:=ExceptionToVariantError(E);
  613. end;
  614. SetUnlockResult(psa,Result);
  615. end;
  616. Function SafeArrayPutElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  617. const Data: Pointer): HRESULT;stdcall;
  618. var
  619. P: Pointer;
  620. begin
  621. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,P,True);
  622. if Result<>VAR_OK then
  623. exit;
  624. try
  625. case VariantArrayType(psa) of
  626. vatNormal:
  627. Move(Data^,P^,psa^.ElementSize);
  628. vatInterface:
  629. NoInterfaces;
  630. vatWideString:
  631. NoWideStrings;
  632. end;
  633. except
  634. On E : Exception do
  635. Result:=ExceptionToVariantError(E);
  636. end;
  637. SetUnlockResult(psa,Result);
  638. end;
  639. Function SafeArrayPtrOfIndex(psa: PVarArray; Indices: PVarArrayCoorArray;
  640. var Address: Pointer): HRESULT;stdcall;
  641. begin
  642. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,Address,False);
  643. end;
  644. Function SafeArrayGetElemSize(psa: PVarArray): LongWord;stdcall;
  645. begin
  646. if CheckVarArray(psa)<>VAR_OK then
  647. Result:=0
  648. else
  649. Result:=psa^.ElementSize;
  650. end;