Hi, This comes from debugging Past.exe, a statistical analysis program. I added testcases for all fixes and checked them with native oleaut32. Ciao, Marcus Changelog: fixed index handling for multi dimensional arrays. Index: dlls/oleaut32/safearray.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/safearray.c,v retrieving revision 1.24 diff -u -r1.24 safearray.c --- dlls/oleaut32/safearray.c 19 May 2003 21:43:20 -0000 1.24 +++ dlls/oleaut32/safearray.c 9 Jun 2003 18:49:13 -0000 @@ -43,9 +43,6 @@ #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); @@ -303,6 +316,18 @@ } /************************************************************************* + * SafeArrayCreate (OLEAUT32.15) + * Create a SafeArray object by encapsulating AllocDescriptor and AllocData + */ +SAFEARRAY* WINAPI SafeArrayCreate( + VARTYPE vt, + UINT cDims, + SAFEARRAYBOUND *rgsabound +) { + return SafeArrayCreateEx(vt, cDims, rgsabound, NULL); +} + +/************************************************************************* * SafeArrayDestroyDescriptor (OLEAUT32.38) * Frees the memory associated with the descriptor. */ @@ -485,6 +510,7 @@ /************************************************************************* * 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 +526,8 @@ 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 +535,7 @@ /************************************************************************* * 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 +551,7 @@ if(0 == nDim) return DISP_E_BADINDEX; - *plLbound = psa->rgsabound[nDim-1].lLbound; + *plLbound = psa->rgsabound[psa->cDims - nDim].lLbound; return S_OK; } @@ -1088,31 +1115,19 @@ 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 Index: tests/safearray.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/tests/safearray.c,v retrieving revision 1.6 diff -u -r1.6 dlls/oleaut32/test/safearray.c --- dlls/oleaut32/tests/safearray.c 13 May 2003 23:36:33 -0000 1.6 +++ dlls/oleaut32/tests/safearray.c 9 Jun 2003 18:49:14 -0000 @@ -100,12 +100,15 @@ 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 @@ 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)) ||