varutils.inc 19 KB

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