1*e1f63238SAndrew Rist /************************************************************** 2*e1f63238SAndrew Rist * 3*e1f63238SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*e1f63238SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*e1f63238SAndrew Rist * distributed with this work for additional information 6*e1f63238SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*e1f63238SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*e1f63238SAndrew Rist * "License"); you may not use this file except in compliance 9*e1f63238SAndrew Rist * with the License. You may obtain a copy of the License at 10*e1f63238SAndrew Rist * 11*e1f63238SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*e1f63238SAndrew Rist * 13*e1f63238SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*e1f63238SAndrew Rist * software distributed under the License is distributed on an 15*e1f63238SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*e1f63238SAndrew Rist * KIND, either express or implied. See the License for the 17*e1f63238SAndrew Rist * specific language governing permissions and limitations 18*e1f63238SAndrew Rist * under the License. 19*e1f63238SAndrew Rist * 20*e1f63238SAndrew Rist *************************************************************/ 21*e1f63238SAndrew Rist 22*e1f63238SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "precompiled_basic.hxx" 25cdf0e10cSrcweir #include "sal/config.h" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <algorithm> 28cdf0e10cSrcweir #include <cstddef> 29cdf0e10cSrcweir #include <list> 30cdf0e10cSrcweir #include <map> 31cdf0e10cSrcweir #include <vector> 32cdf0e10cSrcweir 33cdf0e10cSrcweir #include "basic/sbx.hxx" 34cdf0e10cSrcweir #include "basic/sbxvar.hxx" 35cdf0e10cSrcweir #include "runtime.hxx" 36cdf0e10cSrcweir #include "osl/thread.h" 37cdf0e10cSrcweir #include "rtl/ref.hxx" 38cdf0e10cSrcweir #include "rtl/string.hxx" 39cdf0e10cSrcweir #include "rtl/ustring.hxx" 40cdf0e10cSrcweir #include "salhelper/simplereferenceobject.hxx" 41cdf0e10cSrcweir #include "tools/svwin.h" 42cdf0e10cSrcweir 43cdf0e10cSrcweir #undef max 44cdf0e10cSrcweir 45cdf0e10cSrcweir #include "dllmgr.hxx" 46cdf0e10cSrcweir 47cdf0e10cSrcweir /* Open issues: 48cdf0e10cSrcweir 49cdf0e10cSrcweir Only 32-bit Windows for now. 50cdf0e10cSrcweir 51cdf0e10cSrcweir Missing support for functions returning structs (see TODO in call()). 52cdf0e10cSrcweir 53cdf0e10cSrcweir Missing support for additional data types (64 bit integers, Any, ...; would 54cdf0e10cSrcweir trigger OSL_ASSERT(false) in various switches). 55cdf0e10cSrcweir 56cdf0e10cSrcweir It is assumed that the variables passed into SbiDllMgr::Call to represent 57cdf0e10cSrcweir the arguments and return value have types that exactly match the Declare 58cdf0e10cSrcweir statement; it would be better if this code had access to the function 59cdf0e10cSrcweir signature from the Declare statement, so that it could convert the passed 60cdf0e10cSrcweir variables accordingly. 61cdf0e10cSrcweir */ 62cdf0e10cSrcweir 63cdf0e10cSrcweir #if defined WNT // only 32-bit Windows, actually 64cdf0e10cSrcweir 65cdf0e10cSrcweir extern "C" { 66cdf0e10cSrcweir 67cdf0e10cSrcweir int __stdcall DllMgr_call32(FARPROC, void const * stack, std::size_t size); 68cdf0e10cSrcweir double __stdcall DllMgr_callFp(FARPROC, void const * stack, std::size_t size); 69cdf0e10cSrcweir 70cdf0e10cSrcweir } 71cdf0e10cSrcweir 72cdf0e10cSrcweir namespace { 73cdf0e10cSrcweir 74cdf0e10cSrcweir char * address(std::vector< char > & blob) { 75cdf0e10cSrcweir return blob.empty() ? 0 : &blob[0]; 76cdf0e10cSrcweir } 77cdf0e10cSrcweir 78cdf0e10cSrcweir SbError convert(rtl::OUString const & source, rtl::OString * target) { 79cdf0e10cSrcweir return 80cdf0e10cSrcweir source.convertToString( 81cdf0e10cSrcweir target, osl_getThreadTextEncoding(), 82cdf0e10cSrcweir (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | 83cdf0e10cSrcweir RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)) 84cdf0e10cSrcweir ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT; 85cdf0e10cSrcweir //TODO: more specific errcode? 86cdf0e10cSrcweir } 87cdf0e10cSrcweir 88cdf0e10cSrcweir SbError convert(char const * source, sal_Int32 length, rtl::OUString * target) { 89cdf0e10cSrcweir return 90cdf0e10cSrcweir rtl_convertStringToUString( 91cdf0e10cSrcweir &target->pData, source, length, osl_getThreadTextEncoding(), 92cdf0e10cSrcweir (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | 93cdf0e10cSrcweir RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | 94cdf0e10cSrcweir RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)) 95cdf0e10cSrcweir ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT; 96cdf0e10cSrcweir //TODO: more specific errcode? 97cdf0e10cSrcweir } 98cdf0e10cSrcweir 99cdf0e10cSrcweir struct UnmarshalData { 100cdf0e10cSrcweir UnmarshalData(SbxVariable * theVariable, void * theBuffer): 101cdf0e10cSrcweir variable(theVariable), buffer(theBuffer) {} 102cdf0e10cSrcweir 103cdf0e10cSrcweir SbxVariable * variable; 104cdf0e10cSrcweir void * buffer; 105cdf0e10cSrcweir }; 106cdf0e10cSrcweir 107cdf0e10cSrcweir struct StringData: public UnmarshalData { 108cdf0e10cSrcweir StringData(SbxVariable * theVariable, void * theBuffer, bool theSpecial): 109cdf0e10cSrcweir UnmarshalData(theVariable, theBuffer), special(theSpecial) {} 110cdf0e10cSrcweir 111cdf0e10cSrcweir bool special; 112cdf0e10cSrcweir }; 113cdf0e10cSrcweir 114cdf0e10cSrcweir class MarshalData: private boost::noncopyable { 115cdf0e10cSrcweir public: 116cdf0e10cSrcweir std::vector< char > * newBlob() { 117cdf0e10cSrcweir blobs_.push_front(std::vector< char >()); 118cdf0e10cSrcweir return &blobs_.front(); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir 121cdf0e10cSrcweir std::vector< UnmarshalData > unmarshal; 122cdf0e10cSrcweir 123cdf0e10cSrcweir std::vector< StringData > unmarshalStrings; 124cdf0e10cSrcweir 125cdf0e10cSrcweir private: 126cdf0e10cSrcweir std::list< std::vector< char > > blobs_; 127cdf0e10cSrcweir }; 128cdf0e10cSrcweir 129cdf0e10cSrcweir std::size_t align(std::size_t address, std::size_t alignment) { 130cdf0e10cSrcweir // alignment = 2^k for some k >= 0 131cdf0e10cSrcweir return (address + (alignment - 1)) & ~(alignment - 1); 132cdf0e10cSrcweir } 133cdf0e10cSrcweir 134cdf0e10cSrcweir char * align( 135cdf0e10cSrcweir std::vector< char > & blob, std::size_t alignment, std::size_t offset, 136cdf0e10cSrcweir std::size_t add) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir std::vector< char >::size_type n = blob.size(); 139cdf0e10cSrcweir n = align(n - offset, alignment) + offset; //TODO: overflow in align() 140cdf0e10cSrcweir blob.resize(n + add); //TODO: overflow 141cdf0e10cSrcweir return address(blob) + n; 142cdf0e10cSrcweir } 143cdf0e10cSrcweir 144cdf0e10cSrcweir template< typename T > void add( 145cdf0e10cSrcweir std::vector< char > & blob, T const & data, std::size_t alignment, 146cdf0e10cSrcweir std::size_t offset) 147cdf0e10cSrcweir { 148cdf0e10cSrcweir *reinterpret_cast< T * >(align(blob, alignment, offset, sizeof (T))) = data; 149cdf0e10cSrcweir } 150cdf0e10cSrcweir 151cdf0e10cSrcweir std::size_t alignment(SbxVariable * variable) { 152cdf0e10cSrcweir OSL_ASSERT(variable != 0); 153cdf0e10cSrcweir if ((variable->GetType() & SbxARRAY) == 0) { 154cdf0e10cSrcweir switch (variable->GetType()) { 155cdf0e10cSrcweir case SbxINTEGER: 156cdf0e10cSrcweir return 2; 157cdf0e10cSrcweir case SbxLONG: 158cdf0e10cSrcweir case SbxSINGLE: 159cdf0e10cSrcweir case SbxSTRING: 160cdf0e10cSrcweir return 4; 161cdf0e10cSrcweir case SbxDOUBLE: 162cdf0e10cSrcweir return 8; 163cdf0e10cSrcweir case SbxOBJECT: 164cdf0e10cSrcweir { 165cdf0e10cSrcweir std::size_t n = 1; 166cdf0e10cSrcweir SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())-> 167cdf0e10cSrcweir GetProperties(); 168cdf0e10cSrcweir for (sal_uInt16 i = 0; i < props->Count(); ++i) { 169cdf0e10cSrcweir n = std::max(n, alignment(props->Get(i))); 170cdf0e10cSrcweir } 171cdf0e10cSrcweir return n; 172cdf0e10cSrcweir } 173cdf0e10cSrcweir case SbxBOOL: 174cdf0e10cSrcweir case SbxBYTE: 175cdf0e10cSrcweir return 1; 176cdf0e10cSrcweir default: 177cdf0e10cSrcweir OSL_ASSERT(false); 178cdf0e10cSrcweir return 1; 179cdf0e10cSrcweir } 180cdf0e10cSrcweir } else { 181cdf0e10cSrcweir SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject()); 182cdf0e10cSrcweir int dims = arr->GetDims(); 183cdf0e10cSrcweir std::vector< sal_Int32 > low(dims); 184cdf0e10cSrcweir for (int i = 0; i < dims; ++i) { 185cdf0e10cSrcweir sal_Int32 up; 186cdf0e10cSrcweir arr->GetDim32(i + 1, low[i], up); 187cdf0e10cSrcweir } 188cdf0e10cSrcweir return alignment(arr->Get32(&low[0])); 189cdf0e10cSrcweir } 190cdf0e10cSrcweir } 191cdf0e10cSrcweir 192cdf0e10cSrcweir SbError marshal( 193cdf0e10cSrcweir bool outer, SbxVariable * variable, bool special, 194cdf0e10cSrcweir std::vector< char > & blob, std::size_t offset, MarshalData & data); 195cdf0e10cSrcweir 196cdf0e10cSrcweir SbError marshalString( 197cdf0e10cSrcweir SbxVariable * variable, bool special, MarshalData & data, void ** buffer) 198cdf0e10cSrcweir { 199cdf0e10cSrcweir OSL_ASSERT(variable != 0 && buffer != 0); 200cdf0e10cSrcweir rtl::OString str; 201cdf0e10cSrcweir SbError e = convert(variable->GetString(), &str); 202cdf0e10cSrcweir if (e != ERRCODE_NONE) { 203cdf0e10cSrcweir return e; 204cdf0e10cSrcweir } 205cdf0e10cSrcweir std::vector< char > * blob = data.newBlob(); 206cdf0e10cSrcweir blob->insert( 207cdf0e10cSrcweir blob->begin(), str.getStr(), str.getStr() + str.getLength() + 1); 208cdf0e10cSrcweir *buffer = address(*blob); 209cdf0e10cSrcweir data.unmarshalStrings.push_back(StringData(variable, *buffer, special)); 210cdf0e10cSrcweir return ERRCODE_NONE; 211cdf0e10cSrcweir } 212cdf0e10cSrcweir 213cdf0e10cSrcweir SbError marshalStruct( 214cdf0e10cSrcweir SbxVariable * variable, std::vector< char > & blob, std::size_t offset, 215cdf0e10cSrcweir MarshalData & data) 216cdf0e10cSrcweir { 217cdf0e10cSrcweir OSL_ASSERT(variable != 0); 218cdf0e10cSrcweir SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())-> 219cdf0e10cSrcweir GetProperties(); 220cdf0e10cSrcweir for (sal_uInt16 i = 0; i < props->Count(); ++i) { 221cdf0e10cSrcweir SbError e = marshal(false, props->Get(i), false, blob, offset, data); 222cdf0e10cSrcweir if (e != ERRCODE_NONE) { 223cdf0e10cSrcweir return e; 224cdf0e10cSrcweir } 225cdf0e10cSrcweir } 226cdf0e10cSrcweir return ERRCODE_NONE; 227cdf0e10cSrcweir } 228cdf0e10cSrcweir 229cdf0e10cSrcweir SbError marshalArray( 230cdf0e10cSrcweir SbxVariable * variable, std::vector< char > & blob, std::size_t offset, 231cdf0e10cSrcweir MarshalData & data) 232cdf0e10cSrcweir { 233cdf0e10cSrcweir OSL_ASSERT(variable != 0); 234cdf0e10cSrcweir SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject()); 235cdf0e10cSrcweir int dims = arr->GetDims(); 236cdf0e10cSrcweir std::vector< sal_Int32 > low(dims); 237cdf0e10cSrcweir std::vector< sal_Int32 > up(dims); 238cdf0e10cSrcweir for (int i = 0; i < dims; ++i) { 239cdf0e10cSrcweir arr->GetDim32(i + 1, low[i], up[i]); 240cdf0e10cSrcweir } 241cdf0e10cSrcweir for (std::vector< sal_Int32 > idx = low;;) { 242cdf0e10cSrcweir SbError e = marshal( 243cdf0e10cSrcweir false, arr->Get32(&idx[0]), false, blob, offset, data); 244cdf0e10cSrcweir if (e != ERRCODE_NONE) { 245cdf0e10cSrcweir return e; 246cdf0e10cSrcweir } 247cdf0e10cSrcweir int i = dims - 1; 248cdf0e10cSrcweir while (idx[i] == up[i]) { 249cdf0e10cSrcweir idx[i] = low[i]; 250cdf0e10cSrcweir if (i == 0) { 251cdf0e10cSrcweir return ERRCODE_NONE; 252cdf0e10cSrcweir } 253cdf0e10cSrcweir --i; 254cdf0e10cSrcweir } 255cdf0e10cSrcweir ++idx[i]; 256cdf0e10cSrcweir } 257cdf0e10cSrcweir } 258cdf0e10cSrcweir 259cdf0e10cSrcweir // 8-aligned structs are only 4-aligned on stack, so alignment of members in 260cdf0e10cSrcweir // such structs must take that into account via "offset" 261cdf0e10cSrcweir SbError marshal( 262cdf0e10cSrcweir bool outer, SbxVariable * variable, bool special, 263cdf0e10cSrcweir std::vector< char > & blob, std::size_t offset, MarshalData & data) 264cdf0e10cSrcweir { 265cdf0e10cSrcweir OSL_ASSERT(variable != 0); 266cdf0e10cSrcweir 267cdf0e10cSrcweir SbxDataType eVarType = variable->GetType(); 268cdf0e10cSrcweir bool bByVal = (variable->GetFlags() & SBX_REFERENCE) == 0; 269cdf0e10cSrcweir if( !bByVal && !SbiRuntime::isVBAEnabled() && eVarType == SbxSTRING ) 270cdf0e10cSrcweir bByVal = true; 271cdf0e10cSrcweir 272cdf0e10cSrcweir if (bByVal) { 273cdf0e10cSrcweir if ((eVarType & SbxARRAY) == 0) { 274cdf0e10cSrcweir switch (eVarType) { 275cdf0e10cSrcweir case SbxINTEGER: 276cdf0e10cSrcweir add(blob, variable->GetInteger(), outer ? 4 : 2, offset); 277cdf0e10cSrcweir break; 278cdf0e10cSrcweir case SbxLONG: 279cdf0e10cSrcweir add(blob, variable->GetLong(), 4, offset); 280cdf0e10cSrcweir break; 281cdf0e10cSrcweir case SbxSINGLE: 282cdf0e10cSrcweir add(blob, variable->GetSingle(), 4, offset); 283cdf0e10cSrcweir break; 284cdf0e10cSrcweir case SbxDOUBLE: 285cdf0e10cSrcweir add(blob, variable->GetDouble(), outer ? 4 : 8, offset); 286cdf0e10cSrcweir break; 287cdf0e10cSrcweir case SbxSTRING: 288cdf0e10cSrcweir { 289cdf0e10cSrcweir void * p; 290cdf0e10cSrcweir SbError e = marshalString(variable, special, data, &p); 291cdf0e10cSrcweir if (e != ERRCODE_NONE) { 292cdf0e10cSrcweir return e; 293cdf0e10cSrcweir } 294cdf0e10cSrcweir add(blob, p, 4, offset); 295cdf0e10cSrcweir break; 296cdf0e10cSrcweir } 297cdf0e10cSrcweir case SbxOBJECT: 298cdf0e10cSrcweir { 299cdf0e10cSrcweir align(blob, outer ? 4 : alignment(variable), offset, 0); 300cdf0e10cSrcweir SbError e = marshalStruct(variable, blob, offset, data); 301cdf0e10cSrcweir if (e != ERRCODE_NONE) { 302cdf0e10cSrcweir return e; 303cdf0e10cSrcweir } 304cdf0e10cSrcweir break; 305cdf0e10cSrcweir } 306cdf0e10cSrcweir case SbxBOOL: 307cdf0e10cSrcweir add(blob, variable->GetBool(), outer ? 4 : 1, offset); 308cdf0e10cSrcweir break; 309cdf0e10cSrcweir case SbxBYTE: 310cdf0e10cSrcweir add(blob, variable->GetByte(), outer ? 4 : 1, offset); 311cdf0e10cSrcweir break; 312cdf0e10cSrcweir default: 313cdf0e10cSrcweir OSL_ASSERT(false); 314cdf0e10cSrcweir break; 315cdf0e10cSrcweir } 316cdf0e10cSrcweir } else { 317cdf0e10cSrcweir SbError e = marshalArray(variable, blob, offset, data); 318cdf0e10cSrcweir if (e != ERRCODE_NONE) { 319cdf0e10cSrcweir return e; 320cdf0e10cSrcweir } 321cdf0e10cSrcweir } 322cdf0e10cSrcweir } else { 323cdf0e10cSrcweir if ((eVarType & SbxARRAY) == 0) { 324cdf0e10cSrcweir switch (eVarType) { 325cdf0e10cSrcweir case SbxINTEGER: 326cdf0e10cSrcweir case SbxLONG: 327cdf0e10cSrcweir case SbxSINGLE: 328cdf0e10cSrcweir case SbxDOUBLE: 329cdf0e10cSrcweir case SbxBOOL: 330cdf0e10cSrcweir case SbxBYTE: 331cdf0e10cSrcweir add(blob, variable->data(), 4, offset); 332cdf0e10cSrcweir break; 333cdf0e10cSrcweir case SbxSTRING: 334cdf0e10cSrcweir { 335cdf0e10cSrcweir std::vector< char > * blob2 = data.newBlob(); 336cdf0e10cSrcweir void * p; 337cdf0e10cSrcweir SbError e = marshalString(variable, special, data, &p); 338cdf0e10cSrcweir if (e != ERRCODE_NONE) { 339cdf0e10cSrcweir return e; 340cdf0e10cSrcweir } 341cdf0e10cSrcweir add(*blob2, p, 4, 0); 342cdf0e10cSrcweir add(blob, address(*blob2), 4, offset); 343cdf0e10cSrcweir break; 344cdf0e10cSrcweir } 345cdf0e10cSrcweir case SbxOBJECT: 346cdf0e10cSrcweir { 347cdf0e10cSrcweir std::vector< char > * blob2 = data.newBlob(); 348cdf0e10cSrcweir SbError e = marshalStruct(variable, *blob2, 0, data); 349cdf0e10cSrcweir if (e != ERRCODE_NONE) { 350cdf0e10cSrcweir return e; 351cdf0e10cSrcweir } 352cdf0e10cSrcweir void * p = address(*blob2); 353cdf0e10cSrcweir if (outer) { 354cdf0e10cSrcweir data.unmarshal.push_back(UnmarshalData(variable, p)); 355cdf0e10cSrcweir } 356cdf0e10cSrcweir add(blob, p, 4, offset); 357cdf0e10cSrcweir break; 358cdf0e10cSrcweir } 359cdf0e10cSrcweir default: 360cdf0e10cSrcweir OSL_ASSERT(false); 361cdf0e10cSrcweir break; 362cdf0e10cSrcweir } 363cdf0e10cSrcweir } else { 364cdf0e10cSrcweir std::vector< char > * blob2 = data.newBlob(); 365cdf0e10cSrcweir SbError e = marshalArray(variable, *blob2, 0, data); 366cdf0e10cSrcweir if (e != ERRCODE_NONE) { 367cdf0e10cSrcweir return e; 368cdf0e10cSrcweir } 369cdf0e10cSrcweir void * p = address(*blob2); 370cdf0e10cSrcweir if (outer) { 371cdf0e10cSrcweir data.unmarshal.push_back(UnmarshalData(variable, p)); 372cdf0e10cSrcweir } 373cdf0e10cSrcweir add(blob, p, 4, offset); 374cdf0e10cSrcweir } 375cdf0e10cSrcweir } 376cdf0e10cSrcweir return ERRCODE_NONE; 377cdf0e10cSrcweir } 378cdf0e10cSrcweir 379cdf0e10cSrcweir template< typename T > T read(void const ** pointer) { 380cdf0e10cSrcweir T const * p = static_cast< T const * >(*pointer); 381cdf0e10cSrcweir *pointer = static_cast< void const * >(p + 1); 382cdf0e10cSrcweir return *p; 383cdf0e10cSrcweir } 384cdf0e10cSrcweir 385cdf0e10cSrcweir void const * unmarshal(SbxVariable * variable, void const * data) { 386cdf0e10cSrcweir OSL_ASSERT(variable != 0); 387cdf0e10cSrcweir if ((variable->GetType() & SbxARRAY) == 0) { 388cdf0e10cSrcweir switch (variable->GetType()) { 389cdf0e10cSrcweir case SbxINTEGER: 390cdf0e10cSrcweir variable->PutInteger(read< sal_Int16 >(&data)); 391cdf0e10cSrcweir break; 392cdf0e10cSrcweir case SbxLONG: 393cdf0e10cSrcweir variable->PutLong(read< sal_Int32 >(&data)); 394cdf0e10cSrcweir break; 395cdf0e10cSrcweir case SbxSINGLE: 396cdf0e10cSrcweir variable->PutSingle(read< float >(&data)); 397cdf0e10cSrcweir break; 398cdf0e10cSrcweir case SbxDOUBLE: 399cdf0e10cSrcweir variable->PutDouble(read< double >(&data)); 400cdf0e10cSrcweir break; 401cdf0e10cSrcweir case SbxSTRING: 402cdf0e10cSrcweir read< char * >(&data); // handled by unmarshalString 403cdf0e10cSrcweir break; 404cdf0e10cSrcweir case SbxOBJECT: 405cdf0e10cSrcweir { 406cdf0e10cSrcweir data = reinterpret_cast< void const * >( 407cdf0e10cSrcweir align( 408cdf0e10cSrcweir reinterpret_cast< sal_uIntPtr >(data), 409cdf0e10cSrcweir alignment(variable))); 410cdf0e10cSrcweir SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())-> 411cdf0e10cSrcweir GetProperties(); 412cdf0e10cSrcweir for (sal_uInt16 i = 0; i < props->Count(); ++i) { 413cdf0e10cSrcweir data = unmarshal(props->Get(i), data); 414cdf0e10cSrcweir } 415cdf0e10cSrcweir break; 416cdf0e10cSrcweir } 417cdf0e10cSrcweir case SbxBOOL: 418cdf0e10cSrcweir variable->PutBool(read< sal_Bool >(&data)); 419cdf0e10cSrcweir break; 420cdf0e10cSrcweir case SbxBYTE: 421cdf0e10cSrcweir variable->PutByte(read< sal_uInt8 >(&data)); 422cdf0e10cSrcweir break; 423cdf0e10cSrcweir default: 424cdf0e10cSrcweir OSL_ASSERT(false); 425cdf0e10cSrcweir break; 426cdf0e10cSrcweir } 427cdf0e10cSrcweir } else { 428cdf0e10cSrcweir SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject()); 429cdf0e10cSrcweir int dims = arr->GetDims(); 430cdf0e10cSrcweir std::vector< sal_Int32 > low(dims); 431cdf0e10cSrcweir std::vector< sal_Int32 > up(dims); 432cdf0e10cSrcweir for (int i = 0; i < dims; ++i) { 433cdf0e10cSrcweir arr->GetDim32(i + 1, low[i], up[i]); 434cdf0e10cSrcweir } 435cdf0e10cSrcweir for (std::vector< sal_Int32 > idx = low;;) { 436cdf0e10cSrcweir data = unmarshal(arr->Get32(&idx[0]), data); 437cdf0e10cSrcweir int i = dims - 1; 438cdf0e10cSrcweir while (idx[i] == up[i]) { 439cdf0e10cSrcweir idx[i] = low[i]; 440cdf0e10cSrcweir if (i == 0) { 441cdf0e10cSrcweir goto done; 442cdf0e10cSrcweir } 443cdf0e10cSrcweir --i; 444cdf0e10cSrcweir } 445cdf0e10cSrcweir ++idx[i]; 446cdf0e10cSrcweir } 447cdf0e10cSrcweir done:; 448cdf0e10cSrcweir } 449cdf0e10cSrcweir return data; 450cdf0e10cSrcweir } 451cdf0e10cSrcweir 452cdf0e10cSrcweir SbError unmarshalString(StringData const & data, SbxVariable & result) { 453cdf0e10cSrcweir rtl::OUString str; 454cdf0e10cSrcweir if (data.buffer != 0) { 455cdf0e10cSrcweir char const * p = static_cast< char const * >(data.buffer); 456cdf0e10cSrcweir sal_Int32 len; 457cdf0e10cSrcweir if (data.special) { 458cdf0e10cSrcweir len = static_cast< sal_Int32 >(result.GetULong()); 459cdf0e10cSrcweir if (len < 0) { // i.e., DWORD result >= 2^31 460cdf0e10cSrcweir return ERRCODE_BASIC_BAD_ARGUMENT; 461cdf0e10cSrcweir //TODO: more specific errcode? 462cdf0e10cSrcweir } 463cdf0e10cSrcweir } else { 464cdf0e10cSrcweir len = rtl_str_getLength(p); 465cdf0e10cSrcweir } 466cdf0e10cSrcweir SbError e = convert(p, len, &str); 467cdf0e10cSrcweir if (e != ERRCODE_NONE) { 468cdf0e10cSrcweir return e; 469cdf0e10cSrcweir } 470cdf0e10cSrcweir } 471cdf0e10cSrcweir data.variable->PutString(String(str)); 472cdf0e10cSrcweir return ERRCODE_NONE; 473cdf0e10cSrcweir } 474cdf0e10cSrcweir 475cdf0e10cSrcweir struct ProcData { 476cdf0e10cSrcweir rtl::OString name; 477cdf0e10cSrcweir FARPROC proc; 478cdf0e10cSrcweir }; 479cdf0e10cSrcweir 480cdf0e10cSrcweir SbError call( 481cdf0e10cSrcweir rtl::OUString const & dll, ProcData const & proc, SbxArray * arguments, 482cdf0e10cSrcweir SbxVariable & result) 483cdf0e10cSrcweir { 484cdf0e10cSrcweir std::vector< char > stack; 485cdf0e10cSrcweir MarshalData data; 486cdf0e10cSrcweir // For DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer) 487cdf0e10cSrcweir // from kernel32, upon return, filled lpBuffer length is result DWORD, which 488cdf0e10cSrcweir // requires special handling in unmarshalString; other functions might 489cdf0e10cSrcweir // require similar treatment, too: 490cdf0e10cSrcweir bool special = 491cdf0e10cSrcweir dll.equalsIgnoreAsciiCaseAsciiL( 492cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("KERNEL32.DLL")) && 493cdf0e10cSrcweir (proc.name == 494cdf0e10cSrcweir rtl::OString(RTL_CONSTASCII_STRINGPARAM("GetLogicalDriveStringsA"))); 495cdf0e10cSrcweir for (sal_uInt16 i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) { 496cdf0e10cSrcweir SbError e = marshal( 497cdf0e10cSrcweir true, arguments->Get(i), special && i == 2, stack, stack.size(), 498cdf0e10cSrcweir data); 499cdf0e10cSrcweir if (e != ERRCODE_NONE) { 500cdf0e10cSrcweir return e; 501cdf0e10cSrcweir } 502cdf0e10cSrcweir align(stack, 4, 0, 0); 503cdf0e10cSrcweir } 504cdf0e10cSrcweir switch (result.GetType()) { 505cdf0e10cSrcweir case SbxEMPTY: 506cdf0e10cSrcweir DllMgr_call32(proc.proc, address(stack), stack.size()); 507cdf0e10cSrcweir break; 508cdf0e10cSrcweir case SbxINTEGER: 509cdf0e10cSrcweir result.PutInteger( 510cdf0e10cSrcweir static_cast< sal_Int16 >( 511cdf0e10cSrcweir DllMgr_call32(proc.proc, address(stack), stack.size()))); 512cdf0e10cSrcweir break; 513cdf0e10cSrcweir case SbxLONG: 514cdf0e10cSrcweir result.PutLong( 515cdf0e10cSrcweir static_cast< sal_Int32 >( 516cdf0e10cSrcweir DllMgr_call32(proc.proc, address(stack), stack.size()))); 517cdf0e10cSrcweir break; 518cdf0e10cSrcweir case SbxSINGLE: 519cdf0e10cSrcweir result.PutSingle( 520cdf0e10cSrcweir static_cast< float >( 521cdf0e10cSrcweir DllMgr_callFp(proc.proc, address(stack), stack.size()))); 522cdf0e10cSrcweir break; 523cdf0e10cSrcweir case SbxDOUBLE: 524cdf0e10cSrcweir result.PutDouble( 525cdf0e10cSrcweir DllMgr_callFp(proc.proc, address(stack), stack.size())); 526cdf0e10cSrcweir break; 527cdf0e10cSrcweir case SbxSTRING: 528cdf0e10cSrcweir { 529cdf0e10cSrcweir char const * s1 = reinterpret_cast< char const * >( 530cdf0e10cSrcweir DllMgr_call32(proc.proc, address(stack), stack.size())); 531cdf0e10cSrcweir rtl::OUString s2; 532cdf0e10cSrcweir SbError e = convert(s1, rtl_str_getLength(s1), &s2); 533cdf0e10cSrcweir if (e != ERRCODE_NONE) { 534cdf0e10cSrcweir return e; 535cdf0e10cSrcweir } 536cdf0e10cSrcweir result.PutString(String(s2)); 537cdf0e10cSrcweir break; 538cdf0e10cSrcweir } 539cdf0e10cSrcweir case SbxOBJECT: 540cdf0e10cSrcweir //TODO 541cdf0e10cSrcweir DllMgr_call32(proc.proc, address(stack), stack.size()); 542cdf0e10cSrcweir break; 543cdf0e10cSrcweir case SbxBOOL: 544cdf0e10cSrcweir result.PutBool( 545cdf0e10cSrcweir static_cast< sal_Bool >( 546cdf0e10cSrcweir DllMgr_call32(proc.proc, address(stack), stack.size()))); 547cdf0e10cSrcweir break; 548cdf0e10cSrcweir case SbxBYTE: 549cdf0e10cSrcweir result.PutByte( 550cdf0e10cSrcweir static_cast< sal_uInt8 >( 551cdf0e10cSrcweir DllMgr_call32(proc.proc, address(stack), stack.size()))); 552cdf0e10cSrcweir break; 553cdf0e10cSrcweir default: 554cdf0e10cSrcweir OSL_ASSERT(false); 555cdf0e10cSrcweir break; 556cdf0e10cSrcweir } 557cdf0e10cSrcweir for (sal_uInt16 i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) { 558cdf0e10cSrcweir arguments->Get(i)->ResetFlag(SBX_REFERENCE); 559cdf0e10cSrcweir //TODO: skipped for errors?!? 560cdf0e10cSrcweir } 561cdf0e10cSrcweir for (std::vector< UnmarshalData >::iterator i(data.unmarshal.begin()); 562cdf0e10cSrcweir i != data.unmarshal.end(); ++i) 563cdf0e10cSrcweir { 564cdf0e10cSrcweir unmarshal(i->variable, i->buffer); 565cdf0e10cSrcweir } 566cdf0e10cSrcweir for (std::vector< StringData >::iterator i(data.unmarshalStrings.begin()); 567cdf0e10cSrcweir i != data.unmarshalStrings.end(); ++i) 568cdf0e10cSrcweir { 569cdf0e10cSrcweir SbError e = unmarshalString(*i, result); 570cdf0e10cSrcweir if (e != ERRCODE_NONE) { 571cdf0e10cSrcweir return e; 572cdf0e10cSrcweir } 573cdf0e10cSrcweir } 574cdf0e10cSrcweir return ERRCODE_NONE; 575cdf0e10cSrcweir } 576cdf0e10cSrcweir 577cdf0e10cSrcweir SbError getProcData(HMODULE handle, rtl::OUString const & name, ProcData * proc) 578cdf0e10cSrcweir { 579cdf0e10cSrcweir OSL_ASSERT(proc != 0); 580cdf0e10cSrcweir if (name.getLength() != 0 && name[0] == '@') { //TODO: "@" vs. "#"??? 581cdf0e10cSrcweir sal_Int32 n = name.copy(1).toInt32(); //TODO: handle bad input 582cdf0e10cSrcweir if (n <= 0 || n > 0xFFFF) { 583cdf0e10cSrcweir return ERRCODE_BASIC_BAD_ARGUMENT; //TODO: more specific errcode? 584cdf0e10cSrcweir } 585cdf0e10cSrcweir FARPROC p = GetProcAddress(handle, reinterpret_cast< LPCSTR >(n)); 586cdf0e10cSrcweir if (p != 0) { 587cdf0e10cSrcweir proc->name = rtl::OString(RTL_CONSTASCII_STRINGPARAM("#")) + 588cdf0e10cSrcweir rtl::OString::valueOf(n); 589cdf0e10cSrcweir proc->proc = p; 590cdf0e10cSrcweir return ERRCODE_NONE; 591cdf0e10cSrcweir } 592cdf0e10cSrcweir } else { 593cdf0e10cSrcweir rtl::OString name8; 594cdf0e10cSrcweir SbError e = convert(name, &name8); 595cdf0e10cSrcweir if (e != ERRCODE_NONE) { 596cdf0e10cSrcweir return e; 597cdf0e10cSrcweir } 598cdf0e10cSrcweir FARPROC p = GetProcAddress(handle, name8.getStr()); 599cdf0e10cSrcweir if (p != 0) { 600cdf0e10cSrcweir proc->name = name8; 601cdf0e10cSrcweir proc->proc = p; 602cdf0e10cSrcweir return ERRCODE_NONE; 603cdf0e10cSrcweir } 604cdf0e10cSrcweir sal_Int32 i = name8.indexOf('#'); 605cdf0e10cSrcweir if (i != -1) { 606cdf0e10cSrcweir name8 = name8.copy(0, i); 607cdf0e10cSrcweir p = GetProcAddress(handle, name8.getStr()); 608cdf0e10cSrcweir if (p != 0) { 609cdf0e10cSrcweir proc->name = name8; 610cdf0e10cSrcweir proc->proc = p; 611cdf0e10cSrcweir return ERRCODE_NONE; 612cdf0e10cSrcweir } 613cdf0e10cSrcweir } 614cdf0e10cSrcweir rtl::OString real( 615cdf0e10cSrcweir rtl::OString(RTL_CONSTASCII_STRINGPARAM("_")) + name8); 616cdf0e10cSrcweir p = GetProcAddress(handle, real.getStr()); 617cdf0e10cSrcweir if (p != 0) { 618cdf0e10cSrcweir proc->name = real; 619cdf0e10cSrcweir proc->proc = p; 620cdf0e10cSrcweir return ERRCODE_NONE; 621cdf0e10cSrcweir } 622cdf0e10cSrcweir real = name8 + rtl::OString(RTL_CONSTASCII_STRINGPARAM("A")); 623cdf0e10cSrcweir p = GetProcAddress(handle, real.getStr()); 624cdf0e10cSrcweir if (p != 0) { 625cdf0e10cSrcweir proc->name = real; 626cdf0e10cSrcweir proc->proc = p; 627cdf0e10cSrcweir return ERRCODE_NONE; 628cdf0e10cSrcweir } 629cdf0e10cSrcweir } 630cdf0e10cSrcweir return ERRCODE_BASIC_PROC_UNDEFINED; 631cdf0e10cSrcweir } 632cdf0e10cSrcweir 633cdf0e10cSrcweir struct Dll: public salhelper::SimpleReferenceObject { 634cdf0e10cSrcweir private: 635cdf0e10cSrcweir typedef std::map< rtl::OUString, ProcData > Procs; 636cdf0e10cSrcweir 637cdf0e10cSrcweir virtual ~Dll(); 638cdf0e10cSrcweir 639cdf0e10cSrcweir public: 640cdf0e10cSrcweir Dll(): handle(0) {} 641cdf0e10cSrcweir 642cdf0e10cSrcweir SbError getProc(rtl::OUString const & name, ProcData * proc); 643cdf0e10cSrcweir 644cdf0e10cSrcweir HMODULE handle; 645cdf0e10cSrcweir Procs procs; 646cdf0e10cSrcweir }; 647cdf0e10cSrcweir 648cdf0e10cSrcweir Dll::~Dll() { 649cdf0e10cSrcweir if (handle != 0 && !FreeLibrary(handle)) { 650cdf0e10cSrcweir OSL_TRACE("FreeLibrary(%p) failed with %u", handle, GetLastError()); 651cdf0e10cSrcweir } 652cdf0e10cSrcweir } 653cdf0e10cSrcweir 654cdf0e10cSrcweir SbError Dll::getProc(rtl::OUString const & name, ProcData * proc) { 655cdf0e10cSrcweir Procs::iterator i(procs.find(name)); 656cdf0e10cSrcweir if (i != procs.end()) { 657cdf0e10cSrcweir *proc = i->second; 658cdf0e10cSrcweir return ERRCODE_NONE; 659cdf0e10cSrcweir } 660cdf0e10cSrcweir SbError e = getProcData(handle, name, proc); 661cdf0e10cSrcweir if (e == ERRCODE_NONE) { 662cdf0e10cSrcweir procs.insert(Procs::value_type(name, *proc)); 663cdf0e10cSrcweir } 664cdf0e10cSrcweir return e; 665cdf0e10cSrcweir } 666cdf0e10cSrcweir 667cdf0e10cSrcweir rtl::OUString fullDllName(rtl::OUString const & name) { 668cdf0e10cSrcweir rtl::OUString full(name); 669cdf0e10cSrcweir if (full.indexOf('.') == -1) { 670cdf0e10cSrcweir full += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".DLL")); 671cdf0e10cSrcweir } 672cdf0e10cSrcweir return full; 673cdf0e10cSrcweir } 674cdf0e10cSrcweir 675cdf0e10cSrcweir } 676cdf0e10cSrcweir 677cdf0e10cSrcweir struct SbiDllMgr::Impl: private boost::noncopyable { 678cdf0e10cSrcweir private: 679cdf0e10cSrcweir typedef std::map< rtl::OUString, rtl::Reference< Dll > > Dlls; 680cdf0e10cSrcweir 681cdf0e10cSrcweir public: 682cdf0e10cSrcweir Dll * getDll(rtl::OUString const & name); 683cdf0e10cSrcweir 684cdf0e10cSrcweir Dlls dlls; 685cdf0e10cSrcweir }; 686cdf0e10cSrcweir 687cdf0e10cSrcweir Dll * SbiDllMgr::Impl::getDll(rtl::OUString const & name) { 688cdf0e10cSrcweir Dlls::iterator i(dlls.find(name)); 689cdf0e10cSrcweir if (i == dlls.end()) { 690cdf0e10cSrcweir i = dlls.insert(Dlls::value_type(name, new Dll)).first; 691cdf0e10cSrcweir HMODULE h = LoadLibraryW(reinterpret_cast<LPCWSTR>(name.getStr())); 692cdf0e10cSrcweir if (h == 0) { 693cdf0e10cSrcweir dlls.erase(i); 694cdf0e10cSrcweir return 0; 695cdf0e10cSrcweir } 696cdf0e10cSrcweir i->second->handle = h; 697cdf0e10cSrcweir } 698cdf0e10cSrcweir return i->second.get(); 699cdf0e10cSrcweir } 700cdf0e10cSrcweir 701cdf0e10cSrcweir SbError SbiDllMgr::Call( 702cdf0e10cSrcweir rtl::OUString const & function, rtl::OUString const & library, 703cdf0e10cSrcweir SbxArray * arguments, SbxVariable & result, bool cdeclConvention) 704cdf0e10cSrcweir { 705cdf0e10cSrcweir if (cdeclConvention) { 706cdf0e10cSrcweir return ERRCODE_BASIC_NOT_IMPLEMENTED; 707cdf0e10cSrcweir } 708cdf0e10cSrcweir rtl::OUString dllName(fullDllName(library)); 709cdf0e10cSrcweir Dll * dll = impl_->getDll(dllName); 710cdf0e10cSrcweir if (dll == 0) { 711cdf0e10cSrcweir return ERRCODE_BASIC_BAD_DLL_LOAD; 712cdf0e10cSrcweir } 713cdf0e10cSrcweir ProcData proc; 714cdf0e10cSrcweir SbError e = dll->getProc(function, &proc); 715cdf0e10cSrcweir if (e != ERRCODE_NONE) { 716cdf0e10cSrcweir return e; 717cdf0e10cSrcweir } 718cdf0e10cSrcweir return call(dllName, proc, arguments, result); 719cdf0e10cSrcweir } 720cdf0e10cSrcweir 721cdf0e10cSrcweir void SbiDllMgr::FreeDll(rtl::OUString const & library) { 722cdf0e10cSrcweir impl_->dlls.erase(library); 723cdf0e10cSrcweir } 724cdf0e10cSrcweir 725cdf0e10cSrcweir #else 726cdf0e10cSrcweir 727cdf0e10cSrcweir struct SbiDllMgr::Impl {}; 728cdf0e10cSrcweir 729cdf0e10cSrcweir SbError SbiDllMgr::Call( 730cdf0e10cSrcweir rtl::OUString const &, rtl::OUString const &, SbxArray *, SbxVariable &, 731cdf0e10cSrcweir bool) 732cdf0e10cSrcweir { 733cdf0e10cSrcweir return ERRCODE_BASIC_NOT_IMPLEMENTED; 734cdf0e10cSrcweir } 735cdf0e10cSrcweir 736cdf0e10cSrcweir void SbiDllMgr::FreeDll(rtl::OUString const &) {} 737cdf0e10cSrcweir 738cdf0e10cSrcweir #endif 739cdf0e10cSrcweir 740cdf0e10cSrcweir SbiDllMgr::SbiDllMgr(): impl_(new Impl) {} 741cdf0e10cSrcweir 742cdf0e10cSrcweir SbiDllMgr::~SbiDllMgr() {} 743