varutils.inc 18 KB

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