1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 
31 #pragma warning(disable: 4917)
32 #include <windows.h>
33 #include <comdef.h>
34 #include <tchar.h>
35 #include <atlbase.h>
36 #include<atlcom.h>
37 #include <stdio.h>
38 #include <com/sun/star/bridge/ModelDependent.hpp>
39 #include <com/sun/star/bridge/XBridgeSupplier2.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/script/XInvocation.hpp>
42 #include <oletest/XCallback.hpp>
43 #include <rtl/process.h>
44 #include <com/sun/star/uno/Reference.h>
45 #include <cppuhelper/servicefactory.hxx>
46 #include <rtl/string.h>
47 
48 
49 
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::script;
53 using namespace com::sun::star::bridge;
54 using namespace com::sun::star::bridge::ModelDependent;
55 using namespace cppu;
56 using namespace rtl;
57 HRESULT doTest();
58 bool incrementMultidimensionalIndex(
59     sal_Int32 dimensions,
60     const sal_Int32 * parDimensionLengths,
61     sal_Int32 * parMultidimensionalIndex);
62 
63 int __cdecl _tmain( int /*argc*/, _TCHAR * /*argv[]*/ )
64 {
65 	HRESULT hr;
66 	if( FAILED( hr=CoInitialize(NULL)))
67 	{
68 		_tprintf(_T("CoInitialize failed \n"));
69 		return -1;
70 	}
71 
72 
73 	if( FAILED(hr=doTest()))
74 	{
75 		_com_error err( hr);
76 		const TCHAR * errMsg= err.ErrorMessage();
77 		MessageBox( NULL, errMsg, "Test failed", MB_ICONERROR);
78 	}
79 
80 	CoUninitialize();
81 	return 0;
82 }
83 
84 
85 
86 
87 HRESULT doTest()
88 {
89 	HRESULT hr= S_OK;
90 	long j = 0;
91 	SAFEARRAY* par;
92 	CComDispatchDriver disp;
93 	CComVariant result;
94 	CComVariant param1;
95 	CComPtr<IUnknown> spUnkFactory;
96 	if( SUCCEEDED( spUnkFactory.CoCreateInstance(L"com.sun.star.ServiceManager")))
97 	{
98 		disp= spUnkFactory;
99 		param1= L"oletest.OleTest";
100 		disp.Invoke1( L"createInstance", &param1, &result);
101 
102 		disp= result.pdispVal;
103 
104 		// disp contains now oletest.OleTest
105 
106 		// one dimensional array
107 		par= SafeArrayCreateVector( VT_UI1, 0, 5);
108 		unsigned char arbyte[]= { 1,2,3,4,5};
109 		for(long i= 0; i < 5;i++)
110 			hr=	SafeArrayPutElement( par, &i, &arbyte[i]);
111 
112 		result.Clear();
113 		param1.vt= VT_ARRAY| VT_UI1;
114 		param1.byref= par;
115 		disp.Invoke1(L"methodByte", &param1, &result);
116 		SafeArrayDestroy( par);
117 
118 
119 		// two dimensional array
120 		SAFEARRAYBOUND bounds[2];
121 		// least significant dimension first, Dimension 1
122 		bounds[0].cElements= 3;
123 		bounds[0].lLbound= 0;
124 		// Dimension 2
125 		bounds[1].cElements= 2;
126 		bounds[1].lLbound= 0;
127 		par= SafeArrayCreate( VT_I4, 2, bounds );
128 
129 		long uBound1;
130 		long uBound2;
131 		hr= SafeArrayGetUBound( par, 1, &uBound1);
132 		hr= SafeArrayGetUBound( par, 2, &uBound2);
133 
134 		long index2[2];
135 		memset( index2, 0, 2 * sizeof( long) );
136 		long dimLengths[]={3,2};
137 
138 		long data;
139 		do
140 		{
141 			data= index2[1] * 3 + index2[0] +1;
142 			hr= SafeArrayPutElement( par, index2, &data);
143 		}while( incrementMultidimensionalIndex( 2, dimLengths, index2) );
144 
145 		long* pdata;
146 		long (*dataL)[2][3];
147 		hr= SafeArrayAccessData( par, (void**)&pdata);
148 		dataL= (long(*)[2][3])pdata;
149 
150 		for (long i= 0; i < 2; i ++)
151 		{
152 			for(long j= 0; j < 3; j++)
153 				data= (*dataL)[i][j];
154 		}
155 		hr= SafeArrayUnaccessData(par);
156 
157 		result.Clear();
158 		param1.vt= VT_ARRAY | VT_I4;
159 		param1.byref= par;
160 		disp.Invoke1(L"methodSequence", &param1, &result);
161 
162 		SAFEARRAY* arRet= result.parray;
163 
164 		for(long i= 0; i < 2 ; i++)
165 		{
166 			CComVariant varx;
167 			varx.Clear();
168 			hr= SafeArrayGetElement( arRet, &i, &varx);
169 			SAFEARRAY* ari= varx.parray;
170 
171 			for( j= 0; j < 3; j++)
172 			{
173 				CComVariant varj;
174 				varj.Clear();
175 				hr= SafeArrayGetElement( ari, &j, &varj);
176 			}
177 
178 
179 
180 		}
181 		SafeArrayDestroy( par);
182 	}
183 
184 	return hr;
185 }
186 
187 // left index is least significant
188 bool incrementMultidimensionalIndex(
189     sal_Int32 dimensions,
190     const sal_Int32 * parDimensionLengths,
191 	sal_Int32 * parMultidimensionalIndex)
192 {
193 	if( dimensions < 1)
194 		return sal_False;
195 
196 	bool ret= sal_True;
197 	bool carry= sal_True; // to get into the while loop
198 
199 	sal_Int32 currentDimension= 0; //most significant is 1
200 	while( carry)
201 	{
202 		parMultidimensionalIndex[ currentDimension ]++;
203 		// if carryover, set index to 0 and handle carry on a level above
204 		if( parMultidimensionalIndex[ currentDimension] > (parDimensionLengths[ currentDimension] - 1))
205 			parMultidimensionalIndex[ currentDimension]= 0;
206 		else
207 			carry= sal_False;
208 
209 		currentDimension ++;
210 		// if dimensions drops below 1 and carry is set than then all indices are 0 again
211 		// this is signalled by returning sal_False
212 		if( currentDimension > dimensions - 1 && carry)
213 		{
214 			carry= sal_False;
215 			ret= sal_False;
216 		}
217 	}
218 	return ret;
219 }
220