Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

709 lines
17 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // array.c - array functions
  24. ////
  25. #include "winlocal.h"
  26. #include "array.h"
  27. #include "sort.h"
  28. #include "mem.h"
  29. #include "str.h"
  30. #include "trace.h"
  31. ////
  32. // private definitions
  33. ////
  34. // compare element <i> with element <j>
  35. //
  36. #define ElemCompare(lpi, lpj) \
  37. (lpfnCompare == NULL ? MemCmp(lpi, lpj, sizeof(ARRAYELEM)) : lpfnCompare(lpi, lpj))
  38. // array control struct
  39. //
  40. typedef struct ARRAY
  41. {
  42. DWORD dwVersion;
  43. HINSTANCE hInst;
  44. HTASK hTask;
  45. ARRAYSIZE_T nSize;
  46. ARRAYSIZE_T nMaxSize;
  47. ARRAYSIZE_T nGrowBy;
  48. LPARRAYELEM lpelem;
  49. } ARRAY, FAR *LPARRAY;
  50. // helper functions
  51. //
  52. static LPARRAY ArrayGetPtr(HARRAY hArray);
  53. static HARRAY ArrayGetHandle(LPARRAY lpArray);
  54. ////
  55. // public functions
  56. ////
  57. ////
  58. // array constructor and destructor functions
  59. ////
  60. // ArrayCreate - array constructor (array is initially empty)
  61. // <dwVersion> (i) must be ARRAY_VERSION
  62. // <hInst> (i) instance handle of calling module
  63. // return new array handle (NULL if error)
  64. //
  65. HARRAY DLLEXPORT WINAPI ArrayCreate(DWORD dwVersion, HINSTANCE hInst)
  66. {
  67. BOOL fSuccess = TRUE;
  68. LPARRAY lpArray = NULL;
  69. if (dwVersion != ARRAY_VERSION)
  70. fSuccess = TraceFALSE(NULL);
  71. else if (hInst == NULL)
  72. fSuccess = TraceFALSE(NULL);
  73. else if ((lpArray = (LPARRAY) MemAlloc(NULL, sizeof(ARRAY), 0)) == NULL)
  74. fSuccess = TraceFALSE(NULL);
  75. else
  76. {
  77. // initially the array is empty
  78. //
  79. lpArray->dwVersion = dwVersion;
  80. lpArray->hInst = hInst;
  81. lpArray->hTask = GetCurrentTask();
  82. lpArray->nSize = 0;
  83. lpArray->nMaxSize = 0;
  84. lpArray->nGrowBy = 0;
  85. lpArray->lpelem = NULL;
  86. }
  87. return fSuccess ? ArrayGetHandle(lpArray) : NULL;
  88. }
  89. // ArrayDestroy - array destructor
  90. // <hArray> (i) handle returned from ArrayCreate
  91. // return 0 if success
  92. //
  93. int DLLEXPORT WINAPI ArrayDestroy(HARRAY hArray)
  94. {
  95. BOOL fSuccess = TRUE;
  96. LPARRAY lpArray;
  97. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  98. fSuccess = TraceFALSE(NULL);
  99. // make sure the array is emptied
  100. //
  101. else if (ArrayRemoveAll(hArray) != 0)
  102. fSuccess = TraceFALSE(NULL);
  103. else if ((lpArray = MemFree(NULL, lpArray)) != NULL)
  104. fSuccess = TraceFALSE(NULL);
  105. return fSuccess ? 0 : -1;
  106. }
  107. ////
  108. // array size functions
  109. ////
  110. // ArrayGetSize - get array size
  111. // <hArray> (i) handle returned from ArrayCreate
  112. // return size of array (0 if empty, -1 if error)
  113. // array indexes are zero-based, so the size is 1 greater than largest index
  114. //
  115. ARRAYSIZE_T DLLEXPORT WINAPI ArrayGetSize(HARRAY hArray)
  116. {
  117. BOOL fSuccess = TRUE;
  118. LPARRAY lpArray;
  119. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  120. fSuccess = TraceFALSE(NULL);
  121. return fSuccess ? lpArray->nSize : -1;
  122. }
  123. // ArrayGetUpperBound - get array upper bound
  124. // <hArray> (i) handle returned from ArrayCreate
  125. // return largest valid array index (-1 if empty, -2 if error)
  126. //
  127. ARRAYSIZE_T DLLEXPORT WINAPI ArrayGetUpperBound(HARRAY hArray)
  128. {
  129. return ArrayGetSize(hArray) - 1;
  130. }
  131. // ArraySetSize - establish new size and grow amount for array
  132. // <hArray> (i) handle returned from ArrayCreate
  133. // <nNewSize> (i) new array size (number of elements)
  134. // 0 make empty array
  135. // <nGrowBy> (i) when array needs to grow, grow by this amount
  136. // 0 use default grow amount
  137. // -1 leave grow amount unchanged
  138. // return 0 if success
  139. //
  140. int DLLEXPORT WINAPI ArraySetSize(HARRAY hArray, ARRAYSIZE_T nNewSize, ARRAYSIZE_T nGrowBy)
  141. {
  142. BOOL fSuccess = TRUE;
  143. LPARRAY lpArray;
  144. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  145. fSuccess = TraceFALSE(NULL);
  146. else if (nNewSize < 0)
  147. fSuccess = TraceFALSE(NULL);
  148. else
  149. {
  150. // if specified, set new grow amount
  151. //
  152. if (nGrowBy >= 0)
  153. lpArray->nGrowBy = nGrowBy;
  154. // if new size is zero, just shrink array to nothing
  155. //
  156. if (nNewSize == 0)
  157. {
  158. if (lpArray->lpelem != NULL)
  159. {
  160. if ((lpArray->lpelem = MemFree(NULL, lpArray->lpelem)) != NULL)
  161. fSuccess = TraceFALSE(NULL);
  162. else
  163. {
  164. lpArray->nSize = 0;
  165. lpArray->nMaxSize = 0;
  166. }
  167. }
  168. }
  169. // if array is already empty, grow it to exact size requested
  170. //
  171. else if (lpArray->lpelem == NULL)
  172. {
  173. if ((lpArray->lpelem = (LPARRAYELEM) MemAlloc(NULL,
  174. nNewSize * sizeof(ARRAYELEM), 0)) == NULL)
  175. {
  176. fSuccess = TraceFALSE(NULL);
  177. }
  178. else
  179. {
  180. lpArray->nSize = nNewSize;
  181. lpArray->nMaxSize = nNewSize;
  182. }
  183. }
  184. // if new size will fit within current array
  185. //
  186. else if (nNewSize <= lpArray->nMaxSize)
  187. {
  188. if (nNewSize > lpArray->nSize)
  189. {
  190. // clear elements outside of new size
  191. //
  192. MemSet(&lpArray->lpelem[lpArray->nSize], 0,
  193. (nNewSize - lpArray->nSize) * sizeof(ARRAYELEM));
  194. }
  195. // adjust virtual size variable, but leave memory block alone
  196. //
  197. lpArray->nSize = nNewSize;
  198. }
  199. // otherwise grow array to accomodate new size
  200. //
  201. else
  202. {
  203. ARRAYSIZE_T nGrowBy = lpArray->nGrowBy;
  204. ARRAYSIZE_T nNewMaxSize;
  205. LPARRAYELEM lpelem;
  206. // if nGrowBy not specified, compute it
  207. //
  208. if (nGrowBy == 0)
  209. nGrowBy = min(1024, max(4, lpArray->nSize / 8));
  210. // make sure the new array size is at least
  211. // nGrowBy elements larger than the old array size
  212. //
  213. nNewMaxSize = max(nNewSize, lpArray->nMaxSize + nGrowBy);
  214. #if 0
  215. // [From the WinSDK KnowledgeBase PSS ID Number: Q92942]
  216. // When GlobalReAlloc() is used with GMEM_ZEROINIT, it may not
  217. // zero out all of the reallocated memory when GlobalReAlloc()
  218. // is called to shrink a block of memory and then enlarge it.
  219. //
  220. if ((lpelem = (LPARRAYELEM) MemReAlloc(NULL, lpArray->lpelem,
  221. nNewMaxSize * sizeof(ARRAYELEM), 0)) == NULL)
  222. fSuccess = TraceFALSE(NULL);
  223. else
  224. {
  225. // compensate for GlobalReAlloc bug cited above
  226. //
  227. MemSet(&lpelem[lpArray->nSize], 0,
  228. (nNewMaxSize - lpArray->nSize) * sizeof(ARRAYELEM));
  229. lpArray->lpelem = lpelem;
  230. lpArray->nSize = nNewSize;
  231. lpArray->nMaxSize = nNewMaxSize;
  232. }
  233. #else
  234. // allocate new array
  235. //
  236. if ((lpelem = (LPARRAYELEM) MemAlloc(NULL,
  237. nNewMaxSize * sizeof(ARRAYELEM), 0)) == NULL)
  238. {
  239. fSuccess = TraceFALSE(NULL);
  240. }
  241. else
  242. {
  243. // copy old array into new array
  244. //
  245. MemCpy(lpelem, lpArray->lpelem,
  246. lpArray->nSize * sizeof(ARRAYELEM));
  247. // free old array
  248. //
  249. if ((lpArray->lpelem = MemFree(NULL, lpArray->lpelem)) != NULL)
  250. {
  251. fSuccess = TraceFALSE(NULL);
  252. if ((lpArray->lpelem = MemFree(NULL, lpArray->lpelem)) != NULL)
  253. fSuccess = TraceFALSE(NULL);
  254. }
  255. else
  256. {
  257. lpArray->lpelem = lpelem;
  258. lpArray->nSize = nNewSize;
  259. lpArray->nMaxSize = nNewMaxSize;
  260. }
  261. }
  262. #endif
  263. }
  264. }
  265. return fSuccess ? 0 : -1;
  266. }
  267. ////
  268. // array clean up functions
  269. ////
  270. // ArrayFreeExtra - free unused memory above the array upper bound
  271. // <hArray> (i) handle returned from ArrayCreate
  272. // return 0 if success
  273. //
  274. int DLLEXPORT WINAPI ArrayFreeExtra(HARRAY hArray)
  275. {
  276. BOOL fSuccess = TRUE;
  277. LPARRAY lpArray;
  278. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  279. fSuccess = TraceFALSE(NULL);
  280. else if (lpArray->lpelem != NULL && lpArray->nSize != lpArray->nMaxSize)
  281. {
  282. LPARRAYELEM lpelem;
  283. #if 0
  284. // shrink array so there are no unused elements
  285. //
  286. if ((lpelem = (LPARRAYELEM) MemReAlloc(NULL, lpArray->lpelem,
  287. lpArray->nSize * sizeof(ARRAYELEM), 0)) == NULL)
  288. fSuccess = TraceFALSE(NULL);
  289. else
  290. {
  291. lpArray->lpelem = lpelem;
  292. lpArray->nMaxSize = lpArray->nSize;
  293. }
  294. #else
  295. // allocate new array
  296. //
  297. if ((lpelem = (LPARRAYELEM) MemAlloc(NULL,
  298. lpArray->nSize * sizeof(ARRAYELEM), 0)) == NULL)
  299. {
  300. fSuccess = TraceFALSE(NULL);
  301. }
  302. else
  303. {
  304. // copy old array into new array
  305. //
  306. MemCpy(lpelem, lpArray->lpelem,
  307. lpArray->nSize * sizeof(ARRAYELEM));
  308. // free old array
  309. //
  310. if ((lpArray->lpelem = MemFree(NULL, lpArray->lpelem)) != NULL)
  311. {
  312. fSuccess = TraceFALSE(NULL);
  313. if ((lpelem = MemFree(NULL, lpelem)) != NULL)
  314. fSuccess = TraceFALSE(NULL);
  315. }
  316. else
  317. {
  318. lpArray->lpelem = lpelem;
  319. lpArray->nMaxSize = lpArray->nSize;
  320. }
  321. }
  322. #endif
  323. }
  324. return fSuccess ? 0 : -1;
  325. }
  326. // ArrayRemoveAll - remove all elements from array
  327. // <hArray> (i) handle returned from ArrayCreate
  328. // return 0 if success
  329. //
  330. int DLLEXPORT WINAPI ArrayRemoveAll(HARRAY hArray)
  331. {
  332. return ArraySetSize(hArray, 0, -1);
  333. }
  334. ////
  335. // array element access functions
  336. ////
  337. // ArrayGetAt - return data element at specified index
  338. // <hArray> (i) handle returned from ArrayCreate
  339. // <nIndex> (i) zero based index into array
  340. // return data element value (NULL if error)
  341. //
  342. ARRAYELEM DLLEXPORT WINAPI ArrayGetAt(HARRAY hArray, ARRAYSIZE_T nIndex)
  343. {
  344. BOOL fSuccess = TRUE;
  345. LPARRAY lpArray;
  346. ARRAYELEM elem;
  347. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  348. fSuccess = TraceFALSE(NULL);
  349. else if (nIndex < 0 || nIndex >= lpArray->nSize)
  350. fSuccess = TraceFALSE(NULL);
  351. else
  352. elem = lpArray->lpelem[nIndex];
  353. return fSuccess ? elem : (ARRAYELEM) NULL;
  354. }
  355. // ArraySetAt - set data element at specified index
  356. // <hArray> (i) handle returned from ArrayCreate
  357. // <nIndex> (i) zero based index into array
  358. // <elem> (i) new data element value
  359. // return 0 if success
  360. //
  361. int DLLEXPORT WINAPI ArraySetAt(HARRAY hArray, ARRAYSIZE_T nIndex, ARRAYELEM elem)
  362. {
  363. BOOL fSuccess = TRUE;
  364. LPARRAY lpArray;
  365. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  366. fSuccess = TraceFALSE(NULL);
  367. else if (nIndex < 0 || nIndex >= lpArray->nSize)
  368. fSuccess = TraceFALSE(NULL);
  369. else
  370. lpArray->lpelem[nIndex] = elem;
  371. return fSuccess ? 0 : -1;
  372. }
  373. ////
  374. // array grow functions
  375. ////
  376. // ArraySetAtGrow - set data element at specified index
  377. // <hArray> (i) handle returned from ArrayCreate
  378. // <nIndex> (i) zero based index into array
  379. // <elem> (i) new data element value
  380. // return 0 if success
  381. // NOTE: array size is increased if nIndex > upper bound
  382. //
  383. int DLLEXPORT WINAPI ArraySetAtGrow(HARRAY hArray, ARRAYSIZE_T nIndex, ARRAYELEM elem)
  384. {
  385. BOOL fSuccess = TRUE;
  386. LPARRAY lpArray;
  387. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  388. fSuccess = TraceFALSE(NULL);
  389. else if (nIndex >= lpArray->nSize &&
  390. ArraySetSize(hArray, nIndex + 1, -1) != 0)
  391. fSuccess = TraceFALSE(NULL);
  392. else
  393. lpArray->lpelem[nIndex] = elem;
  394. return fSuccess ? 0 : -1;
  395. }
  396. // ArrayAdd - add data element to end of array
  397. // <hArray> (i) handle returned from ArrayCreate
  398. // <elem> (i) new data element value
  399. // return index of added element (-1 if error)
  400. //
  401. ARRAYSIZE_T DLLEXPORT WINAPI ArrayAdd(HARRAY hArray, ARRAYELEM elem)
  402. {
  403. BOOL fSuccess = TRUE;
  404. ARRAYSIZE_T nIndexNew;
  405. if ((nIndexNew = ArrayGetSize(hArray)) < 0)
  406. fSuccess = TraceFALSE(NULL);
  407. else if (ArraySetAtGrow(hArray, nIndexNew, elem) != 0)
  408. fSuccess = TraceFALSE(NULL);
  409. return fSuccess ? nIndexNew : -1;
  410. }
  411. ////
  412. // array element insertion and removal
  413. ////
  414. // ArrayInsertAt - insert <nCount> copies of <elem> at specified index
  415. // <hArray> (i) handle returned from ArrayCreate
  416. // <nIndex> (i) zero based index into array
  417. // <elem> (i) new data element value
  418. // <nCount> (i) number of elements to insert
  419. // return 0 if success
  420. // NOTE: elements at end of array will be shifted if necessary
  421. //
  422. int DLLEXPORT WINAPI ArrayInsertAt(HARRAY hArray, ARRAYSIZE_T nIndex, ARRAYELEM elem, ARRAYSIZE_T nCount)
  423. {
  424. BOOL fSuccess = TRUE;
  425. LPARRAY lpArray;
  426. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  427. fSuccess = TraceFALSE(NULL);
  428. else if (nIndex < 0)
  429. fSuccess = TraceFALSE(NULL);
  430. else if (nCount <= 0)
  431. fSuccess = TraceFALSE(NULL);
  432. // inserting at or after the end of array
  433. //
  434. else if (nIndex >= lpArray->nSize)
  435. {
  436. // grow so nIndex is valid
  437. //
  438. if (ArraySetSize(hArray, nIndex + nCount, -1) != 0)
  439. fSuccess = TraceFALSE(NULL);
  440. }
  441. // inserting in the middle of the array
  442. //
  443. else
  444. {
  445. ARRAYSIZE_T nOldSize = lpArray->nSize;
  446. // grow array to new size
  447. //
  448. if (ArraySetSize(hArray, lpArray->nSize + nCount, -1) != 0)
  449. fSuccess = TraceFALSE(NULL);
  450. else
  451. {
  452. MemMove(&lpArray->lpelem[nIndex + nCount],
  453. &lpArray->lpelem[nIndex],
  454. (nOldSize - nIndex) * sizeof(ARRAYELEM));
  455. #if 1
  456. // initialize inserted elements
  457. MemSet(&lpArray->lpelem[nIndex], 0, nCount * sizeof(ARRAYELEM));
  458. #endif
  459. }
  460. }
  461. if (fSuccess)
  462. {
  463. // insert new element values
  464. //
  465. while (nCount-- > 0)
  466. lpArray->lpelem[nIndex++] = elem;
  467. }
  468. return fSuccess ? 0 : -1;
  469. }
  470. // ArrayRemoveAt - remove <nCount> data elements at specified index
  471. // <hArray> (i) handle returned from ArrayCreate
  472. // <nIndex> (i) zero based index into array
  473. // <nCount> (i) number of elements to remove
  474. // return 0 if success
  475. // NOTE: elements at end of array will be shifted if necessary
  476. //
  477. int DLLEXPORT WINAPI ArrayRemoveAt(HARRAY hArray, ARRAYSIZE_T nIndex, ARRAYSIZE_T nCount)
  478. {
  479. BOOL fSuccess = TRUE;
  480. LPARRAY lpArray;
  481. ARRAYSIZE_T nMoveCount;
  482. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  483. fSuccess = TraceFALSE(NULL);
  484. else if (nIndex < 0)
  485. fSuccess = TraceFALSE(NULL);
  486. else if (nCount < 0)
  487. fSuccess = TraceFALSE(NULL);
  488. else if (nIndex + nCount > lpArray->nSize)
  489. fSuccess = TraceFALSE(NULL);
  490. else if ((nMoveCount = lpArray->nSize - (nIndex + nCount)) > 0)
  491. {
  492. // shift remaining elements on top of removed elements
  493. //
  494. MemCpy(&lpArray->lpelem[nIndex],
  495. &lpArray->lpelem[nIndex + nCount],
  496. nMoveCount * sizeof(ARRAYELEM));
  497. #if 1
  498. // initialize elements beyond remaining elements
  499. //
  500. MemSet(&lpArray->lpelem[lpArray->nSize - nCount], 0,
  501. nCount * sizeof(ARRAYELEM));
  502. #endif
  503. }
  504. if (fSuccess)
  505. lpArray->nSize -= nCount;
  506. return fSuccess ? 0 : -1;
  507. }
  508. ////
  509. // array element sorting and searching
  510. ////
  511. // ArraySort - sort array
  512. // <hArray> (i) handle returned from ArrayCreate
  513. // <lpfnCompare> (i) comparison function pointer
  514. // NULL direct comparison (MemCmp)
  515. // return 0 if success
  516. //
  517. int DLLEXPORT WINAPI ArraySort(HARRAY hArray,
  518. int (WINAPI *lpfnCompare)(const LPARRAYELEM lpElem1, const LPARRAYELEM lpElem2))
  519. {
  520. BOOL fSuccess = TRUE;
  521. LPARRAY lpArray;
  522. ARRAYSIZE_T sizArray;
  523. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  524. fSuccess = TraceFALSE(NULL);
  525. else if ((sizArray = ArrayGetSize(hArray)) < 0)
  526. fSuccess = TraceFALSE(NULL);
  527. else if (Sort(lpArray->lpelem, (SORTSIZE_T) sizArray,
  528. (SORTSIZE_T) sizeof(ARRAYELEM), lpfnCompare, 0) != 0)
  529. fSuccess = TraceFALSE(NULL);
  530. return fSuccess ? 0 : -1;
  531. }
  532. // ArraySearch - search array for matching element
  533. // <hArray> (i) handle returned from ArrayCreate
  534. // <elem> (i) data element to match
  535. // <nIndex> (i) start search after this array index
  536. // -1 start search at start of array
  537. // <dwFlags> (i) reserved; must be 0
  538. // <lpfnCompare> (i) comparison function pointer
  539. // NULL direct comparison (MemCmp)
  540. // return index of matching element (-1 if no match, -2 if error)
  541. //
  542. ARRAYSIZE_T DLLEXPORT WINAPI ArraySearch(HARRAY hArray, ARRAYELEM elem,
  543. ARRAYSIZE_T nIndex, DWORD dwFlags,
  544. int (WINAPI *lpfnCompare)(const LPARRAYELEM lpElem1, const LPARRAYELEM lpElem2))
  545. {
  546. BOOL fSuccess = TRUE;
  547. BOOL fMatch = FALSE;
  548. LPARRAY lpArray;
  549. if ((lpArray = ArrayGetPtr(hArray)) == NULL)
  550. fSuccess = TraceFALSE(NULL);
  551. else if (++nIndex < 0 || nIndex >= lpArray->nSize)
  552. fSuccess = TraceFALSE(NULL);
  553. else for (; nIndex < lpArray->nSize; ++nIndex)
  554. {
  555. if (ElemCompare(&lpArray->lpelem[nIndex], &elem) == 0)
  556. {
  557. fMatch = TRUE;
  558. break;
  559. }
  560. }
  561. return fSuccess ? (fMatch ? nIndex : -1) : -2;
  562. }
  563. ////
  564. // private functions
  565. ////
  566. // ArrayGetPtr - verify that array handle is valid,
  567. // <hArray> (i) handle returned from ArrayCreate
  568. // return corresponding array pointer (NULL if error)
  569. //
  570. static LPARRAY ArrayGetPtr(HARRAY hArray)
  571. {
  572. BOOL fSuccess = TRUE;
  573. LPARRAY lpArray;
  574. if ((lpArray = (LPARRAY) hArray) == NULL)
  575. fSuccess = TraceFALSE(NULL);
  576. else if (IsBadWritePtr(lpArray, sizeof(ARRAY)))
  577. fSuccess = TraceFALSE(NULL);
  578. #ifdef CHECKTASK
  579. // make sure current task owns the array handle
  580. //
  581. else if (lpArray->hTask != GetCurrentTask())
  582. fSuccess = TraceFALSE(NULL);
  583. #endif
  584. return fSuccess ? lpArray : NULL;
  585. }
  586. // ArrayGetHandle - verify that array pointer is valid,
  587. // <lpArray> pointer to ARRAY struct
  588. // return corresponding array handle (NULL if error)
  589. //
  590. static HARRAY ArrayGetHandle(LPARRAY lpArray)
  591. {
  592. BOOL fSuccess = TRUE;
  593. HARRAY hArray;
  594. if ((hArray = (HARRAY) lpArray) == NULL)
  595. fSuccess = TraceFALSE(NULL);
  596. return fSuccess ? hArray : NULL;
  597. }