varutils.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  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(v.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. varUnknown:
  95. NoInterfaces; // We should bump up reference count here (Addref)
  96. else
  97. Exit(VAR_BADVARTYPE);
  98. end;
  99. end;
  100. VargDest.VType:=VType;
  101. end;
  102. end;
  103. function VariantCopyInd(var VargDest: TVarData; const VargSrc: TVarData): HRESULT;stdcall;
  104. begin
  105. if (VargSrc.VType and varByRef) = 0 then
  106. Exit(VariantCopy(VargDest, VargSrc));
  107. With VargSrc do
  108. begin
  109. if (VType and varArray) <> 0 then
  110. Exit(VAR_INVALIDARG);
  111. case (VType and varTypeMask) of
  112. varEmpty, varNull:;
  113. varSmallint : VargDest.VSmallInt:=PSmallInt(VPointer)^;
  114. varInteger : VargDest.VInteger:=PLongint(VPointer)^;
  115. varSingle : VargDest.VSingle:=PSingle(VPointer)^;
  116. varDouble : VargDest.VDouble:=PDouble(VPointer)^;
  117. varCurrency : VargDest.VCurrency:=PCurrency(VPointer)^;
  118. varDate : VargDest.VDate:=PDate(VPointer)^;
  119. varBoolean : VargDest.VBoolean:=PWordBool(VPointer)^;
  120. varError : VargDest.VError:=PError(VPointer)^;
  121. varByte : VargDest.VByte:=PByte(VPointer)^;
  122. varWord : VargDest.VWord:=PWord(VPointer)^;
  123. VarShortInt : VargDest.VShortInt:=PShortInt(VPointer)^;
  124. VarInt64 : VargDest.VInt64:=PInt64(VPointer)^;
  125. VarLongWord : VargDest.VLongWord:=PCardinal(VPointer)^;
  126. VarQWord : VargDest.VQWord:=PQWord(VPointer)^;
  127. varVariant : Variant(VargDest):=Variant(PVarData(VPointer)^);
  128. varOleStr : CopyAsWideString(VargDest.VOleStr,PVarData(VPointer)^.VoleStr);
  129. varDispatch,
  130. varUnknown : NoInterfaces;
  131. else
  132. Exit(VAR_BADVARTYPE);
  133. end;
  134. VargDest.VType:=VType and VarTypeMask;
  135. end;
  136. Result:=VAR_OK;
  137. end;
  138. Function VariantChangeTypeEx(var VargDest: TVarData; const VargSrc: TVarData;
  139. LCID: Integer; Flags: Word; VarType: Word): HRESULT; stdcall;
  140. var
  141. Tmp : TVarData;
  142. begin
  143. if ((VarType and varArray) <> 0) or
  144. ((VargSrc.VType and varArray) <> 0) or
  145. ((VarType and varByRef) <> 0) then
  146. Exit(VAR_INVALIDARG);
  147. Result:=VariantCopyInd(Tmp, VargSrc);
  148. if Result = VAR_OK then
  149. try
  150. Result:=VariantClear(VargDest);
  151. {$RANGECHECKS ON}
  152. if Result = VAR_OK then
  153. try
  154. case Vartype of
  155. varSmallInt : VargDest.VSmallInt:=VariantToSmallInt(Tmp);
  156. varInteger : VargDest.VInteger:=VariantToLongint(Tmp);
  157. varSingle : VargDest.VSingle:=VariantToSingle(Tmp);
  158. varDouble : VargDest.VDouble:=VariantToDouble(Tmp);
  159. varCurrency : VargDest.VCurrency:=VariantToCurrency(Tmp);
  160. varDate : VargDest.VDate:=VariantToDate(tmp);
  161. varOleStr : MakeWideString(VargDest.VoleStr, VariantToWideString(tmp));
  162. varDispatch : Result:=VAR_TYPEMISMATCH;
  163. varUnknown : Result:=VAR_TYPEMISMATCH;
  164. varBoolean : VargDest.VBoolean:=VariantToBoolean(Tmp);
  165. varByte : VargDest.VByte:=VariantToByte(Tmp);
  166. VarShortInt : VargDest.VShortInt:=VariantToShortInt(Tmp);
  167. VarInt64 : VargDest.Vint64:=VariantToInt64(Tmp);
  168. VarLongWord : VargDest.VLongWord:=VariantToCardinal(Tmp);
  169. VarQWord : VargDest.VQWord:=VariantToQword(tmp);
  170. else
  171. Result:=VAR_BADVARTYPE;
  172. end;
  173. If Result = VAR_OK then
  174. VargDest.VType:=VarType;
  175. except
  176. On E : EVariantError do
  177. Result:=E.ErrCode;
  178. else
  179. Result:=VAR_INVALIDARG;
  180. end;
  181. finally
  182. VariantClear(Tmp);
  183. end;
  184. end;
  185. { ---------------------------------------------------------------------
  186. Variant array support
  187. ---------------------------------------------------------------------}
  188. Function CheckArrayUnlocked (psa : PVarArray) : HResult;
  189. begin
  190. If psa^.LockCount = 0 Then
  191. Result:=VAR_OK
  192. else
  193. Result:=VAR_ARRAYISLOCKED;
  194. end;
  195. Function CheckVarArray(psa: PVarArray ): HRESULT;
  196. begin
  197. If psa=nil then
  198. Result:=VAR_INVALIDARG
  199. else
  200. Result:=VAR_OK;
  201. end;
  202. Function SafeArrayCalculateElementAddress(psa: PVarArray; aElement: Integer): Pointer;
  203. begin
  204. Result:=Pointer(psa^.Data)+(aElement*psa^.ElementSize);
  205. end;
  206. Function CheckVarArrayAndCalculateAddress(psa: PVarArray;
  207. Indices: PVarArrayCoorArray; var Address: Pointer; Lockit: Boolean): HRESULT;
  208. Function CountElements(D: Longint): Longint;
  209. begin
  210. if (D<psa^.DimCount) then
  211. Result:=CountElements(D+1)+psa^.Bounds[D-1].ElementCount
  212. else
  213. Result:=1;
  214. end;
  215. var
  216. LB,HB,I,Count : LongInt;
  217. begin
  218. Result:=CheckVarArray(psa);
  219. Address:=nil;
  220. Count:=0;
  221. If Result<>VAR_OK then
  222. exit;
  223. for I:=1 to psa^.DimCount do
  224. begin
  225. LB:=psa^.Bounds[I-1].LowBound;
  226. HB:=LB+psa^.Bounds[I-1].ElementCount;
  227. if (LB=HB) or ((Indices^[I-1]< LB) or(Indices^[I-1]>HB)) then
  228. Exit(VAR_BADINDEX);
  229. Count:=Count+(Indices^[I-1]-LB)*CountElements(I+1);
  230. end;
  231. Address:=SafeArrayCalculateElementAddress(psa, Count);
  232. if LockIt then
  233. Result:=SafeArrayLock(psa);
  234. end;
  235. Function SafeArrayElementTotal(psa: PVarArray): Integer;
  236. var
  237. I: Integer;
  238. begin
  239. Result:=1;
  240. With psa^ do
  241. for I:=0 to DimCount - 1 do
  242. Result:=Result*Bounds[I].ElementCount;
  243. end;
  244. type
  245. TVariantArrayType = (vatNormal, varInterface, varWideString);
  246. Function VariantArrayType(psa: PVarArray): TVariantArrayType;
  247. begin
  248. if ((psa^.Flags and ARR_DISPATCH) <> 0) or
  249. ((psa^.Flags and ARR_UNKNOWN) <> 0) then
  250. Result:=varInterface
  251. else if (psa^.Flags AND ARR_OLESTR) <> 0 then
  252. Result:=varWideString
  253. else
  254. Result:=vatNormal;
  255. end;
  256. Function SafeArrayClearDataSpace(psa: PVarArray; WipeBytes: Boolean {= True}): HRESULT;
  257. var
  258. I : Integer;
  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. varInterface : NoInterfaces;
  268. varWideString : 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. I : Integer;
  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. varInterface : NoInterfaces; // Copy element per element...
  289. varWideString: 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: Integer; const Bounds: TVarArrayBoundArray): PVarArray;stdcall;
  310. var
  311. res : HRESULT;
  312. I : Longint;
  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. With Result^ do
  321. begin
  322. DimCount:=Dim;
  323. Flags:=psaElementFlags[VarType];
  324. ElementSize:=psaElementSizes[VarType];
  325. for i:=0 to Dim-1 do
  326. begin
  327. Bounds[i].LowBound:=Bounds[Dim-I-1].LowBound;
  328. Bounds[I].ElementCount:=Bounds[Dim-I-1].ElementCount;
  329. end;
  330. end;
  331. res:=SafeArrayAllocData(Result);
  332. if res<>VAR_OK then
  333. begin
  334. SafeArrayDestroyDescriptor(Result);
  335. Result:=nil;
  336. end;
  337. end;
  338. Function SafeArrayAllocDescriptor(DimCount: Integer; var psa: PVarArray): HRESULT;stdcall;
  339. begin
  340. try
  341. psa:=GetMem(SizeOf(TVarArray) + SizeOf(TVarArrayBound) * (DimCount - 1));
  342. Result:=VAR_OK;
  343. except
  344. On E : Exception do
  345. Result:=ExceptionToVariantError(E);
  346. end;
  347. end;
  348. Function SafeArrayAllocData(psa: PVarArray): HRESULT;stdcall;
  349. begin
  350. try
  351. With psa^ do
  352. Data:=GetMem(SafeArrayElementTotal(psa)*ElementSize);
  353. Result:=VAR_OK;
  354. except
  355. On E : Exception do
  356. Result:=ExceptionToVariantError(E);
  357. end;
  358. end;
  359. Function SafeArrayDestroy(psa: PVarArray): HRESULT;stdcall;
  360. begin
  361. Result:=CheckVarArray(psa);
  362. if Result<> VAR_OK then
  363. exit;
  364. Result:=CheckArrayUnlocked(psa);
  365. if Result<> VAR_OK then
  366. exit;
  367. Result:=SafeArrayDestroyData(psa);
  368. if Result<>VAR_OK then
  369. exit;
  370. Result:=SafeArrayDestroyDescriptor(psa);
  371. end;
  372. Function SafeArrayDestroyDescriptor(psa: PVarArray): HRESULT;stdcall;
  373. begin
  374. Result:=CheckVarArray(psa);
  375. if Result<>VAR_OK then
  376. exit;
  377. Result:=CheckArrayUnlocked(psa);
  378. if Result<> VAR_OK then
  379. exit;
  380. try
  381. FreeMem(psa);
  382. except
  383. On E : Exception do
  384. Result:=ExceptionToVariantError(E);
  385. end;
  386. end;
  387. Function SafeArrayDestroyData(psa: PVarArray): HRESULT;stdcall;
  388. begin
  389. Result:=CheckVarArray(psa);
  390. if Result<>VAR_OK then
  391. exit;
  392. Result:=CheckArrayUnlocked(psa);
  393. if Result<> VAR_OK then
  394. exit;
  395. try
  396. Result:=SafeArrayClearDataSpace(psa, False);
  397. if (Result=VAR_OK) and ((psa^.Flags and ARR_FIXEDSIZE)=0) then
  398. begin
  399. FreeMem(psa^.Data);
  400. psa^.Data:=nil;
  401. end;
  402. except
  403. On E : Exception do
  404. Result:=ExceptionToVariantError(E);
  405. end;
  406. end;
  407. Function SafeArrayRedim(psa: PVarArray; const NewBound: TVarArrayBound): HRESULT;stdcall;
  408. var
  409. vat: TVariantArrayType;
  410. i, D,j,count : Integer;
  411. P : Pointer;
  412. begin
  413. Result:=CheckVarArray(psa);
  414. if Result <> VAR_OK then
  415. exit;
  416. if (psa^.Flags and ARR_FIXEDSIZE) <> 0 then
  417. Exit(VAR_INVALIDARG);
  418. Result:=SafeArrayLock(psa);
  419. if Result<>VAR_OK then
  420. exit;
  421. try
  422. D:=NewBound.ElementCount - psa^.Bounds[0].ElementCount;
  423. for i:=1 to psa^.DimCount - 1 do
  424. D:=D*psa^.Bounds[i].ElementCount;
  425. if D<>0 then
  426. begin
  427. Count:=SafeArrayElementTotal(psa);
  428. if D<0 then
  429. begin
  430. vat:=VariantArrayType(psa);
  431. for j:=Count-1 downto Count+D do
  432. begin
  433. P:=SafeArrayCalculateElementAddress(psa,j);
  434. if vat = varInterface then
  435. NoInterfaces // Set to nil
  436. else
  437. NoWideStrings; // Set to empty...
  438. end;
  439. end;
  440. ReAllocMem(psa^.Data,Count+D);
  441. end;
  442. psa^.Bounds[0].ElementCount:=NewBound.ElementCount;
  443. psa^.Bounds[0].LowBound:=NewBound.LowBound;
  444. except
  445. On E : Exception do
  446. Result:=ExceptionToVariantError(E);
  447. end;
  448. SetUnlockResult(psa,Result);
  449. end;
  450. Function SafeArrayCopy(psa: PVarArray; var psaOut: PVarArray): HRESULT;stdcall;
  451. var
  452. i : Integer;
  453. begin
  454. Result:=CheckVarArray(psa);
  455. if Result<>VAR_OK then
  456. exit;
  457. Result:=SafeArrayLock(psa);
  458. if Result<>VAR_OK then
  459. exit;
  460. try
  461. Result:=SafeArrayAllocDescriptor(psa^.DimCount,psaOut);
  462. if Result<>VAR_OK then
  463. Exit;
  464. try
  465. With psaOut^ do
  466. begin
  467. Flags:=psa^.Flags;
  468. ElementSize:=psa^.ElementSize;
  469. DimCount:=psa^.DimCount;
  470. for i:=0 to DimCount-1 do
  471. begin
  472. Bounds[i].ElementCount:=psa^.Bounds[i].ElementCount;
  473. Bounds[i].LowBound:=psa^.Bounds[i].LowBound;
  474. end;
  475. end;
  476. Result:=SafeArrayAllocData(psaOut);
  477. if Result<>VAR_OK then
  478. exit;
  479. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  480. finally
  481. if Result<>VAR_OK then
  482. begin
  483. SafeArrayDestroyDescriptor(psaOut);
  484. psaOut:=nil;
  485. end;
  486. end;
  487. except
  488. On E : Exception do
  489. Result:=ExceptionToVariantError(E)
  490. end;
  491. SetUnlockResult(psa,Result);
  492. end;
  493. Function SafeArrayCopyData(psa, psaOut: PVarArray): HRESULT;stdcall;
  494. var
  495. i : Integer;
  496. begin
  497. Result:=CheckVarArray(psa);
  498. if Result<>VAR_OK then
  499. exit;
  500. Result:=CheckVarArray(psaOut);
  501. if Result<>VAR_OK then
  502. exit;
  503. Result:=SafeArrayLock(psaOut);
  504. if Result<>VAR_OK then
  505. exit;
  506. try
  507. Result:=SafeArrayLock(psa);
  508. if Result<>VAR_OK then
  509. exit;
  510. try
  511. With psaOut^ do
  512. begin
  513. if (psa^.Flags<>Flags) or
  514. (psa^.ElementSize<>ElementSize) or
  515. (psa^.DimCount<>DimCount) then
  516. Exit(VAR_INVALIDARG);
  517. for i:=0 to psa^.DimCount - 1 do
  518. if (psa^.Bounds[i].LowBound<>Bounds[i].LowBound) or
  519. (psa^.Bounds[i].ElementCount<>Bounds[i].ElementCount) then
  520. exit(VAR_INVALIDARG);
  521. end;
  522. Result:=SafeArrayClearDataSpace(psaOut,True);
  523. if Result<> VAR_OK then
  524. exit;
  525. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  526. finally
  527. SetUnlockResult(psa,Result);
  528. end;
  529. finally
  530. SetUnlockResult(psaOut,Result);
  531. end;
  532. end;
  533. Function SafeArrayGetLBound(psa: PVarArray; Dim: Integer; var LBound: Integer): HRESULT;stdcall;
  534. begin
  535. Result:=CheckVarArray(psa);
  536. if Result<>VAR_OK then
  537. exit;
  538. if (Dim>0) and (Dim<=psa^.DimCount) then
  539. LBound:=psa^.Bounds[Dim-1].LowBound
  540. else
  541. Result:=VAR_BADINDEX;
  542. end;
  543. Function SafeArrayGetUBound(psa: PVarArray; Dim: Integer; var UBound: Integer): HRESULT;stdcall;
  544. begin
  545. Result:=CheckVarArray(psa);
  546. if Result<>VAR_OK then
  547. exit;
  548. if (Dim>0) and (Dim<=psa^.DimCount) then
  549. UBound:=psa^.Bounds[Dim-1].LowBound +
  550. psa^.Bounds[Dim-1].ElementCount-1
  551. else
  552. Result:=VAR_BADINDEX
  553. end;
  554. Function SafeArrayGetDim(psa: PVarArray): Integer;stdcall;
  555. begin
  556. if CheckVarArray(psa)<>VAR_OK then
  557. Result:=0
  558. else
  559. Result:=psa^.DimCount;
  560. end;
  561. Function SafeArrayAccessData(psa: PVarArray; var ppvData: Pointer): HRESULT;stdcall;
  562. begin
  563. Result:=SafeArrayLock(psa);
  564. if Result<>VAR_OK then
  565. ppvData:=nil
  566. else
  567. ppvData:=psa^.Data;
  568. end;
  569. Function SafeArrayUnaccessData(psa: PVarArray): HRESULT;stdcall;
  570. begin
  571. Result:=SafeArrayUnlock(psa);
  572. end;
  573. Function SafeArrayLock(psa: PVarArray): HRESULT;stdcall;
  574. begin
  575. Result:=CheckVarArray(psa);
  576. if Result<>VAR_OK then
  577. exit;
  578. Inc(psa^.LockCount);
  579. end;
  580. Function SafeArrayUnlock(psa: PVarArray): HRESULT;stdcall;
  581. begin
  582. Result:=CheckVarArray(psa);
  583. if (Result<>VAR_OK) then
  584. exit;
  585. If (psa^.LockCount>0) then
  586. Dec(psa^.LockCount);
  587. end;
  588. Function SafeArrayGetElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  589. Data: Pointer): HRESULT;stdcall;
  590. var
  591. P: Pointer;
  592. begin
  593. Result:=CheckVarArrayAndCalculateAddress(psa, Indices, P, True);
  594. if Result<>VAR_OK then
  595. exit;
  596. try
  597. case VariantArrayType(psa) of
  598. vatNormal:
  599. Move(P^, Data^, psa^.ElementSize);
  600. varInterface:
  601. NoInterfaces; // Just assign...
  602. varWideString:
  603. NoWideStrings; // Just assign...
  604. end;
  605. except
  606. On E : Exception do
  607. Result:=ExceptionToVariantError(E);
  608. end;
  609. SetUnlockResult(psa,Result);
  610. end;
  611. Function SafeArrayPutElement(psa: PVarArray; Indices: PVarArrayCoorArray;
  612. const Data: Pointer): HRESULT;stdcall;
  613. var
  614. P: Pointer;
  615. begin
  616. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,P,True);
  617. if Result<>VAR_OK then
  618. exit;
  619. try
  620. case VariantArrayType(psa) of
  621. vatNormal: Move(Data^,P^,psa^.ElementSize);
  622. varInterface: NoInterfaces;
  623. varWideString: NoWideStrings;
  624. end;
  625. except
  626. On E : Exception do
  627. Result:=ExceptionToVariantError(E);
  628. end;
  629. SetUnlockResult(psa,Result);
  630. end;
  631. Function SafeArrayPtrOfIndex(psa: PVarArray; Indices: PVarArrayCoorArray;
  632. var Address: Pointer): HRESULT;stdcall;
  633. begin
  634. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,Address,False);
  635. end;
  636. Function SafeArrayGetElemSize(psa: PVarArray): LongWord;stdcall;
  637. begin
  638. if CheckVarArray(psa)<>VAR_OK then
  639. Result:=0
  640. else
  641. Result:=psa^.ElementSize;
  642. end;
  643. {$endif HASVARIANT}
  644. {
  645. $Log$
  646. Revision 1.16 2005-02-07 21:52:08 florian
  647. + basic variant<->intf conversion
  648. Revision 1.15 2005/01/16 16:56:32 florian
  649. + some missing word handling added
  650. Revision 1.14 2005/01/16 16:15:30 florian
  651. * olestring copying fixed
  652. Revision 1.13 2005/01/15 18:47:26 florian
  653. * several variant init./final. stuff fixed
  654. Revision 1.12 2005/01/08 16:19:42 florian
  655. * made some variants stuff more readable
  656. Revision 1.11 2004/04/28 20:48:20 peter
  657. * ordinal-pointer conversions fixed
  658. Revision 1.10 2002/11/22 16:30:05 peter
  659. * Widestring->PWidechar requires a typecast
  660. Revision 1.9 2002/10/11 12:21:55 florian
  661. * fixes for new widestring handling
  662. Revision 1.8 2002/09/07 16:01:23 peter
  663. * old logs removed and tabs fixed
  664. }