[Libreoffice-commits] .: 4 commits - avmedia/source basic/source .gitignore sfx2/source

Tor Lillqvist tml at kemper.freedesktop.org
Mon Jan 24 10:55:31 PST 2011


 .gitignore                           |    4 
 avmedia/source/win/player.cxx        |    3 
 basic/source/runtime/dllmgr-none.cxx |   64 ++
 basic/source/runtime/dllmgr-x64.cxx  |  772 +++++++++++++++++++++++++++++++++++
 basic/source/runtime/dllmgr-x86.cxx  |  722 ++++++++++++++++++++++++++++++++
 basic/source/runtime/dllmgr.cxx      |  741 ---------------------------------
 basic/source/runtime/makefile.mk     |   22 
 basic/source/runtime/wnt-x86.asm     |   56 ++
 basic/source/runtime/wnt.asm         |   56 --
 sfx2/source/bastyp/progress.cxx      |    2 
 10 files changed, 1635 insertions(+), 807 deletions(-)

New commits:
commit d9d430de93fae2a47bac6b143e2579cca1714bfe
Author: Tor Lillqvist <tlillqvist at novell.com>
Date:   Mon Jan 24 20:50:35 2011 +0200

    Add x64 Windows implementation of SbiDllMgr
    
    Work in progress. The passing of struct parameters is for sure
    incorrect, for instance: A temporary copy needs to be allocated and
    its address passed.
    
    No assembly involved. The idea is to call the external function as if
    it was a varargs one, and passing the four first qword-size parameters
    as if they were doubles, thus nicely causing them to be both in the
    integer and floating-point parameter registers, from either of which
    the callee will get them, depending on their actual expected type.
    
    Rename existing files a bit for clarity.

diff --git a/basic/source/runtime/dllmgr-none.cxx b/basic/source/runtime/dllmgr-none.cxx
new file mode 100644
index 0000000..db32b64
--- /dev/null
+++ b/basic/source/runtime/dllmgr-none.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_basic.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <list>
+#include <map>
+#include <vector>
+
+#include "basic/sbx.hxx"
+#include "basic/sbxvar.hxx"
+#include "osl/thread.h"
+#include "rtl/ref.hxx"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "salhelper/simplereferenceobject.hxx"
+#include "tools/svwin.h"
+
+#include "dllmgr.hxx"
+
+struct SbiDllMgr::Impl {};
+
+SbError SbiDllMgr::Call(
+    rtl::OUString const &, rtl::OUString const &, SbxArray *, SbxVariable &,
+    bool)
+{
+    return ERRCODE_BASIC_NOT_IMPLEMENTED;
+}
+
+void SbiDllMgr::FreeDll(rtl::OUString const &) {}
+
+SbiDllMgr::SbiDllMgr(): impl_(new Impl) {}
+
+SbiDllMgr::~SbiDllMgr() {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/dllmgr-x64.cxx b/basic/source/runtime/dllmgr-x64.cxx
new file mode 100644
index 0000000..aa3ce5e
--- /dev/null
+++ b/basic/source/runtime/dllmgr-x64.cxx
@@ -0,0 +1,772 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_basic.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <list>
+#include <map>
+#include <vector>
+
+#include "basic/sbx.hxx"
+#include "basic/sbxvar.hxx"
+#include "osl/thread.h"
+#include "rtl/ref.hxx"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "salhelper/simplereferenceobject.hxx"
+#include "tools/svwin.h"
+
+#undef max
+
+#include "dllmgr.hxx"
+
+/* Open issues:
+
+   Missing support for functions returning structs (see TODO in call()).
+
+   Missing support for additional data types (64 bit integers, Any, ...; would
+   trigger OSL_ASSERT(false) in various switches).
+
+   It is assumed that the variables passed into SbiDllMgr::Call to represent
+   the arguments and return value have types that exactly match the Declare
+   statement; it would be better if this code had access to the function
+   signature from the Declare statement, so that it could convert the passed
+   variables accordingly.
+*/
+
+namespace {
+
+char * address(std::vector< char > & blob) {
+    return blob.empty() ? 0 : &blob[0];
+}
+
+SbError convert(rtl::OUString const & source, rtl::OString * target) {
+    return
+        source.convertToString(
+            target, osl_getThreadTextEncoding(),
+            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
+             RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
+        ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
+        //TODO: more specific errcode?
+}
+
+SbError convert(char const * source, sal_Int32 length, rtl::OUString * target) {
+    return
+        rtl_convertStringToUString(
+            &target->pData, source, length, osl_getThreadTextEncoding(),
+            (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+             RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+             RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))
+        ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
+        //TODO: more specific errcode?
+}
+
+struct UnmarshalData {
+    UnmarshalData(SbxVariable * theVariable, void * theBuffer):
+        variable(theVariable), buffer(theBuffer) {}
+
+    SbxVariable * variable;
+    void * buffer;
+};
+
+struct StringData: public UnmarshalData {
+    StringData(SbxVariable * theVariable, void * theBuffer, bool theSpecial):
+        UnmarshalData(theVariable, theBuffer), special(theSpecial) {}
+
+    bool special;
+};
+
+class MarshalData: private boost::noncopyable {
+public:
+    std::vector< char > * newBlob() {
+        blobs_.push_front(std::vector< char >());
+        return &blobs_.front();
+    }
+
+    std::vector< UnmarshalData > unmarshal;
+
+    std::vector< StringData > unmarshalStrings;
+
+private:
+    std::list< std::vector< char > > blobs_;
+};
+
+std::size_t align(std::size_t address, std::size_t alignment) {
+    // alignment = 2^k for some k >= 0
+    return (address + (alignment - 1)) & ~(alignment - 1);
+}
+
+char * align(
+    std::vector< char > & blob, std::size_t alignment, std::size_t offset,
+    std::size_t add)
+{
+    std::vector< char >::size_type n = blob.size();
+    n = align(n - offset, alignment) + offset; //TODO: overflow in align()
+    blob.resize(n + add); //TODO: overflow
+    return address(blob) + n;
+}
+
+template< typename T > void add(
+    std::vector< char > & blob, T const & data, std::size_t alignment,
+    std::size_t offset)
+{
+    *reinterpret_cast< T * >(align(blob, alignment, offset, sizeof (T))) = data;
+}
+
+std::size_t alignment(SbxVariable * variable) {
+    OSL_ASSERT(variable != 0);
+    if ((variable->GetType() & SbxARRAY) == 0) {
+        switch (variable->GetType()) {
+        case SbxINTEGER:
+            return 2;
+        case SbxLONG:
+        case SbxSINGLE:
+        case SbxSTRING:
+            return 4;
+        case SbxDOUBLE:
+            return 8;
+        case SbxOBJECT:
+            {
+                std::size_t n = 1;
+                SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+                    GetProperties();
+                for (USHORT i = 0; i < props->Count(); ++i) {
+                    n = std::max(n, alignment(props->Get(i)));
+                }
+                return n;
+            }
+        case SbxBOOL:
+        case SbxBYTE:
+            return 1;
+        default:
+            OSL_ASSERT(false);
+            return 1;
+        }
+    } else {
+        SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+        int dims = arr->GetDims();
+        std::vector< INT32 > low(dims);
+        for (int i = 0; i < dims; ++i) {
+            INT32 up;
+            arr->GetDim32(i + 1, low[i], up);
+        }
+        return alignment(arr->Get32(&low[0]));
+    }
+}
+
+SbError marshal(
+    bool outer, SbxVariable * variable, bool special,
+    std::vector< char > & blob, std::size_t offset, MarshalData & data);
+
+SbError marshalString(
+    SbxVariable * variable, bool special, MarshalData & data, void ** buffer)
+{
+    OSL_ASSERT(variable != 0 && buffer != 0);
+    rtl::OString str;
+    SbError e = convert(variable->GetString(), &str);
+    if (e != ERRCODE_NONE) {
+        return e;
+    }
+    std::vector< char > * blob = data.newBlob();
+    blob->insert(blob->begin(), str.getStr(), str.getStr() + str.getLength());
+    *buffer = address(*blob);
+    data.unmarshalStrings.push_back(StringData(variable, *buffer, special));
+    return ERRCODE_NONE;
+}
+
+SbError marshalStruct(
+    SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
+    MarshalData & data)
+{
+    OSL_ASSERT(variable != 0);
+    SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+        GetProperties();
+    for (USHORT i = 0; i < props->Count(); ++i) {
+        SbError e = marshal(false, props->Get(i), false, blob, offset, data);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+    }
+    return ERRCODE_NONE;
+}
+
+SbError marshalArray(
+    SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
+    MarshalData & data)
+{
+    OSL_ASSERT(variable != 0);
+    SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+    int dims = arr->GetDims();
+    std::vector< INT32 > low(dims);
+    std::vector< INT32 > up(dims);
+    for (int i = 0; i < dims; ++i) {
+        arr->GetDim32(i + 1, low[i], up[i]);
+    }
+    for (std::vector< INT32 > idx = low;;) {
+        SbError e = marshal(
+            false, arr->Get32(&idx[0]), false, blob, offset, data);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+        int i = dims - 1;
+        while (idx[i] == up[i]) {
+            idx[i] = low[i];
+            if (i == 0) {
+                return ERRCODE_NONE;
+            }
+            --i;
+        }
+        ++idx[i];
+    }
+}
+
+// 8-aligned structs are only 4-aligned on stack, so alignment of members in
+// such structs must take that into account via "offset"
+SbError marshal(
+    bool outer, SbxVariable * variable, bool special,
+    std::vector< char > & blob, std::size_t offset, MarshalData & data)
+{
+    OSL_ASSERT(variable != 0);
+    if ((variable->GetFlags() & SBX_REFERENCE) == 0) {
+        if ((variable->GetType() & SbxARRAY) == 0) {
+            switch (variable->GetType()) {
+            case SbxINTEGER:
+                add(blob, variable->GetInteger(), outer ? 8 : 2, offset);
+                break;
+            case SbxLONG:
+                add(blob, variable->GetLong(), outer ? 8 : 4, offset);
+                break;
+            case SbxSINGLE:
+                add(blob, variable->GetSingle(), outer ? 8 : 4, offset);
+                break;
+            case SbxDOUBLE:
+                add(blob, variable->GetDouble(), 8, offset);
+                break;
+            case SbxSTRING:
+                {
+                    void * p;
+                    SbError e = marshalString(variable, special, data, &p);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    add(blob, p, 8, offset);
+                    break;
+                }
+            case SbxOBJECT:
+                {
+                    align(blob, outer ? 8 : alignment(variable), offset, 0);
+                    SbError e = marshalStruct(variable, blob, offset, data);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    break;
+                }
+            case SbxBOOL:
+                add(blob, variable->GetBool(), outer ? 8 : 1, offset);
+                break;
+            case SbxBYTE:
+                add(blob, variable->GetByte(), outer ? 8 : 1, offset);
+                break;
+            default:
+                OSL_ASSERT(false);
+                break;
+            }
+        } else {
+            SbError e = marshalArray(variable, blob, offset, data);
+            if (e != ERRCODE_NONE) {
+                return e;
+            }
+        }
+    } else {
+        if ((variable->GetType() & SbxARRAY) == 0) {
+            switch (variable->GetType()) {
+            case SbxINTEGER:
+            case SbxLONG:
+            case SbxSINGLE:
+            case SbxDOUBLE:
+            case SbxBOOL:
+            case SbxBYTE:
+                add(blob, variable->data(), 8, offset);
+                break;
+            case SbxSTRING:
+                {
+                    std::vector< char > * blob2 = data.newBlob();
+                    void * p;
+                    SbError e = marshalString(variable, special, data, &p);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    add(*blob2, p, 8, 0);
+                    add(blob, address(*blob2), 8, offset);
+                    break;
+                }
+            case SbxOBJECT:
+                {
+                    std::vector< char > * blob2 = data.newBlob();
+                    SbError e = marshalStruct(variable, *blob2, 0, data);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    void * p = address(*blob2);
+                    if (outer) {
+                        data.unmarshal.push_back(UnmarshalData(variable, p));
+                    }
+                    add(blob, p, 8, offset);
+                    break;
+                }
+            default:
+                OSL_ASSERT(false);
+                break;
+            }
+        } else {
+            std::vector< char > * blob2 = data.newBlob();
+            SbError e = marshalArray(variable, *blob2, 0, data);
+            if (e != ERRCODE_NONE) {
+                return e;
+            }
+            void * p = address(*blob2);
+            if (outer) {
+                data.unmarshal.push_back(UnmarshalData(variable, p));
+            }
+            add(blob, p, 8, offset);
+        }
+    }
+    return ERRCODE_NONE;
+}
+
+template< typename T > T read(void const ** pointer) {
+    T const * p = static_cast< T const * >(*pointer);
+    *pointer = static_cast< void const * >(p + 1);
+    return *p;
+}
+
+void const * unmarshal(SbxVariable * variable, void const * data) {
+    OSL_ASSERT(variable != 0);
+    if ((variable->GetType() & SbxARRAY) == 0) {
+        switch (variable->GetType()) {
+        case SbxINTEGER:
+            variable->PutInteger(read< sal_Int16 >(&data));
+            break;
+        case SbxLONG:
+            variable->PutLong(read< sal_Int32 >(&data));
+            break;
+        case SbxSINGLE:
+            variable->PutSingle(read< float >(&data));
+            break;
+        case SbxDOUBLE:
+            variable->PutDouble(read< double >(&data));
+            break;
+        case SbxSTRING:
+            read< char * >(&data); // handled by unmarshalString
+            break;
+        case SbxOBJECT:
+            {
+                data = reinterpret_cast< void const * >(
+                    align(
+                        reinterpret_cast< sal_uIntPtr >(data),
+                        alignment(variable)));
+                SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+                    GetProperties();
+                for (USHORT i = 0; i < props->Count(); ++i) {
+                    data = unmarshal(props->Get(i), data);
+                }
+                break;
+            }
+        case SbxBOOL:
+            variable->PutBool(read< sal_Bool >(&data));
+            break;
+        case SbxBYTE:
+            variable->PutByte(read< sal_uInt8 >(&data));
+            break;
+        default:
+            OSL_ASSERT(false);
+            break;
+        }
+    } else {
+        SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+        int dims = arr->GetDims();
+        std::vector< INT32 > low(dims);
+        std::vector< INT32 > up(dims);
+        for (int i = 0; i < dims; ++i) {
+            arr->GetDim32(i + 1, low[i], up[i]);
+        }
+        for (std::vector< INT32 > idx = low;;) {
+            data = unmarshal(arr->Get32(&idx[0]), data);
+            int i = dims - 1;
+            while (idx[i] == up[i]) {
+                idx[i] = low[i];
+                if (i == 0) {
+                    goto done;
+                }
+                --i;
+            }
+            ++idx[i];
+        }
+    done:;
+    }
+    return data;
+}
+
+SbError unmarshalString(StringData const & data, SbxVariable & result) {
+    rtl::OUString str;
+    if (data.buffer != 0) {
+        char const * p = static_cast< char const * >(data.buffer);
+        sal_Int32 len;
+        if (data.special) {
+            len = static_cast< sal_Int32 >(result.GetULong());
+            if (len < 0) { // i.e., DWORD result >= 2^31
+                return ERRCODE_BASIC_BAD_ARGUMENT;
+                    //TODO: more specific errcode?
+            }
+        } else {
+            len = rtl_str_getLength(p);
+        }
+        SbError e = convert(p, len, &str);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+    }
+    data.variable->PutString(String(str));
+    return ERRCODE_NONE;
+}
+
+struct ProcData {
+    rtl::OString name;
+    FARPROC proc;
+};
+
+SbError call(
+    rtl::OUString const & dll, ProcData const & proc, SbxArray * arguments,
+    SbxVariable & result)
+{
+    if (arguments->Count() > 20)
+        return ERRCODE_BASIC_NOT_IMPLEMENTED;
+
+    std::vector< char > stack;
+    MarshalData data;
+
+    // For DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
+    // from kernel32, upon return, filled lpBuffer length is result DWORD, which
+    // requires special handling in unmarshalString; other functions might
+    // require similar treatment, too:
+    bool special =
+        dll.equalsIgnoreAsciiCaseAsciiL(
+            RTL_CONSTASCII_STRINGPARAM("KERNEL32.DLL")) &&
+        (proc.name ==
+         rtl::OString(RTL_CONSTASCII_STRINGPARAM("GetLogicalDriveStringsA")));
+    for (int i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
+        SbError e = marshal(
+            true, arguments->Get(i), special && i == 2, stack, stack.size(),
+            data);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+        align(stack, 8, 0, 0);
+    }
+
+    stack.resize(20*8);
+
+    // We fake all calls as being to a varargs function,
+    // as this means any floating-point argument among the first four
+    // ones will end up in a XMM register where the callee expects it.
+    sal_Int32 (*proc_i)(double d, ...) = (sal_Int32 (*)(double, ...)) proc.proc;
+    double (*proc_d)(double d, ...) = (double (*)(double, ...)) proc.proc;
+
+    sal_Int64 iRetVal;
+    double dRetVal;
+
+    switch (result.GetType()) {
+    case SbxEMPTY:
+    case SbxINTEGER:
+    case SbxLONG:
+    case SbxSTRING:
+    case SbxOBJECT:
+    case SbxBOOL:
+    case SbxBYTE:
+        iRetVal =
+            proc_i(*(double *)&stack[0*8],
+                   *(double *)&stack[1*8],
+                   *(double *)&stack[2*8],
+                   *(double *)&stack[3*8],
+                   *(sal_uInt64 *)&stack[4*8],
+                   *(sal_uInt64 *)&stack[5*8],
+                   *(sal_uInt64 *)&stack[6*8],
+                   *(sal_uInt64 *)&stack[7*8],
+                   *(sal_uInt64 *)&stack[8*8],
+                   *(sal_uInt64 *)&stack[9*8],
+                   *(sal_uInt64 *)&stack[10*8],
+                   *(sal_uInt64 *)&stack[11*8],
+                   *(sal_uInt64 *)&stack[12*8],
+                   *(sal_uInt64 *)&stack[13*8],
+                   *(sal_uInt64 *)&stack[14*8],
+                   *(sal_uInt64 *)&stack[15*8],
+                   *(sal_uInt64 *)&stack[16*8],
+                   *(sal_uInt64 *)&stack[17*8],
+                   *(sal_uInt64 *)&stack[18*8],
+                   *(sal_uInt64 *)&stack[19*8]);
+        break;
+    case SbxSINGLE:
+    case SbxDOUBLE:
+        dRetVal =
+            proc_d(*(double *)&stack[0*8],
+                   *(double *)&stack[1*8],
+                   *(double *)&stack[2*8],
+                   *(double *)&stack[3*8],
+                   *(sal_uInt64 *)&stack[4*8],
+                   *(sal_uInt64 *)&stack[5*8],
+                   *(sal_uInt64 *)&stack[6*8],
+                   *(sal_uInt64 *)&stack[7*8],
+                   *(sal_uInt64 *)&stack[8*8],
+                   *(sal_uInt64 *)&stack[9*8],
+                   *(sal_uInt64 *)&stack[10*8],
+                   *(sal_uInt64 *)&stack[11*8],
+                   *(sal_uInt64 *)&stack[12*8],
+                   *(sal_uInt64 *)&stack[13*8],
+                   *(sal_uInt64 *)&stack[14*8],
+                   *(sal_uInt64 *)&stack[15*8],
+                   *(sal_uInt64 *)&stack[16*8],
+                   *(sal_uInt64 *)&stack[17*8],
+                   *(sal_uInt64 *)&stack[18*8],
+                   *(sal_uInt64 *)&stack[19*8]);
+    }
+
+    switch (result.GetType()) {
+    case SbxEMPTY:
+        break;
+    case SbxINTEGER:
+        result.PutInteger(static_cast< sal_Int16 >(iRetVal));
+        break;
+    case SbxLONG:
+        result.PutLong(static_cast< sal_Int32 >(iRetVal));
+        break;
+    case SbxSINGLE:
+        result.PutSingle(static_cast< float >(dRetVal));
+        break;
+    case SbxDOUBLE:
+        result.PutDouble(dRetVal);
+        break;
+    case SbxSTRING:
+        {
+            char const * s1 = reinterpret_cast< char const * >(iRetVal);
+            rtl::OUString s2;
+            SbError e = convert(s1, rtl_str_getLength(s1), &s2);
+            if (e != ERRCODE_NONE) {
+                return e;
+            }
+            result.PutString(String(s2));
+            break;
+        }
+    case SbxOBJECT:
+        //TODO
+        break;
+    case SbxBOOL:
+        result.PutBool(static_cast< sal_Bool >(iRetVal));
+        break;
+    case SbxBYTE:
+        result.PutByte(static_cast< sal_uInt8 >(iRetVal));
+        break;
+    default:
+        OSL_ASSERT(false);
+        break;
+    }
+    for (int i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
+        arguments->Get(i)->ResetFlag(SBX_REFERENCE);
+            //TODO: skipped for errors?!?
+    }
+    for (std::vector< UnmarshalData >::iterator i(data.unmarshal.begin());
+         i != data.unmarshal.end(); ++i)
+    {
+        unmarshal(i->variable, i->buffer);
+    }
+    for (std::vector< StringData >::iterator i(data.unmarshalStrings.begin());
+         i != data.unmarshalStrings.end(); ++i)
+    {
+        SbError e = unmarshalString(*i, result);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+    }
+    return ERRCODE_NONE;
+}
+
+SbError getProcData(HMODULE handle, rtl::OUString const & name, ProcData * proc)
+{
+    OSL_ASSERT(proc != 0);
+    if (name.getLength() != 0 && name[0] == '@') { //TODO: "@" vs. "#"???
+        sal_Int32 n = name.copy(1).toInt32(); //TODO: handle bad input
+        if (n <= 0 || n > 0xFFFF) {
+            return ERRCODE_BASIC_BAD_ARGUMENT; //TODO: more specific errcode?
+        }
+        FARPROC p = GetProcAddress(handle, reinterpret_cast< LPCSTR >(n));
+        if (p != 0) {
+            proc->name = rtl::OString(RTL_CONSTASCII_STRINGPARAM("#")) +
+                rtl::OString::valueOf(n);
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+    } else {
+        rtl::OString name8;
+        SbError e = convert(name, &name8);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+        FARPROC p = GetProcAddress(handle, name8.getStr());
+        if (p != 0) {
+            proc->name = name8;
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+        sal_Int32 i = name8.indexOf('#');
+        if (i != -1) {
+            name8 = name8.copy(0, i);
+            p = GetProcAddress(handle, name8.getStr());
+            if (p != 0) {
+                proc->name = name8;
+                proc->proc = p;
+                return ERRCODE_NONE;
+            }
+        }
+        rtl::OString real(
+            rtl::OString(RTL_CONSTASCII_STRINGPARAM("_")) + name8);
+        p = GetProcAddress(handle, real.getStr());
+        if (p != 0) {
+            proc->name = real;
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+        real = name8 + rtl::OString(RTL_CONSTASCII_STRINGPARAM("A"));
+        p = GetProcAddress(handle, real.getStr());
+        if (p != 0) {
+            proc->name = real;
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+    }
+    return ERRCODE_BASIC_PROC_UNDEFINED;
+}
+
+struct Dll: public salhelper::SimpleReferenceObject {
+private:
+    typedef std::map< rtl::OUString, ProcData > Procs;
+
+    virtual ~Dll();
+
+public:
+    Dll(): handle(0) {}
+
+    SbError getProc(rtl::OUString const & name, ProcData * proc);
+
+    HMODULE handle;
+    Procs procs;
+};
+
+Dll::~Dll() {
+    if (handle != 0 && !FreeLibrary(handle)) {
+        OSL_TRACE("FreeLibrary(%p) failed with %u", handle, GetLastError());
+    }
+}
+
+SbError Dll::getProc(rtl::OUString const & name, ProcData * proc) {
+    Procs::iterator i(procs.find(name));
+    if (i != procs.end()) {
+        *proc = i->second;
+        return ERRCODE_NONE;
+    }
+    SbError e = getProcData(handle, name, proc);
+    if (e == ERRCODE_NONE) {
+        procs.insert(Procs::value_type(name, *proc));
+    }
+    return e;
+}
+
+rtl::OUString fullDllName(rtl::OUString const & name) {
+    rtl::OUString full(name);
+    if (full.indexOf('.') == -1) {
+        full += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".DLL"));
+    }
+    return full;
+}
+
+}
+
+struct SbiDllMgr::Impl: private boost::noncopyable {
+private:
+    typedef std::map< rtl::OUString, rtl::Reference< Dll > > Dlls;
+
+public:
+    Dll * getDll(rtl::OUString const & name);
+
+    Dlls dlls;
+};
+
+Dll * SbiDllMgr::Impl::getDll(rtl::OUString const & name) {
+    Dlls::iterator i(dlls.find(name));
+    if (i == dlls.end()) {
+        i = dlls.insert(Dlls::value_type(name, new Dll)).first;
+        HMODULE h = LoadLibraryW(reinterpret_cast<LPCWSTR>(name.getStr()));
+        if (h == 0) {
+            dlls.erase(i);
+            return 0;
+        }
+        i->second->handle = h;
+    }
+    return i->second.get();
+}
+
+SbError SbiDllMgr::Call(
+    rtl::OUString const & function, rtl::OUString const & library,
+    SbxArray * arguments, SbxVariable & result, bool cdeclConvention)
+{
+    if (cdeclConvention) {
+        return ERRCODE_BASIC_NOT_IMPLEMENTED;
+    }
+    rtl::OUString dllName(fullDllName(library));
+    Dll * dll = impl_->getDll(dllName);
+    if (dll == 0) {
+        return ERRCODE_BASIC_BAD_DLL_LOAD;
+    }
+    ProcData proc;
+    SbError e = dll->getProc(function, &proc);
+    if (e != ERRCODE_NONE) {
+        return e;
+    }
+    return call(dllName, proc, arguments, result);
+}
+
+void SbiDllMgr::FreeDll(rtl::OUString const & library) {
+    impl_->dlls.erase(library);
+}
+
+SbiDllMgr::SbiDllMgr(): impl_(new Impl) {}
+
+SbiDllMgr::~SbiDllMgr() {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/dllmgr-x86.cxx b/basic/source/runtime/dllmgr-x86.cxx
new file mode 100644
index 0000000..09aee07
--- /dev/null
+++ b/basic/source/runtime/dllmgr-x86.cxx
@@ -0,0 +1,722 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_basic.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <list>
+#include <map>
+#include <vector>
+
+#include "basic/sbx.hxx"
+#include "basic/sbxvar.hxx"
+#include "osl/thread.h"
+#include "rtl/ref.hxx"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "salhelper/simplereferenceobject.hxx"
+#include "tools/svwin.h"
+
+#undef max
+
+#include "dllmgr.hxx"
+
+/* Open issues:
+
+   Missing support for functions returning structs (see TODO in call()).
+
+   Missing support for additional data types (64 bit integers, Any, ...; would
+   trigger OSL_ASSERT(false) in various switches).
+
+   It is assumed that the variables passed into SbiDllMgr::Call to represent
+   the arguments and return value have types that exactly match the Declare
+   statement; it would be better if this code had access to the function
+   signature from the Declare statement, so that it could convert the passed
+   variables accordingly.
+*/
+
+extern "C" {
+
+int __stdcall DllMgr_call32(FARPROC, void const * stack, std::size_t size);
+double __stdcall DllMgr_callFp(FARPROC, void const * stack, std::size_t size);
+
+}
+
+namespace {
+
+char * address(std::vector< char > & blob) {
+    return blob.empty() ? 0 : &blob[0];
+}
+
+SbError convert(rtl::OUString const & source, rtl::OString * target) {
+    return
+        source.convertToString(
+            target, osl_getThreadTextEncoding(),
+            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
+             RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
+        ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
+        //TODO: more specific errcode?
+}
+
+SbError convert(char const * source, sal_Int32 length, rtl::OUString * target) {
+    return
+        rtl_convertStringToUString(
+            &target->pData, source, length, osl_getThreadTextEncoding(),
+            (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+             RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+             RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))
+        ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
+        //TODO: more specific errcode?
+}
+
+struct UnmarshalData {
+    UnmarshalData(SbxVariable * theVariable, void * theBuffer):
+        variable(theVariable), buffer(theBuffer) {}
+
+    SbxVariable * variable;
+    void * buffer;
+};
+
+struct StringData: public UnmarshalData {
+    StringData(SbxVariable * theVariable, void * theBuffer, bool theSpecial):
+        UnmarshalData(theVariable, theBuffer), special(theSpecial) {}
+
+    bool special;
+};
+
+class MarshalData: private boost::noncopyable {
+public:
+    std::vector< char > * newBlob() {
+        blobs_.push_front(std::vector< char >());
+        return &blobs_.front();
+    }
+
+    std::vector< UnmarshalData > unmarshal;
+
+    std::vector< StringData > unmarshalStrings;
+
+private:
+    std::list< std::vector< char > > blobs_;
+};
+
+std::size_t align(std::size_t address, std::size_t alignment) {
+    // alignment = 2^k for some k >= 0
+    return (address + (alignment - 1)) & ~(alignment - 1);
+}
+
+char * align(
+    std::vector< char > & blob, std::size_t alignment, std::size_t offset,
+    std::size_t add)
+{
+    std::vector< char >::size_type n = blob.size();
+    n = align(n - offset, alignment) + offset; //TODO: overflow in align()
+    blob.resize(n + add); //TODO: overflow
+    return address(blob) + n;
+}
+
+template< typename T > void add(
+    std::vector< char > & blob, T const & data, std::size_t alignment,
+    std::size_t offset)
+{
+    *reinterpret_cast< T * >(align(blob, alignment, offset, sizeof (T))) = data;
+}
+
+std::size_t alignment(SbxVariable * variable) {
+    OSL_ASSERT(variable != 0);
+    if ((variable->GetType() & SbxARRAY) == 0) {
+        switch (variable->GetType()) {
+        case SbxINTEGER:
+            return 2;
+        case SbxLONG:
+        case SbxSINGLE:
+        case SbxSTRING:
+            return 4;
+        case SbxDOUBLE:
+            return 8;
+        case SbxOBJECT:
+            {
+                std::size_t n = 1;
+                SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+                    GetProperties();
+                for (USHORT i = 0; i < props->Count(); ++i) {
+                    n = std::max(n, alignment(props->Get(i)));
+                }
+                return n;
+            }
+        case SbxBOOL:
+        case SbxBYTE:
+            return 1;
+        default:
+            OSL_ASSERT(false);
+            return 1;
+        }
+    } else {
+        SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+        int dims = arr->GetDims();
+        std::vector< INT32 > low(dims);
+        for (int i = 0; i < dims; ++i) {
+            INT32 up;
+            arr->GetDim32(i + 1, low[i], up);
+        }
+        return alignment(arr->Get32(&low[0]));
+    }
+}
+
+SbError marshal(
+    bool outer, SbxVariable * variable, bool special,
+    std::vector< char > & blob, std::size_t offset, MarshalData & data);
+
+SbError marshalString(
+    SbxVariable * variable, bool special, MarshalData & data, void ** buffer)
+{
+    OSL_ASSERT(variable != 0 && buffer != 0);
+    rtl::OString str;
+    SbError e = convert(variable->GetString(), &str);
+    if (e != ERRCODE_NONE) {
+        return e;
+    }
+    std::vector< char > * blob = data.newBlob();
+    blob->insert(blob->begin(), str.getStr(), str.getStr() + str.getLength());
+    *buffer = address(*blob);
+    data.unmarshalStrings.push_back(StringData(variable, *buffer, special));
+    return ERRCODE_NONE;
+}
+
+SbError marshalStruct(
+    SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
+    MarshalData & data)
+{
+    OSL_ASSERT(variable != 0);
+    SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+        GetProperties();
+    for (USHORT i = 0; i < props->Count(); ++i) {
+        SbError e = marshal(false, props->Get(i), false, blob, offset, data);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+    }
+    return ERRCODE_NONE;
+}
+
+SbError marshalArray(
+    SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
+    MarshalData & data)
+{
+    OSL_ASSERT(variable != 0);
+    SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+    int dims = arr->GetDims();
+    std::vector< INT32 > low(dims);
+    std::vector< INT32 > up(dims);
+    for (int i = 0; i < dims; ++i) {
+        arr->GetDim32(i + 1, low[i], up[i]);
+    }
+    for (std::vector< INT32 > idx = low;;) {
+        SbError e = marshal(
+            false, arr->Get32(&idx[0]), false, blob, offset, data);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+        int i = dims - 1;
+        while (idx[i] == up[i]) {
+            idx[i] = low[i];
+            if (i == 0) {
+                return ERRCODE_NONE;
+            }
+            --i;
+        }
+        ++idx[i];
+    }
+}
+
+// 8-aligned structs are only 4-aligned on stack, so alignment of members in
+// such structs must take that into account via "offset"
+SbError marshal(
+    bool outer, SbxVariable * variable, bool special,
+    std::vector< char > & blob, std::size_t offset, MarshalData & data)
+{
+    OSL_ASSERT(variable != 0);
+    if ((variable->GetFlags() & SBX_REFERENCE) == 0) {
+        if ((variable->GetType() & SbxARRAY) == 0) {
+            switch (variable->GetType()) {
+            case SbxINTEGER:
+                add(blob, variable->GetInteger(), outer ? 4 : 2, offset);
+                break;
+            case SbxLONG:
+                add(blob, variable->GetLong(), 4, offset);
+                break;
+            case SbxSINGLE:
+                add(blob, variable->GetSingle(), 4, offset);
+                break;
+            case SbxDOUBLE:
+                add(blob, variable->GetDouble(), outer ? 4 : 8, offset);
+                break;
+            case SbxSTRING:
+                {
+                    void * p;
+                    SbError e = marshalString(variable, special, data, &p);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    add(blob, p, 4, offset);
+                    break;
+                }
+            case SbxOBJECT:
+                {
+                    align(blob, outer ? 4 : alignment(variable), offset, 0);
+                    SbError e = marshalStruct(variable, blob, offset, data);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    break;
+                }
+            case SbxBOOL:
+                add(blob, variable->GetBool(), outer ? 4 : 1, offset);
+                break;
+            case SbxBYTE:
+                add(blob, variable->GetByte(), outer ? 4 : 1, offset);
+                break;
+            default:
+                OSL_ASSERT(false);
+                break;
+            }
+        } else {
+            SbError e = marshalArray(variable, blob, offset, data);
+            if (e != ERRCODE_NONE) {
+                return e;
+            }
+        }
+    } else {
+        if ((variable->GetType() & SbxARRAY) == 0) {
+            switch (variable->GetType()) {
+            case SbxINTEGER:
+            case SbxLONG:
+            case SbxSINGLE:
+            case SbxDOUBLE:
+            case SbxBOOL:
+            case SbxBYTE:
+                add(blob, variable->data(), 4, offset);
+                break;
+            case SbxSTRING:
+                {
+                    std::vector< char > * blob2 = data.newBlob();
+                    void * p;
+                    SbError e = marshalString(variable, special, data, &p);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    add(*blob2, p, 4, 0);
+                    add(blob, address(*blob2), 4, offset);
+                    break;
+                }
+            case SbxOBJECT:
+                {
+                    std::vector< char > * blob2 = data.newBlob();
+                    SbError e = marshalStruct(variable, *blob2, 0, data);
+                    if (e != ERRCODE_NONE) {
+                        return e;
+                    }
+                    void * p = address(*blob2);
+                    if (outer) {
+                        data.unmarshal.push_back(UnmarshalData(variable, p));
+                    }
+                    add(blob, p, 4, offset);
+                    break;
+                }
+            default:
+                OSL_ASSERT(false);
+                break;
+            }
+        } else {
+            std::vector< char > * blob2 = data.newBlob();
+            SbError e = marshalArray(variable, *blob2, 0, data);
+            if (e != ERRCODE_NONE) {
+                return e;
+            }
+            void * p = address(*blob2);
+            if (outer) {
+                data.unmarshal.push_back(UnmarshalData(variable, p));
+            }
+            add(blob, p, 4, offset);
+        }
+    }
+    return ERRCODE_NONE;
+}
+
+template< typename T > T read(void const ** pointer) {
+    T const * p = static_cast< T const * >(*pointer);
+    *pointer = static_cast< void const * >(p + 1);
+    return *p;
+}
+
+void const * unmarshal(SbxVariable * variable, void const * data) {
+    OSL_ASSERT(variable != 0);
+    if ((variable->GetType() & SbxARRAY) == 0) {
+        switch (variable->GetType()) {
+        case SbxINTEGER:
+            variable->PutInteger(read< sal_Int16 >(&data));
+            break;
+        case SbxLONG:
+            variable->PutLong(read< sal_Int32 >(&data));
+            break;
+        case SbxSINGLE:
+            variable->PutSingle(read< float >(&data));
+            break;
+        case SbxDOUBLE:
+            variable->PutDouble(read< double >(&data));
+            break;
+        case SbxSTRING:
+            read< char * >(&data); // handled by unmarshalString
+            break;
+        case SbxOBJECT:
+            {
+                data = reinterpret_cast< void const * >(
+                    align(
+                        reinterpret_cast< sal_uIntPtr >(data),
+                        alignment(variable)));
+                SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+                    GetProperties();
+                for (USHORT i = 0; i < props->Count(); ++i) {
+                    data = unmarshal(props->Get(i), data);
+                }
+                break;
+            }
+        case SbxBOOL:
+            variable->PutBool(read< sal_Bool >(&data));
+            break;
+        case SbxBYTE:
+            variable->PutByte(read< sal_uInt8 >(&data));
+            break;
+        default:
+            OSL_ASSERT(false);
+            break;
+        }
+    } else {
+        SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+        int dims = arr->GetDims();
+        std::vector< INT32 > low(dims);
+        std::vector< INT32 > up(dims);
+        for (int i = 0; i < dims; ++i) {
+            arr->GetDim32(i + 1, low[i], up[i]);
+        }
+        for (std::vector< INT32 > idx = low;;) {
+            data = unmarshal(arr->Get32(&idx[0]), data);
+            int i = dims - 1;
+            while (idx[i] == up[i]) {
+                idx[i] = low[i];
+                if (i == 0) {
+                    goto done;
+                }
+                --i;
+            }
+            ++idx[i];
+        }
+    done:;
+    }
+    return data;
+}
+
+SbError unmarshalString(StringData const & data, SbxVariable & result) {
+    rtl::OUString str;
+    if (data.buffer != 0) {
+        char const * p = static_cast< char const * >(data.buffer);
+        sal_Int32 len;
+        if (data.special) {
+            len = static_cast< sal_Int32 >(result.GetULong());
+            if (len < 0) { // i.e., DWORD result >= 2^31
+                return ERRCODE_BASIC_BAD_ARGUMENT;
+                    //TODO: more specific errcode?
+            }
+        } else {
+            len = rtl_str_getLength(p);
+        }
+        SbError e = convert(p, len, &str);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+    }
+    data.variable->PutString(String(str));
+    return ERRCODE_NONE;
+}
+
+struct ProcData {
+    rtl::OString name;
+    FARPROC proc;
+};
+
+SbError call(
+    rtl::OUString const & dll, ProcData const & proc, SbxArray * arguments,
+    SbxVariable & result)
+{
+    std::vector< char > stack;
+    MarshalData data;
+    // For DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
+    // from kernel32, upon return, filled lpBuffer length is result DWORD, which
+    // requires special handling in unmarshalString; other functions might
+    // require similar treatment, too:
+    bool special =
+        dll.equalsIgnoreAsciiCaseAsciiL(
+            RTL_CONSTASCII_STRINGPARAM("KERNEL32.DLL")) &&
+        (proc.name ==
+         rtl::OString(RTL_CONSTASCII_STRINGPARAM("GetLogicalDriveStringsA")));
+    for (USHORT i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
+        SbError e = marshal(
+            true, arguments->Get(i), special && i == 2, stack, stack.size(),
+            data);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+        align(stack, 4, 0, 0);
+    }
+    switch (result.GetType()) {
+    case SbxEMPTY:
+        DllMgr_call32(proc.proc, address(stack), stack.size());
+        break;
+    case SbxINTEGER:
+        result.PutInteger(
+            static_cast< sal_Int16 >(
+                DllMgr_call32(proc.proc, address(stack), stack.size())));
+        break;
+    case SbxLONG:
+        result.PutLong(
+            static_cast< sal_Int32 >(
+                DllMgr_call32(proc.proc, address(stack), stack.size())));
+        break;
+    case SbxSINGLE:
+        result.PutSingle(
+            static_cast< float >(
+                DllMgr_callFp(proc.proc, address(stack), stack.size())));
+        break;
+    case SbxDOUBLE:
+        result.PutDouble(
+            DllMgr_callFp(proc.proc, address(stack), stack.size()));
+        break;
+    case SbxSTRING:
+        {
+            char const * s1 = reinterpret_cast< char const * >(
+                DllMgr_call32(proc.proc, address(stack), stack.size()));
+            rtl::OUString s2;
+            SbError e = convert(s1, rtl_str_getLength(s1), &s2);
+            if (e != ERRCODE_NONE) {
+                return e;
+            }
+            result.PutString(String(s2));
+            break;
+        }
+    case SbxOBJECT:
+        //TODO
+        DllMgr_call32(proc.proc, address(stack), stack.size());
+        break;
+    case SbxBOOL:
+        result.PutBool(
+            static_cast< sal_Bool >(
+                DllMgr_call32(proc.proc, address(stack), stack.size())));
+        break;
+    case SbxBYTE:
+        result.PutByte(
+            static_cast< sal_uInt8 >(
+                DllMgr_call32(proc.proc, address(stack), stack.size())));
+        break;
+    default:
+        OSL_ASSERT(false);
+        break;
+    }
+    for (USHORT i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
+        arguments->Get(i)->ResetFlag(SBX_REFERENCE);
+            //TODO: skipped for errors?!?
+    }
+    for (std::vector< UnmarshalData >::iterator i(data.unmarshal.begin());
+         i != data.unmarshal.end(); ++i)
+    {
+        unmarshal(i->variable, i->buffer);
+    }
+    for (std::vector< StringData >::iterator i(data.unmarshalStrings.begin());
+         i != data.unmarshalStrings.end(); ++i)
+    {
+        SbError e = unmarshalString(*i, result);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+    }
+    return ERRCODE_NONE;
+}
+
+SbError getProcData(HMODULE handle, rtl::OUString const & name, ProcData * proc)
+{
+    OSL_ASSERT(proc != 0);
+    if (name.getLength() != 0 && name[0] == '@') { //TODO: "@" vs. "#"???
+        sal_Int32 n = name.copy(1).toInt32(); //TODO: handle bad input
+        if (n <= 0 || n > 0xFFFF) {
+            return ERRCODE_BASIC_BAD_ARGUMENT; //TODO: more specific errcode?
+        }
+        FARPROC p = GetProcAddress(handle, reinterpret_cast< LPCSTR >(n));
+        if (p != 0) {
+            proc->name = rtl::OString(RTL_CONSTASCII_STRINGPARAM("#")) +
+                rtl::OString::valueOf(n);
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+    } else {
+        rtl::OString name8;
+        SbError e = convert(name, &name8);
+        if (e != ERRCODE_NONE) {
+            return e;
+        }
+        FARPROC p = GetProcAddress(handle, name8.getStr());
+        if (p != 0) {
+            proc->name = name8;
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+        sal_Int32 i = name8.indexOf('#');
+        if (i != -1) {
+            name8 = name8.copy(0, i);
+            p = GetProcAddress(handle, name8.getStr());
+            if (p != 0) {
+                proc->name = name8;
+                proc->proc = p;
+                return ERRCODE_NONE;
+            }
+        }
+        rtl::OString real(
+            rtl::OString(RTL_CONSTASCII_STRINGPARAM("_")) + name8);
+        p = GetProcAddress(handle, real.getStr());
+        if (p != 0) {
+            proc->name = real;
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+        real = name8 + rtl::OString(RTL_CONSTASCII_STRINGPARAM("A"));
+        p = GetProcAddress(handle, real.getStr());
+        if (p != 0) {
+            proc->name = real;
+            proc->proc = p;
+            return ERRCODE_NONE;
+        }
+    }
+    return ERRCODE_BASIC_PROC_UNDEFINED;
+}
+
+struct Dll: public salhelper::SimpleReferenceObject {
+private:
+    typedef std::map< rtl::OUString, ProcData > Procs;
+
+    virtual ~Dll();
+
+public:
+    Dll(): handle(0) {}
+
+    SbError getProc(rtl::OUString const & name, ProcData * proc);
+
+    HMODULE handle;
+    Procs procs;
+};
+
+Dll::~Dll() {
+    if (handle != 0 && !FreeLibrary(handle)) {
+        OSL_TRACE("FreeLibrary(%p) failed with %u", handle, GetLastError());
+    }
+}
+
+SbError Dll::getProc(rtl::OUString const & name, ProcData * proc) {
+    Procs::iterator i(procs.find(name));
+    if (i != procs.end()) {
+        *proc = i->second;
+        return ERRCODE_NONE;
+    }
+    SbError e = getProcData(handle, name, proc);
+    if (e == ERRCODE_NONE) {
+        procs.insert(Procs::value_type(name, *proc));
+    }
+    return e;
+}
+
+rtl::OUString fullDllName(rtl::OUString const & name) {
+    rtl::OUString full(name);
+    if (full.indexOf('.') == -1) {
+        full += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".DLL"));
+    }
+    return full;
+}
+
+}
+
+struct SbiDllMgr::Impl: private boost::noncopyable {
+private:
+    typedef std::map< rtl::OUString, rtl::Reference< Dll > > Dlls;
+
+public:
+    Dll * getDll(rtl::OUString const & name);
+
+    Dlls dlls;
+};
+
+Dll * SbiDllMgr::Impl::getDll(rtl::OUString const & name) {
+    Dlls::iterator i(dlls.find(name));
+    if (i == dlls.end()) {
+        i = dlls.insert(Dlls::value_type(name, new Dll)).first;
+        HMODULE h = LoadLibraryW(reinterpret_cast<LPCWSTR>(name.getStr()));
+        if (h == 0) {
+            dlls.erase(i);
+            return 0;
+        }
+        i->second->handle = h;
+    }
+    return i->second.get();
+}
+
+SbError SbiDllMgr::Call(
+    rtl::OUString const & function, rtl::OUString const & library,
+    SbxArray * arguments, SbxVariable & result, bool cdeclConvention)
+{
+    if (cdeclConvention) {
+        return ERRCODE_BASIC_NOT_IMPLEMENTED;
+    }
+    rtl::OUString dllName(fullDllName(library));
+    Dll * dll = impl_->getDll(dllName);
+    if (dll == 0) {
+        return ERRCODE_BASIC_BAD_DLL_LOAD;
+    }
+    ProcData proc;
+    SbError e = dll->getProc(function, &proc);
+    if (e != ERRCODE_NONE) {
+        return e;
+    }
+    return call(dllName, proc, arguments, result);
+}
+
+void SbiDllMgr::FreeDll(rtl::OUString const & library) {
+    impl_->dlls.erase(library);
+}
+
+SbiDllMgr::SbiDllMgr(): impl_(new Impl) {}
+
+SbiDllMgr::~SbiDllMgr() {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/dllmgr.cxx b/basic/source/runtime/dllmgr.cxx
deleted file mode 100644
index 2afaa35..0000000
--- a/basic/source/runtime/dllmgr.cxx
+++ /dev/null
@@ -1,741 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org.  If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-#include "precompiled_basic.hxx"
-#include "sal/config.h"
-
-#include <algorithm>
-#include <cstddef>
-#include <list>
-#include <map>
-#include <vector>
-
-#include "basic/sbx.hxx"
-#include "basic/sbxvar.hxx"
-#include "osl/thread.h"
-#include "rtl/ref.hxx"
-#include "rtl/string.hxx"
-#include "rtl/ustring.hxx"
-#include "salhelper/simplereferenceobject.hxx"
-#include "tools/svwin.h"
-
-#undef max
-
-#include "dllmgr.hxx"
-
-/* Open issues:
-
-   Only 32-bit Windows for now.
-
-   Missing support for functions returning structs (see TODO in call()).
-
-   Missing support for additional data types (64 bit integers, Any, ...; would
-   trigger OSL_ASSERT(false) in various switches).
-
-   It is assumed that the variables passed into SbiDllMgr::Call to represent
-   the arguments and return value have types that exactly match the Declare
-   statement; it would be better if this code had access to the function
-   signature from the Declare statement, so that it could convert the passed
-   variables accordingly.
-*/
-
-#if defined WNT // only 32-bit Windows, actually
-
-extern "C" {
-
-int __stdcall DllMgr_call32(FARPROC, void const * stack, std::size_t size);
-double __stdcall DllMgr_callFp(FARPROC, void const * stack, std::size_t size);
-
-}
-
-namespace {
-
-char * address(std::vector< char > & blob) {
-    return blob.empty() ? 0 : &blob[0];
-}
-
-SbError convert(rtl::OUString const & source, rtl::OString * target) {
-    return
-        source.convertToString(
-            target, osl_getThreadTextEncoding(),
-            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
-             RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
-        ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
-        //TODO: more specific errcode?
-}
-
-SbError convert(char const * source, sal_Int32 length, rtl::OUString * target) {
-    return
-        rtl_convertStringToUString(
-            &target->pData, source, length, osl_getThreadTextEncoding(),
-            (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
-             RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
-             RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))
-        ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
-        //TODO: more specific errcode?
-}
-
-struct UnmarshalData {
-    UnmarshalData(SbxVariable * theVariable, void * theBuffer):
-        variable(theVariable), buffer(theBuffer) {}
-
-    SbxVariable * variable;
-    void * buffer;
-};
-
-struct StringData: public UnmarshalData {
-    StringData(SbxVariable * theVariable, void * theBuffer, bool theSpecial):
-        UnmarshalData(theVariable, theBuffer), special(theSpecial) {}
-
-    bool special;
-};
-
-class MarshalData: private boost::noncopyable {
-public:
-    std::vector< char > * newBlob() {
-        blobs_.push_front(std::vector< char >());
-        return &blobs_.front();
-    }
-
-    std::vector< UnmarshalData > unmarshal;
-
-    std::vector< StringData > unmarshalStrings;
-
-private:
-    std::list< std::vector< char > > blobs_;
-};
-
-std::size_t align(std::size_t address, std::size_t alignment) {
-    // alignment = 2^k for some k >= 0
-    return (address + (alignment - 1)) & ~(alignment - 1);
-}
-
-char * align(
-    std::vector< char > & blob, std::size_t alignment, std::size_t offset,
-    std::size_t add)
-{
-    std::vector< char >::size_type n = blob.size();
-    n = align(n - offset, alignment) + offset; //TODO: overflow in align()
-    blob.resize(n + add); //TODO: overflow
-    return address(blob) + n;
-}
-
-template< typename T > void add(
-    std::vector< char > & blob, T const & data, std::size_t alignment,
-    std::size_t offset)
-{
-    *reinterpret_cast< T * >(align(blob, alignment, offset, sizeof (T))) = data;
-}
-
-std::size_t alignment(SbxVariable * variable) {
-    OSL_ASSERT(variable != 0);
-    if ((variable->GetType() & SbxARRAY) == 0) {
-        switch (variable->GetType()) {
-        case SbxINTEGER:
-            return 2;
-        case SbxLONG:
-        case SbxSINGLE:
-        case SbxSTRING:
-            return 4;
-        case SbxDOUBLE:
-            return 8;
-        case SbxOBJECT:
-            {
-                std::size_t n = 1;
-                SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
-                    GetProperties();
-                for (USHORT i = 0; i < props->Count(); ++i) {
-                    n = std::max(n, alignment(props->Get(i)));
-                }
-                return n;
-            }
-        case SbxBOOL:
-        case SbxBYTE:
-            return 1;
-        default:
-            OSL_ASSERT(false);
-            return 1;
-        }
-    } else {
-        SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
-        int dims = arr->GetDims();
-        std::vector< INT32 > low(dims);
-        for (int i = 0; i < dims; ++i) {
-            INT32 up;
-            arr->GetDim32(i + 1, low[i], up);
-        }
-        return alignment(arr->Get32(&low[0]));
-    }
-}
-
-SbError marshal(
-    bool outer, SbxVariable * variable, bool special,
-    std::vector< char > & blob, std::size_t offset, MarshalData & data);
-
-SbError marshalString(
-    SbxVariable * variable, bool special, MarshalData & data, void ** buffer)
-{
-    OSL_ASSERT(variable != 0 && buffer != 0);
-    rtl::OString str;
-    SbError e = convert(variable->GetString(), &str);
-    if (e != ERRCODE_NONE) {
-        return e;
-    }
-    std::vector< char > * blob = data.newBlob();
-    blob->insert(blob->begin(), str.getStr(), str.getStr() + str.getLength());
-    *buffer = address(*blob);
-    data.unmarshalStrings.push_back(StringData(variable, *buffer, special));
-    return ERRCODE_NONE;
-}
-
-SbError marshalStruct(
-    SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
-    MarshalData & data)
-{
-    OSL_ASSERT(variable != 0);
-    SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
-        GetProperties();
-    for (USHORT i = 0; i < props->Count(); ++i) {
-        SbError e = marshal(false, props->Get(i), false, blob, offset, data);
-        if (e != ERRCODE_NONE) {
-            return e;
-        }
-    }
-    return ERRCODE_NONE;
-}
-
-SbError marshalArray(
-    SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
-    MarshalData & data)
-{
-    OSL_ASSERT(variable != 0);
-    SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
-    int dims = arr->GetDims();
-    std::vector< INT32 > low(dims);
-    std::vector< INT32 > up(dims);
-    for (int i = 0; i < dims; ++i) {
-        arr->GetDim32(i + 1, low[i], up[i]);
-    }
-    for (std::vector< INT32 > idx = low;;) {
-        SbError e = marshal(
-            false, arr->Get32(&idx[0]), false, blob, offset, data);
-        if (e != ERRCODE_NONE) {
-            return e;
-        }
-        int i = dims - 1;
-        while (idx[i] == up[i]) {
-            idx[i] = low[i];
-            if (i == 0) {
-                return ERRCODE_NONE;
-            }
-            --i;
-        }
-        ++idx[i];
-    }
-}
-
-// 8-aligned structs are only 4-aligned on stack, so alignment of members in
-// such structs must take that into account via "offset"
-SbError marshal(
-    bool outer, SbxVariable * variable, bool special,
-    std::vector< char > & blob, std::size_t offset, MarshalData & data)
-{
-    OSL_ASSERT(variable != 0);
-    if ((variable->GetFlags() & SBX_REFERENCE) == 0) {
-        if ((variable->GetType() & SbxARRAY) == 0) {
-            switch (variable->GetType()) {
-            case SbxINTEGER:
-                add(blob, variable->GetInteger(), outer ? 4 : 2, offset);
-                break;
-            case SbxLONG:
-                add(blob, variable->GetLong(), 4, offset);
-                break;
-            case SbxSINGLE:
-                add(blob, variable->GetSingle(), 4, offset);
-                break;
-            case SbxDOUBLE:
-                add(blob, variable->GetDouble(), outer ? 4 : 8, offset);
-                break;
-            case SbxSTRING:
-                {
-                    void * p;
-                    SbError e = marshalString(variable, special, data, &p);
-                    if (e != ERRCODE_NONE) {
-                        return e;
-                    }
-                    add(blob, p, 4, offset);
-                    break;
-                }
-            case SbxOBJECT:
-                {
-                    align(blob, outer ? 4 : alignment(variable), offset, 0);
-                    SbError e = marshalStruct(variable, blob, offset, data);
-                    if (e != ERRCODE_NONE) {
-                        return e;
-                    }
-                    break;
-                }
-            case SbxBOOL:
-                add(blob, variable->GetBool(), outer ? 4 : 1, offset);
-                break;
-            case SbxBYTE:
-                add(blob, variable->GetByte(), outer ? 4 : 1, offset);
-                break;
-            default:
-                OSL_ASSERT(false);
-                break;
-            }
-        } else {
-            SbError e = marshalArray(variable, blob, offset, data);
-            if (e != ERRCODE_NONE) {
-                return e;
-            }
-        }
-    } else {
-        if ((variable->GetType() & SbxARRAY) == 0) {
-            switch (variable->GetType()) {
-            case SbxINTEGER:
-            case SbxLONG:
-            case SbxSINGLE:
-            case SbxDOUBLE:
-            case SbxBOOL:
-            case SbxBYTE:
-                add(blob, variable->data(), 4, offset);
-                break;
-            case SbxSTRING:
-                {
-                    std::vector< char > * blob2 = data.newBlob();
-                    void * p;
-                    SbError e = marshalString(variable, special, data, &p);
-                    if (e != ERRCODE_NONE) {
-                        return e;
-                    }
-                    add(*blob2, p, 4, 0);
-                    add(blob, address(*blob2), 4, offset);
-                    break;
-                }
-            case SbxOBJECT:
-                {
-                    std::vector< char > * blob2 = data.newBlob();
-                    SbError e = marshalStruct(variable, *blob2, 0, data);
-                    if (e != ERRCODE_NONE) {
-                        return e;
-                    }
-                    void * p = address(*blob2);
-                    if (outer) {
-                        data.unmarshal.push_back(UnmarshalData(variable, p));
-                    }
-                    add(blob, p, 4, offset);
-                    break;
-                }
-            default:
-                OSL_ASSERT(false);
-                break;
-            }
-        } else {
-            std::vector< char > * blob2 = data.newBlob();
-            SbError e = marshalArray(variable, *blob2, 0, data);
-            if (e != ERRCODE_NONE) {
-                return e;
-            }
-            void * p = address(*blob2);
-            if (outer) {
-                data.unmarshal.push_back(UnmarshalData(variable, p));
-            }
-            add(blob, p, 4, offset);
-        }
-    }
-    return ERRCODE_NONE;
-}
-
-template< typename T > T read(void const ** pointer) {
-    T const * p = static_cast< T const * >(*pointer);
-    *pointer = static_cast< void const * >(p + 1);
-    return *p;
-}
-
-void const * unmarshal(SbxVariable * variable, void const * data) {
-    OSL_ASSERT(variable != 0);
-    if ((variable->GetType() & SbxARRAY) == 0) {
-        switch (variable->GetType()) {
-        case SbxINTEGER:
-            variable->PutInteger(read< sal_Int16 >(&data));
-            break;
-        case SbxLONG:
-            variable->PutLong(read< sal_Int32 >(&data));
-            break;
-        case SbxSINGLE:
-            variable->PutSingle(read< float >(&data));
-            break;
-        case SbxDOUBLE:
-            variable->PutDouble(read< double >(&data));
-            break;
-        case SbxSTRING:
-            read< char * >(&data); // handled by unmarshalString
-            break;
-        case SbxOBJECT:
-            {
-                data = reinterpret_cast< void const * >(
-                    align(
-                        reinterpret_cast< sal_uIntPtr >(data),
-                        alignment(variable)));
-                SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
-                    GetProperties();
-                for (USHORT i = 0; i < props->Count(); ++i) {
-                    data = unmarshal(props->Get(i), data);
-                }
-                break;
-            }
-        case SbxBOOL:
-            variable->PutBool(read< sal_Bool >(&data));
-            break;
-        case SbxBYTE:
-            variable->PutByte(read< sal_uInt8 >(&data));
-            break;
-        default:
-            OSL_ASSERT(false);
-            break;
-        }
-    } else {
-        SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
-        int dims = arr->GetDims();
-        std::vector< INT32 > low(dims);
-        std::vector< INT32 > up(dims);
-        for (int i = 0; i < dims; ++i) {
-            arr->GetDim32(i + 1, low[i], up[i]);
-        }
-        for (std::vector< INT32 > idx = low;;) {
-            data = unmarshal(arr->Get32(&idx[0]), data);
-            int i = dims - 1;
-            while (idx[i] == up[i]) {
-                idx[i] = low[i];
-                if (i == 0) {
-                    goto done;
-                }
-                --i;
-            }
-            ++idx[i];
-        }
-    done:;
-    }
-    return data;
-}
-
-SbError unmarshalString(StringData const & data, SbxVariable & result) {
-    rtl::OUString str;
-    if (data.buffer != 0) {
-        char const * p = static_cast< char const * >(data.buffer);
-        sal_Int32 len;
-        if (data.special) {
-            len = static_cast< sal_Int32 >(result.GetULong());
-            if (len < 0) { // i.e., DWORD result >= 2^31
-                return ERRCODE_BASIC_BAD_ARGUMENT;
-                    //TODO: more specific errcode?
-            }
-        } else {
-            len = rtl_str_getLength(p);
-        }
-        SbError e = convert(p, len, &str);
-        if (e != ERRCODE_NONE) {
-            return e;
-        }
-    }
-    data.variable->PutString(String(str));
-    return ERRCODE_NONE;
-}
-
-struct ProcData {
-    rtl::OString name;
-    FARPROC proc;
-};
-
-SbError call(
-    rtl::OUString const & dll, ProcData const & proc, SbxArray * arguments,
-    SbxVariable & result)
-{
-    std::vector< char > stack;
-    MarshalData data;
-    // For DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
-    // from kernel32, upon return, filled lpBuffer length is result DWORD, which
-    // requires special handling in unmarshalString; other functions might
-    // require similar treatment, too:
-    bool special =
-        dll.equalsIgnoreAsciiCaseAsciiL(
-            RTL_CONSTASCII_STRINGPARAM("KERNEL32.DLL")) &&
-        (proc.name ==
-         rtl::OString(RTL_CONSTASCII_STRINGPARAM("GetLogicalDriveStringsA")));
-    for (USHORT i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
-        SbError e = marshal(
-            true, arguments->Get(i), special && i == 2, stack, stack.size(),
-            data);
-        if (e != ERRCODE_NONE) {
-            return e;
-        }
-        align(stack, 4, 0, 0);
-    }
-    switch (result.GetType()) {
-    case SbxEMPTY:
-        DllMgr_call32(proc.proc, address(stack), stack.size());
-        break;
-    case SbxINTEGER:
-        result.PutInteger(
-            static_cast< sal_Int16 >(
-                DllMgr_call32(proc.proc, address(stack), stack.size())));
-        break;
-    case SbxLONG:
-        result.PutLong(
-            static_cast< sal_Int32 >(
-                DllMgr_call32(proc.proc, address(stack), stack.size())));
-        break;
-    case SbxSINGLE:
-        result.PutSingle(
-            static_cast< float >(
-                DllMgr_callFp(proc.proc, address(stack), stack.size())));
-        break;
-    case SbxDOUBLE:
-        result.PutDouble(
-            DllMgr_callFp(proc.proc, address(stack), stack.size()));
-        break;
-    case SbxSTRING:
-        {
-            char const * s1 = reinterpret_cast< char const * >(
-                DllMgr_call32(proc.proc, address(stack), stack.size()));
-            rtl::OUString s2;
-            SbError e = convert(s1, rtl_str_getLength(s1), &s2);
-            if (e != ERRCODE_NONE) {
-                return e;
-            }
-            result.PutString(String(s2));
-            break;
-        }
-    case SbxOBJECT:
-        //TODO
-        DllMgr_call32(proc.proc, address(stack), stack.size());
-        break;
-    case SbxBOOL:
-        result.PutBool(
-            static_cast< sal_Bool >(
-                DllMgr_call32(proc.proc, address(stack), stack.size())));
-        break;
-    case SbxBYTE:
-        result.PutByte(
-            static_cast< sal_uInt8 >(
-                DllMgr_call32(proc.proc, address(stack), stack.size())));
-        break;
-    default:
-        OSL_ASSERT(false);
-        break;
-    }
-    for (USHORT i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
-        arguments->Get(i)->ResetFlag(SBX_REFERENCE);
-            //TODO: skipped for errors?!?
-    }
-    for (std::vector< UnmarshalData >::iterator i(data.unmarshal.begin());
-         i != data.unmarshal.end(); ++i)
-    {
-        unmarshal(i->variable, i->buffer);
-    }
-    for (std::vector< StringData >::iterator i(data.unmarshalStrings.begin());
-         i != data.unmarshalStrings.end(); ++i)
-    {
-        SbError e = unmarshalString(*i, result);
-        if (e != ERRCODE_NONE) {
-            return e;
-        }
-    }
-    return ERRCODE_NONE;
-}
-
-SbError getProcData(HMODULE handle, rtl::OUString const & name, ProcData * proc)
-{
-    OSL_ASSERT(proc != 0);
-    if (name.getLength() != 0 && name[0] == '@') { //TODO: "@" vs. "#"???
-        sal_Int32 n = name.copy(1).toInt32(); //TODO: handle bad input
-        if (n <= 0 || n > 0xFFFF) {
-            return ERRCODE_BASIC_BAD_ARGUMENT; //TODO: more specific errcode?
-        }
-        FARPROC p = GetProcAddress(handle, reinterpret_cast< LPCSTR >(n));
-        if (p != 0) {
-            proc->name = rtl::OString(RTL_CONSTASCII_STRINGPARAM("#")) +
-                rtl::OString::valueOf(n);
-            proc->proc = p;
-            return ERRCODE_NONE;
-        }
-    } else {
-        rtl::OString name8;
-        SbError e = convert(name, &name8);
-        if (e != ERRCODE_NONE) {
-            return e;
-        }
-        FARPROC p = GetProcAddress(handle, name8.getStr());
-        if (p != 0) {
-            proc->name = name8;
-            proc->proc = p;
-            return ERRCODE_NONE;
-        }
-        sal_Int32 i = name8.indexOf('#');
-        if (i != -1) {
-            name8 = name8.copy(0, i);
-            p = GetProcAddress(handle, name8.getStr());
-            if (p != 0) {
-                proc->name = name8;
-                proc->proc = p;
-                return ERRCODE_NONE;
-            }
-        }
-        rtl::OString real(
-            rtl::OString(RTL_CONSTASCII_STRINGPARAM("_")) + name8);
-        p = GetProcAddress(handle, real.getStr());
-        if (p != 0) {
-            proc->name = real;
-            proc->proc = p;
-            return ERRCODE_NONE;
-        }
-        real = name8 + rtl::OString(RTL_CONSTASCII_STRINGPARAM("A"));
-        p = GetProcAddress(handle, real.getStr());
-        if (p != 0) {
-            proc->name = real;
-            proc->proc = p;
-            return ERRCODE_NONE;
-        }
-    }
-    return ERRCODE_BASIC_PROC_UNDEFINED;
-}
-
-struct Dll: public salhelper::SimpleReferenceObject {
-private:
-    typedef std::map< rtl::OUString, ProcData > Procs;
-
-    virtual ~Dll();
-
-public:
-    Dll(): handle(0) {}
-
-    SbError getProc(rtl::OUString const & name, ProcData * proc);
-
-    HMODULE handle;
-    Procs procs;
-};
-
-Dll::~Dll() {
-    if (handle != 0 && !FreeLibrary(handle)) {
-        OSL_TRACE("FreeLibrary(%p) failed with %u", handle, GetLastError());
-    }
-}
-
-SbError Dll::getProc(rtl::OUString const & name, ProcData * proc) {
-    Procs::iterator i(procs.find(name));
-    if (i != procs.end()) {
-        *proc = i->second;
-        return ERRCODE_NONE;
-    }
-    SbError e = getProcData(handle, name, proc);
-    if (e == ERRCODE_NONE) {
-        procs.insert(Procs::value_type(name, *proc));
-    }
-    return e;
-}
-
-rtl::OUString fullDllName(rtl::OUString const & name) {
-    rtl::OUString full(name);
-    if (full.indexOf('.') == -1) {
-        full += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".DLL"));
-    }
-    return full;
-}
-
-}
-
-struct SbiDllMgr::Impl: private boost::noncopyable {
-private:
-    typedef std::map< rtl::OUString, rtl::Reference< Dll > > Dlls;
-
-public:
-    Dll * getDll(rtl::OUString const & name);
-
-    Dlls dlls;
-};
-
-Dll * SbiDllMgr::Impl::getDll(rtl::OUString const & name) {
-    Dlls::iterator i(dlls.find(name));
-    if (i == dlls.end()) {
-        i = dlls.insert(Dlls::value_type(name, new Dll)).first;
-        HMODULE h = LoadLibraryW(reinterpret_cast<LPCWSTR>(name.getStr()));
-        if (h == 0) {
-            dlls.erase(i);
-            return 0;
-        }
-        i->second->handle = h;
-    }
-    return i->second.get();
-}
-
-SbError SbiDllMgr::Call(
-    rtl::OUString const & function, rtl::OUString const & library,
-    SbxArray * arguments, SbxVariable & result, bool cdeclConvention)
-{
-    if (cdeclConvention) {
-        return ERRCODE_BASIC_NOT_IMPLEMENTED;
-    }
-    rtl::OUString dllName(fullDllName(library));
-    Dll * dll = impl_->getDll(dllName);
-    if (dll == 0) {
-        return ERRCODE_BASIC_BAD_DLL_LOAD;
-    }
-    ProcData proc;
-    SbError e = dll->getProc(function, &proc);
-    if (e != ERRCODE_NONE) {
-        return e;
-    }
-    return call(dllName, proc, arguments, result);
-}
-
-void SbiDllMgr::FreeDll(rtl::OUString const & library) {
-    impl_->dlls.erase(library);
-}
-
-#else
-
-struct SbiDllMgr::Impl {};
-
-SbError SbiDllMgr::Call(
-    rtl::OUString const &, rtl::OUString const &, SbxArray *, SbxVariable &,
-    bool)
-{
-    return ERRCODE_BASIC_NOT_IMPLEMENTED;
-}
-
-void SbiDllMgr::FreeDll(rtl::OUString const &) {}
-
-#endif
-
-SbiDllMgr::SbiDllMgr(): impl_(new Impl) {}
-
-SbiDllMgr::~SbiDllMgr() {}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/makefile.mk b/basic/source/runtime/makefile.mk
index f2ed111..f8c8103 100644
--- a/basic/source/runtime/makefile.mk
+++ b/basic/source/runtime/makefile.mk
@@ -41,7 +41,7 @@ ENABLE_EXCEPTIONS = TRUE
 
 SLOFILES=	\
     $(SLO)$/basrdll.obj	\
-    $(SLO)$/inputbox.obj	\
+    $(SLO)$/inputbox.obj\
     $(SLO)$/runtime.obj	\
     $(SLO)$/step0.obj	\
     $(SLO)$/step1.obj	\
@@ -50,15 +50,25 @@ SLOFILES=	\
     $(SLO)$/stdobj.obj	\
     $(SLO)$/stdobj1.obj	\
     $(SLO)$/methods.obj	\
-    $(SLO)$/methods1.obj	\
+    $(SLO)$/methods1.obj\
     $(SLO)$/props.obj	\
-    $(SLO)$/ddectrl.obj	\
-    $(SLO)$/dllmgr.obj
+    $(SLO)$/ddectrl.obj
 
+.IF "$(GUI)$(CPU)" == "WNTI"
+SLOFILES+= \
+    $(SLO)$/dllmgr-x86.obj
+.ELIF "$(GUI)$(CPU)" == "WNTX"
+SLOFILES+= \
+    $(SLO)$/dllmgr-x64.obj
+.ELSE
+SLOFILES+= \
+    $(SLO)$/dllmgr-none.obj
+.ENDIF
 .IF "$(GUI)$(COM)$(CPU)" == "WNTMSCI"
-SLOFILES+=	$(SLO)$/wnt.obj
+    $(SLO)$/wnt-x86.obj
 .ELIF "$(GUI)$(COM)$(CPU)" == "WNTGCCI"
-SLOFILES+=	$(SLO)$/wnt-mingw.obj
+SLOFILES+= \
+    $(SLO)$/wnt-mingw.obj
 .ENDIF
 
 # --- Targets -------------------------------------------------------------
diff --git a/basic/source/runtime/wnt-x86.asm b/basic/source/runtime/wnt-x86.asm
new file mode 100644
index 0000000..2a8710e
--- /dev/null
+++ b/basic/source/runtime/wnt-x86.asm
@@ -0,0 +1,56 @@
+;*************************************************************************
+;
+; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+;
+; Copyright 2000, 2010 Oracle and/or its affiliates.
+;
+; OpenOffice.org - a multi-platform office productivity suite
+;
+; This file is part of OpenOffice.org.
+;
+; OpenOffice.org is free software: you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License version 3
+; only, as published by the Free Software Foundation.
+;
+; OpenOffice.org is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU Lesser General Public License version 3 for more details
+; (a copy is included in the LICENSE file that accompanied this code).
+;
+; You should have received a copy of the GNU Lesser General Public License
+; version 3 along with OpenOffice.org.  If not, see
+; <http://www.openoffice.org/license.html>
+; for a copy of the LGPLv3 License.
+;
+;***********************************************************************/
+
+.386
+
+PUBLIC _DllMgr_call32 at 12
+PUBLIC _DllMgr_callFp at 12
+
+_TEXT SEGMENT
+_DllMgr_call32 at 12:
+_DllMgr_callFp at 12:
+    push ebp
+    mov ebp, esp
+    push esi
+    push edi
+    mov ecx, [ebp+16]
+    jecxz $1
+    sub esp, ecx
+    mov edi, esp
+    mov esi, [ebp+12]
+    shr ecx, 2
+    rep movsd
+$1: call DWORD PTR [ebp+8]
+    ; for extra safety, do not trust esp after call (in case the Basic Declare
+    ; signature is wrong):
+    mov edi, [ebp-8]
+    mov esi, [ebp-4]
+    mov esp, ebp
+    pop ebp
+    ret 12
+_TEXT ENDS
+END
diff --git a/basic/source/runtime/wnt.asm b/basic/source/runtime/wnt.asm
deleted file mode 100644
index 2a8710e..0000000
--- a/basic/source/runtime/wnt.asm
+++ /dev/null
@@ -1,56 +0,0 @@
-;*************************************************************************
-;
-; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-;
-; Copyright 2000, 2010 Oracle and/or its affiliates.
-;
-; OpenOffice.org - a multi-platform office productivity suite
-;
-; This file is part of OpenOffice.org.
-;
-; OpenOffice.org is free software: you can redistribute it and/or modify
-; it under the terms of the GNU Lesser General Public License version 3
-; only, as published by the Free Software Foundation.
-;
-; OpenOffice.org is distributed in the hope that it will be useful,
-; but WITHOUT ANY WARRANTY; without even the implied warranty of
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-; GNU Lesser General Public License version 3 for more details
-; (a copy is included in the LICENSE file that accompanied this code).
-;
-; You should have received a copy of the GNU Lesser General Public License
-; version 3 along with OpenOffice.org.  If not, see
-; <http://www.openoffice.org/license.html>
-; for a copy of the LGPLv3 License.
-;
-;***********************************************************************/
-
-.386
-
-PUBLIC _DllMgr_call32 at 12
-PUBLIC _DllMgr_callFp at 12
-
-_TEXT SEGMENT
-_DllMgr_call32 at 12:
-_DllMgr_callFp at 12:
-    push ebp
-    mov ebp, esp
-    push esi
-    push edi
-    mov ecx, [ebp+16]
-    jecxz $1
-    sub esp, ecx
-    mov edi, esp
-    mov esi, [ebp+12]
-    shr ecx, 2
-    rep movsd
-$1: call DWORD PTR [ebp+8]
-    ; for extra safety, do not trust esp after call (in case the Basic Declare
-    ; signature is wrong):
-    mov edi, [ebp-8]
-    mov esi, [ebp-4]
-    mov esp, ebp
-    pop ebp
-    ret 12
-_TEXT ENDS
-END
commit 6947ec9f4f7a2d6dee18e14f962bd8dedc05357a
Author: Tor Lillqvist <tlillqvist at novell.com>
Date:   Mon Jan 24 20:49:24 2011 +0200

    Make Get10ThSec declaration match the implementation

diff --git a/sfx2/source/bastyp/progress.cxx b/sfx2/source/bastyp/progress.cxx
index 9225093..9b27953 100644
--- a/sfx2/source/bastyp/progress.cxx
+++ b/sfx2/source/bastyp/progress.cxx
@@ -113,7 +113,7 @@ struct SfxProgress_Impl
 #define aTypeLibInfo aProgressTypeLibImpl
 
 //========================================================================
-extern ULONG Get10ThSec();
+extern sal_uInt32 Get10ThSec();
 
 // -----------------------------------------------------------------------
 
commit e38dd82dc73245c652dd30bf0d5ec9f3a673befc
Author: Tor Lillqvist <tlillqvist at novell.com>
Date:   Mon Jan 24 20:40:35 2011 +0200

    Use correct LONG_PTR for parameters to IMediaEvent::GetEvent

diff --git a/avmedia/source/win/player.cxx b/avmedia/source/win/player.cxx
index 9b7e8f7..5f45b50 100644
--- a/avmedia/source/win/player.cxx
+++ b/avmedia/source/win/player.cxx
@@ -207,7 +207,8 @@ void Player::setDDrawParams( IDirectDraw* pDDraw, IDirectDrawSurface* pDDrawSurf
 
 long Player::processEvent()
 {   
-    long nCode, nParam1, nParam2;
+    long nCode;
+    LONG_PTR nParam1, nParam2;
     
     if( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) )
     {
commit cf4f81cd71edbda8e79eb68acd79284a95d00236
Author: Tor Lillqvist <tlillqvist at novell.com>
Date:   Mon Jan 24 13:55:50 2011 +0200

    Include the wntmscx build directories

diff --git a/.gitignore b/.gitignore
index 2fc1892..25df106 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,7 @@
 # the build directories
 /*/unxlng??
 /*/unxlng??.pro
-/*/wntmsci??
-/*/wntmsci??.pro
+/*/wntmsc???
+/*/wntmsc???.pro
 /*/unxmac??
 /*/unxmac??.pro


More information about the Libreoffice-commits mailing list