varutils.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2001 by the Free Pascal development team
  5. Variant routines for non-windows oses.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$ifdef HASVARIANT}
  13. { ---------------------------------------------------------------------
  14. Some general stuff: Error handling and so on.
  15. ---------------------------------------------------------------------}
  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. end;
  186. { ---------------------------------------------------------------------
  187. Variant array support
  188. ---------------------------------------------------------------------}
  189. Function CheckArrayUnlocked (psa : PVarArray) : HResult;
  190. begin
  191. If psa^.LockCount = 0 Then
  192. Result:=VAR_OK
  193. else
  194. Result:=VAR_ARRAYISLOCKED;
  195. end;
  196. Function CheckVarArray(psa: PVarArray ): HRESULT;
  197. begin
  198. If psa=nil then
  199. Result:=VAR_INVALIDARG
  200. else
  201. Result:=VAR_OK;
  202. end;
  203. Function SafeArrayCalculateElementAddress(psa: PVarArray; aElement: SizeInt): Pointer;
  204. begin
  205. Result:=Pointer(psa^.Data)+(aElement*psa^.ElementSize);
  206. end;
  207. Function CheckVarArrayAndCalculateAddress(psa: PVarArray;
  208. Indices: PVarArrayCoorArray; var Address: Pointer; Lockit: Boolean): HRESULT;
  209. Function CountElements(D: Longint): Longint;
  210. begin
  211. if (D<psa^.DimCount) then
  212. Result:=CountElements(D+1)+psa^.Bounds[D-1].ElementCount
  213. else
  214. Result:=1;
  215. end;
  216. var
  217. LB,HB,I,Count : LongInt;
  218. begin
  219. Result:=CheckVarArray(psa);
  220. Address:=nil;
  221. Count:=0;
  222. If Result<>VAR_OK then
  223. exit;
  224. for I:=1 to psa^.DimCount do
  225. begin
  226. LB:=psa^.Bounds[I-1].LowBound;
  227. HB:=LB+psa^.Bounds[I-1].ElementCount;
  228. if (LB=HB) or ((Indices^[I-1]< LB) or(Indices^[I-1]>HB)) then
  229. Exit(VAR_BADINDEX);
  230. Count:=Count+(Indices^[I-1]-LB)*CountElements(I+1);
  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);
  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
  255. Result:=vatNormal;
  256. end;
  257. Function SafeArrayClearDataSpace(psa: PVarArray; WipeBytes: Boolean {= True}): HRESULT;
  258. var
  259. vat: TVariantArrayType;
  260. begin
  261. try
  262. vat:=VariantArrayType(psa);
  263. case vat of
  264. vatNormal : FillChar(psa^.Data^,
  265. SafeArrayElementTotal(psa)*psa^.ElementSize,
  266. 0);
  267. vatInterface : NoInterfaces;
  268. vatWideString : NoWidestrings;
  269. end;
  270. Result:=VAR_OK;
  271. except
  272. On E : Exception do
  273. Result:=ExceptionToVariantError (E);
  274. end;
  275. end;
  276. Function SafeArrayCopyDataSpace(psa, psaOut: PVarArray): HRESULT;
  277. var
  278. vVargSrc, vTarget: Pointer;
  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: SizeInt; 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. for i:=0 to Dim-1 do
  323. begin
  324. Result^.Bounds[i].LowBound:=Bounds[Dim-I-1].LowBound;
  325. Result^.Bounds[I].ElementCount:=Bounds[Dim-I-1].ElementCount;
  326. end;
  327. res:=SafeArrayAllocData(Result);
  328. if res<>VAR_OK then
  329. begin
  330. SafeArrayDestroyDescriptor(Result);
  331. Result:=nil;
  332. end;
  333. end;
  334. Function SafeArrayAllocDescriptor(DimCount: SizeInt; var psa: PVarArray): HRESULT;stdcall;
  335. begin
  336. try
  337. psa:=GetMem(SizeOf(TVarArray) + SizeOf(TVarArrayBound) * (DimCount - 1));
  338. Result:=VAR_OK;
  339. except
  340. On E : Exception do
  341. Result:=ExceptionToVariantError(E);
  342. end;
  343. end;
  344. Function SafeArrayAllocData(psa: PVarArray): HRESULT;stdcall;
  345. begin
  346. try
  347. With psa^ do
  348. Data:=GetMem(SafeArrayElementTotal(psa)*ElementSize);
  349. Result:=VAR_OK;
  350. except
  351. On E : Exception do
  352. Result:=ExceptionToVariantError(E);
  353. end;
  354. end;
  355. Function SafeArrayDestroy(psa: PVarArray): HRESULT;stdcall;
  356. begin
  357. Result:=CheckVarArray(psa);
  358. if Result<> VAR_OK then
  359. exit;
  360. Result:=CheckArrayUnlocked(psa);
  361. if Result<> VAR_OK then
  362. exit;
  363. Result:=SafeArrayDestroyData(psa);
  364. if Result<>VAR_OK then
  365. exit;
  366. Result:=SafeArrayDestroyDescriptor(psa);
  367. end;
  368. Function SafeArrayDestroyDescriptor(psa: PVarArray): HRESULT;stdcall;
  369. begin
  370. Result:=CheckVarArray(psa);
  371. if Result<>VAR_OK then
  372. exit;
  373. Result:=CheckArrayUnlocked(psa);
  374. if Result<> VAR_OK then
  375. exit;
  376. try
  377. FreeMem(psa);
  378. except
  379. On E : Exception do
  380. Result:=ExceptionToVariantError(E);
  381. end;
  382. end;
  383. Function SafeArrayDestroyData(psa: PVarArray): HRESULT;stdcall;
  384. begin
  385. Result:=CheckVarArray(psa);
  386. if Result<>VAR_OK then
  387. exit;
  388. Result:=CheckArrayUnlocked(psa);
  389. if Result<> VAR_OK then
  390. exit;
  391. try
  392. Result:=SafeArrayClearDataSpace(psa, False);
  393. if (Result=VAR_OK) and ((psa^.Flags and ARR_FIXEDSIZE)=0) then
  394. begin
  395. FreeMem(psa^.Data);
  396. psa^.Data:=nil;
  397. end;
  398. except
  399. On E : Exception do
  400. Result:=ExceptionToVariantError(E);
  401. end;
  402. end;
  403. Function SafeArrayRedim(psa: PVarArray; const NewBound: TVarArrayBound): HRESULT;stdcall;
  404. var
  405. vat: TVariantArrayType;
  406. i, D,j,count : Integer;
  407. P : Pointer;
  408. begin
  409. Result:=CheckVarArray(psa);
  410. if Result <> VAR_OK then
  411. exit;
  412. if (psa^.Flags and ARR_FIXEDSIZE) <> 0 then
  413. Exit(VAR_INVALIDARG);
  414. Result:=SafeArrayLock(psa);
  415. if Result<>VAR_OK then
  416. exit;
  417. try
  418. D:=NewBound.ElementCount - psa^.Bounds[0].ElementCount;
  419. for i:=1 to psa^.DimCount - 1 do
  420. D:=D*psa^.Bounds[i].ElementCount;
  421. if D<>0 then
  422. begin
  423. Count:=SafeArrayElementTotal(psa);
  424. if D<0 then
  425. begin
  426. vat:=VariantArrayType(psa);
  427. for j:=Count-1 downto Count+D do
  428. begin
  429. P:=SafeArrayCalculateElementAddress(psa,j);
  430. if vat = vatInterface then
  431. NoInterfaces // Set to nil
  432. else
  433. NoWideStrings; // Set to empty...
  434. end;
  435. end;
  436. ReAllocMem(psa^.Data,Count+D);
  437. end;
  438. psa^.Bounds[0].ElementCount:=NewBound.ElementCount;
  439. psa^.Bounds[0].LowBound:=NewBound.LowBound;
  440. except
  441. On E : Exception do
  442. Result:=ExceptionToVariantError(E);
  443. end;
  444. SetUnlockResult(psa,Result);
  445. end;
  446. Function SafeArrayCopy(psa: PVarArray; var psaOut: PVarArray): HRESULT;stdcall;
  447. var
  448. i : Integer;
  449. begin
  450. Result:=CheckVarArray(psa);
  451. if Result<>VAR_OK then
  452. exit;
  453. Result:=SafeArrayLock(psa);
  454. if Result<>VAR_OK then
  455. exit;
  456. try
  457. Result:=SafeArrayAllocDescriptor(psa^.DimCount,psaOut);
  458. if Result<>VAR_OK then
  459. Exit;
  460. try
  461. With psaOut^ do
  462. begin
  463. Flags:=psa^.Flags;
  464. ElementSize:=psa^.ElementSize;
  465. DimCount:=psa^.DimCount;
  466. for i:=0 to DimCount-1 do
  467. begin
  468. Bounds[i].ElementCount:=psa^.Bounds[i].ElementCount;
  469. Bounds[i].LowBound:=psa^.Bounds[i].LowBound;
  470. end;
  471. end;
  472. Result:=SafeArrayAllocData(psaOut);
  473. if Result<>VAR_OK then
  474. exit;
  475. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  476. finally
  477. if Result<>VAR_OK then
  478. begin
  479. SafeArrayDestroyDescriptor(psaOut);
  480. psaOut:=nil;
  481. end;
  482. end;
  483. except
  484. On E : Exception do
  485. Result:=ExceptionToVariantError(E)
  486. end;
  487. SetUnlockResult(psa,Result);
  488. end;
  489. Function SafeArrayCopyData(psa, psaOut: PVarArray): HRESULT;stdcall;
  490. var
  491. i : Integer;
  492. begin
  493. Result:=CheckVarArray(psa);
  494. if Result<>VAR_OK then
  495. exit;
  496. Result:=CheckVarArray(psaOut);
  497. if Result<>VAR_OK then
  498. exit;
  499. Result:=SafeArrayLock(psaOut);
  500. if Result<>VAR_OK then
  501. exit;
  502. try
  503. Result:=SafeArrayLock(psa);
  504. if Result<>VAR_OK then
  505. exit;
  506. try
  507. With psaOut^ do
  508. begin
  509. if (psa^.Flags<>Flags) or
  510. (psa^.ElementSize<>ElementSize) or
  511. (psa^.DimCount<>DimCount) then
  512. Exit(VAR_INVALIDARG);
  513. for i:=0 to psa^.DimCount - 1 do
  514. if (psa^.Bounds[i].LowBound<>Bounds[i].LowBound) or
  515. (psa^.Bounds[i].ElementCount<>Bounds[i].ElementCount) then
  516. exit(VAR_INVALIDARG);
  517. end;
  518. Result:=SafeArrayClearDataSpace(psaOut,True);
  519. if Result<> VAR_OK then
  520. exit;
  521. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  522. finally
  523. SetUnlockResult(psa,Result);
  524. end;
  525. finally
  526. SetUnlockResult(psaOut,Result);
  527. end;
  528. end;
  529. Function SafeArrayGetLBound(psa: PVarArray; Dim: SizeInt; var LBound: SizeInt): HRESULT;stdcall;
  530. begin
  531. Result:=CheckVarArray(psa);
  532. if Result<>VAR_OK then
  533. exit;
  534. if (Dim>0) and (Dim<=psa^.DimCount) then
  535. LBound:=psa^.Bounds[Dim-1].LowBound
  536. else
  537. Result:=VAR_BADINDEX;
  538. end;
  539. Function SafeArrayGetUBound(psa: PVarArray; Dim: SizeInt; var UBound: SizeInt): HRESULT;stdcall;
  540. begin
  541. Result:=CheckVarArray(psa);
  542. if Result<>VAR_OK then
  543. exit;
  544. if (Dim>0) and (Dim<=psa^.DimCount) then
  545. UBound:=psa^.Bounds[Dim-1].LowBound +
  546. psa^.Bounds[Dim-1].ElementCount-1
  547. else
  548. Result:=VAR_BADINDEX
  549. end;
  550. Function SafeArrayGetDim(psa: PVarArray): SizeInt;stdcall;
  551. begin
  552. if CheckVarArray(psa)<>VAR_OK then
  553. Result:=0
  554. else
  555. Result:=psa^.DimCount;
  556. end;
  557. Function SafeArrayAccessData(psa: PVarArray; var ppvData: Pointer): HRESULT;stdcall;
  558. begin
  559. Result:=SafeArrayLock(psa);
  560. if Result<>VAR_OK then
  561. ppvData:=nil
  562. else
  563. ppvData:=psa^.Data;
  564. end;
  565. Function SafeArrayUnaccessData(psa: PVarArray): HRESULT;stdcall;
  566. begin
  567. Result:=SafeArrayUnlock(psa);
  568. end;
  569. Function SafeArrayLock(psa: PVarArray): HRESULT;stdcall;
  570. begin
  571. Result:=CheckVarArray(psa);
  572. if Result<>VAR_OK then
  573. exit;
  574. InterlockedIncrement(psa^.LockCount);
  575. end;
  576. Function SafeArrayUnlock(psa: PVarArray): HRESULT;stdcall;
  577. begin
  578. Result:=CheckVarArray(psa);
  579. if (Result<>VAR_OK) then
  580. exit;
  581. if InterlockedDecrement(psa^.LockCount)<0 then
  582. begin
  583. InterlockedIncrement(psa^.LockCount);
  584. result:=VAR_UNEXPECTED;
  585. end;
  586. end;
  587. Function SafeArrayGetElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  588. Data: Pointer): HRESULT;stdcall;
  589. var
  590. P: Pointer;
  591. begin
  592. Result:=CheckVarArrayAndCalculateAddress(psa, Indices, P, True);
  593. if Result<>VAR_OK then
  594. exit;
  595. try
  596. case VariantArrayType(psa) of
  597. vatNormal:
  598. Move(P^, Data^, psa^.ElementSize);
  599. vatInterface:
  600. NoInterfaces; // Just assign...
  601. vatWideString:
  602. NoWideStrings; // Just assign...
  603. end;
  604. except
  605. On E : Exception do
  606. Result:=ExceptionToVariantError(E);
  607. end;
  608. SetUnlockResult(psa,Result);
  609. end;
  610. Function SafeArrayPutElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  611. const Data: Pointer): HRESULT;stdcall;
  612. var
  613. P: Pointer;
  614. begin
  615. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,P,True);
  616. if Result<>VAR_OK then
  617. exit;
  618. try
  619. case VariantArrayType(psa) of
  620. vatNormal:
  621. Move(Data^,P^,psa^.ElementSize);
  622. vatInterface:
  623. NoInterfaces;
  624. vatWideString:
  625. NoWideStrings;
  626. end;
  627. except
  628. On E : Exception do
  629. Result:=ExceptionToVariantError(E);
  630. end;
  631. SetUnlockResult(psa,Result);
  632. end;
  633. Function SafeArrayPtrOfIndex(psa: PVarArray; Indices: PVarArrayCoorArray;
  634. var Address: Pointer): HRESULT;stdcall;
  635. begin
  636. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,Address,False);
  637. end;
  638. Function SafeArrayGetElemSize(psa: PVarArray): LongWord;stdcall;
  639. begin
  640. if CheckVarArray(psa)<>VAR_OK then
  641. Result:=0
  642. else
  643. Result:=psa^.ElementSize;
  644. end;
  645. {$endif HASVARIANT}
  646. {
  647. $Log$
  648. Revision 1.24 2005-03-28 21:52:43 florian
  649. * SafeCreateArray fixed
  650. Revision 1.23 2005/03/28 17:04:58 florian
  651. * compilation on non win32 fixed
  652. Revision 1.22 2005/03/28 13:38:05 florian
  653. + a lot of vararray stuff
  654. Revision 1.21 2005/02/25 14:39:31 peter
  655. * 64bit fixes
  656. Revision 1.20 2005/02/24 22:36:36 florian
  657. + some variant stuff fixed and added
  658. Revision 1.19 2005/02/14 17:13:31 peter
  659. * truncate log
  660. Revision 1.18 2005/02/08 21:17:25 florian
  661. * fixed variant copy for interfaces
  662. Revision 1.17 2005/02/08 07:25:26 marco
  663. * patch from Peter
  664. Revision 1.16 2005/02/07 21:52:08 florian
  665. + basic variant<->intf conversion
  666. Revision 1.15 2005/01/16 16:56:32 florian
  667. + some missing word handling added
  668. Revision 1.14 2005/01/16 16:15:30 florian
  669. * olestring copying fixed
  670. Revision 1.13 2005/01/15 18:47:26 florian
  671. * several variant init./final. stuff fixed
  672. Revision 1.12 2005/01/08 16:19:42 florian
  673. * made some variants stuff more readable
  674. }