varutils.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  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: Integer): 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, varInterface, varWideString);
  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:=varInterface
  252. else if (psa^.Flags AND ARR_OLESTR) <> 0 then
  253. Result:=varWideString
  254. else
  255. Result:=vatNormal;
  256. end;
  257. Function SafeArrayClearDataSpace(psa: PVarArray; WipeBytes: Boolean {= True}): HRESULT;
  258. var
  259. I : Integer;
  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. varInterface : NoInterfaces;
  269. varWideString : 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. I : Integer;
  280. vVargSrc, vTarget: Pointer;
  281. vat: TVariantArrayType;
  282. begin
  283. try
  284. vat:=VariantArrayType(psa);
  285. case vat of
  286. vatNormal: Move(psa^.Data^,
  287. psaOut^.Data^,
  288. SafeArrayElementTotal(psa)*psa^.ElementSize);
  289. varInterface : NoInterfaces; // Copy element per element...
  290. varWideString: NoWideStrings; // here also...
  291. end;
  292. Result:=VAR_OK;
  293. except
  294. On E : Exception do
  295. Result:=ExceptionToVariantError(E);
  296. end;
  297. end;
  298. Type
  299. TVartypes = varEmpty..varByte;
  300. Const
  301. Supportedpsas : set of TVarTypes =
  302. [varSmallint,varInteger,varSingle,varDouble,varCurrency,varDate,varOleStr,
  303. varDispatch,varError,varBoolean,varVariant,varUnknown,varByte];
  304. psaElementSizes : Array [varEmpty..varByte] of Byte =
  305. (0,0,2,4,4,8,8,8,4,4,4,2,16,4,0,0,0,1);
  306. psaElementFlags : Array [varEmpty..varByte] of Longint =
  307. (ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE,
  308. ARR_OLESTR,ARR_DISPATCH,ARR_NONE,ARR_NONE,ARR_NONE,ARR_UNKNOWN,
  309. ARR_NONE,ARR_NONE,ARR_NONE,ARR_NONE);
  310. Function SafeArrayCreate(VarType, Dim: Integer; const Bounds: TVarArrayBoundArray): PVarArray;stdcall;
  311. var
  312. res : HRESULT;
  313. I : Longint;
  314. begin
  315. Result:=nil;
  316. if Not (VarType in Supportedpsas) Then
  317. exit;
  318. Res:=SafeArrayAllocDescriptor(Dim, Result);
  319. if Res<>VAR_OK then
  320. exit;
  321. With Result^ do
  322. begin
  323. DimCount:=Dim;
  324. Flags:=psaElementFlags[VarType];
  325. ElementSize:=psaElementSizes[VarType];
  326. for i:=0 to Dim-1 do
  327. begin
  328. Bounds[i].LowBound:=Bounds[Dim-I-1].LowBound;
  329. Bounds[I].ElementCount:=Bounds[Dim-I-1].ElementCount;
  330. end;
  331. end;
  332. res:=SafeArrayAllocData(Result);
  333. if res<>VAR_OK then
  334. begin
  335. SafeArrayDestroyDescriptor(Result);
  336. Result:=nil;
  337. end;
  338. end;
  339. Function SafeArrayAllocDescriptor(DimCount: Integer; var psa: PVarArray): HRESULT;stdcall;
  340. begin
  341. try
  342. psa:=GetMem(SizeOf(TVarArray) + SizeOf(TVarArrayBound) * (DimCount - 1));
  343. Result:=VAR_OK;
  344. except
  345. On E : Exception do
  346. Result:=ExceptionToVariantError(E);
  347. end;
  348. end;
  349. Function SafeArrayAllocData(psa: PVarArray): HRESULT;stdcall;
  350. begin
  351. try
  352. With psa^ do
  353. Data:=GetMem(SafeArrayElementTotal(psa)*ElementSize);
  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 = varInterface 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. DimCount:=psa^.DimCount;
  471. for i:=0 to DimCount-1 do
  472. begin
  473. Bounds[i].ElementCount:=psa^.Bounds[i].ElementCount;
  474. Bounds[i].LowBound:=psa^.Bounds[i].LowBound;
  475. end;
  476. end;
  477. Result:=SafeArrayAllocData(psaOut);
  478. if Result<>VAR_OK then
  479. exit;
  480. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  481. finally
  482. if Result<>VAR_OK then
  483. begin
  484. SafeArrayDestroyDescriptor(psaOut);
  485. psaOut:=nil;
  486. end;
  487. end;
  488. except
  489. On E : Exception do
  490. Result:=ExceptionToVariantError(E)
  491. end;
  492. SetUnlockResult(psa,Result);
  493. end;
  494. Function SafeArrayCopyData(psa, psaOut: PVarArray): HRESULT;stdcall;
  495. var
  496. i : Integer;
  497. begin
  498. Result:=CheckVarArray(psa);
  499. if Result<>VAR_OK then
  500. exit;
  501. Result:=CheckVarArray(psaOut);
  502. if Result<>VAR_OK then
  503. exit;
  504. Result:=SafeArrayLock(psaOut);
  505. if Result<>VAR_OK then
  506. exit;
  507. try
  508. Result:=SafeArrayLock(psa);
  509. if Result<>VAR_OK then
  510. exit;
  511. try
  512. With psaOut^ do
  513. begin
  514. if (psa^.Flags<>Flags) or
  515. (psa^.ElementSize<>ElementSize) or
  516. (psa^.DimCount<>DimCount) then
  517. Exit(VAR_INVALIDARG);
  518. for i:=0 to psa^.DimCount - 1 do
  519. if (psa^.Bounds[i].LowBound<>Bounds[i].LowBound) or
  520. (psa^.Bounds[i].ElementCount<>Bounds[i].ElementCount) then
  521. exit(VAR_INVALIDARG);
  522. end;
  523. Result:=SafeArrayClearDataSpace(psaOut,True);
  524. if Result<> VAR_OK then
  525. exit;
  526. Result:=SafeArrayCopyDataSpace(psa, psaOut);
  527. finally
  528. SetUnlockResult(psa,Result);
  529. end;
  530. finally
  531. SetUnlockResult(psaOut,Result);
  532. end;
  533. end;
  534. Function SafeArrayGetLBound(psa: PVarArray; Dim: Integer; var LBound: Integer): HRESULT;stdcall;
  535. begin
  536. Result:=CheckVarArray(psa);
  537. if Result<>VAR_OK then
  538. exit;
  539. if (Dim>0) and (Dim<=psa^.DimCount) then
  540. LBound:=psa^.Bounds[Dim-1].LowBound
  541. else
  542. Result:=VAR_BADINDEX;
  543. end;
  544. Function SafeArrayGetUBound(psa: PVarArray; Dim: Integer; var UBound: Integer): HRESULT;stdcall;
  545. begin
  546. Result:=CheckVarArray(psa);
  547. if Result<>VAR_OK then
  548. exit;
  549. if (Dim>0) and (Dim<=psa^.DimCount) then
  550. UBound:=psa^.Bounds[Dim-1].LowBound +
  551. psa^.Bounds[Dim-1].ElementCount-1
  552. else
  553. Result:=VAR_BADINDEX
  554. end;
  555. Function SafeArrayGetDim(psa: PVarArray): Integer;stdcall;
  556. begin
  557. if CheckVarArray(psa)<>VAR_OK then
  558. Result:=0
  559. else
  560. Result:=psa^.DimCount;
  561. end;
  562. Function SafeArrayAccessData(psa: PVarArray; var ppvData: Pointer): HRESULT;stdcall;
  563. begin
  564. Result:=SafeArrayLock(psa);
  565. if Result<>VAR_OK then
  566. ppvData:=nil
  567. else
  568. ppvData:=psa^.Data;
  569. end;
  570. Function SafeArrayUnaccessData(psa: PVarArray): HRESULT;stdcall;
  571. begin
  572. Result:=SafeArrayUnlock(psa);
  573. end;
  574. Function SafeArrayLock(psa: PVarArray): HRESULT;stdcall;
  575. begin
  576. Result:=CheckVarArray(psa);
  577. if Result<>VAR_OK then
  578. exit;
  579. Inc(psa^.LockCount);
  580. end;
  581. Function SafeArrayUnlock(psa: PVarArray): HRESULT;stdcall;
  582. begin
  583. Result:=CheckVarArray(psa);
  584. if (Result<>VAR_OK) then
  585. exit;
  586. If (psa^.LockCount>0) then
  587. Dec(psa^.LockCount);
  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. varInterface:
  602. NoInterfaces; // Just assign...
  603. varWideString:
  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: Move(Data^,P^,psa^.ElementSize);
  623. varInterface: NoInterfaces;
  624. varWideString: NoWideStrings;
  625. end;
  626. except
  627. On E : Exception do
  628. Result:=ExceptionToVariantError(E);
  629. end;
  630. SetUnlockResult(psa,Result);
  631. end;
  632. Function SafeArrayPtrOfIndex(psa: PVarArray; Indices: PVarArrayCoorArray;
  633. var Address: Pointer): HRESULT;stdcall;
  634. begin
  635. Result:=CheckVarArrayAndCalculateAddress(psa,Indices,Address,False);
  636. end;
  637. Function SafeArrayGetElemSize(psa: PVarArray): LongWord;stdcall;
  638. begin
  639. if CheckVarArray(psa)<>VAR_OK then
  640. Result:=0
  641. else
  642. Result:=psa^.ElementSize;
  643. end;
  644. {$endif HASVARIANT}
  645. {
  646. $Log$
  647. Revision 1.18 2005-02-08 21:17:25 florian
  648. * fixed variant copy for interfaces
  649. Revision 1.17 2005/02/08 07:25:26 marco
  650. * patch from Peter
  651. Revision 1.16 2005/02/07 21:52:08 florian
  652. + basic variant<->intf conversion
  653. Revision 1.15 2005/01/16 16:56:32 florian
  654. + some missing word handling added
  655. Revision 1.14 2005/01/16 16:15:30 florian
  656. * olestring copying fixed
  657. Revision 1.13 2005/01/15 18:47:26 florian
  658. * several variant init./final. stuff fixed
  659. Revision 1.12 2005/01/08 16:19:42 florian
  660. * made some variants stuff more readable
  661. Revision 1.11 2004/04/28 20:48:20 peter
  662. * ordinal-pointer conversions fixed
  663. Revision 1.10 2002/11/22 16:30:05 peter
  664. * Widestring->PWidechar requires a typecast
  665. Revision 1.9 2002/10/11 12:21:55 florian
  666. * fixes for new widestring handling
  667. Revision 1.8 2002/09/07 16:01:23 peter
  668. * old logs removed and tabs fixed
  669. }