From eee3a24dc94c48c1c7d356d60b80c89a90953570 Mon Sep 17 00:00:00 2001
From: Marcus Meissner <marcus@jet.franken.de>
Date: Fri, 13 Jun 2003 16:35:07 +0000
Subject: [PATCH] Fixed index handling for multi dimensional arrays.

---
 dlls/oleaut32/safearray.c       | 41 ++++++----------
 dlls/oleaut32/tests/safearray.c | 87 ++++++++++++++++++++++++++++++++-
 2 files changed, 99 insertions(+), 29 deletions(-)

diff --git a/dlls/oleaut32/safearray.c b/dlls/oleaut32/safearray.c
index 6ce5b2c8791..46a0af30794 100644
--- a/dlls/oleaut32/safearray.c
+++ b/dlls/oleaut32/safearray.c
@@ -43,9 +43,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
 #define SYSDUPSTRING(str) SysAllocStringLen((str), SysStringLen(str))
 
 /* Locally used methods */
-static INT
-endOfDim(LONG *coor, SAFEARRAYBOUND *mat, LONG dim, LONG realDim);
-
 static ULONG
 calcDisplacement(LONG *coor, SAFEARRAYBOUND *mat, LONG dim);
 
@@ -485,6 +482,7 @@ HRESULT WINAPI SafeArrayGetElement(
 /*************************************************************************
  *		SafeArrayGetUBound (OLEAUT32.19)
  * return the UP bound for a given array dimension
+ * Note: [0] is the right most (least significant) array index!
  */
 HRESULT WINAPI SafeArrayGetUBound(
   SAFEARRAY *psa,
@@ -500,8 +498,8 @@ HRESULT WINAPI SafeArrayGetUBound(
   if(0 == nDim)
     return DISP_E_BADINDEX;
 
-  *plUbound = psa->rgsabound[nDim-1].lLbound +
-              psa->rgsabound[nDim-1].cElements - 1;
+  *plUbound = psa->rgsabound[psa->cDims - nDim].lLbound +
+              psa->rgsabound[psa->cDims - nDim].cElements - 1;
 
   return S_OK;
 }
@@ -509,6 +507,7 @@ HRESULT WINAPI SafeArrayGetUBound(
 /*************************************************************************
  *		SafeArrayGetLBound (OLEAUT32.20)
  * Return the LO bound for a given array dimension
+ * Note: [0] is the right most (least significant) array index!
  */
 HRESULT WINAPI SafeArrayGetLBound(
   SAFEARRAY *psa,
@@ -524,7 +523,7 @@ HRESULT WINAPI SafeArrayGetLBound(
   if(0 == nDim)
     return DISP_E_BADINDEX;
 
-  *plLbound = psa->rgsabound[nDim-1].lLbound;
+  *plLbound = psa->rgsabound[psa->cDims - nDim].lLbound;
   return S_OK;
 }
 
@@ -1088,32 +1087,20 @@ static ULONG calcDisplacement(
   ULONG res = 0;
   LONG  iterDim;
 
-  for(iterDim=0; iterDim<dim; iterDim++)
-    /* the -mat[dim] bring coor[dim] relative to 0 for calculation */
-    res += ((coor[iterDim]-mat[iterDim].lLbound) *
-            endOfDim(coor, mat, iterDim+1, dim));
+  TRACE("dims is %ld\n", dim);
+
+  for (iterDim = dim-1; iterDim >= 0; iterDim--) {
+	TRACE("%ld: lbound is %ld, adding %ld\n", iterDim, mat[dim-iterDim-1].lLbound,(coor[iterDim] - mat[dim-iterDim-1].lLbound));
+	res += (coor[iterDim] - mat[dim-iterDim-1].lLbound);
+
+	if (iterDim > 0)
+		res *= mat[dim-iterDim].cElements;
+  }
 
   TRACE("SafeArray: calculated displacement is %lu.\n", res);
   return(res);
 }
 
-/************************************************************************
- * Recursivity agent for calcDisplacement method.  Used within Put and
- * Get methods.
- */
-static INT endOfDim(
-  LONG           *coor,
-  SAFEARRAYBOUND *mat,
-  LONG           dim,
-  LONG           realDim)
-{
-  if(dim==realDim)
-    return 1;
-  else
-    return (endOfDim(coor, mat, dim+1, realDim) * mat[dim].cElements);
-}
-
-
 /************************************************************************
  * Method used to validate the coordinate received in Put and Get
  * methods.
diff --git a/dlls/oleaut32/tests/safearray.c b/dlls/oleaut32/tests/safearray.c
index 30c66a577a2..68926098aa5 100644
--- a/dlls/oleaut32/tests/safearray.c
+++ b/dlls/oleaut32/tests/safearray.c
@@ -100,12 +100,15 @@ START_TEST(safearray)
 	HMODULE hdll;
 	SAFEARRAY 	*a, b, *c;
 	unsigned int 	i;
+	long		indices[2];
 	HRESULT 	hres;
-	SAFEARRAYBOUND	bound;
+	SAFEARRAYBOUND	bound, bounds[2];
 	VARIANT		v;
 	LPVOID		data;
 	IID		iid;
 	VARTYPE		vt;
+	LONG		l;
+	unsigned char	*ptr1, *ptr2;
 
     hdll=LoadLibraryA("oleaut32.dll");
     pSafeArrayAllocDescriptorEx=(void*)GetProcAddress(hdll,"SafeArrayAllocDescriptorEx");
@@ -145,7 +148,87 @@ START_TEST(safearray)
 	bound.lLbound	= 0;
 	a = SafeArrayCreate(-1, 1, &bound);
 	ok(NULL == a,"SAC(-1,1,[1,0]) not failed?");
-	
+
+
+	bounds[0].cElements = 42;	bounds[0].lLbound =  1;
+	bounds[1].cElements =  2;	bounds[1].lLbound = 23;
+    a = SafeArrayCreate(VT_I4,2,bounds);
+    ok(a != NULL,"SAC(VT_INT32,2,...) failed.");
+
+	hres = SafeArrayGetLBound (a, 0, &l);
+	ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %lx", hres);
+	hres = SafeArrayGetLBound (a, 1, &l);
+	ok (hres == S_OK, "SAGLB 1 failed with %lx", hres);
+	ok (l == 1, "SAGLB 1 returned %ld instead of 1", l);
+	hres = SafeArrayGetLBound (a, 2, &l);
+	ok (hres == S_OK, "SAGLB 2 failed with %lx", hres);
+	ok (l == 23, "SAGLB 2 returned %ld instead of 1", l);
+	hres = SafeArrayGetLBound (a, 3, &l);
+	ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %lx", hres);
+
+	hres = SafeArrayGetUBound (a, 0, &l);
+	ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %lx", hres);
+	hres = SafeArrayGetUBound (a, 1, &l);
+	ok (hres == S_OK, "SAGUB 1 failed with %lx", hres);
+	ok (l == 42, "SAGUB 1 returned %ld instead of 1", l);
+	hres = SafeArrayGetUBound (a, 2, &l);
+	ok (hres == S_OK, "SAGUB 2 failed with %lx", hres);
+	ok (l == 24, "SAGUB 2 returned %ld instead of 24", l);
+	hres = SafeArrayGetUBound (a, 3, &l);
+	ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %lx", hres);
+
+	i = SafeArrayGetDim(a);
+	ok(i == 2, "getdims of 2 din array returned %d",i);
+
+	indices[0] = 0;
+	indices[1] = 23;
+	hres = SafeArrayGetElement(a, indices, &i);
+	ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%lx",hres);
+
+	indices[0] = 1;
+	indices[1] = 22;
+	hres = SafeArrayGetElement(a, indices, &i);
+	ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%lx",hres);
+
+	indices[0] = 1;
+	indices[1] = 23;
+	hres = SafeArrayGetElement(a, indices, &i);
+	ok(S_OK == hres,"SAGE failed [1,23], hres 0x%lx",hres);
+
+	indices[0] = 1;
+	indices[1] = 25;
+	hres = SafeArrayGetElement(a, indices, &i);
+	ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%lx",hres);
+
+	indices[0] = 3;
+	indices[1] = 23;
+	hres = SafeArrayGetElement(a, indices, &i);
+	ok(S_OK == hres,"SAGE failed [42,23], hres 0x%lx",hres);
+
+	hres = SafeArrayAccessData(a, (void**)&ptr1);
+	ok(S_OK == hres, "SAAD failed with 0x%lx", hres);
+
+	indices[0] = 3;
+	indices[1] = 23;
+	hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
+	ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%lx",hres);
+	ok(ptr2 - ptr1 == 8,"ptr difference is not 8, but %d (%p vs %p)", ptr2-ptr1, ptr2, ptr1);
+
+	indices[0] = 3;
+	indices[1] = 24;
+	hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
+	ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%lx",hres);
+	ok(ptr2 - ptr1 == 176,"ptr difference is not 176, but %d (%p vs %p)", ptr2-ptr1, ptr2, ptr1);
+
+	indices[0] = 20;
+	indices[1] = 23;
+	hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
+	ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%lx",hres);
+	ok(ptr2 - ptr1 == 76,"ptr difference is not 176, but %d (%p vs %p)", ptr2-ptr1, ptr2, ptr1);
+
+	hres = SafeArrayUnaccessData(a);
+	ok(S_OK == hres, "SAUAD failed with 0x%lx", hres);
+
 	for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
 		a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
 		ok(	((a == NULL) && (vttypes[i].elemsize == 0)) ||
-- 
GitLab