summaryrefslogtreecommitdiff
path: root/sal/osl/w32
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/w32')
-rw-r--r--sal/osl/w32/MAKEFILE.MK118
-rw-r--r--sal/osl/w32/conditn.c141
-rw-r--r--sal/osl/w32/diagnose.c189
-rw-r--r--sal/osl/w32/dllentry.c370
-rw-r--r--sal/osl/w32/file.cxx1194
-rw-r--r--sal/osl/w32/file_dirvol.cxx1867
-rw-r--r--sal/osl/w32/file_error.c151
-rw-r--r--sal/osl/w32/file_error.h51
-rw-r--r--sal/osl/w32/file_url.cxx1143
-rw-r--r--sal/osl/w32/file_url.h96
-rw-r--r--sal/osl/w32/interlck.c142
-rw-r--r--sal/osl/w32/libutil.c54
-rw-r--r--sal/osl/w32/module.cxx480
-rw-r--r--sal/osl/w32/mutex.c206
-rw-r--r--sal/osl/w32/nlsupport.c231
-rw-r--r--sal/osl/w32/path_helper.cxx118
-rw-r--r--sal/osl/w32/path_helper.h70
-rw-r--r--sal/osl/w32/path_helper.hxx118
-rw-r--r--sal/osl/w32/pipe.c636
-rw-r--r--sal/osl/w32/pipeimpl.cxx785
-rw-r--r--sal/osl/w32/pipeimpl.h88
-rw-r--r--sal/osl/w32/process.cxx620
-rw-r--r--sal/osl/w32/procimpl.cxx606
-rw-r--r--sal/osl/w32/procimpl.h47
-rw-r--r--sal/osl/w32/profile.cxx2707
-rw-r--r--sal/osl/w32/salinit.cxx82
-rw-r--r--sal/osl/w32/secimpl.h54
-rw-r--r--sal/osl/w32/security.c991
-rw-r--r--sal/osl/w32/semaphor.c111
-rw-r--r--sal/osl/w32/signal.cxx436
-rw-r--r--sal/osl/w32/socket.cxx2190
-rw-r--r--sal/osl/w32/sockimpl.h108
-rw-r--r--sal/osl/w32/system.h126
-rw-r--r--sal/osl/w32/tempfile.cxx274
-rw-r--r--sal/osl/w32/thread.c593
-rw-r--r--sal/osl/w32/time.c216
-rw-r--r--sal/osl/w32/util.c37
37 files changed, 17446 insertions, 0 deletions
diff --git a/sal/osl/w32/MAKEFILE.MK b/sal/osl/w32/MAKEFILE.MK
new file mode 100644
index 000000000000..4749048847b5
--- /dev/null
+++ b/sal/osl/w32/MAKEFILE.MK
@@ -0,0 +1,118 @@
+#*************************************************************************
+#
+# 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.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sal
+TARGET=cpposl
+USE_LDUMP2=TRUE
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=cont_pch
+PROJECTPCHSOURCE=cont_pch
+
+MULTITHREAD_OBJ=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# Uncomment the following line if you want to compile with -Wall
+# it disables lots of unnecessary warnings comming from the Win32
+# header files (disabling warnings via command line only works with
+# MSVC >= 7.x)
+#
+# CFLAGS+=/wd4668 /wd4711 /wd4201 /wd4710 /wd4619 /wd4514 /wd4820
+
+# --- Files --------------------------------------------------------
+.IF "$(CCNUMVER)" >= "001400000000"
+CDEFS+=-D_CRT_NON_CONFORMING_SWPRINTFS
+.ENDIF
+
+.IF "$(header)" == ""
+
+SLOFILES= $(SLO)$/conditn.obj \
+ $(SLO)$/diagnose.obj \
+ $(SLO)$/dllentry.obj \
+ $(SLO)$/semaphor.obj \
+ $(SLO)$/socket.obj \
+ $(SLO)$/interlck.obj \
+ $(SLO)$/nlsupport.obj\
+ $(SLO)$/mutex.obj \
+ $(SLO)$/thread.obj \
+ $(SLO)$/module.obj \
+ $(SLO)$/process.obj \
+ $(SLO)$/security.obj \
+ $(SLO)$/profile.obj \
+ $(SLO)$/time.obj \
+ $(SLO)$/signal.obj \
+ $(SLO)$/pipeimpl.obj \
+ $(SLO)$/pipe.obj \
+ $(SLO)$/util.obj \
+ $(SLO)$/file.obj\
+ $(SLO)$/file_dirvol.obj\
+ $(SLO)$/file_error.obj\
+ $(SLO)$/file_url.obj\
+ $(SLO)$/tempfile.obj\
+ $(SLO)$/path_helper.obj\
+ $(SLO)$/procimpl.obj \
+ $(SLO)$/salinit.obj
+
+OBJFILES= $(OBJ)$/conditn.obj \
+ $(OBJ)$/diagnose.obj \
+ $(OBJ)$/libutil.obj \
+ $(OBJ)$/semaphor.obj \
+ $(OBJ)$/socket.obj \
+ $(OBJ)$/interlck.obj \
+ $(OBJ)$/nlsupport.obj\
+ $(OBJ)$/mutex.obj \
+ $(OBJ)$/thread.obj \
+ $(OBJ)$/module.obj \
+ $(OBJ)$/process.obj \
+ $(OBJ)$/security.obj \
+ $(OBJ)$/profile.obj \
+ $(OBJ)$/time.obj \
+ $(OBJ)$/signal.obj \
+ $(OBJ)$/pipeimpl.obj \
+ $(OBJ)$/pipe.obj \
+ $(OBJ)$/util.obj \
+ $(OBJ)$/file.obj\
+ $(OBJ)$/file_dirvol.obj\
+ $(OBJ)$/file_error.obj\
+ $(OBJ)$/file_url.obj\
+ $(OBJ)$/tempfile.obj\
+ $(OBJ)$/path_helper.obj\
+ $(OBJ)$/procimpl.obj \
+ $(OBJ)$/salinit.obj
+
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+
diff --git a/sal/osl/w32/conditn.c b/sal/osl/w32/conditn.c
new file mode 100644
index 000000000000..1a382af89fcf
--- /dev/null
+++ b/sal/osl/w32/conditn.c
@@ -0,0 +1,141 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include <osl/conditn.h>
+#include <osl/diagnose.h>
+#include <osl/time.h>
+
+/*
+ under WIN32, we use the void* oslCondition
+ as a WIN32 HANDLE (which is also a 32-bit value)
+*/
+
+/*****************************************************************************/
+/* osl_createCondition */
+/*****************************************************************************/
+oslCondition SAL_CALL osl_createCondition(void)
+{
+ oslCondition Condition;
+
+ Condition= (oslCondition)CreateEvent(0, /* no security */
+ sal_True, /* manual reset */
+ sal_False, /* initial state not signaled */
+ 0); /* automatic name */
+
+ return Condition;
+
+}
+
+/*****************************************************************************/
+/* osl_destroyCondition */
+/*****************************************************************************/
+void SAL_CALL osl_destroyCondition(oslCondition Condition)
+{
+ if(Condition)
+ {
+ OSL_VERIFY(CloseHandle(Condition));
+ }
+}
+
+/*****************************************************************************/
+/* osl_setCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return (sal_Bool)(SetEvent((HANDLE)Condition) != FALSE);
+}
+
+/*****************************************************************************/
+/* osl_resetCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_resetCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return (sal_Bool)(ResetEvent((HANDLE)Condition) != FALSE);
+}
+
+/*****************************************************************************/
+/* osl_waitCondition */
+/*****************************************************************************/
+oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition,
+ const TimeValue* pTimeout)
+{
+ DWORD timeout;
+
+ OSL_ASSERT(Condition);
+
+ if (pTimeout)
+ timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L;
+ else
+ timeout = INFINITE;
+
+ /* It's necessary to process SendMessage calls to the current thread to give other threads
+ access to COM objects instatiated in this thread */
+
+ while ( 1 )
+ {
+ /* Only wake up if a SendMessage call to the threads message loop is detected */
+ switch( MsgWaitForMultipleObjects( 1, (HANDLE *)(&Condition), FALSE, timeout, QS_SENDMESSAGE ) )
+ {
+ case WAIT_OBJECT_0 + 1:
+ {
+ MSG msg;
+
+ /* We Must not dispatch the message. PM_NOREMOVE leaves the message queue untouched
+ but dispatches SendMessage calls automatically */
+
+ PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );
+ }
+ break;
+
+ case WAIT_OBJECT_0:
+ return (osl_cond_result_ok);
+
+ case WAIT_TIMEOUT:
+ return (osl_cond_result_timeout);
+
+ default:
+ return (osl_cond_result_error);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* osl_checkCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_checkCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return (sal_Bool)(WaitForSingleObject((HANDLE)Condition, 0) == WAIT_OBJECT_0);
+}
+
diff --git a/sal/osl/w32/diagnose.c b/sal/osl/w32/diagnose.c
new file mode 100644
index 000000000000..239628abcecc
--- /dev/null
+++ b/sal/osl/w32/diagnose.c
@@ -0,0 +1,189 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#define NO_DEBUG_CRT
+
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+
+#define NO_DEBUG_CRT
+
+static pfunc_osl_printDebugMessage _pPrintDebugMessage = NULL;
+static pfunc_osl_printDetailedDebugMessage _pPrintDetailedDebugMessage = NULL;
+
+pfunc_osl_printDebugMessage SAL_CALL osl_setDebugMessageFunc( pfunc_osl_printDebugMessage pNewFunc )
+{
+ pfunc_osl_printDebugMessage pOldFunc = _pPrintDebugMessage;
+ _pPrintDebugMessage = pNewFunc;
+
+ return pOldFunc;
+}
+
+pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc( pfunc_osl_printDetailedDebugMessage pNewFunc )
+{
+ pfunc_osl_printDetailedDebugMessage pOldFunc = _pPrintDetailedDebugMessage;
+ _pPrintDetailedDebugMessage = pNewFunc;
+ return pOldFunc;
+}
+
+/*
+ Trace output
+*/
+
+void SAL_CALL osl_breakDebug(void)
+{
+ DebugBreak();
+}
+
+
+
+/* Uncomment this define to get profiling time output */
+/* #define OSL_PROFILING */
+/* comment this define to stop output thread identifier*/
+#define OSL_TRACE_THREAD 1
+void SAL_CALL osl_trace(const sal_Char* lpszFormat, ...)
+{
+ va_list args;
+ int written = 0;
+
+ va_start(args, lpszFormat);
+
+#if defined(OSL_PROFILING)
+ fprintf(stderr, "time : %06lu : ", osl_getGlobalTimer() );
+#else
+#if defined(OSL_TRACE_THREAD)
+ fprintf(stderr,"Thread: %6d :",osl_getThreadIdentifier(NULL));
+#else
+ fprintf(stderr,"Trace Message : ");
+#endif
+#endif
+
+ if ( IsDebuggerPresent() )
+ {
+ sal_Char szMessage[512];
+ szMessage[sizeof(szMessage)-1] = 0;
+ written = _vsnprintf( szMessage, sizeof(szMessage) - 2, lpszFormat, args );
+ if ( written == -1 )
+ written = sizeof(szMessage) - 2;
+ szMessage[ written++ ] = '\n';
+ szMessage[ written ] = 0;
+ OutputDebugString( szMessage );
+ }
+
+ vfprintf(stderr,lpszFormat, args);
+
+ fprintf(stderr,"\n");
+
+ fflush(stderr);
+
+ va_end(args);
+}
+
+sal_Bool SAL_CALL osl_assertFailedLine(const sal_Char* pszFileName, sal_Int32 nLine, const sal_Char* pszMessage)
+{
+#ifndef NO_DEBUG_CRT
+ return (_CrtDbgReport(_CRT_ASSERT, pszFileName, nLine, NULL, pszMessage));
+#else
+ HWND hWndParent;
+ UINT nFlags;
+ int nCode;
+
+ /* get app name or NULL if unknown (don't call assert) */
+ LPCSTR lpszAppName = "Error";
+ sal_Char szMessage[512];
+
+ /* format message into buffer */
+ szMessage[sizeof(szMessage)-1] = '\0'; /* zero terminate always */
+ _snprintf(szMessage, sizeof(szMessage)-1, "%s: File %hs, Line %d\n:%s\n",
+ lpszAppName, pszFileName, nLine, pszMessage);
+
+ OutputDebugString(szMessage);
+
+ if ( _pPrintDetailedDebugMessage )
+ _pPrintDetailedDebugMessage( pszFileName, nLine, pszMessage );
+ else if ( _pPrintDebugMessage )
+ _pPrintDebugMessage( szMessage );
+ else if ( !getenv( "DISABLE_SAL_DBGBOX" ) )
+ {
+ TCHAR szBoxMessage[1024];
+
+ /* active popup window for the current thread */
+ hWndParent = GetActiveWindow();
+ if (hWndParent != NULL)
+ hWndParent = GetLastActivePopup(hWndParent);
+
+ /* set message box flags */
+ nFlags = MB_TASKMODAL | MB_ICONWARNING | MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_SETFOREGROUND;
+ if (hWndParent == NULL)
+ nFlags |= MB_SERVICE_NOTIFICATION;
+
+ /* display the assert */
+
+ szBoxMessage[sizeof(szBoxMessage)-1] = 0;
+ _snprintf(szBoxMessage, sizeof(szBoxMessage)-1, "%s\n( Yes=Abort / No=Ignore / Cancel=Debugger )",
+ szMessage);
+
+ nCode = MessageBox(hWndParent, szBoxMessage, "Assertion Failed!", nFlags);
+
+ if (nCode == IDYES)
+ FatalExit(-1);
+
+ if (nCode == IDNO)
+ return sal_False; /* ignore */
+
+ if (nCode == IDCANCEL)
+ return sal_True; /* will cause oslDebugBreak */
+ }
+#endif /* NO_DEBUG_CRT */
+ return sal_False; /* not shure, not care */
+}
+
+sal_Int32 SAL_CALL osl_reportError(sal_uInt32 nType, const sal_Char* pszMessage)
+{
+ UINT nFlags;
+ int nDisposition;
+
+ // active popup window for the current thread
+ HWND hWndParent = GetActiveWindow();
+ if (hWndParent != NULL)
+ hWndParent = GetLastActivePopup(hWndParent);
+
+ nType = nType; /* avoid warnings */
+
+ /* set message box flags */
+ nFlags = MB_TASKMODAL | MB_ICONERROR | MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_SETFOREGROUND;
+ if (hWndParent == NULL)
+ nFlags |= MB_SERVICE_NOTIFICATION;
+
+ // display the assert
+ nDisposition = MessageBox(hWndParent, pszMessage, "Exception!", nFlags);
+
+ return nDisposition;
+}
+
diff --git a/sal/osl/w32/dllentry.c b/sal/osl/w32/dllentry.c
new file mode 100644
index 000000000000..b6a21d6c2724
--- /dev/null
+++ b/sal/osl/w32/dllentry.c
@@ -0,0 +1,370 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#include <tlhelp32.h>
+#include <systools/win32/uwinapi.h>
+#include <winsock.h>
+#include <osl/diagnose.h>
+#include <sal/types.h>
+#include <float.h>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <sal/types.h>
+
+//------------------------------------------------------------------------------
+// externals
+//------------------------------------------------------------------------------
+
+extern DWORD g_dwTLSTextEncodingIndex;
+extern void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void);
+extern CRITICAL_SECTION g_ThreadKeyListCS;
+extern oslMutex g_Mutex;
+extern oslMutex g_CurrentDirectoryMutex;
+
+extern void rtl_locale_fini (void);
+extern void rtl_memory_fini (void);
+extern void rtl_cache_fini (void);
+extern void rtl_arena_fini (void);
+
+#ifdef __MINGW32__
+
+typedef void (*func_ptr) (void);
+extern func_ptr __CTOR_LIST__[];
+extern func_ptr __DTOR_LIST__[];
+
+static void do_startup(void);
+static void do_cleanup(void);
+
+#else
+
+/*
+This is needed because DllMain is called after static constructors. A DLL's
+startup and shutdown sequence looks like this:
+
+_pRawDllMain()
+_CRT_INIT()
+DllMain()
+....
+DllMain()
+_CRT_INIT()
+_pRawDllMain()
+
+*/
+
+static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved );
+extern BOOL (WINAPI *_pRawDllMain)(HANDLE, DWORD, LPVOID) = _RawDllMain;
+
+#endif
+
+//------------------------------------------------------------------------------
+// globales
+//------------------------------------------------------------------------------
+
+DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; // remember plattform
+
+//------------------------------------------------------------------------------
+// DllMain
+//------------------------------------------------------------------------------
+#ifdef _M_IX86
+int osl_isSingleCPU = 0;
+#endif
+
+#ifdef __MINGW32__
+
+void
+__do_global_dtors (void)
+{
+ static func_ptr *p = __DTOR_LIST__ + 1;
+
+ /*
+ * Call each destructor in the destructor list until a null pointer
+ * is encountered.
+ */
+ while (*p)
+ {
+ (*(p)) ();
+ p++;
+ }
+}
+
+void
+__do_global_ctors (void)
+{
+ unsigned long nptrs = (unsigned long) __CTOR_LIST__[0];
+ unsigned i;
+
+ /*
+ * If the first entry in the constructor list is -1 then the list
+ * is terminated with a null entry. Otherwise the first entry was
+ * the number of pointers in the list.
+ */
+ if (nptrs == -1)
+ {
+ for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++)
+ ;
+ }
+
+ /*
+ * Go through the list backwards calling constructors.
+ */
+ for (i = nptrs; i >= 1; i--)
+ {
+ __CTOR_LIST__[i] ();
+ }
+
+ /*
+ * Register the destructors for processing on exit.
+ */
+ atexit (__do_global_dtors);
+}
+
+static int initialized = 0;
+
+void
+__main (void)
+{
+ if (!initialized)
+ {
+ initialized = 1;
+ do_startup();
+ __do_global_ctors ();
+ }
+}
+
+static void do_startup( void )
+{
+#else
+static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ (void)hinstDLL; /* avoid warnings */
+ (void)lpvReserved; /* avoid warnings */
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+#endif
+ OSVERSIONINFO aInfo;
+
+#ifdef _M_IX86
+ SYSTEM_INFO SystemInfo;
+
+ GetSystemInfo(&SystemInfo);
+
+ /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system
+ *
+ * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount()
+ * comes with a cost and is especially expensive on pre HT x86 single processor
+ * systems, where it isn't needed at all.
+ */
+ if ( SystemInfo.dwNumberOfProcessors == 1 ) {
+ osl_isSingleCPU = 1;
+ }
+#endif
+ /* Suppress file error messages from system like "Floppy A: not inserted" */
+ SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
+
+ /* initialize global mutex */
+ g_Mutex = osl_createMutex();
+
+ /* initialize "current directory" mutex */
+ g_CurrentDirectoryMutex = osl_createMutex();
+
+
+ /* initialize Win9x unicode functions */
+ aInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+
+ if ( GetVersionEx(&aInfo) )
+ g_dwPlatformId = aInfo.dwPlatformId;
+
+ g_dwTLSTextEncodingIndex = TlsAlloc();
+ InitializeCriticalSection( &g_ThreadKeyListCS );
+
+ //We disable floating point exceptions. This is the usual state at program startup
+ //but on Windows 98 and ME this is not always the case.
+ _control87(_MCW_EM, _MCW_EM);
+#ifdef __MINGW32__
+ atexit(do_cleanup);
+}
+
+void do_cleanup( void )
+{
+#else
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+#endif
+
+ WSACleanup( );
+
+ TlsFree( g_dwTLSTextEncodingIndex );
+ DeleteCriticalSection( &g_ThreadKeyListCS );
+
+ osl_destroyMutex( g_Mutex );
+
+ osl_destroyMutex( g_CurrentDirectoryMutex );
+
+#ifndef __MINGW32__
+
+ /*
+
+ On a product build memory management finalization might
+ cause a crash without assertion (assertions off) if heap is
+ corrupted. But a crash report won't help here because at
+ this point all other threads have been terminated and only
+ ntdll is on the stack. No chance to find the reason for the
+ corrupted heap if so.
+
+ So annoying the user with a crash report is completly useless.
+
+ */
+
+#ifndef DBG_UTIL
+ __try
+#endif
+ {
+ /* cleanup locale hashtable */
+ rtl_locale_fini();
+
+ /* finalize memory management */
+ rtl_memory_fini();
+ rtl_cache_fini();
+ rtl_arena_fini();
+ }
+#ifndef DBG_UTIL
+ __except( EXCEPTION_EXECUTE_HANDLER )
+ {
+ }
+#endif
+ break;
+ }
+
+ return TRUE;
+#endif
+}
+
+static DWORD GetParentProcessId()
+{
+ DWORD dwParentProcessId = 0;
+ HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+
+ if ( IsValidHandle( hSnapshot ) )
+ {
+ PROCESSENTRY32 pe;
+ BOOL fSuccess;
+
+ ZeroMemory( &pe, sizeof(pe) );
+ pe.dwSize = sizeof(pe);
+ fSuccess = Process32First( hSnapshot, &pe );
+
+ while( fSuccess )
+ {
+ if ( GetCurrentProcessId() == pe.th32ProcessID )
+ {
+ dwParentProcessId = pe.th32ParentProcessID;
+ break;
+ }
+
+ fSuccess = Process32Next( hSnapshot, &pe );
+ }
+
+ CloseHandle( hSnapshot );
+ }
+
+ return dwParentProcessId;
+}
+
+static DWORD WINAPI ParentMonitorThreadProc( LPVOID lpParam )
+{
+ DWORD dwParentProcessId = (DWORD)lpParam;
+
+ HANDLE hParentProcess = OpenProcess( SYNCHRONIZE, FALSE, dwParentProcessId );
+ if ( IsValidHandle( hParentProcess ) )
+ {
+ if ( WAIT_OBJECT_0 == WaitForSingleObject( hParentProcess, INFINITE ) )
+ {
+ TerminateProcess( GetCurrentProcess(), 0 );
+ }
+ CloseHandle( hParentProcess );
+ }
+ return 0;
+}
+
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ (void)hinstDLL; /* avoid warning */
+ (void)lpvReserved; /* avoid warning */
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ TCHAR szBuffer[64];
+
+ // This code will attach the process to it's parent process
+ // if the parent process had set the environment variable.
+ // The corresponding code (setting the environment variable)
+ // is is desktop/win32/source/officeloader.cxx
+
+
+ DWORD dwResult = GetEnvironmentVariable( "ATTACHED_PARENT_PROCESSID", szBuffer, sizeof(szBuffer) );
+
+ if ( dwResult && dwResult < sizeof(szBuffer) )
+ {
+ DWORD dwThreadId = 0;
+
+ DWORD dwParentProcessId = (DWORD)atol( szBuffer );
+
+ if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId )
+ {
+ // No error check, it works or it does not
+ // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx
+ CreateThread( NULL, 0, ParentMonitorThreadProc, (LPVOID)dwParentProcessId, 0, &dwThreadId ); //
+ }
+ }
+
+ return TRUE;
+ }
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ _osl_callThreadKeyCallbackOnThreadDetach( );
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/sal/osl/w32/file.cxx b/sal/osl/w32/file.cxx
new file mode 100644
index 000000000000..7728189387cd
--- /dev/null
+++ b/sal/osl/w32/file.cxx
@@ -0,0 +1,1194 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT 0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "osl/file.hxx"
+
+#include "file_url.h"
+#include "file_error.h"
+
+#include "osl/diagnose.h"
+#include "rtl/alloc.h"
+#include "rtl/byteseq.h"
+#include "rtl/ustring.hxx"
+
+#include <stdio.h>
+#include <tchar.h>
+
+#ifdef __MINGW32__
+#include <wchar.h>
+#include <ctype.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+
+#ifdef max /* conflict w/ std::numeric_limits<T>::max() */
+#undef max
+#endif
+#ifdef min
+#undef min
+#endif
+
+//##################################################################
+// File handle implementation
+//##################################################################
+struct FileHandle_Impl
+{
+ CRITICAL_SECTION m_mutex;
+ HANDLE m_hFile;
+
+ /** State
+ */
+ enum StateBits
+ {
+ STATE_SEEKABLE = 1, /* open() sets, iff regular file */
+ STATE_READABLE = 2, /* open() sets, read() requires */
+ STATE_WRITEABLE = 4, /* open() sets, write() requires */
+ STATE_MODIFIED = 8 /* write() sets, flush() resets */
+ };
+ int m_state;
+
+ sal_uInt64 m_size; /* file size */
+ LONGLONG m_offset; /* physical offset from begin of file */
+ LONGLONG m_filepos; /* logical offset from begin of file */
+
+ LONGLONG m_bufptr; /* buffer offset from begin of file */
+ SIZE_T m_buflen; /* buffer filled [0, m_bufsiz - 1] */
+
+ SIZE_T m_bufsiz;
+ sal_uInt8 * m_buffer;
+
+ explicit FileHandle_Impl (HANDLE hFile);
+ ~FileHandle_Impl();
+
+ static void* operator new(size_t n);
+ static void operator delete(void * p, size_t);
+ static SIZE_T getpagesize();
+
+ sal_uInt64 getPos() const;
+ oslFileError setPos (sal_uInt64 uPos);
+
+ sal_uInt64 getSize() const;
+ oslFileError setSize (sal_uInt64 uPos);
+
+ oslFileError readAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ DWORD nBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ DWORD nBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readFileAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeFileAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readLineAt (
+ LONGLONG nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ SIZE_T * pnOffset,
+ const void * pBuffer,
+ SIZE_T nBytes);
+
+ oslFileError syncFile();
+
+ /** Buffer cache / allocator.
+ */
+ class Allocator
+ {
+ rtl_cache_type * m_cache;
+ SIZE_T m_bufsiz;
+
+ Allocator (Allocator const &);
+ Allocator & operator= (Allocator const &);
+
+ public:
+ static Allocator & get();
+
+ void allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize);
+ void deallocate (sal_uInt8 * pBuffer);
+
+ protected:
+ Allocator();
+ ~Allocator();
+ };
+
+ /** Guard.
+ */
+ class Guard
+ {
+ LPCRITICAL_SECTION m_mutex;
+
+ public:
+ explicit Guard(LPCRITICAL_SECTION pMutex);
+ ~Guard();
+ };
+};
+
+FileHandle_Impl::Allocator &
+FileHandle_Impl::Allocator::get()
+{
+ static Allocator g_aBufferAllocator;
+ return g_aBufferAllocator;
+}
+
+FileHandle_Impl::Allocator::Allocator()
+ : m_cache (0),
+ m_bufsiz (0)
+{
+ SIZE_T const pagesize = FileHandle_Impl::getpagesize();
+ m_cache = rtl_cache_create (
+ "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
+ if (0 != m_cache)
+ m_bufsiz = pagesize;
+}
+
+FileHandle_Impl::Allocator::~Allocator()
+{
+ rtl_cache_destroy(m_cache), m_cache = 0;
+}
+
+void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize)
+{
+ OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation");
+ *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
+}
+
+void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
+{
+ if (0 != pBuffer)
+ rtl_cache_free (m_cache, pBuffer);
+}
+
+FileHandle_Impl::Guard::Guard(LPCRITICAL_SECTION pMutex)
+ : m_mutex (pMutex)
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
+ ::EnterCriticalSection (m_mutex);
+}
+FileHandle_Impl::Guard::~Guard()
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
+ ::LeaveCriticalSection (m_mutex);
+}
+
+FileHandle_Impl::FileHandle_Impl(HANDLE hFile)
+ : m_hFile (hFile),
+ m_state (STATE_READABLE | STATE_WRITEABLE),
+ m_size (0),
+ m_offset (0),
+ m_filepos (0),
+ m_bufptr (-1),
+ m_buflen (0),
+ m_bufsiz (0),
+ m_buffer (0)
+{
+ ::InitializeCriticalSection (&m_mutex);
+ Allocator::get().allocate (&m_buffer, &m_bufsiz);
+ if (m_buffer != 0)
+ memset (m_buffer, 0, m_bufsiz);
+}
+
+FileHandle_Impl::~FileHandle_Impl()
+{
+ Allocator::get().deallocate (m_buffer), m_buffer = 0;
+ ::DeleteCriticalSection (&m_mutex);
+}
+
+void * FileHandle_Impl::operator new(size_t n)
+{
+ return rtl_allocateMemory(n);
+}
+
+void FileHandle_Impl::operator delete(void * p, size_t)
+{
+ rtl_freeMemory(p);
+}
+
+SIZE_T FileHandle_Impl::getpagesize()
+{
+ SYSTEM_INFO info;
+ ::GetSystemInfo (&info);
+ return sal::static_int_cast< SIZE_T >(info.dwPageSize);
+}
+
+sal_uInt64 FileHandle_Impl::getPos() const
+{
+ return sal::static_int_cast< sal_uInt64 >(m_filepos);
+}
+
+oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
+{
+ m_filepos = sal::static_int_cast< LONGLONG >(uPos);
+ return osl_File_E_None;
+}
+
+sal_uInt64 FileHandle_Impl::getSize() const
+{
+ LONGLONG bufend = std::max((LONGLONG)(0), m_bufptr) + m_buflen;
+ return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
+}
+
+oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
+{
+ LARGE_INTEGER nDstPos; nDstPos.QuadPart = sal::static_int_cast< LONGLONG >(uSize);
+ if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+
+ if (!::SetEndOfFile(m_hFile))
+ return oslTranslateFileError( GetLastError() );
+ m_size = uSize;
+
+ nDstPos.QuadPart = m_offset;
+ if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ DWORD nBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::readAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND(m_state & STATE_READABLE, "FileHandle_Impl::readAt(): not readable");
+ if (!(m_state & STATE_READABLE))
+ return osl_File_E_BADF;
+
+ if (nOffset != m_offset)
+ {
+ LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
+ if (!::SetFilePointerEx(m_hFile, liOffset, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+ m_offset = nOffset;
+ }
+
+ DWORD dwDone = 0;
+ if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ m_offset += dwDone;
+
+ *pBytesRead = dwDone;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ DWORD nBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::writeAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND(m_state & STATE_WRITEABLE, "FileHandle_Impl::writeAt(): not writeable");
+ if (!(m_state & STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ if (nOffset != m_offset)
+ {
+ LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
+ if (!::SetFilePointerEx (m_hFile, liOffset, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+ m_offset = nOffset;
+ }
+
+ DWORD dwDone = 0;
+ if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ m_offset += dwDone;
+
+ m_size = std::max(m_size, sal::static_int_cast< sal_uInt64 >(m_offset));
+
+ *pBytesWritten = dwDone;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readFileAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
+ if (g_limit_dword < uBytesRequested)
+ return osl_File_E_OVERFLOW;
+ DWORD nBytesRequested = sal::static_int_cast< DWORD >(uBytesRequested);
+
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ DWORD dwDone = 0;
+ if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ *pBytesRead = dwDone;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
+ }
+ else
+ {
+ sal_uInt8 * buffer = static_cast< sal_uInt8* >(pBuffer);
+ for (*pBytesRead = 0; nBytesRequested > 0; )
+ {
+ LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ SIZE_T const bufpos = (nOffset % m_bufsiz);
+
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesRequested >= m_bufsiz)
+ {
+ // buffer too small, read through from file
+ sal_uInt64 uDone = 0;
+ result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ nBytesRequested -= sal::static_int_cast< DWORD >(uDone), *pBytesRead += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+ if (bufpos >= m_buflen)
+ {
+ // end of file
+ return osl_File_E_None;
+ }
+
+ SIZE_T const bytes = std::min(m_buflen - bufpos, nBytesRequested);
+ memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
+ nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::writeFileAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
+ if (g_limit_dword < uBytesToWrite)
+ return osl_File_E_OVERFLOW;
+ DWORD nBytesToWrite = sal::static_int_cast< DWORD >(uBytesToWrite);
+
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ DWORD dwDone = 0;
+ if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ *pBytesWritten = dwDone;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return writeAt(nOffset, pBuffer, nBytesToWrite, pBytesWritten);
+ }
+ else
+ {
+ sal_uInt8 const * buffer = static_cast< sal_uInt8 const* >(pBuffer);
+ for (*pBytesWritten = 0; nBytesToWrite > 0; )
+ {
+ LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ SIZE_T const bufpos = (nOffset % m_bufsiz);
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesToWrite >= m_bufsiz)
+ {
+ // buffer too small, write through to file
+ sal_uInt64 uDone = 0;
+ result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != nBytesToWrite)
+ return osl_File_E_IO;
+
+ nBytesToWrite -= sal::static_int_cast< DWORD >(uDone), *pBytesWritten += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+
+ SIZE_T const bytes = std::min(m_bufsiz - bufpos, nBytesToWrite);
+ memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
+ nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
+
+ m_buflen = std::max(m_buflen, bufpos + bytes);
+ m_state |= STATE_MODIFIED;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::readLineAt (
+ LONGLONG nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead)
+{
+ oslFileError result = osl_File_E_None;
+
+ LONGLONG bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* flush current buffer */
+ result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+
+ static int const LINE_STATE_BEGIN = 0;
+ static int const LINE_STATE_CR = 1;
+ static int const LINE_STATE_LF = 2;
+
+ SIZE_T bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos, dstpos = 0;
+ int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
+
+ for ( ; state != LINE_STATE_LF; )
+ {
+ if (curpos >= m_buflen)
+ {
+ /* buffer examined */
+ if (0 < (curpos - bufpos))
+ {
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+
+ bufptr = nOffset / m_bufsiz * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+
+ bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos;
+ if (bufpos >= m_buflen)
+ break;
+ }
+ switch (state)
+ {
+ case LINE_STATE_CR:
+ state = LINE_STATE_LF;
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* CRLF */
+ /* eat current char */
+ curpos++;
+ break;
+ default: /* single CR */
+ /* keep current char */
+ break;
+ }
+ break;
+ default:
+ /* determine next state */
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* single LF */
+ state = LINE_STATE_LF;
+ break;
+ case 0x0D: /* CR */
+ state = LINE_STATE_CR;
+ break;
+ default: /* advance to next char */
+ curpos++;
+ break;
+ }
+ if (state != LINE_STATE_BEGIN)
+ {
+ /* store (and eat) the newline char */
+ m_buffer[curpos] = 0x0A, curpos++;
+
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+ break;
+ }
+ }
+
+ result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
+ if (result != osl_File_E_None)
+ return (result);
+ if (0 < dstpos)
+ return osl_File_E_None;
+ if (bufpos >= m_buflen)
+ return osl_File_E_AGAIN;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ SIZE_T * pnOffset,
+ const void * pBuffer,
+ SIZE_T nBytes)
+{
+ sal_Int32 nElements = *pnOffset + nBytes;
+ if (!*ppSequence)
+ {
+ /* construct sequence */
+ rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
+ }
+ else if (nElements != (*ppSequence)->nElements)
+ {
+ /* resize sequence */
+ rtl_byte_sequence_realloc(ppSequence, nElements);
+ }
+ if (*ppSequence != 0)
+ {
+ /* fill sequence */
+ memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
+ }
+ return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
+}
+
+oslFileError FileHandle_Impl::syncFile()
+{
+ oslFileError result = osl_File_E_None;
+ if (m_state & STATE_MODIFIED)
+ {
+ sal_uInt64 uDone = 0;
+ result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != m_buflen)
+ return osl_File_E_IO;
+ m_state &= ~STATE_MODIFIED;
+ }
+ return (result);
+}
+
+//##################################################################
+// File I/O functions
+//##################################################################
+
+extern "C" oslFileHandle
+SAL_CALL osl_createFileHandleFromOSHandle (
+ HANDLE hFile,
+ sal_uInt32 uFlags)
+{
+ if ( !IsValidHandle(hFile) )
+ return 0; // EINVAL
+
+ FileHandle_Impl * pImpl = new FileHandle_Impl(hFile);
+ if (pImpl == 0)
+ {
+ // cleanup and fail
+ (void) ::CloseHandle(hFile);
+ return 0; // ENOMEM
+ }
+
+ /* check for regular file */
+ if (FILE_TYPE_DISK == GetFileType(hFile))
+ {
+ /* mark seekable */
+ pImpl->m_state |= FileHandle_Impl::STATE_SEEKABLE;
+
+ /* init current size */
+ LARGE_INTEGER uSize = { 0, 0 };
+ (void) ::GetFileSizeEx(hFile, &uSize);
+ pImpl->m_size = (sal::static_int_cast<sal_uInt64>(uSize.HighPart) << 32) + uSize.LowPart;
+ }
+
+ if (!(uFlags & osl_File_OpenFlag_Read))
+ pImpl->m_state &= ~FileHandle_Impl::STATE_READABLE;
+ if (!(uFlags & osl_File_OpenFlag_Write))
+ pImpl->m_state &= ~FileHandle_Impl::STATE_WRITEABLE;
+
+ OSL_POSTCOND(
+ (uFlags & osl_File_OpenFlag_Read) || (uFlags & osl_File_OpenFlag_Write),
+ "osl_createFileHandleFromOSHandle(): missing read/write access flags");
+ return (oslFileHandle)(pImpl);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_openFile(
+ rtl_uString * strPath,
+ oslFileHandle * pHandle,
+ sal_uInt32 uFlags )
+{
+ rtl_uString * strSysPath = 0;
+ oslFileError result = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+ if (result != osl_File_E_None)
+ return (result);
+
+ DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ, dwCreation = 0, dwAttributes = 0;
+
+ if ( uFlags & osl_File_OpenFlag_Write )
+ dwAccess |= GENERIC_WRITE;
+ else
+ dwShare |= FILE_SHARE_WRITE;
+
+ if ( uFlags & osl_File_OpenFlag_NoLock )
+ dwShare |= FILE_SHARE_WRITE;
+
+ if ( uFlags & osl_File_OpenFlag_Create )
+ dwCreation |= CREATE_NEW;
+ else
+ dwCreation |= OPEN_EXISTING;
+
+ HANDLE hFile = CreateFileW(
+ reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )),
+ dwAccess, dwShare, NULL, dwCreation, dwAttributes, NULL );
+
+ // @@@ ERROR HANDLING @@@
+ if ( !IsValidHandle( hFile ) )
+ result = oslTranslateFileError( GetLastError() );
+
+ *pHandle = osl_createFileHandleFromOSHandle (hFile, uFlags | osl_File_OpenFlag_Read);
+
+ rtl_uString_release( strSysPath );
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_syncFile(oslFileHandle Handle)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return result;
+
+ if (!FlushFileBuffers(pImpl->m_hFile))
+ return oslTranslateFileError(GetLastError());
+
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_closeFile(oslFileHandle Handle)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+
+ ::EnterCriticalSection (&(pImpl->m_mutex));
+
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ {
+ /* ignore double failure */
+ (void)::CloseHandle(pImpl->m_hFile);
+ }
+ else if (!::CloseHandle(pImpl->m_hFile))
+ {
+ /* translate error code */
+ result = oslTranslateFileError( GetLastError() );
+ }
+
+ ::LeaveCriticalSection (&(pImpl->m_mutex));
+ delete pImpl;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_mapFile(
+ oslFileHandle Handle,
+ void** ppAddr,
+ sal_uInt64 uLength,
+ sal_uInt64 uOffset,
+ sal_uInt32 uFlags)
+{
+ struct FileMapping
+ {
+ HANDLE m_handle;
+
+ explicit FileMapping (HANDLE hMap)
+ : m_handle (hMap)
+ {}
+
+ ~FileMapping()
+ {
+ (void)::CloseHandle(m_handle);
+ }
+ };
+
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppAddr))
+ return osl_File_E_INVAL;
+ *ppAddr = 0;
+
+ static SIZE_T const nLimit = std::numeric_limits< SIZE_T >::max();
+ if (uLength > nLimit)
+ return osl_File_E_OVERFLOW;
+ SIZE_T const nLength = sal::static_int_cast< SIZE_T >(uLength);
+
+ OSVERSIONINFO osinfo;
+ osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ (void)::GetVersionEx(&osinfo);
+
+ if (VER_PLATFORM_WIN32_NT != osinfo.dwPlatformId)
+ return osl_File_E_NOSYS; // Unsupported
+
+ FileMapping aMap( ::CreateFileMapping (pImpl->m_hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL) );
+ if (!IsValidHandle(aMap.m_handle))
+ return oslTranslateFileError( GetLastError() );
+
+ DWORD const dwOffsetHi = sal::static_int_cast<DWORD>(uOffset >> 32);
+ DWORD const dwOffsetLo = sal::static_int_cast<DWORD>(uOffset & 0xFFFFFFFF);
+
+ *ppAddr = ::MapViewOfFile( aMap.m_handle, FILE_MAP_READ, dwOffsetHi, dwOffsetLo, nLength );
+ if (0 == *ppAddr)
+ return oslTranslateFileError( GetLastError() );
+
+ if (uFlags & osl_File_MapFlag_RandomAccess)
+ {
+ // Determine memory pagesize.
+ SYSTEM_INFO info;
+ ::GetSystemInfo( &info );
+ DWORD const dwPageSize = info.dwPageSize;
+
+ /*
+ * Pagein, touching first byte of each memory page.
+ * Note: volatile disables optimizing the loop away.
+ */
+ BYTE * pData (reinterpret_cast<BYTE*>(*ppAddr));
+ SIZE_T nSize (nLength);
+
+ volatile BYTE c = 0;
+ while (nSize > dwPageSize)
+ {
+ c ^= pData[0];
+ pData += dwPageSize;
+ nSize -= dwPageSize;
+ }
+ if (nSize > 0)
+ {
+ c ^= pData[0];
+ pData += nSize;
+ nSize -= nSize;
+ }
+ }
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_unmapFile(void* pAddr, sal_uInt64 /* uLength */)
+{
+ if (0 == pAddr)
+ return osl_File_E_INVAL;
+
+ if (!::UnmapViewOfFile (pAddr))
+ return oslTranslateFileError( GetLastError() );
+
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_readLine(
+ oslFileHandle Handle,
+ sal_Sequence ** ppSequence)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppSequence))
+ return osl_File_E_INVAL;
+ sal_uInt64 uBytesRead = 0;
+
+ // read at current filepos; filepos += uBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readLineAt (
+ pImpl->m_filepos, ppSequence, &uBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_filepos += uBytesRead;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_readFile(
+ oslFileHandle Handle,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+
+ // read at current filepos; filepos += *pBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readFileAt (
+ pImpl->m_filepos, pBuffer, uBytesRequested, pBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_filepos += *pBytesRead;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_writeFile(
+ oslFileHandle Handle,
+ const void * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten )
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+
+ // write at current filepos; filepos += *pBytesWritten;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->writeFileAt (
+ pImpl->m_filepos, pBuffer, uBytesToWrite, pBytesWritten);
+ if (result == osl_File_E_None)
+ pImpl->m_filepos += *pBytesWritten;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_readFileAt(
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ void* pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64* pBytesRead)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uOffset)
+ return osl_File_E_OVERFLOW;
+ LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
+
+ // read at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->readFileAt (nOffset, pBuffer, uBytesRequested, pBytesRead);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_writeFileAt(
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ const void* pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64* pBytesWritten)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uOffset)
+ return osl_File_E_OVERFLOW;
+ LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
+
+ // write at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->writeFileAt (nOffset, pBuffer, uBytesToWrite, pBytesWritten);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_isEndOfFile (oslFileHandle Handle, sal_Bool *pIsEOF)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pIsEOF))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pIsEOF = (pImpl->getPos() == pImpl->getSize());
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_getFilePos(oslFileHandle Handle, sal_uInt64 *pPos)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pPos))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pPos = pImpl->getPos();
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_setFilePos(oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+
+ static sal_Int64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uOffset)
+ return osl_File_E_OVERFLOW;
+ LONGLONG nPos = 0, nOffset = sal::static_int_cast< LONGLONG >(uOffset);
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ switch (uHow)
+ {
+ case osl_Pos_Absolut:
+ if (0 > nOffset)
+ return osl_File_E_INVAL;
+ break;
+
+ case osl_Pos_Current:
+ nPos = sal::static_int_cast< LONGLONG >(pImpl->getPos());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_longlong < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ case osl_Pos_End:
+ nPos = sal::static_int_cast< LONGLONG >(pImpl->getSize());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_longlong < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ default:
+ return osl_File_E_INVAL;
+ }
+
+ return pImpl->setPos (nPos + nOffset);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_getFileSize (oslFileHandle Handle, sal_uInt64 *pSize)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pSize))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pSize = pImpl->getSize();
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_setFileSize (oslFileHandle Handle, sal_uInt64 uSize)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uSize)
+ return osl_File_E_OVERFLOW;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
+
+ return pImpl->setSize (uSize);
+}
+
+//##################################################################
+// File handling functions
+//##################################################################
+
+//#############################################
+oslFileError SAL_CALL osl_removeFile( rtl_uString* strPath )
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ if ( DeleteFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#############################################
+#define osl_File_CopyRecursive 0x0001
+#define osl_File_CopyOverwrite 0x0002
+
+oslFileError SAL_CALL osl_copyFile( rtl_uString* strPath, rtl_uString *strDestPath )
+{
+ rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
+ LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
+
+ if ( CopyFile( src, dst, FALSE ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ if ( strSysPath )
+ rtl_uString_release( strSysPath );
+ if ( strSysDestPath )
+ rtl_uString_release( strSysDestPath );
+
+ return error;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_moveFile( rtl_uString* strPath, rtl_uString *strDestPath )
+{
+ rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
+ LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
+
+ if ( MoveFileEx( src, dst, MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ if ( strSysPath )
+ rtl_uString_release( strSysPath );
+ if ( strSysDestPath )
+ rtl_uString_release( strSysDestPath );
+
+ return error;
+}
diff --git a/sal/osl/w32/file_dirvol.cxx b/sal/osl/w32/file_dirvol.cxx
new file mode 100644
index 000000000000..09bdec7988c3
--- /dev/null
+++ b/sal/osl/w32/file_dirvol.cxx
@@ -0,0 +1,1867 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "osl/file.h"
+
+#include "file_url.h"
+#include "file_error.h"
+
+#include "path_helper.hxx"
+
+#include "osl/diagnose.h"
+#include "osl/time.h"
+#include "rtl/alloc.h"
+#include "rtl/ustring.hxx"
+
+#include <tchar.h>
+#ifdef __MINGW32__
+#include <ctype.h>
+#endif
+
+//#####################################################
+#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+static const wchar_t UNC_PREFIX[] = L"\\\\";
+static const wchar_t BACKSLASH = '\\';
+static const wchar_t SLASH = '/';
+
+//#####################################################
+extern "C" BOOL TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime)
+{
+ SYSTEMTIME BaseSysTime;
+ FILETIME BaseFileTime;
+ FILETIME FTime;
+ __int64 localTime;
+ BOOL fSuccess = FALSE;
+
+ BaseSysTime.wYear = 1970;
+ BaseSysTime.wMonth = 1;
+ BaseSysTime.wDayOfWeek = 0;
+ BaseSysTime.wDay = 1;
+ BaseSysTime.wHour = 0;
+ BaseSysTime.wMinute = 0;
+ BaseSysTime.wSecond = 0;
+ BaseSysTime.wMilliseconds = 0;
+
+ if (cpTimeVal==NULL)
+ return fSuccess;
+
+ if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
+ {
+ __int64 timeValue;
+ localTime=cpTimeVal->Seconds*(__int64)10000000+cpTimeVal->Nanosec/100;
+ *(__int64 *)&FTime=localTime;
+ fSuccess = 0 <= (timeValue= *((__int64 *)&BaseFileTime) + *((__int64 *) &FTime));
+ if (fSuccess)
+ *(__int64 *)pFTime=timeValue;
+ }
+ return fSuccess;
+}
+
+//#####################################################
+extern "C" BOOL FileTimeToTimeValue(const FILETIME *cpFTime, TimeValue *pTimeVal)
+{
+ SYSTEMTIME BaseSysTime;
+ FILETIME BaseFileTime;
+ BOOL fSuccess = FALSE; /* Assume failure */
+
+ BaseSysTime.wYear = 1970;
+ BaseSysTime.wMonth = 1;
+ BaseSysTime.wDayOfWeek = 0;
+ BaseSysTime.wDay = 1;
+ BaseSysTime.wHour = 0;
+ BaseSysTime.wMinute = 0;
+ BaseSysTime.wSecond = 0;
+ BaseSysTime.wMilliseconds = 0;
+
+ if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
+ {
+ __int64 Value;
+
+ fSuccess = 0 <= (Value = *((__int64 *)cpFTime) - *((__int64 *)&BaseFileTime));
+
+ if ( fSuccess )
+ {
+ pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
+ pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
+ }
+ }
+ return fSuccess;
+}
+
+//#####################################################
+namespace /* private */
+{
+ //#####################################################
+ struct Component
+ {
+ Component() :
+ begin_(0), end_(0)
+ {}
+
+ bool isPresent() const
+ { return (static_cast<sal_IntPtr>(end_ - begin_) > 0); }
+
+ const sal_Unicode* begin_;
+ const sal_Unicode* end_;
+ };
+
+ //#####################################################
+ struct UNCComponents
+ {
+ Component server_;
+ Component share_;
+ Component resource_;
+ };
+
+ //#####################################################
+ inline bool is_UNC_path(const sal_Unicode* path)
+ { return (0 == wcsncmp(UNC_PREFIX, reinterpret_cast<LPCWSTR>(path), ELEMENTS_OF_ARRAY(UNC_PREFIX) - 1)); }
+
+ //#####################################################
+ inline bool is_UNC_path(const rtl::OUString& path)
+ { return is_UNC_path(path.getStr()); }
+
+ //#####################################################
+ void parse_UNC_path(const sal_Unicode* path, UNCComponents* puncc)
+ {
+ OSL_PRECOND(is_UNC_path(path), "Precondition violated: No UNC path");
+ OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
+
+ const sal_Unicode* pend = path + rtl_ustr_getLength(path);
+ const sal_Unicode* ppos = path + 2;
+
+ puncc->server_.begin_ = ppos;
+ while ((ppos < pend) && (*ppos != BACKSLASH))
+ ppos++;
+
+ puncc->server_.end_ = ppos;
+
+ if (BACKSLASH == *ppos)
+ {
+ puncc->share_.begin_ = ++ppos;
+ while ((ppos < pend) && (*ppos != BACKSLASH))
+ ppos++;
+
+ puncc->share_.end_ = ppos;
+
+ if (BACKSLASH == *ppos)
+ {
+ puncc->resource_.begin_ = ++ppos;
+ while (ppos < pend)
+ ppos++;
+
+ puncc->resource_.end_ = ppos;
+ }
+ }
+
+ OSL_POSTCOND(puncc->server_.isPresent() && puncc->share_.isPresent(), \
+ "Postcondition violated: Invalid UNC path detected");
+ }
+
+ //#####################################################
+ void parse_UNC_path(const rtl::OUString& path, UNCComponents* puncc)
+ { parse_UNC_path(path.getStr(), puncc); }
+
+
+ //#####################################################
+ bool has_path_parent(const sal_Unicode* path)
+ {
+ // Has the given path a parent or are we already there,
+ // e.g. 'c:\' or '\\server\share\'?
+
+ bool has_parent = false;
+ if (is_UNC_path(path))
+ {
+ UNCComponents unc_comp;
+ parse_UNC_path(path, &unc_comp);
+ has_parent = unc_comp.resource_.isPresent();
+ }
+ else
+ {
+ has_parent = !osl::systemPathIsLogicalDrivePattern(path);
+ }
+ return has_parent;
+ }
+
+ //#####################################################
+ inline bool has_path_parent(const rtl::OUString& path)
+ { return has_path_parent(path.getStr()); }
+
+} // end namespace private
+
+//#####################################################
+// volume handling functions
+//#####################################################
+
+//#####################################################
+oslFileError SAL_CALL osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ return osl_File_E_None;
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ return osl_File_E_None;
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ {
+ rtl_uString_acquire( (rtl_uString *)Handle );
+ return osl_File_E_None;
+ }
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ {
+ rtl_uString_release( (rtl_uString *)Handle );
+ return osl_File_E_None;
+ }
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
+{
+ if ( Handle && pstrPath )
+ {
+ rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
+ return osl_File_E_None;
+ }
+ else
+ return osl_File_E_INVAL;
+}
+
+//##################################################################
+// directory handling functions
+//##################################################################
+
+#define DIRECTORYITEM_DRIVE 0
+#define DIRECTORYITEM_FILE 1
+#define DIRECTORYITEM_SERVER 2
+
+struct DirectoryItem_Impl
+{
+ UINT uType;
+ union {
+ WIN32_FIND_DATA FindData;
+ TCHAR cDriveString[MAX_PATH];
+ };
+ rtl_uString* m_pFullPath;
+ BOOL bFullPathNormalized;
+ int nRefCount;
+};
+
+//#####################################################
+
+#define DIRECTORYTYPE_LOCALROOT 0
+#define DIRECTORYTYPE_NETROOT 1
+#define DIRECTORYTYPE_NETRESORCE 2
+#define DIRECTORYTYPE_FILESYSTEM 3
+
+struct Directory_Impl
+{
+ UINT uType;
+ union {
+ HANDLE hDirectory;
+ HANDLE hEnumDrives;
+ };
+ rtl_uString* m_pDirectoryPath;
+};
+
+//#####################################################
+
+typedef struct tagDRIVEENUM
+{
+ LPCTSTR lpIdent;
+ TCHAR cBuffer[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
+ LPCTSTR lpCurrent;
+} DRIVEENUM, * PDRIVEENUM, FAR * LPDRIVEENUM;
+
+//#####################################################
+
+static HANDLE WINAPI OpenLogicalDrivesEnum(void)
+{
+ LPDRIVEENUM pEnum = (LPDRIVEENUM)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM) );
+ if ( pEnum )
+ {
+ DWORD dwNumCopied = GetLogicalDriveStrings( (sizeof(pEnum->cBuffer) - 1) / sizeof(TCHAR), pEnum->cBuffer );
+
+ if ( dwNumCopied && dwNumCopied < sizeof(pEnum->cBuffer) / sizeof(TCHAR) )
+ {
+ pEnum->lpCurrent = pEnum->cBuffer;
+ pEnum->lpIdent = L"tagDRIVEENUM";
+ }
+ else
+ {
+ HeapFree( GetProcessHeap(), 0, pEnum );
+ pEnum = NULL;
+ }
+ }
+ return pEnum ? (HANDLE)pEnum : INVALID_HANDLE_VALUE;
+}
+
+//#####################################################
+static BOOL WINAPI EnumLogicalDrives(HANDLE hEnum, LPTSTR lpBuffer)
+{
+ BOOL fSuccess = FALSE;
+ LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
+
+ if ( pEnum )
+ {
+ int nLen = _tcslen( pEnum->lpCurrent );
+
+ if ( nLen )
+ {
+ CopyMemory( lpBuffer, pEnum->lpCurrent, (nLen + 1) * sizeof(TCHAR) );
+ pEnum->lpCurrent += nLen + 1;
+ fSuccess = TRUE;
+ }
+ else
+ SetLastError( ERROR_NO_MORE_FILES );
+ }
+ else
+ SetLastError( ERROR_INVALID_HANDLE );
+
+ return fSuccess;
+}
+
+//#####################################################
+static BOOL WINAPI CloseLogicalDrivesEnum(HANDLE hEnum)
+{
+ BOOL fSuccess = FALSE;
+ LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
+
+ if ( pEnum )
+ {
+ HeapFree( GetProcessHeap(), 0, pEnum );
+ fSuccess = TRUE;
+ }
+ else
+ SetLastError( ERROR_INVALID_HANDLE );
+
+ return fSuccess;
+}
+
+//#####################################################
+typedef struct tagDIRECTORY
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA aFirstData;
+} DIRECTORY, *PDIRECTORY, FAR *LPDIRECTORY;
+
+//#####################################################
+static HANDLE WINAPI OpenDirectory( rtl_uString* pPath)
+{
+ LPDIRECTORY pDirectory = NULL;
+
+ if ( pPath )
+ {
+ sal_uInt32 nLen = rtl_uString_getLength( pPath );
+ if ( nLen )
+ {
+ TCHAR* pSuffix = 0;
+ sal_uInt32 nSuffLen = 0;
+
+ if ( pPath->buffer[nLen - 1] != L'\\' )
+ {
+ pSuffix = L"\\*.*";
+ nSuffLen = 4;
+ }
+ else
+ {
+ pSuffix = L"*.*";
+ nSuffLen = 3;
+ }
+
+ TCHAR* szFileMask = reinterpret_cast< TCHAR* >( rtl_allocateMemory( sizeof( TCHAR ) * ( nLen + nSuffLen + 1 ) ) );
+
+ _tcscpy( szFileMask, reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pPath ) ) );
+ _tcscat( szFileMask, pSuffix );
+
+ pDirectory = (LPDIRECTORY)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY));
+ pDirectory->hFind = FindFirstFile(szFileMask, &pDirectory->aFirstData);
+
+ if (!IsValidHandle(pDirectory->hFind))
+ {
+ if ( GetLastError() != ERROR_NO_MORE_FILES )
+ {
+ HeapFree(GetProcessHeap(), 0, pDirectory);
+ pDirectory = NULL;
+ }
+ }
+ }
+ }
+
+ return (HANDLE)pDirectory;
+}
+
+//#####################################################
+BOOL WINAPI EnumDirectory(HANDLE hDirectory, LPWIN32_FIND_DATA pFindData)
+{
+ BOOL fSuccess = FALSE;
+ LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
+
+ if ( pDirectory )
+ {
+ BOOL fValid;
+
+ do
+ {
+ if ( pDirectory->aFirstData.cFileName[0] )
+ {
+ *pFindData = pDirectory->aFirstData;
+ fSuccess = TRUE;
+ pDirectory->aFirstData.cFileName[0] = 0;
+ }
+ else if ( IsValidHandle( pDirectory->hFind ) )
+ fSuccess = FindNextFile( pDirectory->hFind, pFindData );
+ else
+ {
+ fSuccess = FALSE;
+ SetLastError( ERROR_NO_MORE_FILES );
+ }
+
+ fValid = fSuccess && _tcscmp( TEXT("."), pFindData->cFileName ) != 0 && _tcscmp( TEXT(".."), pFindData->cFileName ) != 0;
+
+ } while( fSuccess && !fValid );
+ }
+ else
+ SetLastError( ERROR_INVALID_HANDLE );
+
+ return fSuccess;
+}
+
+//#####################################################
+static BOOL WINAPI CloseDirectory(HANDLE hDirectory)
+{
+ BOOL fSuccess = FALSE;
+ LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
+
+ if (pDirectory)
+ {
+ if (IsValidHandle(pDirectory->hFind))
+ fSuccess = FindClose(pDirectory->hFind);
+
+ fSuccess = HeapFree(GetProcessHeap(), 0, pDirectory) && fSuccess;
+ }
+ else
+ SetLastError(ERROR_INVALID_HANDLE);
+
+ return fSuccess;
+}
+
+//#####################################################
+static oslFileError osl_openLocalRoot(
+ rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error;
+
+ if ( !pDirectory )
+ return osl_File_E_INVAL;
+
+ *pDirectory = NULL;
+
+ error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysPath, sal_False );
+ if ( osl_File_E_None == error )
+ {
+ Directory_Impl *pDirImpl;
+
+ pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory( sizeof(Directory_Impl)));
+ ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
+ rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strSysPath );
+
+ /* Append backslash if neccessary */
+
+ /* @@@ToDo
+ use function ensure backslash
+ */
+ sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
+ if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
+ {
+ rtl_uString* pCurDir = 0;
+ rtl_uString* pBackSlash = 0;
+
+ rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
+ rtl_uString_newFromAscii( &pBackSlash, "\\" );
+ rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
+ rtl_uString_release( pBackSlash );
+ rtl_uString_release( pCurDir );
+ }
+
+ pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
+ pDirImpl->hEnumDrives = OpenLogicalDrivesEnum();
+
+ /* @@@ToDo
+ Use IsValidHandle(...)
+ */
+ if ( pDirImpl->hEnumDrives != INVALID_HANDLE_VALUE )
+ {
+ *pDirectory = (oslDirectory)pDirImpl;
+ error = osl_File_E_None;
+ }
+ else
+ {
+ if ( pDirImpl )
+ {
+ if ( pDirImpl->m_pDirectoryPath )
+ {
+ rtl_uString_release( pDirImpl->m_pDirectoryPath );
+ pDirImpl->m_pDirectoryPath = 0;
+ }
+
+ rtl_freeMemory(pDirImpl);
+ pDirImpl = 0;
+ }
+
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_openFileDirectory(
+ rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
+{
+ oslFileError error = osl_File_E_None;
+
+ if ( !pDirectory )
+ return osl_File_E_INVAL;
+ *pDirectory = NULL;
+
+ Directory_Impl *pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
+ ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
+ rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strDirectoryPath );
+
+ /* Append backslash if neccessary */
+
+ /* @@@ToDo
+ use function ensure backslash
+ */
+ sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
+ if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
+ {
+ rtl_uString* pCurDir = 0;
+ rtl_uString* pBackSlash = 0;
+
+ rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
+ rtl_uString_newFromAscii( &pBackSlash, "\\" );
+ rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
+ rtl_uString_release( pBackSlash );
+ rtl_uString_release( pCurDir );
+ }
+
+
+ pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
+ pDirImpl->hDirectory = OpenDirectory( pDirImpl->m_pDirectoryPath );
+
+ if ( !pDirImpl->hDirectory )
+ {
+ error = oslTranslateFileError( GetLastError() );
+
+ if ( pDirImpl->m_pDirectoryPath )
+ {
+ rtl_uString_release( pDirImpl->m_pDirectoryPath );
+ pDirImpl->m_pDirectoryPath = 0;
+ }
+
+ rtl_freeMemory(pDirImpl), pDirImpl = 0;
+ }
+
+ *pDirectory = (oslDirectory)(pDirImpl);
+ return error;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_openNetworkServer(
+ rtl_uString *strSysDirPath, oslDirectory *pDirectory)
+{
+ NETRESOURCEW aNetResource;
+ HANDLE hEnum;
+ DWORD dwError;
+
+ ZeroMemory( &aNetResource, sizeof(aNetResource) );
+
+ aNetResource.lpRemoteName = reinterpret_cast<LPWSTR>(strSysDirPath->buffer);
+
+ dwError = WNetOpenEnumW(
+ RESOURCE_GLOBALNET,
+ RESOURCETYPE_DISK,
+ RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER,
+ &aNetResource,
+ &hEnum );
+
+ if ( ERROR_SUCCESS == dwError )
+ {
+ Directory_Impl *pDirImpl;
+
+ pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
+ ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
+ pDirImpl->uType = DIRECTORYTYPE_NETROOT;
+ pDirImpl->hDirectory = hEnum;
+ *pDirectory = (oslDirectory)pDirImpl;
+ }
+ return oslTranslateFileError( dwError );
+}
+
+//#############################################
+static DWORD create_dir_with_callback(
+ rtl_uString * dir_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ // Create the specified directory and call the
+ // user specified callback function. On success
+ // the function returns ERROR_SUCCESS else a Win32 error code.
+
+ BOOL bCreated = FALSE;
+
+ bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( dir_path )), NULL );
+
+ if ( bCreated )
+ {
+ if (aDirectoryCreationCallbackFunc)
+ {
+ rtl::OUString url;
+ _osl_getFileURLFromSystemPath(dir_path, &(url.pData));
+ aDirectoryCreationCallbackFunc(pData, url.pData);
+ }
+ return ERROR_SUCCESS;
+ }
+ return GetLastError();
+}
+
+//#############################################
+static int path_make_parent(sal_Unicode* path)
+{
+ /* Cut off the last part of the given path to
+ get the parent only, e.g. 'c:\dir\subdir' ->
+ 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
+ @return The position where the path has been cut
+ off (this is the posistion of the last backslash).
+ If there are no more parents 0 will be returned,
+ e.g. 'c:\' or '\\Share' have no more parents */
+
+ OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
+ OSL_PRECOND(has_path_parent(path), "Path must have a parent");
+
+ sal_Unicode* pos_last_backslash = path + rtl_ustr_lastIndexOfChar(path, BACKSLASH);
+ *pos_last_backslash = 0;
+ return (pos_last_backslash - path);
+}
+
+//#############################################
+static DWORD create_dir_recursively_(
+ rtl_uString * dir_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ OSL_PRECOND(
+ rtl_ustr_lastIndexOfChar_WithLength(dir_path->buffer, dir_path->length, BACKSLASH) != dir_path->length,
+ "Path must not end with a backslash");
+
+ DWORD w32_error = create_dir_with_callback(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+ if (w32_error == ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+
+ if ((w32_error != ERROR_PATH_NOT_FOUND) || !has_path_parent(dir_path->buffer))
+ return w32_error;
+
+ int pos = path_make_parent(dir_path->buffer); // dir_path->buffer[pos] = 0, restore below
+
+ w32_error = create_dir_recursively_(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+
+ dir_path->buffer[pos] = BACKSLASH; // restore
+
+ if (ERROR_SUCCESS != w32_error)
+ return w32_error;
+
+ return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
+}
+
+//#############################################
+oslFileError SAL_CALL osl_createDirectoryPath(
+ rtl_uString* aDirectoryUrl,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ if (aDirectoryUrl == NULL)
+ return osl_File_E_INVAL;
+
+ rtl::OUString sys_path;
+ oslFileError osl_error =
+ _osl_getSystemPathFromFileURL(aDirectoryUrl, &sys_path.pData, sal_False);
+
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+
+ osl::systemPathRemoveSeparator(sys_path);
+
+ // const_cast because sys_path is a local copy
+ // which we want to modify inplace instead of
+ // coyp it into another buffer on the heap again
+ return oslTranslateFileError(create_dir_recursively_(
+ sys_path.pData, aDirectoryCreationCallbackFunc, pData));
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_createDirectory(rtl_uString* strPath)
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ BOOL bCreated = FALSE;
+
+ bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL );
+
+ if ( !bCreated )
+ {
+ /*@@@ToDo
+ The following case is a hack because the ucb or the webtop had some
+ problems with the error code that CreateDirectory returns in
+ case the path is only a logical drive, should be removed!
+ */
+
+ const sal_Unicode *pBuffer = rtl_uString_getStr( strSysPath );
+ sal_Int32 nLen = rtl_uString_getLength( strSysPath );
+
+ if (
+ ( ( pBuffer[0] >= 'A' && pBuffer[0] <= 'Z' ) ||
+ ( pBuffer[0] >= 'a' && pBuffer[0] <= 'z' ) ) &&
+ pBuffer[1] == ':' && ( nLen ==2 || ( nLen == 3 && pBuffer[2] == '\\' ) )
+ )
+ SetLastError( ERROR_ALREADY_EXISTS );
+
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_removeDirectory(rtl_uString* strPath)
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ if ( RemoveDirectory( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_openDirectory(rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
+{
+ oslFileError error;
+
+ if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath->buffer, "file:///" ) )
+ error = osl_openLocalRoot( strDirectoryPath, pDirectory );
+ else
+ {
+ rtl_uString *strSysDirectoryPath = NULL;
+ DWORD dwPathType;
+
+ error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysDirectoryPath, sal_False );
+
+ if ( osl_File_E_None != error )
+ return error;
+
+ dwPathType = IsValidFilePath( strSysDirectoryPath, NULL, VALIDATEPATH_NORMAL, NULL );
+
+ if ( dwPathType & PATHTYPE_IS_SERVER )
+ {
+ error = osl_openNetworkServer( strSysDirectoryPath, pDirectory );
+ }
+ else
+ error = osl_openFileDirectory( strSysDirectoryPath, pDirectory );
+
+ rtl_uString_release( strSysDirectoryPath );
+ }
+ return error;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getNextNetResource(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ BYTE buffer[16384];
+ LPNETRESOURCEW lpNetResource = (LPNETRESOURCEW)buffer;
+ DWORD dwError, dwCount, dwBufSize;
+
+ uHint = uHint; /* to get no warning */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ dwCount = 1;
+ dwBufSize = sizeof(buffer);
+ dwError = WNetEnumResource( pDirImpl->hDirectory, &dwCount, lpNetResource, &dwBufSize );
+
+ switch ( dwError )
+ {
+ case NO_ERROR:
+ case ERROR_MORE_DATA:
+ {
+ pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+
+ wcscpy( pItemImpl->cDriveString, lpNetResource->lpRemoteName );
+
+ *pItem = pItemImpl;
+ }
+ return osl_File_E_None;
+ case ERROR_NO_MORE_ITEMS:
+ return osl_File_E_NOENT;
+ default:
+ return oslTranslateFileError( dwError );
+ }
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getNextDrive(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ BOOL fSuccess;
+
+ uHint = uHint; /* avoid warnings */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+ fSuccess = EnumLogicalDrives( pDirImpl->hEnumDrives, pItemImpl->cDriveString );
+
+ if ( fSuccess )
+ {
+ *pItem = pItemImpl;
+ return osl_File_E_None;
+ }
+ else
+ {
+ if ( pItemImpl->m_pFullPath )
+ {
+ rtl_uString_release( pItemImpl->m_pFullPath );
+ pItemImpl->m_pFullPath = 0;
+ }
+
+ rtl_freeMemory( pItemImpl );
+ return oslTranslateFileError( GetLastError() );
+ }
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getNextFileItem(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ BOOL fFound;
+
+ uHint = uHint; /* avoid warnings */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
+ fFound = EnumDirectory( pDirImpl->hDirectory, &pItemImpl->FindData );
+
+ if ( fFound )
+ {
+ pItemImpl->uType = DIRECTORYITEM_FILE;
+ pItemImpl->nRefCount = 1;
+
+ rtl_uString* pTmpFileName = 0;
+ rtl_uString_newFromStr( &pTmpFileName, reinterpret_cast<const sal_Unicode *>(pItemImpl->FindData.cFileName) );
+ rtl_uString_newConcat( &pItemImpl->m_pFullPath, pDirImpl->m_pDirectoryPath, pTmpFileName );
+ rtl_uString_release( pTmpFileName );
+
+ pItemImpl->bFullPathNormalized = FALSE;
+ *pItem = (oslDirectoryItem)pItemImpl;
+ return osl_File_E_None;
+ }
+ else
+ {
+ if ( pItemImpl->m_pFullPath )
+ {
+ rtl_uString_release( pItemImpl->m_pFullPath );
+ pItemImpl->m_pFullPath = 0;
+ }
+
+ rtl_freeMemory( pItemImpl );
+ return oslTranslateFileError( GetLastError() );
+ }
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getNextDirectoryItem(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+
+ /* Assume failure */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ switch ( pDirImpl->uType )
+ {
+ case DIRECTORYTYPE_LOCALROOT:
+ return osl_getNextDrive( Directory, pItem, uHint );
+ case DIRECTORYTYPE_NETROOT:
+ return osl_getNextNetResource( Directory, pItem, uHint );
+ case DIRECTORYTYPE_FILESYSTEM:
+ return osl_getNextFileItem( Directory, pItem, uHint );
+ default:
+ return osl_File_E_INVAL;
+ }
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_closeDirectory(oslDirectory Directory)
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ oslFileError eError = osl_File_E_INVAL;
+
+ if ( pDirImpl )
+ {
+ switch ( pDirImpl->uType )
+ {
+ case DIRECTORYTYPE_FILESYSTEM:
+ eError = CloseDirectory( pDirImpl->hDirectory ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
+ break;
+ case DIRECTORYTYPE_LOCALROOT:
+ eError = CloseLogicalDrivesEnum( pDirImpl->hEnumDrives ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
+ break;
+ case DIRECTORYTYPE_NETROOT:
+ {
+ DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
+ eError = (err == NO_ERROR) ? osl_File_E_None : oslTranslateFileError(err);
+ }
+ break;
+ default:
+ OSL_ENSURE( 0, "Invalid directory type" );
+ break;
+ }
+
+ if ( pDirImpl->m_pDirectoryPath )
+ {
+ rtl_uString_release( pDirImpl->m_pDirectoryPath );
+ pDirImpl->m_pDirectoryPath = 0;
+ }
+
+ rtl_freeMemory(pDirImpl);
+ }
+ return eError;
+}
+
+//#####################################################
+/* Different types of paths */
+typedef enum _PATHTYPE
+{
+ PATHTYPE_SYNTAXERROR = 0,
+ PATHTYPE_NETROOT,
+ PATHTYPE_NETSERVER,
+ PATHTYPE_VOLUME,
+ PATHTYPE_FILE
+} PATHTYPE;
+
+oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString *strFilePath, oslDirectoryItem *pItem)
+{
+ oslFileError error = osl_File_E_None;
+ rtl_uString* strSysFilePath = NULL;
+ PATHTYPE type = PATHTYPE_FILE;
+ DWORD dwPathType;
+
+ /* Assume failure */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+
+ *pItem = NULL;
+
+
+ error = _osl_getSystemPathFromFileURL( strFilePath, &strSysFilePath, sal_False );
+
+ if ( osl_File_E_None != error )
+ return error;
+
+ dwPathType = IsValidFilePath( strSysFilePath, NULL, VALIDATEPATH_NORMAL, NULL );
+
+ if ( dwPathType & PATHTYPE_IS_VOLUME )
+ type = PATHTYPE_VOLUME;
+ else if ( dwPathType & PATHTYPE_IS_SERVER )
+ type = PATHTYPE_NETSERVER;
+ else
+ type = PATHTYPE_FILE;
+
+ switch ( type )
+ {
+ case PATHTYPE_NETSERVER:
+ {
+ DirectoryItem_Impl* pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ if ( !pItemImpl )
+ error = osl_File_E_NOMEM;
+
+ if ( osl_File_E_None == error )
+ {
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_SERVER;
+
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+ rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
+
+ // Assign a title anyway
+ {
+ int iSrc = 2;
+ int iDst = 0;
+
+ while( iSrc < strSysFilePath->length && strSysFilePath->buffer[iSrc] && strSysFilePath->buffer[iSrc] != '\\' )
+ {
+ pItemImpl->FindData.cFileName[iDst++] = strSysFilePath->buffer[iSrc++];
+ }
+ }
+
+ *pItem = pItemImpl;
+ }
+ }
+ break;
+ case PATHTYPE_VOLUME:
+ {
+ DirectoryItem_Impl* pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ if ( !pItemImpl )
+ error = osl_File_E_NOMEM;
+
+ if ( osl_File_E_None == error )
+ {
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+
+ _tcscpy( pItemImpl->cDriveString, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
+ pItemImpl->cDriveString[0] = _toupper( pItemImpl->cDriveString[0] );
+
+ if ( pItemImpl->cDriveString[_tcslen(pItemImpl->cDriveString) - 1] != '\\' )
+ _tcscat( pItemImpl->cDriveString, TEXT( "\\" ) );
+
+ *pItem = pItemImpl;
+ }
+ }
+ break;
+ case PATHTYPE_SYNTAXERROR:
+ case PATHTYPE_NETROOT:
+ case PATHTYPE_FILE:
+ {
+ HANDLE hFind;
+ WIN32_FIND_DATA aFindData;
+
+ if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
+ rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
+
+ hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)), &aFindData );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ DirectoryItem_Impl *pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+
+ CopyMemory( &pItemImpl->FindData, &aFindData, sizeof(WIN32_FIND_DATA) );
+ rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
+
+ // MT: This costs 600ms startup time on fast v60x!
+ // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
+
+ pItemImpl->uType = DIRECTORYITEM_FILE;
+ *pItem = pItemImpl;
+ FindClose( hFind );
+ }
+ else
+ error = oslTranslateFileError( GetLastError() );
+ }
+ break;
+ }
+
+ if ( strSysFilePath )
+ rtl_uString_release( strSysFilePath );
+
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pItemImpl->nRefCount++;
+ return osl_File_E_None;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ if ( ! --pItemImpl->nRefCount )
+ {
+ if ( pItemImpl->m_pFullPath )
+ {
+ rtl_uString_release( pItemImpl->m_pFullPath );
+ pItemImpl->m_pFullPath = 0;
+ }
+
+ rtl_freeMemory( pItemImpl );
+ }
+
+ return osl_File_E_None;
+}
+
+//#####################################################
+// volume / file info handling functions
+//#####################################################
+
+//#####################################################
+static inline bool is_floppy_A_present()
+{ return (GetLogicalDrives() & 1); }
+
+//#####################################################
+static inline bool is_floppy_B_present()
+{ return (GetLogicalDrives() & 2); }
+
+//#####################################################
+bool is_floppy_volume_mount_point(const rtl::OUString& path)
+{
+ // determines if a volume mount point shows to a floppy
+ // disk by comparing the unique volume names
+ static const LPCWSTR FLOPPY_A = L"A:\\";
+ static const LPCWSTR FLOPPY_B = L"B:\\";
+
+ rtl::OUString p(path);
+ osl::systemPathEnsureSeparator(p);
+
+ TCHAR vn[51];
+ if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
+ {
+ TCHAR vnfloppy[51];
+ if (is_floppy_A_present() &&
+ GetVolumeNameForVolumeMountPoint(FLOPPY_A, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
+ (0 == wcscmp(vn, vnfloppy)))
+ return true;
+
+ if (is_floppy_B_present() &&
+ GetVolumeNameForVolumeMountPoint(FLOPPY_B, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
+ (0 == wcscmp(vn, vnfloppy)))
+ return true;
+ }
+ return false;
+}
+
+//################################################
+static bool is_floppy_drive(const rtl::OUString& path)
+{
+ static const LPCWSTR FLOPPY_DRV_LETTERS = TEXT("AaBb");
+
+ // we must take into account that even a floppy
+ // drive may be mounted to a directory so checking
+ // for the drive letter alone is not sufficient
+ // we must compare the unique volume name with
+ // that of the available floppy disks
+
+ const sal_Unicode* pszPath = path.getStr();
+ return ((wcschr(FLOPPY_DRV_LETTERS, pszPath[0]) && (L':' == pszPath[1])) || is_floppy_volume_mount_point(path));
+}
+
+//#####################################################
+static bool is_volume_mount_point(const rtl::OUString& path)
+{
+ rtl::OUString p(path);
+ osl::systemPathRemoveSeparator(p);
+
+ bool is_volume_root = false;
+
+ if (!is_floppy_drive(p))
+ {
+ DWORD fattr = GetFileAttributes(reinterpret_cast<LPCTSTR>(p.getStr()));
+
+ if ((INVALID_FILE_ATTRIBUTES != fattr) &&
+ (FILE_ATTRIBUTE_REPARSE_POINT & fattr))
+ {
+ WIN32_FIND_DATA find_data;
+ HANDLE h_find = FindFirstFile(reinterpret_cast<LPCTSTR>(p.getStr()), &find_data);
+
+ if (IsValidHandle(h_find) &&
+ (FILE_ATTRIBUTE_REPARSE_POINT & find_data.dwFileAttributes) &&
+ (IO_REPARSE_TAG_MOUNT_POINT == find_data.dwReserved0))
+ {
+ is_volume_root = true;
+ }
+ if (IsValidHandle(h_find))
+ FindClose(h_find);
+ }
+ }
+ return is_volume_root;
+}
+
+//#############################################
+static UINT get_volume_mount_point_drive_type(const rtl::OUString& path)
+{
+ if (0 == path.getLength())
+ return GetDriveType(NULL);
+
+ rtl::OUString p(path);
+ osl::systemPathEnsureSeparator(p);
+
+ TCHAR vn[51];
+ if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
+ return GetDriveType(vn);
+
+ return DRIVE_NO_ROOT_DIR;
+}
+
+//#############################################
+static inline bool is_drivetype_request(sal_uInt32 field_mask)
+{
+ return (field_mask & osl_VolumeInfo_Mask_Attributes);
+}
+
+//#############################################
+static oslFileError osl_get_drive_type(
+ const rtl::OUString& path, oslVolumeInfo* pInfo)
+{
+ // GetDriveType fails on empty volume mount points
+ // see Knowledge Base Q244089
+ UINT drive_type;
+ if (is_volume_mount_point(path))
+ drive_type = get_volume_mount_point_drive_type(path);
+ else
+ drive_type = GetDriveType(reinterpret_cast<LPCTSTR>(path.getStr()));
+
+ if (DRIVE_NO_ROOT_DIR == drive_type)
+ return oslTranslateFileError(ERROR_INVALID_DRIVE);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+
+ switch (drive_type)
+ {
+ case DRIVE_CDROM:
+ pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
+ break;
+ case DRIVE_REMOVABLE:
+ pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
+ if (is_floppy_drive(path))
+ pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
+ break;
+ case DRIVE_FIXED:
+ pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
+ break;
+ case DRIVE_RAMDISK:
+ pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
+ break;
+ case DRIVE_REMOTE:
+ pInfo->uAttributes |= osl_Volume_Attribute_Remote;
+ break;
+ case DRIVE_UNKNOWN:
+ pInfo->uAttributes = 0;
+ break;
+ default:
+ pInfo->uValidFields &= ~osl_VolumeInfo_Mask_Attributes;
+ pInfo->uAttributes = 0;
+ break;
+ }
+ return osl_File_E_None;
+}
+
+//#############################################
+static inline bool is_volume_space_info_request(sal_uInt32 field_mask)
+{
+ return (field_mask &
+ (osl_VolumeInfo_Mask_TotalSpace |
+ osl_VolumeInfo_Mask_UsedSpace |
+ osl_VolumeInfo_Mask_FreeSpace));
+}
+
+//#############################################
+static void get_volume_space_information(
+ const rtl::OUString& path, oslVolumeInfo *pInfo)
+{
+ BOOL ret = GetDiskFreeSpaceEx(
+ reinterpret_cast<LPCTSTR>(path.getStr()),
+ (PULARGE_INTEGER)&(pInfo->uFreeSpace),
+ (PULARGE_INTEGER)&(pInfo->uTotalSpace),
+ NULL);
+
+ if (ret)
+ {
+ pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
+ osl_VolumeInfo_Mask_UsedSpace |
+ osl_VolumeInfo_Mask_FreeSpace;
+ }
+}
+
+//#############################################
+static inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
+{
+ return (field_mask &
+ (osl_VolumeInfo_Mask_MaxNameLength |
+ osl_VolumeInfo_Mask_MaxPathLength |
+ osl_VolumeInfo_Mask_FileSystemName |
+ osl_VolumeInfo_Mask_FileSystemCaseHandling));
+}
+
+//#############################################
+static oslFileError get_filesystem_attributes(
+ const rtl::OUString& path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
+{
+ pInfo->uAttributes = 0;
+
+ // osl_get_drive_type must be called first because
+ // this function resets osl_VolumeInfo_Mask_Attributes
+ // on failure
+ if (is_drivetype_request(field_mask))
+ {
+ oslFileError osl_error = osl_get_drive_type(path, pInfo);
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+ }
+ if (is_filesystem_attributes_request(field_mask))
+ {
+ /* the following two parameters can not be longer than MAX_PATH+1 */
+ WCHAR vn[MAX_PATH+1];
+ WCHAR fsn[MAX_PATH+1];
+
+ DWORD serial;
+ DWORD mcl;
+ DWORD flags;
+
+ LPCTSTR pszPath = reinterpret_cast<LPCTSTR>(path.getStr());
+ if (GetVolumeInformation(pszPath, vn, MAX_PATH+1, &serial, &mcl, &flags, fsn, MAX_PATH+1))
+ {
+ // Currently sal does not use this value, instead MAX_PATH is used
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
+ pInfo->uMaxNameLength = mcl;
+
+ // Should the uMaxPathLength be set to 32767, "\\?\" prefix allowes it
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
+ pInfo->uMaxPathLength = MAX_PATH;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
+ rtl_uString_newFromStr(&pInfo->ustrFileSystemName, reinterpret_cast<const sal_Unicode*>(fsn));
+
+ // volumes (even NTFS) will always be considered case
+ // insensitive because the Win32 API is not able to
+ // deal with case sensitive volumes see M$ Knowledge Base
+ // article 100625 that's why we never set the attribute
+ // osl_Volume_Attribute_Case_Sensitive
+
+ if (flags & FS_CASE_IS_PRESERVED)
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+ }
+ return osl_File_E_None;
+}
+
+//#####################################################
+static bool path_get_parent(rtl::OUString& path)
+{
+ OSL_PRECOND(path.lastIndexOf(SLASH) == -1, "Path must not have slashes");
+
+ if (!has_path_parent(path))
+ {
+ sal_Int32 i = path.lastIndexOf(BACKSLASH);
+ if (-1 < i)
+ {
+ path = rtl::OUString(path.getStr(), i);
+ return true;
+ }
+ }
+ return false;
+}
+
+//#####################################################
+static void path_travel_to_volume_root(const rtl::OUString& system_path, rtl::OUString& volume_root)
+{
+ rtl::OUString sys_path(system_path);
+
+ while(!is_volume_mount_point(sys_path) && path_get_parent(sys_path))
+ /**/;
+
+ volume_root = sys_path;
+ osl::systemPathEnsureSeparator(volume_root);
+}
+
+//#############################################
+oslFileError SAL_CALL osl_getVolumeInformation(
+ rtl_uString *ustrURL, oslVolumeInfo *pInfo, sal_uInt32 uFieldMask )
+{
+ if (!pInfo)
+ return osl_File_E_INVAL;
+
+ rtl::OUString system_path;
+ oslFileError error = _osl_getSystemPathFromFileURL(ustrURL, &system_path.pData, sal_False);
+
+ if (osl_File_E_None != error)
+ return error;
+
+ rtl::OUString volume_root;
+ path_travel_to_volume_root(system_path, volume_root);
+
+ pInfo->uValidFields = 0;
+
+ if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
+ return error;
+
+ if (is_volume_space_info_request(uFieldMask))
+ get_volume_space_information(volume_root, pInfo);
+
+ if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
+ {
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
+ osl_getFileURLFromSystemPath(volume_root.pData, (rtl_uString**)&pInfo->pDeviceHandle);
+ }
+
+ return osl_File_E_None;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getDriveInfo(
+ oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+ TCHAR cDrive[3] = TEXT("A:");
+ TCHAR cRoot[4] = TEXT("A:\\");
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ cDrive[0] = pItemImpl->cDriveString[0];
+ cRoot[0] = pItemImpl->cDriveString[0];
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileName )
+ {
+ if ( pItemImpl->cDriveString[0] == '\\' && pItemImpl->cDriveString[1] == '\\' )
+ {
+ LPCWSTR lpFirstBkSlash = wcschr( &pItemImpl->cDriveString[2], '\\' );
+
+ if ( lpFirstBkSlash && lpFirstBkSlash[1] )
+ {
+ LPCWSTR lpLastBkSlash = wcschr( &lpFirstBkSlash[1], '\\' );
+
+ if ( lpLastBkSlash )
+ rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]), lpLastBkSlash - lpFirstBkSlash - 1 );
+ else
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]) );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ }
+ }
+ else switch ( GetDriveType( cRoot ) )
+ {
+ case DRIVE_REMOTE:
+ {
+ TCHAR szBuffer[1024];
+ DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szBuffer);
+ DWORD dwBufsize = dwBufsizeConst;
+
+ DWORD dwResult = WNetGetConnection( cDrive, szBuffer, &dwBufsize );
+ if ( NO_ERROR == dwResult )
+ {
+ TCHAR szFileName[dwBufsizeConst + 16];
+
+ swprintf( szFileName, L"%s [%s]", cDrive, szBuffer );
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
+ }
+ else
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
+ }
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ break;
+ case DRIVE_FIXED:
+ {
+ TCHAR szVolumeNameBuffer[1024];
+ DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szVolumeNameBuffer);
+
+ if ( GetVolumeInformation( cRoot, szVolumeNameBuffer, dwBufsizeConst, NULL, NULL, NULL, NULL, 0 ) )
+ {
+ TCHAR szFileName[dwBufsizeConst + 16];
+
+ swprintf( szFileName, L"%s [%s]", cDrive, szVolumeNameBuffer );
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
+ }
+ else
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
+ }
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ break;
+ case DRIVE_CDROM:
+ case DRIVE_REMOVABLE:
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cRoot) );
+ break;
+ case DRIVE_UNKNOWN:
+ default:
+ break;
+ }
+ }
+
+ pStatus->eType = osl_File_Type_Volume;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ rtl_uString *ustrSystemPath = NULL;
+
+ rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->cDriveString) );
+ osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
+ rtl_uString_release( ustrSystemPath );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+ return osl_File_E_None;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getServerInfo(
+ oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ // pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+
+ // if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
+ // rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
+ // else
+ // rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
+
+ pStatus->eType = osl_File_Type_Directory;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_getFileStatus(
+ oslDirectoryItem Item,
+ oslFileStatus *pStatus,
+ sal_uInt32 uFieldMask )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ switch ( pItemImpl->uType )
+ {
+ case DIRECTORYITEM_DRIVE:
+ return osl_getDriveInfo( Item, pStatus, uFieldMask );
+ case DIRECTORYITEM_SERVER:
+ return osl_getServerInfo( Item, pStatus, uFieldMask );
+ default:
+ break;
+ }
+
+ if ( uFieldMask & osl_FileStatus_Mask_Validate )
+ {
+ HANDLE hFind = FindFirstFile( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ), &pItemImpl->FindData );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ FindClose( hFind );
+ else
+ return oslTranslateFileError( GetLastError() );
+
+ uFieldMask &= ~ osl_FileStatus_Mask_Validate;
+ }
+
+ /* If no fields to retrieve left ignore pStatus */
+ if ( !uFieldMask )
+ return osl_File_E_None;
+
+ /* Otherwise, this must be a valid pointer */
+ if ( !pStatus )
+ return osl_File_E_INVAL;
+
+ if ( pStatus->uStructSize != sizeof(oslFileStatus) )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ /* File time stamps */
+
+ if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime) &&
+ FileTimeToTimeValue( &pItemImpl->FindData.ftLastWriteTime, &pStatus->aModifyTime ) )
+ pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
+
+ if ( (uFieldMask & osl_FileStatus_Mask_AccessTime) &&
+ FileTimeToTimeValue( &pItemImpl->FindData.ftLastAccessTime, &pStatus->aAccessTime ) )
+ pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
+
+ if ( (uFieldMask & osl_FileStatus_Mask_CreationTime) &&
+ FileTimeToTimeValue( &pItemImpl->FindData.ftCreationTime, &pStatus->aCreationTime ) )
+ pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
+
+ /* Most of the fields are already set, regardless of requiered fields */
+
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(pItemImpl->FindData.cFileName) );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+
+ if ((FILE_ATTRIBUTE_REPARSE_POINT & pItemImpl->FindData.dwFileAttributes) &&
+ (IO_REPARSE_TAG_MOUNT_POINT == pItemImpl->FindData.dwReserved0))
+ pStatus->eType = osl_File_Type_Volume;
+ else if (pItemImpl->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ pStatus->eType = osl_File_Type_Directory;
+ else
+ pStatus->eType = osl_File_Type_Regular;
+
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ pStatus->uAttributes = pItemImpl->FindData.dwFileAttributes;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
+
+ pStatus->uFileSize = (sal_uInt64)pItemImpl->FindData.nFileSizeLow + ((sal_uInt64)pItemImpl->FindData.nFileSizeHigh << 32);
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
+
+ if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
+ {
+ osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrLinkTargetURL );
+
+ pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
+ }
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ if ( !pItemImpl->bFullPathNormalized )
+ {
+ sal_uInt32 nLen = rtl_uString_getLength( pItemImpl->m_pFullPath );
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ),
+ ::osl::mingw_reinterpret_cast<LPTSTR>( aBuffer ),
+ aBuffer.getBufSizeInSymbols(),
+ sal_True );
+
+ if ( nNewLen )
+ {
+ rtl_uString_newFromStr( &pItemImpl->m_pFullPath, aBuffer );
+ pItemImpl->bFullPathNormalized = TRUE;
+ }
+ }
+
+ osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+
+ return osl_File_E_None;
+}
+
+//#####################################################
+// file attributes handling functions
+//#####################################################
+
+//#############################################
+oslFileError SAL_CALL osl_setFileAttributes(
+ rtl_uString *ustrFileURL,
+ sal_uInt64 uAttributes )
+{
+ oslFileError error;
+ rtl_uString *ustrSysPath = NULL;
+ DWORD dwFileAttributes;
+ BOOL fSuccess;
+
+ // Converts the normalized path into a systempath
+ error = _osl_getSystemPathFromFileURL( ustrFileURL, &ustrSysPath, sal_False );
+
+ if ( osl_File_E_None != error )
+ return error;
+
+ dwFileAttributes = GetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)) );
+
+ if ( (DWORD)-1 != dwFileAttributes )
+ {
+ dwFileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN);
+
+ if ( uAttributes & osl_File_Attribute_ReadOnly )
+ dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
+
+ if ( uAttributes & osl_File_Attribute_Hidden )
+ dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+
+ fSuccess = SetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)), dwFileAttributes );
+ }
+ else
+ fSuccess = FALSE;
+
+ if ( !fSuccess )
+ error = oslTranslateFileError( GetLastError() );
+
+ rtl_uString_release( ustrSysPath );
+
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_setFileTime(
+ rtl_uString *filePath,
+ const TimeValue *aCreationTime,
+ const TimeValue *aLastAccessTime,
+ const TimeValue *aLastWriteTime)
+{
+ oslFileError error;
+ rtl_uString *sysPath=NULL;
+ FILETIME *lpCreationTime=NULL;
+ FILETIME *lpLastAccessTime=NULL;
+ FILETIME *lpLastWriteTime=NULL;
+ FILETIME ftCreationTime;
+ FILETIME ftLastAccessTime;
+ FILETIME ftLastWriteTime;
+ HANDLE hFile;
+ BOOL fSuccess;
+
+
+ error=_osl_getSystemPathFromFileURL(filePath, &sysPath, sal_False);
+
+ if (error==osl_File_E_INVAL)
+ return error;
+
+ hFile=CreateFileW(reinterpret_cast<LPCWSTR>(rtl_uString_getStr(sysPath)), GENERIC_WRITE, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ rtl_uString_release(sysPath);
+
+ if (hFile==INVALID_HANDLE_VALUE)
+ return osl_File_E_NOENT;
+
+ if (TimeValueToFileTime(aCreationTime, &ftCreationTime))
+ lpCreationTime=&ftCreationTime;
+
+ if (TimeValueToFileTime(aLastAccessTime, &ftLastAccessTime))
+ lpLastAccessTime=&ftLastAccessTime;
+
+ if (TimeValueToFileTime(aLastWriteTime, &ftLastWriteTime))
+ lpLastWriteTime=&ftLastWriteTime;
+
+ fSuccess=SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
+
+ CloseHandle(hFile);
+
+ if (!fSuccess)
+ return osl_File_E_INVAL;
+ else
+ return osl_File_E_None;
+}
diff --git a/sal/osl/w32/file_error.c b/sal/osl/w32/file_error.c
new file mode 100644
index 000000000000..26e749cc5451
--- /dev/null
+++ b/sal/osl/w32/file_error.c
@@ -0,0 +1,151 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "file_error.h"
+
+#include "osl/diagnose.h"
+#include "osl/thread.h"
+
+/* OS error to oslFileError values mapping table */
+struct osl_file_error_entry
+{
+ unsigned long oscode; /* OS return value */
+ int errnocode; /* oslFileError code */
+};
+
+static const struct osl_file_error_entry errtable[] = {
+ { ERROR_SUCCESS, osl_File_E_None }, /* 0 */
+ { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */
+ { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */
+ { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */
+ { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */
+ { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */
+ { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */
+ { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */
+ { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */
+ { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */
+ { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */
+ { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */
+ { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */
+ { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */
+ { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */
+ { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */
+ { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */
+ { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */
+ { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */
+ { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */
+ { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */
+ { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */
+ { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */
+ { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */
+ { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */
+ { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */
+ { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */
+ { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */
+ { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */
+ { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */
+ { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */
+ { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */
+ { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */
+ { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */
+ { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */
+ { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */
+ { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */
+ { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */
+ { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */
+ { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */
+ { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */
+ { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */
+ { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */
+ { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */
+ { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */
+ { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */
+ { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */
+ { ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM }, /* 1816 */
+ { ERROR_UNEXP_NET_ERR, osl_File_E_NETWORK } /* 59 */
+};
+
+/* The following two constants must be the minimum and maximum
+ values in the (contiguous) range of osl_File_E_xec Failure errors.
+*/
+#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
+#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
+
+/* These are the low and high value in the range of errors that are
+ access violations
+*/
+#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
+#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
+
+oslFileError oslTranslateFileError (/*DWORD*/ unsigned long dwError)
+{
+ static const int n = sizeof(errtable)/sizeof(errtable[0]);
+
+ int i;
+ for (i = 0; i < n; ++i )
+ {
+ if (dwError == errtable[i].oscode)
+ return (oslFileError)(errtable[i].errnocode);
+ }
+
+ /* The error code wasn't in the table. We check for a range of
+ osl_File_E_ACCES errors or exec failure errors (ENOEXEC).
+ Otherwise osl_File_E_INVAL is returned.
+ */
+ if ( (dwError >= MIN_EACCES_RANGE) && (dwError <= MAX_EACCES_RANGE) )
+ return osl_File_E_ACCES;
+ else if ( (dwError >= MIN_EXEC_ERROR) && (dwError <= MAX_EXEC_ERROR) )
+ return osl_File_E_NOEXEC;
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+#if OSL_DEBUG_LEVEL > 0
+void _osl_warnFile( const char *message, rtl_uString *ustrFile )
+{
+ char szBuffer[2048];
+
+ if (ustrFile)
+ {
+ rtl_String *strFile = NULL;
+
+ rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ),
+ osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer );
+ rtl_string_release( strFile );
+
+ message = szBuffer;
+ }
+ OSL_ENSURE( 0, message );
+}
+#endif /* OSL_DEBUG_LEVEL */
diff --git a/sal/osl/w32/file_error.h b/sal/osl/w32/file_error.h
new file mode 100644
index 000000000000..3815a021bb5e
--- /dev/null
+++ b/sal/osl/w32/file_error.h
@@ -0,0 +1,51 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_OSL_FILE_ERROR_H
+#define INCLUDED_OSL_FILE_ERROR_H
+
+#include "osl/file.h"
+#include "rtl/ustring.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+oslFileError oslTranslateFileError (/*DWORD*/ unsigned long dwError);
+
+#if OSL_DEBUG_LEVEL > 0
+void _osl_warnFile (const char * message, rtl_uString * ustrFile);
+#define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) )
+#else
+#define OSL_ENSURE_FILE( cond, msg, file ) ((void)0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_OSL_FILE_ERROR_H */
diff --git a/sal/osl/w32/file_url.cxx b/sal/osl/w32/file_url.cxx
new file mode 100644
index 000000000000..90140cda97c6
--- /dev/null
+++ b/sal/osl/w32/file_url.cxx
@@ -0,0 +1,1143 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "file_url.h"
+#include "file_error.h"
+
+#include "rtl/alloc.h"
+#include "osl/diagnose.h"
+#include "osl/file.h"
+#include "osl/mutex.h"
+
+#include "path_helper.hxx"
+
+#include <stdio.h>
+#include <tchar.h>
+
+#if OSL_DEBUG_LEVEL > 0
+#define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) )
+#else
+#define OSL_ENSURE_FILE( cond, msg, file ) ((void)0)
+#endif
+
+#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+#define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\"
+#define WSTR_LONG_PATH_PREFIX L"\\\\?\\"
+#define WSTR_LONG_PATH_PREFIX_UNC L"\\\\?\\UNC\\"
+
+
+//##################################################################
+// FileURL functions
+//##################################################################
+
+extern "C" oslMutex g_CurrentDirectoryMutex; /* Initialized in dllentry.c */
+oslMutex g_CurrentDirectoryMutex = 0;
+
+//#####################################################
+static BOOL IsValidFilePathComponent(
+ LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags)
+{
+ LPCTSTR lpComponentEnd = NULL;
+ LPCTSTR lpCurrent = lpComponent;
+ BOOL fValid = TRUE; /* Assume success */
+ TCHAR cLast = 0;
+
+ /* Path component length must not exceed MAX_PATH even if long path with "\\?\" prefix is used */
+
+ while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < MAX_PATH )
+ {
+ switch ( *lpCurrent )
+ {
+ /* Both backslash and slash determine the end of a path component */
+ case '\0':
+ case '/':
+ case '\\':
+ switch ( cLast )
+ {
+ /* Component must not end with '.' or blank and can't be empty */
+
+ case '.':
+ if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE )
+ {
+ if ( 1 == lpCurrent - lpComponent )
+ {
+ /* Current directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent )
+ {
+ /* Parent directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ }
+ case 0:
+ case ' ':
+ lpComponentEnd = lpCurrent - 1;
+ fValid = FALSE;
+ break;
+ default:
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ break;
+ /* '?' and '*' are valid wildcards but not valid file name characters */
+ case '?':
+ case '*':
+ if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS )
+ break;
+ /* The following characters are reserved */
+ case '<':
+ case '>':
+ case '\"':
+ case '|':
+ case ':':
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ break;
+ default:
+ /* Characters below ASCII 32 are not allowed */
+ if ( *lpCurrent < ' ' )
+ {
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ }
+ break;
+ }
+ cLast = *lpCurrent++;
+ }
+
+ /* If we don't reached the end of the component the length of the component was to long
+ ( See condition of while loop ) */
+ if ( !lpComponentEnd )
+ {
+ fValid = FALSE;
+ lpComponentEnd = lpCurrent;
+ }
+
+ /* Test wether the component specifies a device name what is not allowed */
+
+ // MT: PERFORMANCE:
+ // This is very expensive. A lot of calls to _tcsicmp.
+ // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp!
+ // Possible optimizations
+ // - Array should be const static
+ // - Sorted array, use binary search
+ // - More intelligent check for com1-9, lpt1-9
+ // Maybe make szComponent upper case, don't search case intensitive
+ // Talked to HRO: Could be removed. Shouldn't be used in OOo, and if used for something like a filename, it will lead to an error anyway.
+ /*
+ if ( fValid )
+ {
+ LPCTSTR alpDeviceNames[] =
+ {
+ TEXT("CON"),
+ TEXT("PRN"),
+ TEXT("AUX"),
+ TEXT("CLOCK$"),
+ TEXT("NUL"),
+ TEXT("LPT1"),
+ TEXT("LPT2"),
+ TEXT("LPT3"),
+ TEXT("LPT4"),
+ TEXT("LPT5"),
+ TEXT("LPT6"),
+ TEXT("LPT7"),
+ TEXT("LPT8"),
+ TEXT("LPT9"),
+ TEXT("COM1"),
+ TEXT("COM2"),
+ TEXT("COM3"),
+ TEXT("COM4"),
+ TEXT("COM5"),
+ TEXT("COM6"),
+ TEXT("COM7"),
+ TEXT("COM8"),
+ TEXT("COM9")
+ };
+
+ TCHAR szComponent[MAX_PATH];
+ int nComponentLength;
+ LPCTSTR lpDot;
+ int i;
+
+ // A device name with an extension is also invalid
+ lpDot = _tcschr( lpComponent, '.' );
+
+ if ( !lpDot || lpDot > lpComponentEnd )
+ nComponentLength = lpComponentEnd - lpComponent;
+ else
+ nComponentLength = lpDot - lpComponent;
+
+ _tcsncpy( szComponent, lpComponent, nComponentLength );
+ szComponent[nComponentLength] = 0;
+
+ for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ )
+ {
+ if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) )
+ {
+ lpComponentEnd = lpComponent;
+ fValid = FALSE;
+ break;
+ }
+ }
+ }
+ */
+
+ if ( fValid )
+ {
+ // Empty components are not allowed
+ if ( lpComponentEnd - lpComponent < 1 )
+ fValid = FALSE;
+
+ // If we reached the end of the string NULL is returned
+ else if ( !*lpComponentEnd )
+ lpComponentEnd = NULL;
+
+ }
+
+ if ( lppComponentEnd )
+ *lppComponentEnd = lpComponentEnd;
+
+ return fValid;
+}
+
+//#####################################################
+#define CHARSET_SEPARATOR TEXT("\\/")
+
+DWORD IsValidFilePath(rtl_uString *path, LPCTSTR *lppError, DWORD dwFlags, rtl_uString **corrected)
+{
+ LPCTSTR lpszPath = reinterpret_cast< LPCTSTR >(path->buffer);
+ LPCTSTR lpComponent = lpszPath;
+ BOOL fValid = TRUE;
+ DWORD dwPathType = PATHTYPE_ERROR;
+ sal_Int32 nLength = rtl_uString_getLength( path );
+
+ if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE;
+
+ if ( !lpszPath )
+ fValid = FALSE;
+
+ DWORD dwCandidatPathType = PATHTYPE_ERROR;
+
+ if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1 ) )
+ {
+ /* This is long path in UNC notation */
+ lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC | PATHTYPE_IS_LONGPATH;
+ }
+ else if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) )
+ {
+ /* This is long path */
+ lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1;
+
+ if ( _istalpha( lpComponent[0] ) && ':' == lpComponent[1] )
+ {
+ lpComponent += 2;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL | PATHTYPE_IS_LONGPATH;
+ }
+ }
+ else if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) )
+ {
+ /* The UNC path notation */
+ lpComponent = lpszPath + 2;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC;
+ }
+ else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] )
+ {
+ /* Local path verification. Must start with <drive>: */
+ lpComponent = lpszPath + 2;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL;
+ }
+
+ if ( ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_UNC )
+ {
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE );
+
+ /* So far we have a valid servername. Now let's see if we also have a network resource */
+
+ dwPathType = dwCandidatPathType;
+
+ if ( fValid )
+ {
+ if ( lpComponent && !*++lpComponent )
+ lpComponent = NULL;
+
+ if ( !lpComponent )
+ {
+ #if 0
+ /* We only have a Server specification what is invalid */
+
+ lpComponent = lpszPath;
+ fValid = FALSE;
+ #else
+ dwPathType |= PATHTYPE_IS_SERVER;
+ #endif
+ }
+ else
+ {
+ /* Now test the network resource */
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 );
+
+ /* If we now reached the end of the path, everything is O.K. */
+
+
+ if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+ }
+ }
+ else if ( ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_LOCAL )
+ {
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ lpComponent++;
+ else if ( *lpComponent )
+ fValid = FALSE;
+
+ dwPathType = dwCandidatPathType;
+
+ /* Now we are behind the backslash or it was a simple drive without backslash */
+
+ if ( fValid && !*lpComponent )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+ else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ {
+ /* Can be a relative path */
+ lpComponent = lpszPath;
+
+ /* Relative path can start with a backslash */
+
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ {
+ lpComponent++;
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+
+ dwPathType = PATHTYPE_RELATIVE;
+ }
+ else
+ {
+ /* Anything else is an error */
+ fValid = FALSE;
+ lpComponent = lpszPath;
+ }
+
+ /* Now validate each component of the path */
+ while ( fValid && lpComponent )
+ {
+ // Correct path by merging consecutive slashes:
+ if (*lpComponent == '\\' && corrected != NULL) {
+ sal_Int32 i = lpComponent - lpszPath;
+ rtl_uString_newReplaceStrAt(corrected, path, i, 1, NULL);
+ //TODO: handle out-of-memory
+ lpszPath = reinterpret_cast< LPCTSTR >((*corrected)->buffer);
+ lpComponent = lpszPath + i;
+ }
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags );
+
+ if ( fValid && lpComponent )
+ {
+ lpComponent++;
+
+ /* If the string behind the backslash is empty, we've done */
+
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+ }
+
+ /* The path can be longer than MAX_PATH only in case it has the longpath prefix */
+ if ( fValid && !( dwPathType & PATHTYPE_IS_LONGPATH ) && _tcslen( lpszPath ) >= MAX_PATH )
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath + MAX_PATH;
+ }
+
+ if ( lppError )
+ *lppError = lpComponent;
+
+ return fValid ? dwPathType : PATHTYPE_ERROR;
+}
+
+//#####################################################
+static sal_Int32 PathRemoveFileSpec(LPTSTR lpPath, LPTSTR lpFileName, sal_Int32 nFileBufLen )
+{
+ sal_Int32 nRemoved = 0;
+
+ if ( nFileBufLen )
+ {
+ lpFileName[0] = 0;
+ LPTSTR lpLastBkSlash = _tcsrchr( lpPath, '\\' );
+ LPTSTR lpLastSlash = _tcsrchr( lpPath, '/' );
+ LPTSTR lpLastDelimiter = lpLastSlash > lpLastBkSlash ? lpLastSlash : lpLastBkSlash;
+
+ if ( lpLastDelimiter )
+ {
+ sal_Int32 nDelLen = _tcslen( lpLastDelimiter );
+ if ( 1 == nDelLen )
+ {
+ if ( lpLastDelimiter > lpPath && *(lpLastDelimiter - 1) != ':' )
+ {
+ *lpLastDelimiter = 0;
+ *lpFileName = 0;
+ nRemoved = nDelLen;
+ }
+ }
+ else if ( nDelLen && nDelLen - 1 < nFileBufLen )
+ {
+ _tcscpy( lpFileName, lpLastDelimiter + 1 );
+ *(++lpLastDelimiter) = 0;
+ nRemoved = nDelLen - 1;
+ }
+ }
+ }
+
+ return nRemoved;
+}
+
+//#####################################################
+// Undocumented in SHELL32.DLL ordinal 32
+static LPTSTR PathAddBackslash(LPTSTR lpPath, sal_Int32 nBufLen)
+{
+ LPTSTR lpEndPath = NULL;
+
+ if ( lpPath )
+ {
+ int nLen = _tcslen(lpPath);
+
+ if ( !nLen || lpPath[nLen-1] != '\\' && lpPath[nLen-1] != '/' && nLen < nBufLen - 1 )
+ {
+ lpEndPath = lpPath + nLen;
+ *lpEndPath++ = '\\';
+ *lpEndPath = 0;
+ }
+ }
+ return lpEndPath;
+}
+
+//#####################################################
+// Same as GetLongPathName but also 95/NT4
+static DWORD GetCaseCorrectPathNameEx(
+ LPTSTR lpszPath, // path buffer to convert
+ DWORD cchBuffer, // size of path buffer
+ DWORD nSkipLevels,
+ BOOL bCheckExistence )
+{
+ ::osl::LongPathBuffer< WCHAR > szFile( MAX_PATH + 1 );
+ sal_Int32 nRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 );
+ sal_Int32 nLastStepRemoved = nRemoved;
+ while ( nLastStepRemoved && szFile[0] == 0 )
+ {
+ // remove separators
+ nLastStepRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 );
+ nRemoved += nLastStepRemoved;
+ }
+
+ if ( nRemoved )
+ {
+ BOOL bSkipThis = FALSE;
+
+ if ( 0 == _tcscmp( szFile, TEXT("..") ) )
+ {
+ bSkipThis = TRUE;
+ nSkipLevels += 1;
+ }
+ else if ( 0 == _tcscmp( szFile, TEXT(".") ) )
+ {
+ bSkipThis = TRUE;
+ }
+ else if ( nSkipLevels )
+ {
+ bSkipThis = TRUE;
+ nSkipLevels--;
+ }
+ else
+ bSkipThis = FALSE;
+
+ GetCaseCorrectPathNameEx( lpszPath, cchBuffer, nSkipLevels, bCheckExistence );
+
+ PathAddBackslash( lpszPath, cchBuffer );
+
+ /* Analyze parent if not only a trailing backslash was cutted but a real file spec */
+ if ( !bSkipThis )
+ {
+ if ( bCheckExistence )
+ {
+ ::osl::LongPathBuffer< WCHAR > aShortPath( MAX_LONG_PATH );
+ _tcscpy( aShortPath, lpszPath );
+ _tcscat( aShortPath, szFile );
+
+ WIN32_FIND_DATA aFindFileData;
+ HANDLE hFind = FindFirstFile( aShortPath, &aFindFileData );
+
+ if ( IsValidHandle(hFind) )
+ {
+ _tcscat( lpszPath, aFindFileData.cFileName[0] ? aFindFileData.cFileName : aFindFileData.cAlternateFileName );
+
+ FindClose( hFind );
+ }
+ else
+ lpszPath[0] = 0;
+ }
+ else
+ {
+ /* add the segment name back */
+ _tcscat( lpszPath, szFile );
+ }
+ }
+ }
+ else
+ {
+ /* File specification can't be removed therefore the short path is either a drive
+ or a network share. If still levels to skip are left, the path specification
+ tries to travel below the file system root */
+ if ( nSkipLevels )
+ lpszPath[0] = 0;
+ else
+ _tcsupr( lpszPath );
+ }
+
+ return _tcslen( lpszPath );
+}
+
+//#####################################################
+#define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\"
+
+DWORD GetCaseCorrectPathName(
+ LPCTSTR lpszShortPath, // file name
+ LPTSTR lpszLongPath, // path buffer
+ DWORD cchBuffer, // size of path buffer
+ BOOL bCheckExistence
+)
+{
+ /* Special handling for "\\.\" as system root */
+ if ( lpszShortPath && 0 == wcscmp( lpszShortPath, WSTR_SYSTEM_ROOT_PATH ) )
+ {
+ if ( cchBuffer >= ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) )
+ {
+ wcscpy( lpszLongPath, WSTR_SYSTEM_ROOT_PATH );
+ return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
+ }
+ else
+ {
+ return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
+ }
+ }
+ else if ( lpszShortPath )
+ {
+ if ( _tcslen( lpszShortPath ) <= cchBuffer )
+ {
+ _tcscpy( lpszLongPath, lpszShortPath );
+ return GetCaseCorrectPathNameEx( lpszLongPath, cchBuffer, 0, bCheckExistence );
+ }
+ }
+
+ return 0;
+}
+
+
+//#############################################
+static sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL )
+{
+ sal_Char *pBuffer;
+ const sal_Char *pSrcEnd;
+ const sal_Char *pSrc;
+ sal_Char *pDest;
+ sal_Int32 nSrcLen;
+ sal_Bool bValidEncoded = sal_True; /* Assume success */
+
+ /* The resulting decoded string length is shorter or equal to the source length */
+
+ nSrcLen = rtl_string_getLength(strUTF8);
+ pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1));
+
+ pDest = pBuffer;
+ pSrc = rtl_string_getStr(strUTF8);
+ pSrcEnd = pSrc + nSrcLen;
+
+ /* Now decode the URL what should result in an UTF8 string */
+ while ( bValidEncoded && pSrc < pSrcEnd )
+ {
+ switch ( *pSrc )
+ {
+ case '%':
+ {
+ sal_Char aToken[3];
+ sal_Char aChar;
+
+ pSrc++;
+ aToken[0] = *pSrc++;
+ aToken[1] = *pSrc++;
+ aToken[2] = 0;
+
+ aChar = (sal_Char)strtoul( aToken, NULL, 16 );
+
+ /* The chars are path delimiters and must not be encoded */
+
+ if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar )
+ bValidEncoded = sal_False;
+ else
+ *pDest++ = aChar;
+ }
+ break;
+ default:
+ *pDest++ = *pSrc++;
+ break;
+ }
+ }
+
+ *pDest++ = 0;
+
+ if ( bValidEncoded )
+ {
+ rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrDecodedURL != 0);
+ }
+
+ rtl_freeMemory( pBuffer );
+
+ return bValidEncoded;
+}
+
+//#############################################
+static void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL )
+{
+ /* Encode non ascii characters within the URL */
+
+ rtl_String *strUTF8 = NULL;
+ sal_Char *pszEncodedURL;
+ const sal_Char *pURLScan;
+ sal_Char *pURLDest;
+ sal_Int32 nURLScanLen;
+ sal_Int32 nURLScanCount;
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) );
+
+ pURLDest = pszEncodedURL;
+ pURLScan = rtl_string_getStr( strUTF8 );
+ nURLScanLen = rtl_string_getLength( strUTF8 );
+ nURLScanCount = 0;
+
+ while ( nURLScanCount < nURLScanLen )
+ {
+ sal_Char cCurrent = *pURLScan;
+ switch ( cCurrent )
+ {
+ default:
+ if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) )
+ {
+ sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent );
+ pURLDest += 3;
+ break;
+ }
+ case '!':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ case '$':
+ case '&':
+ case '+':
+ case ',':
+ case '=':
+ case '@':
+ case ':':
+ case '/':
+ case '\\':
+ case '|':
+ *pURLDest++ = cCurrent;
+ break;
+ case 0:
+ break;
+ }
+
+ pURLScan++;
+ nURLScanCount++;
+ }
+
+ *pURLDest = 0;
+
+ rtl_string_release( strUTF8 );
+ rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL );
+ rtl_freeMemory( pszEncodedURL );
+}
+
+//#############################################
+
+oslFileError _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative )
+{
+ rtl_String *strUTF8 = NULL;
+ rtl_uString *strDecodedURL = NULL;
+ rtl_uString *strTempPath = NULL;
+ const sal_Unicode *pDecodedURL;
+ sal_uInt32 nDecodedLen;
+ sal_Bool bValidEncoded;
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+
+ /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from
+ having a mixed encoded URL later */
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */
+
+ OSL_ENSURE_FILE(
+ strUTF8->length == strURL->length ||
+ 0 != rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 )
+ ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL );
+
+ bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL );
+
+ /* Release the encoded UTF8 string */
+ rtl_string_release( strUTF8 );
+
+ if ( bValidEncoded )
+ {
+ /* Replace backslashes and pipes */
+
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' );
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' );
+
+ pDecodedURL = rtl_uString_getStr( strDecodedURL );
+ nDecodedLen = rtl_uString_getLength( strDecodedURL );
+
+ /* Must start with "file://" */
+ if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) )
+ {
+ sal_uInt32 nSkip;
+
+ if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) )
+ nSkip = 8;
+ else if (
+ 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) ||
+ 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 )
+ )
+ nSkip = 17;
+ else
+ nSkip = 5;
+
+ /* Indicates local root */
+ if ( nDecodedLen == nSkip )
+ rtl_uString_newFromStr_WithLength( &strTempPath, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 );
+ else
+ {
+ /* do not separate the directory and file case, so the maximal path lengs without prefix is MAX_PATH-12 */
+ if ( nDecodedLen - nSkip <= MAX_PATH - 12 )
+ {
+ rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip );
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Unicode > aBuf( MAX_LONG_PATH );
+ sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>(pDecodedURL + nSkip),
+ ::osl::mingw_reinterpret_cast<LPTSTR>(aBuf),
+ aBuf.getBufSizeInSymbols(),
+ sal_False );
+
+ if ( nNewLen <= MAX_PATH - 12
+ || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 )
+ || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) )
+ {
+ rtl_uString_newFromStr_WithLength( &strTempPath, aBuf, nNewLen );
+ }
+ else if ( pDecodedURL[nSkip] == (sal_Unicode)'\\' && pDecodedURL[nSkip+1] == (sal_Unicode)'\\' )
+ {
+ /* it should be an UNC path, use the according prefix */
+ rtl_uString *strSuffix = NULL;
+ rtl_uString *strPrefix = NULL;
+ rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1 );
+ rtl_uString_newFromStr_WithLength( &strSuffix, aBuf + 2, nNewLen - 2 );
+
+ rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix );
+
+ rtl_uString_release( strPrefix );
+ rtl_uString_release( strSuffix );
+ }
+ else
+ {
+ rtl_uString *strSuffix = NULL;
+ rtl_uString *strPrefix = NULL;
+ rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1 );
+ rtl_uString_newFromStr_WithLength( &strSuffix, aBuf, nNewLen );
+
+ rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix );
+
+ rtl_uString_release( strPrefix );
+ rtl_uString_release( strSuffix );
+ }
+ }
+ }
+
+ if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
+ nError = osl_File_E_None;
+ }
+ else if ( bAllowRelative ) /* This maybe a relative file URL */
+ {
+ /* In future the relative path could be converted to absolute if it is too long */
+ rtl_uString_assign( &strTempPath, strDecodedURL );
+
+ if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
+ nError = osl_File_E_None;
+ }
+ /*
+ else
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL );
+ */
+
+ }
+
+ if ( strDecodedURL )
+ rtl_uString_release( strDecodedURL );
+
+ if ( osl_File_E_None == nError )
+ rtl_uString_assign( pustrPath, strTempPath );
+
+ if ( strTempPath )
+ rtl_uString_release( strTempPath );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL );
+ */
+
+ return nError;
+}
+
+//#############################################
+oslFileError _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL )
+{
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+ rtl_uString *strTempURL = NULL;
+ DWORD dwPathType = PATHTYPE_ERROR;
+
+ if (strPath)
+ dwPathType = IsValidFilePath(strPath, NULL, VALIDATEPATH_ALLOW_RELATIVE, NULL);
+
+ if (dwPathType)
+ {
+ rtl_uString *strTempPath = NULL;
+
+ if ( dwPathType & PATHTYPE_IS_LONGPATH )
+ {
+ rtl_uString *strBuffer = NULL;
+ sal_uInt32 nIgnore = 0;
+ sal_uInt32 nLength = 0;
+
+ /* the path has the longpath prefix, lets remove it */
+ switch ( dwPathType & PATHTYPE_MASK_TYPE )
+ {
+ case PATHTYPE_ABSOLUTE_UNC:
+ nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1;
+ OSL_ENSURE( nIgnore == 8, "Unexpected long path UNC prefix!" );
+
+ /* generate the normal UNC path */
+ nLength = rtl_uString_getLength( strPath );
+ rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore - 2, nLength - nIgnore + 2 );
+ strBuffer->buffer[0] = '\\';
+
+ rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' );
+ rtl_uString_release( strBuffer );
+ break;
+
+ case PATHTYPE_ABSOLUTE_LOCAL:
+ nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1;
+ OSL_ENSURE( nIgnore == 4, "Unexpected long path prefix!" );
+
+ /* generate the normal path */
+ nLength = rtl_uString_getLength( strPath );
+ rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore, nLength - nIgnore );
+
+ rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' );
+ rtl_uString_release( strBuffer );
+ break;
+
+ default:
+ OSL_ASSERT( "Unexpected long path format!" );
+ rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
+ break;
+ }
+ }
+ else
+ {
+ /* Replace backslashes */
+ rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
+ }
+
+ switch ( dwPathType & PATHTYPE_MASK_TYPE )
+ {
+ case PATHTYPE_RELATIVE:
+ rtl_uString_assign( &strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_UNC:
+ rtl_uString_newFromAscii( &strTempURL, "file:" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_LOCAL:
+ rtl_uString_newFromAscii( &strTempURL, "file:///" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ default:
+ break;
+ }
+
+ /* Release temp path */
+ rtl_uString_release( strTempPath );
+ }
+
+ if ( osl_File_E_None == nError )
+ {
+ rtl_String *strEncodedURL = NULL;
+
+ /* Encode the URL */
+ _osl_encodeURL( strTempURL, &strEncodedURL );
+
+ /* Provide URL via unicode string */
+ rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrURL != 0);
+ rtl_string_release( strEncodedURL );
+ }
+
+ /* Release temp URL */
+ if ( strTempURL )
+ rtl_uString_release( strTempURL );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath );
+ */
+ return nError;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getFileURLFromSystemPath(
+ rtl_uString* ustrPath, rtl_uString** pustrURL )
+{
+ return _osl_getFileURLFromSystemPath( ustrPath, pustrURL );
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getSystemPathFromFileURL(
+ rtl_uString *ustrURL, rtl_uString **pustrPath)
+{
+ return _osl_getSystemPathFromFileURL( ustrURL, pustrPath, sal_True );
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_searchFileURL(
+ rtl_uString *ustrFileName,
+ rtl_uString *ustrSystemSearchPath,
+ rtl_uString **pustrPath)
+{
+ rtl_uString *ustrUNCPath = NULL;
+ rtl_uString *ustrSysPath = NULL;
+ oslFileError error;
+
+ /* First try to interpret the file name as an URL even a relative one */
+ error = _osl_getSystemPathFromFileURL( ustrFileName, &ustrUNCPath, sal_True );
+
+ /* So far we either have an UNC path or something invalid
+ Now create a system path */
+ if ( osl_File_E_None == error )
+ error = _osl_getSystemPathFromFileURL( ustrUNCPath, &ustrSysPath, sal_True );
+
+ if ( osl_File_E_None == error )
+ {
+ DWORD nBufferLength;
+ DWORD dwResult;
+ LPTSTR lpBuffer = NULL;
+ LPTSTR lpszFilePart;
+
+ /* Repeat calling SearchPath ...
+ Start with MAX_PATH for the buffer. In most cases this
+ will be enough and does not force the loop to runtwice */
+ dwResult = MAX_PATH;
+
+ do
+ {
+ /* If search path is empty use a NULL pointer instead according to MSDN documentation of SearchPath */
+ LPCTSTR lpszSearchPath = ustrSystemSearchPath && ustrSystemSearchPath->length ? reinterpret_cast<LPCTSTR>(ustrSystemSearchPath->buffer) : NULL;
+ LPCTSTR lpszSearchFile = reinterpret_cast<LPCTSTR>(ustrSysPath->buffer);
+
+ /* Allocate space for buffer according to previous returned count of required chars */
+ /* +1 is not neccessary if we follow MSDN documentation but for robustness we do so */
+ nBufferLength = dwResult + 1;
+ lpBuffer = lpBuffer ?
+ reinterpret_cast<LPTSTR>(rtl_reallocateMemory(lpBuffer, nBufferLength * sizeof(TCHAR))) :
+ reinterpret_cast<LPTSTR>(rtl_allocateMemory(nBufferLength * sizeof(TCHAR)));
+
+ dwResult = SearchPath( lpszSearchPath, lpszSearchFile, NULL, nBufferLength, lpBuffer, &lpszFilePart );
+ } while ( dwResult && dwResult >= nBufferLength );
+
+ /* ... until an error occures or buffer is large enough.
+ dwResult == nBufferLength can not happen according to documentation but lets be robust ;-) */
+
+ if ( dwResult )
+ {
+ rtl_uString_newFromStr( &ustrSysPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
+ error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
+ }
+ else
+ {
+ WIN32_FIND_DATA aFindFileData;
+ HANDLE hFind;
+
+ /* Somthing went wrong, perhaps the path was absolute */
+ error = oslTranslateFileError( GetLastError() );
+
+ hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(ustrSysPath->buffer), &aFindFileData );
+
+ if ( IsValidHandle(hFind) )
+ {
+ error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
+ FindClose( hFind );
+ }
+ }
+
+ rtl_freeMemory( lpBuffer );
+ }
+
+ if ( ustrSysPath )
+ rtl_uString_release( ustrSysPath );
+
+ if ( ustrUNCPath )
+ rtl_uString_release( ustrUNCPath );
+
+ return error;
+}
+
+//#####################################################
+
+oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL )
+{
+ oslFileError eError;
+ rtl_uString *ustrRelSysPath = NULL;
+ rtl_uString *ustrBaseSysPath = NULL;
+
+ if ( ustrBaseURL && ustrBaseURL->length )
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" );
+
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True );
+ }
+ else
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" );
+ }
+
+ if ( !eError )
+ {
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ ::osl::LongPathBuffer< sal_Unicode > aCurrentDir( MAX_LONG_PATH );
+ LPTSTR lpFilePart = NULL;
+ DWORD dwResult;
+
+/*@@@ToDo
+ Bad, bad hack, this only works if the base path
+ really exists which is not necessary according
+ to RFC2396
+ The whole FileURL implementation should be merged
+ with the rtl/uri class.
+*/
+ if ( ustrBaseSysPath )
+ {
+ osl_acquireMutex( g_CurrentDirectoryMutex );
+
+ GetCurrentDirectoryW( aCurrentDir.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aCurrentDir) );
+ SetCurrentDirectoryW( reinterpret_cast<LPCWSTR>(ustrBaseSysPath->buffer) );
+ }
+
+ dwResult = GetFullPathNameW( reinterpret_cast<LPCWSTR>(ustrRelSysPath->buffer), aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), &lpFilePart );
+
+ if ( ustrBaseSysPath )
+ {
+ SetCurrentDirectoryW( ::osl::mingw_reinterpret_cast<LPCWSTR>(aCurrentDir) );
+
+ osl_releaseMutex( g_CurrentDirectoryMutex );
+ }
+
+ if ( dwResult )
+ {
+ if ( dwResult >= aBuffer.getBufSizeInSymbols() )
+ eError = osl_File_E_INVAL;
+ else
+ {
+ rtl_uString *ustrAbsSysPath = NULL;
+
+ rtl_uString_newFromStr( &ustrAbsSysPath, aBuffer );
+
+ eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL );
+
+ if ( ustrAbsSysPath )
+ rtl_uString_release( ustrAbsSysPath );
+ }
+ }
+ else
+ eError = oslTranslateFileError( GetLastError() );
+ }
+
+ if ( ustrBaseSysPath )
+ rtl_uString_release( ustrBaseSysPath );
+
+ if ( ustrRelSysPath )
+ rtl_uString_release( ustrRelSysPath );
+
+ return eError;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getCanonicalName( rtl_uString *strRequested, rtl_uString **strValid )
+{
+ rtl_uString_newFromString(strValid, strRequested);
+ return osl_File_E_None;
+}
diff --git a/sal/osl/w32/file_url.h b/sal/osl/w32/file_url.h
new file mode 100644
index 000000000000..d9137c8c2fcc
--- /dev/null
+++ b/sal/osl/w32/file_url.h
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_OSL_FILE_URL_H
+#define INCLUDED_OSL_FILE_URL_H
+
+#include "sal/types.h"
+#include "rtl/ustring.h"
+#include "osl/file.h"
+
+#ifdef _MSC_VER
+#pragma warning(push,1)
+#endif
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PATHTYPE_ERROR 0
+#define PATHTYPE_RELATIVE 1
+#define PATHTYPE_ABSOLUTE_UNC 2
+#define PATHTYPE_ABSOLUTE_LOCAL 3
+#define PATHTYPE_MASK_TYPE 0xFF
+#define PATHTYPE_IS_VOLUME 0x0100
+#define PATHTYPE_IS_SERVER 0x0200
+#define PATHTYPE_IS_LONGPATH 0x0400
+
+#define VALIDATEPATH_NORMAL 0x0000
+#define VALIDATEPATH_ALLOW_WILDCARDS 0x0001
+#define VALIDATEPATH_ALLOW_ELLIPSE 0x0002
+#define VALIDATEPATH_ALLOW_RELATIVE 0x0004
+#define VALIDATEPATH_ALLOW_UNC 0x0008
+
+#define MAX_LONG_PATH 32767
+
+DWORD IsValidFilePath (
+ rtl_uString * path,
+ LPCTSTR * lppError,
+ DWORD dwFlags,
+ rtl_uString ** corrected
+);
+
+DWORD GetCaseCorrectPathName (
+ LPCTSTR lpszShortPath, // file name
+ LPTSTR lpszLongPath, // path buffer
+ DWORD cchBuffer, // size of path buffer
+ BOOL bCheckExistence
+);
+
+oslFileError _osl_getSystemPathFromFileURL (
+ rtl_uString * strURL,
+ rtl_uString ** pustrPath,
+ sal_Bool bAllowRelative
+);
+
+oslFileError _osl_getFileURLFromSystemPath (
+ rtl_uString * strPath,
+ rtl_uString ** pstrURL
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_OSL_FILE_URL_H */
diff --git a/sal/osl/w32/interlck.c b/sal/osl/w32/interlck.c
new file mode 100644
index 000000000000..14589e56184a
--- /dev/null
+++ b/sal/osl/w32/interlck.c
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include <osl/interlck.h>
+#include <osl/diagnose.h>
+
+extern int osl_isSingleCPU;
+
+/* For all Intel x86 above x486 we use a spezial inline assembler implementation.
+ The main reason is that WIN9? does not return the result of the operation.
+ Instead there is only returned a value greater than zero is the increment
+ result is greater than zero, but not the the result of the addition.
+ For Windows NT the native function could be used, because the correct result
+ is returned. Beacuse of simpler code maintance and performace reasons we use
+ on every x86-Windows-Platform the inline assembler implementation.
+*/
+
+/*****************************************************************************/
+/* osl_incrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
+#ifdef _M_IX86
+#ifdef __MINGW32__
+{
+ asm
+ (
+ " movl %0, %%ecx\n"
+ " movl $1, %%eax\n"
+ " movl %1, %%edx\n"
+ " cmpl $0, %%edx\n"
+ " je 1f\n"
+ " xadd %%eax, (%%ecx)\n"
+ " jmp 2f\n"
+ "1:\n"
+ " lock xadd %%eax, (%%ecx)\n"
+ "2:\n"
+ " incl %%eax\n"
+ ::"m"(pCount),"m"(osl_isSingleCPU)
+ );
+}
+#else
+#pragma warning(disable: 4035)
+{
+ __asm
+ {
+ mov ecx, pCount
+ mov eax, 1
+ mov edx, osl_isSingleCPU
+ cmp edx, 0
+ je is_not_single
+ xadd dword ptr [ecx],eax
+ jmp cont
+ is_not_single:
+ lock xadd dword ptr [ecx],eax
+ cont:
+ inc eax
+ }
+}
+#pragma warning(default: 4035)
+#endif
+#else
+#pragma message("WARNING: Using system InterlockedIncrement")
+{
+ return (InterlockedIncrement(pCount));
+}
+#endif
+
+/*****************************************************************************/
+/* osl_decrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
+#ifdef _M_IX86
+#ifdef __MINGW32__
+{
+ asm
+ (
+ " movl %0, %%ecx\n"
+ " orl $-1, %%eax\n"
+ " movl %1, %%edx\n"
+ " cmpl $0, %%edx\n"
+ " je 1f\n"
+ " xadd %%eax, (%%ecx)\n"
+ " jmp 2f\n"
+ "1:\n"
+ " lock xadd %%eax, (%%ecx)\n"
+ "2:\n"
+ " decl %%eax\n"
+ ::"m"(pCount),"m"(osl_isSingleCPU)
+ );
+}
+#else
+#pragma warning(disable: 4035)
+{
+ __asm
+ {
+ mov ecx, pCount
+ or eax, -1
+ mov edx, osl_isSingleCPU
+ cmp edx, 0
+ je is_not_single
+ xadd dword ptr [ecx],eax
+ jmp cont
+ is_not_single:
+ lock xadd dword ptr [ecx],eax
+ cont:
+ dec eax
+ }
+}
+#pragma warning(default: 4035)
+#endif
+#else
+#pragma message("WARNING: Using system InterlockedDecrement")
+{
+ return (InterlockedDecrement(pCount));
+}
+#endif
diff --git a/sal/osl/w32/libutil.c b/sal/osl/w32/libutil.c
new file mode 100644
index 000000000000..e00aef2e158d
--- /dev/null
+++ b/sal/osl/w32/libutil.c
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+static BOOL g_bInit = FALSE;
+static DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
+
+DWORD GetPlatformId()
+{
+
+ if (!g_bInit)
+ {
+ OSVERSIONINFO aInfo;
+
+ aInfo.dwOSVersionInfoSize = sizeof(aInfo);
+ if (GetVersionEx(&aInfo))
+ g_dwPlatformId = aInfo.dwPlatformId;
+
+ g_bInit = TRUE;
+ }
+
+ return g_dwPlatformId;
+}
diff --git a/sal/osl/w32/module.cxx b/sal/osl/w32/module.cxx
new file mode 100644
index 000000000000..b730bd3347df
--- /dev/null
+++ b/sal/osl/w32/module.cxx
@@ -0,0 +1,480 @@
+/*************************************************************************
+*
+* 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 "system.h"
+#include <tlhelp32.h>
+
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include <osl/module.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <rtl/logfile.h>
+
+/*
+ under WIN32, we use the void* oslModule
+ as a WIN32 HANDLE (which is also a 32-bit value)
+*/
+
+/*****************************************************************************/
+/* osl_loadModule */
+/*****************************************************************************/
+oslModule SAL_CALL osl_loadModule(rtl_uString *strModuleName, sal_Int32 nRtldMode )
+{
+ HINSTANCE hInstance;
+ UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
+ rtl_uString* Module = NULL;
+ oslModule ret = 0;
+ oslFileError nError;
+
+ RTL_LOGFILE_TRACE1( "{ osl_loadModule start: %S", (LPTSTR)&strModuleName->buffer );
+
+ OSL_ASSERT(strModuleName);
+
+ nRtldMode = nRtldMode; /* avoid warnings */
+
+ nError = osl_getSystemPathFromFileURL(strModuleName, &Module);
+
+ if ( osl_File_E_None != nError )
+ rtl_uString_assign(&Module, strModuleName);
+
+ hInstance = LoadLibraryW(reinterpret_cast<LPCWSTR>(Module->buffer));
+ if (hInstance == NULL)
+ hInstance = LoadLibraryExW(reinterpret_cast<LPCWSTR>(Module->buffer), NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH);
+
+ if (hInstance <= (HINSTANCE)HINSTANCE_ERROR)
+ hInstance = 0;
+
+ ret = (oslModule) hInstance;
+ rtl_uString_release(Module);
+ SetErrorMode(errorMode);
+
+ RTL_LOGFILE_TRACE1( "} osl_loadModule end: %S", (LPTSTR)&strModuleName->buffer );
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* osl_getModuleHandle */
+/*****************************************************************************/
+
+sal_Bool SAL_CALL
+osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
+{
+ HINSTANCE hInstance = GetModuleHandleW(reinterpret_cast<LPCWSTR>(pModuleName->buffer));
+ if( hInstance )
+ {
+ *pResult = (oslModule) hInstance;
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_unloadModule */
+/*****************************************************************************/
+void SAL_CALL osl_unloadModule(oslModule Module)
+{
+ FreeLibrary((HINSTANCE)Module);
+}
+
+/*****************************************************************************/
+/* osl_getSymbol */
+/*****************************************************************************/
+void* SAL_CALL osl_getSymbol(oslModule Module, rtl_uString *strSymbolName)
+{
+ /* casting from a function pointer to a data pointer is invalid
+ be in this case unavoidable because the API has to stay
+ compitable we need to keep this function which returns a
+ void* by definition */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4054)
+#endif
+ return (void*)(osl_getFunctionSymbol(Module, strSymbolName));
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+}
+
+/*****************************************************************************/
+/* osl_getFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName )
+{
+ rtl_String *symbolName = NULL;
+ oslGenericFunction address;
+
+ OSL_ASSERT(Module);
+ OSL_ASSERT(strSymbolName);
+
+ rtl_uString2String(
+ &symbolName,
+ strSymbolName->buffer,
+ strSymbolName->length,
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS
+ );
+
+ address=osl_getAsciiFunctionSymbol(Module, rtl_string_getStr(symbolName));
+ rtl_string_release(symbolName);
+
+ return address;
+}
+
+/*****************************************************************************/
+/* osl_getAsciiFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL
+osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol )
+{
+ oslGenericFunction fncAddr = NULL;
+
+ if( pSymbol )
+ fncAddr=(oslGenericFunction)GetProcAddress((HINSTANCE) Module, pSymbol);
+
+ return fncAddr;
+}
+
+
+
+/*****************************************************************************/
+/* osl_addressGetModuleURL */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* Implementation for Windows 95, 98 and Me */
+/*****************************************************************************/
+
+/* Undefine because there is no explicit "A" definition */
+
+#ifdef MODULEENTRY32
+#undef MODULEENTRY32
+#endif
+
+#ifdef LPMODULEENTRY32
+#undef LPMODULEENTRY32
+#endif
+
+typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_PROC)( DWORD dwFlags, DWORD th32ProcessID );
+typedef BOOL (WINAPI *Module32First_PROC)( HANDLE hSnapshot, LPMODULEENTRY32 lpme32 );
+typedef BOOL (WINAPI *Module32Next_PROC)( HANDLE hSnapshot, LPMODULEENTRY32 lpme32 );
+
+static sal_Bool SAL_CALL _osl_addressGetModuleURL_Windows( void *pv, rtl_uString **pustrURL )
+{
+ sal_Bool bSuccess = sal_False; /* Assume failure */
+ HMODULE hModKernel32 = GetModuleHandleA( "KERNEL32.DLL" );
+
+ if ( hModKernel32 )
+ {
+ CreateToolhelp32Snapshot_PROC lpfnCreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_PROC)GetProcAddress( hModKernel32, "CreateToolhelp32Snapshot" );
+ Module32First_PROC lpfnModule32First = (Module32First_PROC)GetProcAddress( hModKernel32, "Module32First" );
+ Module32Next_PROC lpfnModule32Next = (Module32Next_PROC)GetProcAddress( hModKernel32, "Module32Next" );
+
+ if ( lpfnCreateToolhelp32Snapshot && lpfnModule32First && lpfnModule32Next )
+ {
+ HANDLE hModuleSnap = NULL;
+ DWORD dwProcessId = GetCurrentProcessId();
+
+ // Take a snapshot of all modules in the specified process.
+
+ hModuleSnap = lpfnCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId );
+
+ if ( INVALID_HANDLE_VALUE != hModuleSnap )
+ {
+ MODULEENTRY32 me32 = {0};
+
+ // Fill the size of the structure before using it.
+
+ me32.dwSize = sizeof(MODULEENTRY32);
+
+ // Walk the module list of the process, and find the module of
+ // interest. Then copy the information to the buffer pointed
+ // to by lpMe32 so that it can be returned to the caller.
+
+ if ( lpfnModule32First(hModuleSnap, &me32) )
+ {
+ do
+ {
+ if ( (BYTE *)pv >= (BYTE *)me32.hModule && (BYTE *)pv < (BYTE *)me32.hModule + me32.modBaseSize )
+ {
+ rtl_uString *ustrSysPath = NULL;
+
+ rtl_string2UString( &ustrSysPath, me32.szExePath, strlen(me32.szExePath), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrSysPath != NULL);
+ osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
+ rtl_uString_release( ustrSysPath );
+
+ bSuccess = sal_True;
+ }
+
+ } while ( !bSuccess && lpfnModule32Next( hModuleSnap, &me32 ) );
+ }
+
+
+ // Do not forget to clean up the snapshot object.
+
+ CloseHandle (hModuleSnap);
+ }
+
+ }
+ }
+
+ return bSuccess;
+}
+
+/***************************************************************************************/
+/* Implementation for Windows NT, 2K and XP (2K and XP could use the above method too) */
+/***************************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <imagehlp.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+typedef BOOL (WINAPI *SymInitialize_PROC)(
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess
+ );
+
+typedef BOOL (WINAPI *SymCleanup_PROC)(
+ HANDLE hProcess
+ );
+
+typedef BOOL (WINAPI *SymGetModuleInfo_PROC)(
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PIMAGEHLP_MODULE ModuleInfo
+ );
+
+/* Seems that IMAGEHLP.DLL is always availiable on NT 4. But MSDN from Platform SDK says Win 2K is required. MSDN from VS 6.0a says
+ it's O.K on NT 4 ???!!!
+ BTW: We are using ANSI function because not all version of IMAGEHLP.DLL contain Unicode support
+*/
+
+static sal_Bool SAL_CALL _osl_addressGetModuleURL_NT4( void *pv, rtl_uString **pustrURL )
+{
+ sal_Bool bSuccess = sal_False; /* Assume failure */
+
+ /* IMAGEHELP.DLL has a bug that it recursivly scans subdirectories of
+ the root when calling SymInitialize(), so we preferr DBGHELP.DLL
+ which exports the same symbols and is shipped with OOo */
+
+ HMODULE hModImageHelp = LoadLibrary( "DBGHELP.DLL" );
+
+ if ( !hModImageHelp )
+ hModImageHelp = LoadLibrary( "IMAGEHLP.DLL" );
+
+ if ( hModImageHelp )
+ {
+ SymGetModuleInfo_PROC lpfnSymGetModuleInfo;
+ SymInitialize_PROC lpfnSymInitialize;
+ SymCleanup_PROC lpfnSymCleanup;
+
+
+ lpfnSymInitialize = (SymInitialize_PROC)GetProcAddress( hModImageHelp, "SymInitialize" );
+ lpfnSymCleanup = (SymCleanup_PROC)GetProcAddress( hModImageHelp, "SymCleanup" );
+ lpfnSymGetModuleInfo = (SymGetModuleInfo_PROC)GetProcAddress( hModImageHelp, "SymGetModuleInfo" );
+
+
+ if ( lpfnSymInitialize && lpfnSymCleanup && lpfnSymGetModuleInfo )
+ {
+ IMAGEHLP_MODULE ModuleInfo;
+ ::osl::LongPathBuffer< sal_Char > aModuleFileName( MAX_LONG_PATH );
+ LPSTR lpSearchPath = NULL;
+
+ if ( GetModuleFileNameA( NULL, aModuleFileName, aModuleFileName.getBufSizeInSymbols() ) )
+ {
+ char *pLastBkSlash = strrchr( aModuleFileName, '\\' );
+
+ if (
+ pLastBkSlash &&
+ pLastBkSlash > (sal_Char*)aModuleFileName
+ && *(pLastBkSlash - 1) != ':'
+ && *(pLastBkSlash - 1) != '\\'
+ )
+ {
+ *pLastBkSlash = 0;
+ lpSearchPath = aModuleFileName;
+ }
+ }
+
+ lpfnSymInitialize( GetCurrentProcess(), lpSearchPath, TRUE );
+
+ ZeroMemory( &ModuleInfo, sizeof(ModuleInfo) );
+ ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
+
+ bSuccess = (sal_Bool)(!!lpfnSymGetModuleInfo( GetCurrentProcess(), (DWORD)pv, &ModuleInfo ));
+
+ if ( bSuccess )
+ {
+ /* #99182 On localized (non-english) NT4 and XP (!!!) for some libraries the LoadedImageName member of ModuleInfo isn't filled. Because
+ other members ModuleName and ImageName do not contain the full path we can cast the Member
+ BaseOfImage to a HMODULE (on NT it's the same) and use GetModuleFileName to retrieve the full
+ path of the loaded image */
+
+ if ( ModuleInfo.LoadedImageName[0] || GetModuleFileNameA( (HMODULE)ModuleInfo.BaseOfImage, ModuleInfo.LoadedImageName, sizeof(ModuleInfo.LoadedImageName) ) )
+ {
+ rtl_uString *ustrSysPath = NULL;
+
+ rtl_string2UString( &ustrSysPath, ModuleInfo.LoadedImageName, strlen(ModuleInfo.LoadedImageName), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrSysPath != NULL);
+ osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
+ rtl_uString_release( ustrSysPath );
+ }
+ else
+ bSuccess = sal_False;
+ }
+
+ lpfnSymCleanup( GetCurrentProcess() );
+ }
+
+ FreeLibrary( hModImageHelp );
+ }
+
+ return bSuccess;
+}
+
+
+typedef struct _MODULEINFO {
+ LPVOID lpBaseOfDll;
+ DWORD SizeOfImage;
+ LPVOID EntryPoint;
+} MODULEINFO, *LPMODULEINFO;
+
+typedef BOOL (WINAPI *EnumProcessModules_PROC)(
+ HANDLE hProcess, // handle to the process
+ HMODULE * lphModule, // array to receive the module handles
+ DWORD cb, // size of the array
+ LPDWORD lpcbNeeded // receives the number of bytes returned
+);
+
+typedef BOOL (WINAPI *GetModuleInformation_PROC)(
+ HANDLE hProcess, // handle to the process
+ HMODULE hModule, // handle to the module
+ LPMODULEINFO lpmodinfo, // structure that receives information
+ DWORD cb // size of the structure
+);
+
+#define bufsizeof(buffer) (sizeof(buffer) / sizeof((buffer)[0]))
+
+/* This version can fail because PSAPI.DLL is not always part of NT 4 despite MSDN Libary 6.0a say so */
+
+static sal_Bool SAL_CALL _osl_addressGetModuleURL_NT( void *pv, rtl_uString **pustrURL )
+{
+ sal_Bool bSuccess = sal_False; /* Assume failure */
+ static HMODULE hModPsapi = NULL;
+
+ if ( !hModPsapi )
+ hModPsapi = LoadLibrary( "PSAPI.DLL" );
+
+ if ( hModPsapi )
+ {
+ EnumProcessModules_PROC lpfnEnumProcessModules = (EnumProcessModules_PROC)GetProcAddress( hModPsapi, "EnumProcessModules" );
+ GetModuleInformation_PROC lpfnGetModuleInformation = (GetModuleInformation_PROC)GetProcAddress( hModPsapi, "GetModuleInformation" );
+
+ if ( lpfnEnumProcessModules && lpfnGetModuleInformation )
+ {
+ DWORD cbNeeded = 0;
+ HMODULE *lpModules = NULL;
+ DWORD nModules = 0;
+ UINT iModule = 0;
+ MODULEINFO modinfo;
+
+ lpfnEnumProcessModules( GetCurrentProcess(), NULL, 0, &cbNeeded );
+
+ lpModules = (HMODULE *)_alloca( cbNeeded );
+ lpfnEnumProcessModules( GetCurrentProcess(), lpModules, cbNeeded, &cbNeeded );
+
+ nModules = cbNeeded / sizeof(HMODULE);
+
+ for ( iModule = 0; !bSuccess && iModule < nModules; iModule++ )
+ {
+ lpfnGetModuleInformation( GetCurrentProcess(), lpModules[iModule], &modinfo, sizeof(modinfo) );
+
+ if ( (BYTE *)pv >= (BYTE *)modinfo.lpBaseOfDll && (BYTE *)pv < (BYTE *)modinfo.lpBaseOfDll + modinfo.SizeOfImage )
+ {
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ rtl_uString *ustrSysPath = NULL;
+
+ GetModuleFileNameW( lpModules[iModule], ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols() );
+
+ rtl_uString_newFromStr( &ustrSysPath, aBuffer );
+ osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
+ rtl_uString_release( ustrSysPath );
+
+ bSuccess = sal_True;
+ }
+ }
+ }
+
+ }
+
+ return bSuccess;
+}
+
+/*****************************************************************************/
+/* Dispatcher for osl_osl_addressGetModuleURL */
+/*****************************************************************************/
+
+sal_Bool SAL_CALL osl_getModuleURLFromAddress( void *pv, rtl_uString **pustrURL )
+{
+ /* Use ..._NT first because ..._NT4 is much slower */
+ if ( IS_NT )
+ return _osl_addressGetModuleURL_NT( pv, pustrURL ) || _osl_addressGetModuleURL_NT4( pv, pustrURL );
+ else
+ return _osl_addressGetModuleURL_Windows( pv, pustrURL );
+}
+
+/*****************************************************************************/
+/* osl_getModuleURLFromFunctionAddress */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress( oslGenericFunction addr, rtl_uString ** ppLibraryUrl )
+{
+ /* casting a function pointer to a data pointer (void*) is
+ not allowed according to the C/C++ standards. In this case
+ it is unavoidable because we have to stay compatible we
+ cannot remove any function. */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4054)
+#endif
+ return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+}
+
+
diff --git a/sal/osl/w32/mutex.c b/sal/osl/w32/mutex.c
new file mode 100644
index 000000000000..db16459d7fe7
--- /dev/null
+++ b/sal/osl/w32/mutex.c
@@ -0,0 +1,206 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include <osl/mutex.h>
+#include <osl/diagnose.h>
+
+/*
+ Implementation notes:
+ The void* hidden by oslMutex points to a WIN32
+ CRITICAL_SECTION structure.
+*/
+
+typedef struct _oslMutexImpl {
+ CRITICAL_SECTION m_Mutex;
+ int m_Locks;
+ DWORD m_Owner;
+ DWORD m_Requests;
+} oslMutexImpl;
+
+static BOOL (WINAPI *lpfTryEnterCriticalSection)(LPCRITICAL_SECTION)
+ = (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF;
+
+static CRITICAL_SECTION MutexLock;
+
+/*****************************************************************************/
+/* osl_createMutex */
+/*****************************************************************************/
+oslMutex SAL_CALL osl_createMutex(void)
+{
+ oslMutexImpl *pMutexImpl;
+
+ /* Window 95 does not support "TryEnterCriticalSection" */
+
+ if (lpfTryEnterCriticalSection ==
+ (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF)
+ {
+ OSVERSIONINFO VersionInformation =
+
+ {
+ sizeof(OSVERSIONINFO),
+ 0,
+ 0,
+ 0,
+ 0,
+ "",
+ };
+
+ /* ts: Window 98 does not support "TryEnterCriticalSection" but export the symbol !!!
+ calls to that symbol always returns FALSE */
+ if (
+ GetVersionEx(&VersionInformation) &&
+ (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ )
+ {
+ lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION))
+ GetProcAddress(GetModuleHandle("KERNEL32"),
+ "TryEnterCriticalSection");
+ }
+ else
+ {
+ lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION))NULL;
+ }
+
+
+ InitializeCriticalSection(&MutexLock);
+ }
+
+ pMutexImpl= calloc(sizeof(oslMutexImpl), 1);
+
+ OSL_ASSERT(pMutexImpl); /* alloc successful? */
+
+ InitializeCriticalSection(&pMutexImpl->m_Mutex);
+
+ return (oslMutex)pMutexImpl;
+}
+
+/*****************************************************************************/
+/* osl_destroyMutex */
+/*****************************************************************************/
+void SAL_CALL osl_destroyMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ if (pMutexImpl)
+ {
+ DeleteCriticalSection(&pMutexImpl->m_Mutex);
+ free(pMutexImpl);
+ }
+}
+
+/*****************************************************************************/
+/* osl_acquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ OSL_ASSERT(Mutex);
+
+ if (lpfTryEnterCriticalSection == NULL)
+ {
+ EnterCriticalSection(&MutexLock);
+ pMutexImpl->m_Requests++;
+ LeaveCriticalSection(&MutexLock);
+
+ EnterCriticalSection(&pMutexImpl->m_Mutex);
+
+ EnterCriticalSection(&MutexLock);
+ pMutexImpl->m_Requests--;
+ if (pMutexImpl->m_Locks++ == 0)
+ pMutexImpl->m_Owner = GetCurrentThreadId();
+ LeaveCriticalSection(&MutexLock);
+ }
+ else
+ EnterCriticalSection(&pMutexImpl->m_Mutex);
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex Mutex)
+{
+ sal_Bool ret = sal_False;
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ OSL_ASSERT(Mutex);
+
+ if (lpfTryEnterCriticalSection != NULL)
+ return (sal_Bool)(lpfTryEnterCriticalSection(&pMutexImpl->m_Mutex) != FALSE);
+ else
+ {
+ EnterCriticalSection(&MutexLock);
+
+ if ( ((pMutexImpl->m_Requests == 0) && (pMutexImpl->m_Locks == 0)) ||
+ (pMutexImpl->m_Owner == GetCurrentThreadId()) )
+ ret = osl_acquireMutex(Mutex);
+
+ LeaveCriticalSection(&MutexLock);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* osl_releaseMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ OSL_ASSERT(Mutex);
+
+ if (lpfTryEnterCriticalSection == NULL)
+ {
+ EnterCriticalSection(&MutexLock);
+
+ if (--(pMutexImpl->m_Locks) == 0)
+ pMutexImpl->m_Owner = 0;
+
+ LeaveCriticalSection(&MutexLock);
+ }
+
+ LeaveCriticalSection(&pMutexImpl->m_Mutex);
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getGlobalMutex */
+/*****************************************************************************/
+
+/* initialized in dllentry.c */
+oslMutex g_Mutex;
+
+oslMutex * SAL_CALL osl_getGlobalMutex(void)
+{
+ return &g_Mutex;
+}
diff --git a/sal/osl/w32/nlsupport.c b/sal/osl/w32/nlsupport.c
new file mode 100644
index 000000000000..ad9de5f8492c
--- /dev/null
+++ b/sal/osl/w32/nlsupport.c
@@ -0,0 +1,231 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#include <wchar.h>
+
+#include <osl/mutex.h>
+#include <osl/nlsupport.h>
+#include <osl/diagnose.h>
+#include <osl/process.h>
+#include <rtl/tencinfo.h>
+
+struct EnumLocalesParams
+{
+ WCHAR Language[3];
+ WCHAR Country[3];
+ LCID Locale;
+};
+
+static DWORD g_dwTLSLocaleEncId = (DWORD) -1;
+
+/*****************************************************************************/
+/* callback function test
+/*
+/* osl_getTextEncodingFromLocale calls EnumSystemLocalesA, so that we don't
+/* need to provide a unicode wrapper for this function under Win9x
+/* that means the callback function has an ansi prototype and receives
+/* the locale strings as ansi strings
+/*****************************************************************************/
+
+BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
+{
+ struct EnumLocalesParams * params;
+
+ LCID localeId;
+ LPSTR pszEndA;
+
+ WCHAR langCode[4];
+
+ /* convert hex-string to LCID */
+ localeId = strtol( lpLocaleStringA, &pszEndA, 16 );
+
+ /* check params received via TLS */
+ params = (struct EnumLocalesParams *) TlsGetValue( g_dwTLSLocaleEncId );
+ if( NULL == params || '\0' == params->Language[0] )
+ return FALSE;
+
+ /*
+ get the ISO language code for this locale
+
+ remeber: we call the GetLocaleInfoW function
+ because the ansi version of this function returns
+ an error under WinNT/2000 when called with an
+ unicode only lcid
+ */
+ if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) )
+ {
+ WCHAR ctryCode[4];
+
+ /* continue if language code does not match */
+ if( 0 != wcscmp( langCode, params->Language ) )
+ return TRUE;
+
+ /* check if country code is set and equals the current locale */
+ if( '\0' != params->Country[0] && GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
+ {
+ /* save return value in TLS and break if found desired locale */
+ if( 0 == wcscmp( ctryCode, params->Country ) )
+ {
+ params->Locale = localeId;
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* fill with default values for that language */
+ LANGID langId = LANGIDFROMLCID( localeId );
+
+ /* exchange sublanguage with SUBLANG_NEUTRAL */
+ langId = MAKELANGID( PRIMARYLANGID( langId ), SUBLANG_NEUTRAL );
+
+ /* and use default sorting order */
+ params->Locale = MAKELCID( langId, SORT_DEFAULT );
+
+ return FALSE;
+ }
+ }
+
+ /* retry by going on */
+ return TRUE;
+}
+
+
+/*****************************************************************************/
+/* GetTextEncodingFromLCID
+/*****************************************************************************/
+
+rtl_TextEncoding GetTextEncodingFromLCID( LCID localeId )
+{
+ rtl_TextEncoding Encoding = RTL_TEXTENCODING_DONTKNOW;
+ WCHAR ansiCP[6];
+
+ /* query ansi codepage for given locale */
+ if( localeId && GetLocaleInfo( localeId, LOCALE_IDEFAULTANSICODEPAGE, ansiCP, 6 ) )
+ {
+ /* if GetLocaleInfo returns "0", it is a UNICODE only locale */
+ if( 0 != wcscmp( ansiCP, L"0" ) )
+ {
+ WCHAR *pwcEnd;
+ UINT codepage;
+
+ /* values returned from GetLocaleInfo are dezimal based */
+ codepage = wcstol( ansiCP, &pwcEnd, 10 );
+
+ /* find matching rtl encoding */
+ Encoding = rtl_getTextEncodingFromWindowsCodePage( codepage );
+ }
+ else
+ Encoding = RTL_TEXTENCODING_UNICODE;
+ }
+
+ return Encoding;
+}
+
+
+/*****************************************************************************/
+/* osl_getTextEncodingFromLocale
+/*****************************************************************************/
+
+rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
+{
+ struct EnumLocalesParams params = { L"", L"", 0 };
+
+ /* initialise global TLS id */
+ if( (DWORD) -1 == g_dwTLSLocaleEncId )
+ {
+ oslMutex globalMutex = * osl_getGlobalMutex();
+
+ /* initializing must be thread save */
+ osl_acquireMutex( globalMutex );
+
+ if( (DWORD) -1 == g_dwTLSLocaleEncId )
+ g_dwTLSLocaleEncId = TlsAlloc();
+
+ osl_releaseMutex( globalMutex );
+ }
+
+ /* if pLocale is NULL, use process locale as default */
+ if( NULL == pLocale )
+ osl_getProcessLocale( &pLocale );
+
+ /* copy in parameters to structure */
+ if( pLocale && pLocale->Language )
+ {
+ wcscpy( params.Language, pLocale->Language->buffer );
+
+ if( pLocale->Country )
+ wcscpy( params.Country, pLocale->Country->buffer );
+
+ /* save pointer to local structure in TLS */
+ TlsSetValue( g_dwTLSLocaleEncId, &params );
+
+ /* enum all locales known to Windows */
+ EnumSystemLocalesA( EnumLocalesProcA, LCID_SUPPORTED );
+
+ /* use the LCID found in iteration */
+ return GetTextEncodingFromLCID( params.Locale );
+ }
+
+ return RTL_TEXTENCODING_DONTKNOW;
+}
+
+/*****************************************************************************/
+/* imp_getProcessLocale
+/*****************************************************************************/
+
+void _imp_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ WCHAR langCode[4];
+ WCHAR ctryCode[4];
+ LCID localeId;
+
+ OSL_ASSERT( ppLocale );
+
+ /* get the LCID to retrieve information from */
+ localeId = GetUserDefaultLCID();
+
+ /* call GetLocaleInfo to retrieve the iso codes */
+ if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) &&
+ GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
+ {
+ *ppLocale = rtl_locale_register( langCode, ctryCode, L"" );
+ }
+ else
+ {
+ *ppLocale = rtl_locale_register( L"C", L"", L"" );
+ }
+}
+
+
diff --git a/sal/osl/w32/path_helper.cxx b/sal/osl/w32/path_helper.cxx
new file mode 100644
index 000000000000..a43ff8bca1d8
--- /dev/null
+++ b/sal/osl/w32/path_helper.cxx
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+/*******************************************************************
+ Includes
+ ******************************************************************/
+
+#include "path_helper.hxx"
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+
+#include <algorithm>
+#include <wchar.h>
+
+/*******************************************************************
+ Constants
+ ******************************************************************/
+
+const rtl::OUString BACKSLASH = rtl::OUString::createFromAscii("\\");
+const rtl::OUString SLASH = rtl::OUString::createFromAscii("/");
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ ******************************************************************/
+
+void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath)
+{
+ OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \
+ "osl_systemPathEnsureSeparator: Invalid parameter");
+
+ rtl::OUString path(*ppustrPath);
+ sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
+
+ if (i < (path.getLength()-1))
+ {
+ path += BACKSLASH;
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+
+ OSL_POSTCOND(path.lastIndexOf(BACKSLASH) == (path.getLength() - 1), \
+ "osl_systemPathEnsureSeparator: Post condition failed");
+}
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ ******************************************************************/
+
+void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath)
+{
+ rtl::OUString path(*ppustrPath);
+
+ if (!osl::systemPathIsLogicalDrivePattern(path))
+ {
+ sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
+
+ if (i > -1 && (i == (path.getLength() - 1)))
+ {
+ path = rtl::OUString(path.getStr(), path.getLength() - 1);
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+ }
+}
+
+/*******************************************************************
+ osl_is_logical_drive_pattern
+ ******************************************************************/
+
+// is [A-Za-z]:[/|\]\0
+const sal_Char* LDP = ":";
+const sal_Char* LDP_WITH_BACKSLASH = ":\\";
+const sal_Char* LDP_WITH_SLASH = ":/";
+
+// degenerated case returned by the Windows FileOpen dialog
+// when someone enters for instance "x:filename", the Win32
+// API accepts this case
+const sal_Char* LDP_WITH_DOT_BACKSLASH = ":.\\";
+
+sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath)
+{
+ const sal_Unicode* p = rtl_uString_getStr(const_cast<rtl_uString*>(pustrPath));
+ if (iswalpha(*p++))
+ {
+ return ((0 == rtl_ustr_ascii_compare(p, LDP)) ||
+ (0 == rtl_ustr_ascii_compare(p, LDP_WITH_BACKSLASH)) ||
+ (0 == rtl_ustr_ascii_compare(p, LDP_WITH_SLASH)) ||
+ (0 == rtl_ustr_ascii_compare(p, LDP_WITH_DOT_BACKSLASH)));
+ }
+ return 0;
+}
+
+
diff --git a/sal/osl/w32/path_helper.h b/sal/osl/w32/path_helper.h
new file mode 100644
index 000000000000..79341f538667
--- /dev/null
+++ b/sal/osl/w32/path_helper.h
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _PATH_HELPER_H_
+#define _PATH_HELPER_H_
+
+#include <sal/types.h>
+#include <rtl/ustring.h>
+#include <osl/file.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the given system path if not
+ already there and if the path is not the root path or a logical
+ drive alone
+ ******************************************************************/
+
+void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath);
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the given system path if any and
+ if the path is not the root path '\'
+ ******************************************************************/
+
+void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath);
+
+/*******************************************************************
+ osl_is_logical_drive_pattern
+ Returns whether a given path is only a logical drive pattern or not.
+ A logical drive pattern is something like "a:\", "c:\".
+ No logical drive pattern is something like "c:\test"
+ ******************************************************************/
+
+sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sal/osl/w32/path_helper.hxx b/sal/osl/w32/path_helper.hxx
new file mode 100644
index 000000000000..d157b42aa428
--- /dev/null
+++ b/sal/osl/w32/path_helper.hxx
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4800)
+#endif
+
+#ifndef _PATH_HELPER_HXX_
+#define _PATH_HELPER_HXX_
+
+#include "path_helper.h"
+#include <rtl/ustring.hxx>
+#include <rtl/allocator.hxx>
+
+namespace osl
+{
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the given system path if not
+ already there and if the path is not the root path or a logical
+ drive alone
+ ******************************************************************/
+
+inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path)
+{
+ osl_systemPathEnsureSeparator(&Path.pData);
+}
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the given system path if any and
+ if the path is not the root path '\'
+ ******************************************************************/
+
+inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path)
+{
+ osl_systemPathRemoveSeparator(&Path.pData);
+}
+
+/*******************************************************************
+ osl_systemPathIsLogicalDrivePattern
+ ******************************************************************/
+
+inline bool systemPathIsLogicalDrivePattern(/*in*/ const rtl::OUString& path)
+{
+ return osl_systemPathIsLogicalDrivePattern(path.pData);
+}
+
+/*******************************************************************
+ LongPathBuffer
+ ******************************************************************/
+template< class T >
+class LongPathBuffer
+{
+ T* m_pBuffer;
+ sal_uInt32 m_nCharNum;
+
+ LongPathBuffer();
+ LongPathBuffer( const LongPathBuffer& );
+ LongPathBuffer& operator=( const LongPathBuffer& );
+
+public:
+ LongPathBuffer( sal_uInt32 nCharNum )
+ : m_pBuffer( reinterpret_cast<T*>( rtl_allocateMemory( nCharNum * sizeof( T ) ) ) )
+ , m_nCharNum( nCharNum )
+ {
+ OSL_ENSURE( m_pBuffer, "Can not allocate the buffer!" );
+ }
+
+ ~LongPathBuffer()
+ {
+ if ( m_pBuffer )
+ rtl_freeMemory( m_pBuffer );
+ m_pBuffer = 0;
+ }
+
+ sal_uInt32 getBufSizeInSymbols()
+ {
+ return m_nCharNum;
+ }
+
+ operator T* ()
+ {
+ return m_pBuffer;
+ }
+
+};
+
+ template< class U, class T > U mingw_reinterpret_cast(LongPathBuffer<T>& a) { return reinterpret_cast<U>(static_cast<T*>(a)); }
+
+} // end namespace osl
+
+#endif
diff --git a/sal/osl/w32/pipe.c b/sal/osl/w32/pipe.c
new file mode 100644
index 000000000000..bd5185a2ba2b
--- /dev/null
+++ b/sal/osl/w32/pipe.c
@@ -0,0 +1,636 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include "pipeimpl.h"
+
+#include <osl/pipe.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/mutex.h>
+#include <osl/semaphor.h>
+#include <osl/conditn.h>
+#include <osl/interlck.h>
+#include <osl/process.h>
+
+#include <rtl/alloc.h>
+#include <rtl/memory.h>
+
+#define PIPESYSTEM "\\\\.\\pipe\\"
+#define PIPEPREFIX "OSL_PIPE_"
+
+typedef struct
+{
+ sal_uInt32 m_Size;
+ sal_uInt32 m_ReadPos;
+ sal_uInt32 m_WritePos;
+ BYTE m_Data[1];
+
+} oslPipeBuffer;
+
+/*****************************************************************************/
+/* oslPipeImpl */
+/*****************************************************************************/
+
+struct oslPipeImpl {
+ oslInterlockedCount m_Reference;
+ HANDLE m_File;
+ HANDLE m_NamedObject;
+ PSECURITY_ATTRIBUTES m_Security;
+ HANDLE m_ReadEvent;
+ HANDLE m_WriteEvent;
+ HANDLE m_AcceptEvent;
+ rtl_uString* m_Name;
+ oslPipeError m_Error;
+ sal_Bool m_bClosed;
+};
+
+
+/*****************************************************************************/
+/* osl_create/destroy-PipeImpl */
+/*****************************************************************************/
+
+static oslInterlockedCount nPipes = 0;
+
+oslPipe __osl_createPipeImpl(void)
+{
+ oslPipe pPipe;
+
+ pPipe = (oslPipe) rtl_allocateZeroMemory(sizeof(struct oslPipeImpl));
+
+ pPipe->m_bClosed = sal_False;
+ pPipe->m_Reference = 0;
+ pPipe->m_Name = NULL;
+ pPipe->m_File = INVALID_HANDLE_VALUE;
+ pPipe->m_NamedObject = INVALID_HANDLE_VALUE;
+
+ pPipe->m_ReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ pPipe->m_WriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ pPipe->m_AcceptEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ return pPipe;
+}
+
+void __osl_destroyPipeImpl(oslPipe pPipe)
+{
+ if (pPipe != NULL)
+ {
+ if ( pPipe->m_NamedObject != INVALID_HANDLE_VALUE && pPipe->m_NamedObject != NULL )
+ CloseHandle( pPipe->m_NamedObject );
+
+ if (pPipe->m_Security != NULL)
+ {
+ rtl_freeMemory(pPipe->m_Security->lpSecurityDescriptor);
+ rtl_freeMemory(pPipe->m_Security);
+ }
+
+ CloseHandle(pPipe->m_ReadEvent);
+ CloseHandle(pPipe->m_WriteEvent);
+ CloseHandle(pPipe->m_AcceptEvent);
+
+ if (pPipe->m_Name)
+ rtl_uString_release(pPipe->m_Name);
+
+ rtl_freeMemory(pPipe);
+ }
+}
+
+
+
+/*****************************************************************************/
+/* osl_createPipe */
+/*****************************************************************************/
+oslPipe SAL_CALL osl_createPipe(rtl_uString *strPipeName, oslPipeOptions Options,
+ oslSecurity Security)
+{
+ rtl_uString* name = NULL;
+ rtl_uString* path = NULL;
+ rtl_uString* temp = NULL;
+ oslPipe pPipe;
+
+ PSECURITY_ATTRIBUTES pSecAttr = NULL;
+
+ rtl_uString_newFromAscii(&path, PIPESYSTEM);
+ rtl_uString_newFromAscii(&name, PIPEPREFIX);
+
+ if ( /*IS_NT &&*/ Security)
+ {
+ rtl_uString *Ident = NULL;
+ rtl_uString *Delim = NULL;
+
+ OSL_VERIFY(osl_getUserIdent(Security, &Ident));
+ rtl_uString_newFromAscii(&Delim, "_");
+
+ rtl_uString_newConcat(&temp, name, Ident);
+ rtl_uString_newConcat(&name, temp, Delim);
+
+ rtl_uString_release(Ident);
+ rtl_uString_release(Delim);
+ }
+ else
+ {
+ if (Options & osl_Pipe_CREATE)
+ {
+ PSECURITY_DESCRIPTOR pSecDesc;
+
+ pSecDesc = (PSECURITY_DESCRIPTOR) rtl_allocateMemory(SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+ /* add a NULL disc. ACL to the security descriptor */
+ OSL_VERIFY(InitializeSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION));
+ OSL_VERIFY(SetSecurityDescriptorDacl(pSecDesc, TRUE, (PACL) NULL, FALSE));
+
+ pSecAttr = rtl_allocateMemory(sizeof(SECURITY_ATTRIBUTES));
+ pSecAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
+ pSecAttr->lpSecurityDescriptor = pSecDesc;
+ pSecAttr->bInheritHandle = TRUE;
+ }
+ }
+
+ rtl_uString_assign(&temp, name);
+ rtl_uString_newConcat(&name, temp, strPipeName);
+
+ /* alloc memory */
+ pPipe= __osl_createPipeImpl();
+ osl_incrementInterlockedCount(&(pPipe->m_Reference));
+
+ /* build system pipe name */
+ rtl_uString_assign(&temp, path);
+ rtl_uString_newConcat(&path, temp, name);
+ rtl_uString_release(temp);
+ temp = NULL;
+
+ if (Options & osl_Pipe_CREATE)
+ {
+ SetLastError( ERROR_SUCCESS );
+
+ if ( IS_NT )
+ pPipe->m_NamedObject = CreateMutexW( NULL, FALSE, name->buffer );
+ else
+ {
+ LPSTR pszTempBuffer = NULL;
+ int nCharsNeeded;
+
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, name->buffer, name->length, NULL, 0, NULL, NULL );
+ pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, name->buffer, name->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
+ pszTempBuffer[nCharsNeeded-1] = 0;
+
+ pPipe->m_NamedObject = CreateMutexA( NULL, FALSE, pszTempBuffer );
+ }
+
+ if ( pPipe->m_NamedObject != INVALID_HANDLE_VALUE && pPipe->m_NamedObject != NULL )
+ {
+ if ( GetLastError() != ERROR_ALREADY_EXISTS )
+ {
+ pPipe->m_Security = pSecAttr;
+ rtl_uString_assign(&pPipe->m_Name, name);
+
+ if (IS_NT)
+ {
+ /* try to open system pipe */
+ pPipe->m_File = CreateNamedPipeW(
+ path->buffer,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
+ PIPE_UNLIMITED_INSTANCES,
+ 4096, 4096,
+ NMPWAIT_WAIT_FOREVER,
+ pPipe->m_Security);
+
+ if (pPipe->m_File != INVALID_HANDLE_VALUE)
+ {
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return pPipe;
+ }
+ }
+ else /* Win 9x */
+ {
+ LPSTR pszTempBuffer = NULL;
+ int nCharsNeeded;
+
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, NULL, 0, NULL, NULL );
+ pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
+ pszTempBuffer[nCharsNeeded-1] = 0;
+
+ pPipe->m_File = CreateSimplePipe( pszTempBuffer );
+
+ if ( IsValidHandle(pPipe->m_File) )
+ {
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return pPipe;
+ }
+ }
+ }
+ else
+ {
+ CloseHandle( pPipe->m_NamedObject );
+ pPipe->m_NamedObject = INVALID_HANDLE_VALUE;
+ }
+ }
+ }
+ else
+ {
+ if (IS_NT)
+ {
+ BOOL fPipeAvailable;
+
+ do
+ {
+ /* free instance should be available first */
+ fPipeAvailable = WaitNamedPipeW(path->buffer, NMPWAIT_WAIT_FOREVER);
+
+ /* first try to open system pipe */
+ if ( fPipeAvailable )
+ {
+ pPipe->m_File = CreateFileW(
+ path->buffer,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ if ( pPipe->m_File != INVALID_HANDLE_VALUE )
+ {
+ // We got it !
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return (pPipe);
+ }
+ else
+ {
+ // Pipe instance maybe catched by another client -> try again
+ }
+ }
+ } while ( fPipeAvailable );
+ }
+ else /* Win 9x */
+ {
+ LPSTR pszTempBuffer = NULL;
+ int nCharsNeeded;
+
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, NULL, 0, NULL, NULL );
+ pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
+ pszTempBuffer[nCharsNeeded-1] = 0;
+
+ pPipe->m_File = OpenSimplePipe( pszTempBuffer );
+
+ if ( IsValidHandle(pPipe->m_File) )
+ {
+ // We got it !
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return (pPipe);
+ }
+ }
+ }
+
+ /* if we reach here something went wrong */
+ __osl_destroyPipeImpl(pPipe);
+
+ return NULL;
+}
+
+void SAL_CALL osl_acquirePipe( oslPipe pPipe )
+{
+ osl_incrementInterlockedCount( &(pPipe->m_Reference) );
+}
+
+void SAL_CALL osl_releasePipe( oslPipe pPipe )
+{
+// OSL_ASSERT( pPipe );
+
+ if( 0 == pPipe )
+ return;
+
+ if( 0 == osl_decrementInterlockedCount( &(pPipe->m_Reference) ) )
+ {
+ if( ! pPipe->m_bClosed )
+ osl_closePipe( pPipe );
+
+ __osl_destroyPipeImpl( pPipe );
+ }
+}
+
+void SAL_CALL osl_closePipe( oslPipe pPipe )
+{
+ if( pPipe && ! pPipe->m_bClosed )
+ {
+ pPipe->m_bClosed = sal_True;
+ if (IS_NT)
+ {
+ /* if we have a system pipe close it */
+ if (pPipe->m_File != INVALID_HANDLE_VALUE)
+ {
+ /* FlushFileBuffers(pPipe->m_File); */
+ DisconnectNamedPipe(pPipe->m_File);
+ CloseHandle(pPipe->m_File);
+ }
+ }
+ else
+ {
+ CloseSimplePipe( pPipe->m_File );
+ }
+
+ }
+}
+
+/*****************************************************************************/
+/* osl_acceptPipe */
+/*****************************************************************************/
+oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
+{
+ oslPipe pAcceptedPipe = NULL;
+
+ HANDLE Event;
+ OVERLAPPED os;
+
+ OSL_ASSERT(pPipe);
+
+ if (IS_NT)
+ {
+ DWORD nBytesTransfered;
+ rtl_uString* path = NULL;
+ rtl_uString* temp = NULL;
+
+ OSL_ASSERT (pPipe->m_File != INVALID_HANDLE_VALUE);
+
+ Event = pPipe->m_AcceptEvent;
+ rtl_zeroMemory(&os, sizeof(OVERLAPPED));
+ os.hEvent = pPipe->m_AcceptEvent;
+ ResetEvent(pPipe->m_AcceptEvent);
+
+ if ( !ConnectNamedPipe(pPipe->m_File, &os))
+ {
+ switch ( GetLastError() )
+ {
+ case ERROR_PIPE_CONNECTED: // Client already connected to pipe
+ case ERROR_NO_DATA: // Client was connected but has already closed pipe end
+ // should only appear in nonblocking mode but in fact does
+ // in blocking asynchronous mode.
+ break;
+ case ERROR_PIPE_LISTENING: // Only for nonblocking mode but see ERROR_NO_DATA
+ case ERROR_IO_PENDING: // This is normal if not client is connected yet
+ case ERROR_MORE_DATA: // Should not happen
+ // blocking call to accept
+ if( !GetOverlappedResult( pPipe->m_File, &os, &nBytesTransfered, TRUE ) )
+ {
+ // Possible error could be that between ConnectNamedPipe and GetOverlappedResult a connect
+ // took place.
+
+ switch ( GetLastError() )
+ {
+ case ERROR_PIPE_CONNECTED: // Pipe was already connected
+ case ERROR_NO_DATA: // Pipe was connected but client has already closed -> ver fast client ;-)
+ break; // Everything's fine !!!
+ default:
+ // Something went wrong
+ return 0;
+ }
+ }
+ break;
+ default: // All other error say that somethings going wrong.
+ return 0;
+ }
+ }
+
+
+ pAcceptedPipe = __osl_createPipeImpl();
+ OSL_ASSERT(pAcceptedPipe);
+
+ osl_incrementInterlockedCount(&(pAcceptedPipe->m_Reference));
+ rtl_uString_assign(&pAcceptedPipe->m_Name, pPipe->m_Name);
+ pAcceptedPipe->m_File = pPipe->m_File;
+
+ rtl_uString_newFromAscii(&temp, PIPESYSTEM);
+ rtl_uString_newConcat(&path, temp, pPipe->m_Name);
+ rtl_uString_release(temp);
+
+ // prepare for next accept
+ pPipe->m_File =
+ CreateNamedPipeW(path->buffer,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
+ PIPE_UNLIMITED_INSTANCES,
+ 4096, 4096,
+ NMPWAIT_WAIT_FOREVER,
+ pAcceptedPipe->m_Security);
+ rtl_uString_release( path );
+ }
+ else /* Win9x */
+ {
+ pAcceptedPipe = __osl_createPipeImpl();
+ OSL_ASSERT(pAcceptedPipe);
+
+ osl_incrementInterlockedCount(&(pAcceptedPipe->m_Reference));
+ rtl_uString_assign(&pAcceptedPipe->m_Name, pPipe->m_Name);
+ pAcceptedPipe->m_File = pPipe->m_File;
+
+ pAcceptedPipe->m_File = AcceptSimplePipeConnection( pPipe->m_File );
+ }
+
+ return pAcceptedPipe;
+}
+
+/*****************************************************************************/
+/* osl_receivePipe */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe,
+ void* pBuffer,
+ sal_Int32 BytesToRead)
+{
+ DWORD nBytes;
+
+ OSL_ASSERT(pPipe);
+
+ /* if we have a system pipe use it */
+ if ( IS_NT /*pPipe->m_File != INVALID_HANDLE_VALUE*/)
+ {
+ OVERLAPPED os;
+ rtl_zeroMemory(&os,sizeof(OVERLAPPED));
+ os.hEvent = pPipe->m_ReadEvent;
+
+ ResetEvent(pPipe->m_ReadEvent);
+
+ if (! ReadFile(pPipe->m_File, pBuffer, BytesToRead, &nBytes, &os) &&
+ ((GetLastError() != ERROR_IO_PENDING) ||
+ ! GetOverlappedResult(pPipe->m_File, &os, &nBytes, TRUE)))
+ {
+ DWORD lastError = GetLastError();
+
+ if (lastError == ERROR_MORE_DATA)
+ nBytes = BytesToRead;
+ else
+ {
+ if (lastError == ERROR_PIPE_NOT_CONNECTED)
+ nBytes = 0;
+ else
+ nBytes = (DWORD) -1;
+
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+ }
+ }
+ else
+ {
+ BOOL fSuccess = ReadSimplePipe( pPipe->m_File, pBuffer, BytesToRead, &nBytes, TRUE );
+
+ if ( !fSuccess )
+ {
+ nBytes = 0;
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+
+ }
+
+ return (nBytes);
+}
+
+/*****************************************************************************/
+/* osl_sendPipe */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe,
+ const void* pBuffer,
+ sal_Int32 BytesToSend)
+{
+ DWORD nBytes;
+ OSL_ASSERT(pPipe);
+
+ if (IS_NT/*pPipe->m_File != INVALID_HANDLE_VALUE*/)
+ {
+ OVERLAPPED os;
+ rtl_zeroMemory(&os, sizeof(OVERLAPPED));
+ os.hEvent = pPipe->m_WriteEvent;
+ ResetEvent(pPipe->m_WriteEvent);
+
+ if (! WriteFile(pPipe->m_File, pBuffer, BytesToSend, &nBytes, &os) &&
+ ((GetLastError() != ERROR_IO_PENDING) ||
+ ! GetOverlappedResult(pPipe->m_File, &os, &nBytes, TRUE)))
+ {
+ if (GetLastError() == ERROR_PIPE_NOT_CONNECTED)
+ nBytes = 0;
+ else
+ nBytes = (DWORD) -1;
+
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+ }
+ else
+ {
+ BOOL fSuccess = WriteSimplePipe( pPipe->m_File, pBuffer, BytesToSend, &nBytes, TRUE );
+
+ if ( !fSuccess )
+ {
+ nBytes = 0;
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+ }
+
+ return (nBytes);
+}
+
+sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n )
+{
+ /* loop until all desired bytes were send or an error occured */
+ sal_Int32 BytesSend= 0;
+ sal_Int32 BytesToSend= n;
+
+ OSL_ASSERT(pPipe);
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToSend -= RetVal;
+ BytesSend += RetVal;
+ pBuffer= (sal_Char*)pBuffer + RetVal;
+ }
+
+ return BytesSend;
+}
+
+sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n )
+{
+ /* loop until all desired bytes were read or an error occured */
+ sal_Int32 BytesRead= 0;
+ sal_Int32 BytesToRead= n;
+
+ OSL_ASSERT( pPipe );
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ pBuffer= (sal_Char*)pBuffer + RetVal;
+ }
+ return BytesRead;
+}
+
+
+/*****************************************************************************/
+/* osl_getLastPipeError */
+/*****************************************************************************/
+oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe)
+{
+ oslPipeError Error;
+
+ if (pPipe != NULL)
+ {
+ Error = pPipe->m_Error;
+ pPipe->m_Error = osl_Pipe_E_None;
+ }
+ else
+ Error = osl_Pipe_E_NotFound;
+
+ return (Error);
+}
+
diff --git a/sal/osl/w32/pipeimpl.cxx b/sal/osl/w32/pipeimpl.cxx
new file mode 100644
index 000000000000..1d492115e8c5
--- /dev/null
+++ b/sal/osl/w32/pipeimpl.cxx
@@ -0,0 +1,785 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+# include "pipeimpl.h"
+
+#ifndef _INC_MALLOC
+# include <malloc.h>
+#endif
+
+#ifndef _INC_TCHAR
+# ifdef UNICODE
+# define _UNICODE
+# endif
+# include <tchar.h>
+#endif
+
+const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_");
+const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_");
+const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_");
+
+const DWORD PIPE_BUFFER_SIZE = 4096;
+
+
+//============================================================================
+// PipeData
+//============================================================================
+
+struct PipeData
+{
+ DWORD dwProcessId;
+ HANDLE hReadPipe;
+ HANDLE hWritePipe;
+};
+
+//============================================================================
+// Pipe
+//============================================================================
+
+#ifdef UNICODE
+#define Pipe PipeW
+#define ClientPipe ClientPipeW
+#define ServerPipe ServerPipeW
+#else
+#define Pipe PipeA
+#define ClientPipe ClientPipeA
+#define ServerPipe ServerPipeA
+#endif
+
+class Pipe
+{
+protected:
+ HANDLE m_hReadPipe; // Handle to use for reading
+ HANDLE m_hWritePipe; // Handle to use for writing
+
+ Pipe( HANDLE hReadPipe, HANDLE hWritePipe );
+
+ static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner );
+ static HANDLE CreatePipeDataMapping( LPCTSTR lpName );
+ static HANDLE OpenPipeDataMapping( LPCTSTR lpName );
+ static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount );
+
+public:
+ Pipe( const Pipe& );
+ const Pipe& operator = ( const Pipe& );
+ virtual ~Pipe();
+
+ virtual bool Close();
+ virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true );
+ virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true );
+
+ virtual Pipe *AcceptConnection()
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+
+ void * operator new( size_t nBytes )
+ {
+ return HeapAlloc( GetProcessHeap(), 0, nBytes );
+ }
+
+ void operator delete( void *ptr )
+ {
+ HeapFree( GetProcessHeap(), 0, ptr );
+ }
+
+ bool is() const
+ {
+ return (FALSE != HeapValidate( GetProcessHeap(), 0, this ));
+ }
+
+};
+
+//============================================================================
+// ClientPipe
+//============================================================================
+
+class ClientPipe : public Pipe
+{
+protected:
+ ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ static ClientPipe* Create( LPCTSTR lpName );
+};
+
+//============================================================================
+// ServerPipe
+//============================================================================
+
+class ServerPipe : public Pipe
+{
+protected:
+ HANDLE m_hMapping;
+ HANDLE m_hSynchronize;
+ LPTSTR m_lpName;
+
+ ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ virtual ~ServerPipe();
+
+ static ServerPipe *Create( LPCTSTR lpName );
+
+ virtual Pipe *AcceptConnection();
+};
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ LPTSTR lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) );
+
+ if ( lpMappingFileName )
+ {
+ DWORD nChars = GetTempPath( MAX_PATH, lpMappingFileName );
+
+ if ( MAX_PATH + _tcslen(lpName) < nChars + 1 )
+ {
+ lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) );
+ if ( lpMappingFileName )
+ nChars = GetTempPath( nChars, lpMappingFileName );
+ else
+ {
+ nChars = 0;
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+ }
+
+ if ( nChars )
+ {
+ _tcscat( lpMappingFileName, lpMappingName );
+
+ HANDLE hFile = CreateFile(
+ lpMappingFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+ NULL );
+
+ if ( IsValidHandle(hFile) )
+ {
+ hMapping = CreateFileMapping(
+ (HANDLE)hFile,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ PAGE_READWRITE,
+ 0,
+ sizeof(PipeData),
+ lpMappingName );
+
+ CloseHandle( hFile );
+ }
+ }
+ }
+ else
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::OpenPipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner )
+{
+ HANDLE hMutex = NULL;
+ LPTSTR lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) );
+
+ if ( lpMutexName )
+ {
+ _tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE );
+ _tcscat( lpMutexName, lpName );
+
+ hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName );
+ }
+
+ return hMutex;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount )
+{
+ HANDLE hSemaphore = NULL;
+ LPTSTR lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) );
+
+ if ( lpSemaphoreName )
+ {
+ _tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION );
+ _tcscat( lpSemaphoreName, lpName );
+
+ hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName );
+ }
+
+ return hSemaphore;
+}
+
+
+//----------------------------------------------------------------------------
+// Pipe copy ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( const Pipe& rPipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe assignment operator
+//----------------------------------------------------------------------------
+
+const Pipe& Pipe::operator = ( const Pipe& rPipe )
+{
+ Close();
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+// Pipe ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe dtor
+//----------------------------------------------------------------------------
+
+Pipe::~Pipe()
+{
+ Close();
+}
+
+//----------------------------------------------------------------------------
+// Pipe Close
+//----------------------------------------------------------------------------
+
+bool Pipe::Close()
+{
+ bool fSuccess = false; // Assume failure
+
+ if ( IsValidHandle(m_hReadPipe) )
+ {
+ CloseHandle( m_hReadPipe );
+ m_hReadPipe = INVALID_HANDLE_VALUE;
+ }
+
+ if ( IsValidHandle(m_hWritePipe) )
+ {
+ CloseHandle( m_hWritePipe );
+ m_hWritePipe = INVALID_HANDLE_VALUE;
+ }
+
+ return fSuccess;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Write
+//----------------------------------------------------------------------------
+
+bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable )
+ dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ;
+
+ return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL );
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Read
+//----------------------------------------------------------------------------
+
+bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( bWait || dwBytesAvailable )
+ return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL );
+ else
+ {
+ *lpBytesRead = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+//----------------------------------------------------------------------------
+// Client pipe dtor
+//----------------------------------------------------------------------------
+
+ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe )
+{
+}
+
+//----------------------------------------------------------------------------
+// Client pipe creation
+//----------------------------------------------------------------------------
+
+ClientPipe *ClientPipe::Create( LPCTSTR lpName )
+{
+ ClientPipe *pPipe = NULL; // Assume failure
+
+ HANDLE hMapping = OpenPipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+ HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId );
+
+ if ( IsValidHandle(hSourceProcess) )
+ {
+ BOOL fSuccess;
+ HANDLE hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE;
+
+ fSuccess = DuplicateHandle(
+ hSourceProcess,
+ pData->hReadPipe,
+ GetCurrentProcess(),
+ &hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ fSuccess = fSuccess && DuplicateHandle(
+ hSourceProcess,
+ pData->hWritePipe,
+ GetCurrentProcess(),
+ &hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ if ( fSuccess )
+ pPipe = new ClientPipe( hReadPipe, hWritePipe );
+
+ if ( IsValidHandle(hWritePipe) )
+ CloseHandle( hWritePipe );
+
+ if ( IsValidHandle(hReadPipe) )
+ CloseHandle( hReadPipe );
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 );
+
+ ReleaseSemaphore( hConnectionRequest, 1, NULL );
+
+ CloseHandle( hConnectionRequest );
+
+ CloseHandle( hSourceProcess );
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+
+//----------------------------------------------------------------------------
+// ServerPipe ctor
+//----------------------------------------------------------------------------
+
+ServerPipe::ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ),
+m_hMapping( NULL ),
+m_hSynchronize( NULL ),
+m_lpName( NULL )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hMapping,
+ GetCurrentProcess(),
+ &m_hMapping,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hSynchronize,
+ GetCurrentProcess(),
+ &m_hSynchronize,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ );
+ m_lpName = new TCHAR[_tcslen(lpName) + 1];
+ if ( m_lpName )
+ _tcscpy( m_lpName, lpName );
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe dtor
+//----------------------------------------------------------------------------
+
+ServerPipe::~ServerPipe()
+{
+ if ( IsValidHandle(m_hMapping) )
+ CloseHandle( m_hMapping );
+ if ( m_lpName )
+ delete[]m_lpName;
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe AcceptConnection
+//----------------------------------------------------------------------------
+
+Pipe *ServerPipe::AcceptConnection()
+{
+ Pipe *pPipe = NULL; // Assume failure;
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 );
+
+ if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) )
+ {
+ pPipe = new Pipe( *this );
+ Close();
+
+ // Create new inbound Pipe
+
+ HANDLE hClientWritePipe = NULL, hServerReadPipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hClientReadPipe = NULL, hServerWritePipe = NULL;
+
+ if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) )
+ {
+ m_hReadPipe = hServerReadPipe;
+ m_hWritePipe = hServerWritePipe;
+
+ PipeData *pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) );
+
+ HANDLE hSynchronize = CreatePipeDataMutex( m_lpName, TRUE );
+
+ CloseHandle( pData->hReadPipe );
+ CloseHandle( pData->hWritePipe );
+
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+
+ ReleaseMutex( hSynchronize );
+
+ CloseHandle( hSynchronize );
+
+ }
+ else
+ {
+ CloseHandle( hClientWritePipe );
+ CloseHandle( hServerWritePipe );
+ }
+ }
+
+ ReleaseMutex( hConnectionRequest );
+ }
+
+ CloseHandle( hConnectionRequest );
+
+ return pPipe;
+}
+
+//----------------------------------------------------------------------------
+// Pipe creation
+//----------------------------------------------------------------------------
+
+ServerPipe *ServerPipe::Create( LPCTSTR lpName )
+{
+ ServerPipe *pPipe = NULL;
+
+ HANDLE hMapping = CreatePipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ if ( ERROR_FILE_EXISTS != GetLastError() )
+ {
+ HANDLE hSynchronize = CreatePipeDataMutex( lpName, FALSE);
+
+ WaitForSingleObject( hSynchronize, INFINITE );
+
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+
+ // Initialize pipe data
+
+ pData->dwProcessId = 0;
+ pData->hReadPipe = NULL;
+ pData->hWritePipe = NULL;
+
+ // Create inbound pipe
+
+ HANDLE hServerReadPipe = NULL, hClientWritePipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hServerWritePipe = NULL, hClientReadPipe = NULL;
+
+ fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ pData->dwProcessId = GetCurrentProcessId();
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+ pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe );
+
+ CloseHandle( hServerWritePipe );
+ CloseHandle( hServerReadPipe );
+ }
+ else
+ {
+ CloseHandle( hServerReadPipe );
+ CloseHandle( hClientWritePipe );
+ }
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ ReleaseMutex( hSynchronize );
+ CloseHandle( hSynchronize );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+//----------------------------------------------------------------------------
+// C style API
+//----------------------------------------------------------------------------
+
+const TCHAR LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" );
+
+extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ServerPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ClientPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return (HANDLE)pPipe->AcceptConnection();
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+}
+
+extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ )
+{
+ return FALSE;
+}
+
+extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ {
+ delete pPipe;
+ return TRUE;
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
diff --git a/sal/osl/w32/pipeimpl.h b/sal/osl/w32/pipeimpl.h
new file mode 100644
index 000000000000..83f678f6c49d
--- /dev/null
+++ b/sal/osl/w32/pipeimpl.h
@@ -0,0 +1,88 @@
+#ifndef _PIPEIMPL_H_
+#define _PIPEIMPL_H_
+
+#ifndef _WINDOWS_
+# ifdef _MSC_VER
+# pragma warning(push,1) /* disable warnings within system headers */
+# endif
+# include <windows.h>
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif
+#endif
+
+#ifndef _INC_MALLOC
+# include <malloc.h>
+#endif
+
+#ifndef _INC_TCHAR
+# ifdef UNICODE
+# define _UNICODE
+# endif
+# include <tchar.h>
+#endif
+
+#define EXPORT_PIPE_API
+
+//============================================================================
+// Helper functions
+//============================================================================
+
+// Because the value of an invalid HANDLE returned by API functions differs
+// between different functions and differs on different Windows platforms,
+// this function checks wether the handle has a meaningfull value.
+#ifndef __cplusplus
+
+#define IsValidHandle( handle ) ((DWORD)(handle) + 1 > 1)
+
+#else
+
+inline bool IsValidHandle( HANDLE handle )
+{
+ return INVALID_HANDLE_VALUE != handle && NULL != handle;
+}
+
+extern "C" {
+
+#endif // __cplusplus
+
+
+EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeA( LPCSTR lpName );
+EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeW( LPCWSTR lpName );
+
+#ifdef UNICODE
+#define CreateSimplePipe CreateSimplePipeW
+#else
+#define CreateSimplePipe CreateSimplePipeA
+#endif
+
+EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeA( LPCSTR lpName );
+EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeW( LPCWSTR lpName );
+
+#ifdef UNICODE
+#define OpenSimplePipe OpenSimplePipeW
+#else
+#define OpenSimplePipe OpenSimplePipeA
+#endif
+
+EXPORT_PIPE_API HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe );
+
+EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeA( LPCSTR lpName, DWORD dwTimeOut );
+EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeW( LPCWSTR lpName, DWORD dwTimeOut );
+
+#ifdef UNICODE
+#define WaitForSimplePipe WaitForSimplePipeW
+#else
+#define WaitForSimplePipe WaitForSimplePipeA
+#endif
+
+
+EXPORT_PIPE_API BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait );
+EXPORT_PIPE_API BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait );
+EXPORT_PIPE_API BOOL WINAPI CloseSimplePipe( HANDLE hPipe );
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PIPEIMPL_H_
diff --git a/sal/osl/w32/process.cxx b/sal/osl/w32/process.cxx
new file mode 100644
index 000000000000..96187be7e203
--- /dev/null
+++ b/sal/osl/w32/process.cxx
@@ -0,0 +1,620 @@
+/*************************************************************************
+*
+* 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.
+*
+************************************************************************/
+
+#define UNICODE
+#include "system.h"
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <shellapi.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#include <osl/diagnose.h>
+#include <osl/security.h>
+#include <osl/nlsupport.h>
+#include <osl/mutex.h>
+#include <osl/thread.h>
+
+#include "procimpl.h"
+#include "sockimpl.h"
+#include "file_url.h"
+#include "path_helper.hxx"
+#include <rtl/ustrbuf.h>
+#include <rtl/alloc.h>
+
+/***************************************************************************
+ * Process.
+ ***************************************************************************/
+
+oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
+{
+ if (Process == NULL)
+ return osl_Process_E_Unknown;
+
+ if (TerminateProcess(((oslProcessImpl*)Process)->m_hProcess, 0))
+ return osl_Process_E_None;
+
+
+ return osl_Process_E_Unknown;
+}
+
+/***************************************************************************/
+
+oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
+{
+ oslProcessImpl* pProcImpl;
+ HANDLE hProcess = OpenProcess(
+ STANDARD_RIGHTS_REQUIRED | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, (DWORD)Ident);
+
+ if (hProcess)
+ {
+ pProcImpl = reinterpret_cast< oslProcessImpl*>( rtl_allocateMemory(sizeof(oslProcessImpl)) );
+ pProcImpl->m_hProcess = hProcess;
+ pProcImpl->m_IdProcess = Ident;
+ }
+ else
+ pProcImpl = NULL;
+
+ return (pProcImpl);
+}
+
+/***************************************************************************/
+
+void SAL_CALL osl_freeProcessHandle(oslProcess Process)
+{
+ if (Process != NULL)
+ {
+ CloseHandle(((oslProcessImpl*)Process)->m_hProcess);
+
+ rtl_freeMemory((oslProcessImpl*)Process);
+ }
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields,
+ oslProcessInfo* pInfo)
+{
+ HANDLE hProcess;
+ DWORD IdProcess;
+
+ if (Process == NULL)
+ {
+ hProcess = GetCurrentProcess();
+ IdProcess = GetCurrentProcessId();
+ }
+ else
+ {
+ hProcess = ((oslProcessImpl*)Process)->m_hProcess;
+ IdProcess = ((oslProcessImpl*)Process)->m_IdProcess;
+ }
+
+ if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
+ return osl_Process_E_Unknown;
+
+ pInfo->Fields = 0;
+
+ if (Fields & osl_Process_IDENTIFIER)
+ {
+ pInfo->Ident = IdProcess;
+ pInfo->Fields |= osl_Process_IDENTIFIER;
+ }
+
+ if (Fields & osl_Process_EXITCODE)
+ {
+ if (GetExitCodeProcess(hProcess, &(pInfo->Code)) && (pInfo->Code != STILL_ACTIVE))
+ pInfo->Fields |= osl_Process_EXITCODE;
+ }
+
+ if (Fields & osl_Process_HEAPUSAGE)
+ {
+ void* lpAddress=0;
+ MEMORY_BASIC_INFORMATION Info;
+
+ pInfo->HeapUsage = 0;
+
+ do
+ {
+ if (VirtualQueryEx(hProcess, lpAddress, &Info, sizeof(Info)) == 0)
+ break;
+
+ if ((Info.State == MEM_COMMIT) && (Info.Type == MEM_PRIVATE))
+ pInfo->HeapUsage += Info.RegionSize;
+
+ lpAddress = (LPBYTE)lpAddress + Info.RegionSize;
+ }
+ while (lpAddress < (void *)0x80000000); // 2GB address space
+
+ pInfo->Fields |= osl_Process_HEAPUSAGE;
+ }
+
+ if (Fields & osl_Process_CPUTIMES)
+ {
+ FILETIME CreationTime, ExitTime, KernelTime, UserTime;
+
+ if (GetProcessTimes(hProcess, &CreationTime, &ExitTime,
+ &KernelTime, &UserTime))
+ {
+ __int64 Value;
+
+ Value = *((__int64 *)&UserTime);
+ pInfo->UserTime.Seconds = (unsigned long) (Value / 10000000L);
+ pInfo->UserTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
+
+ Value = *((__int64 *)&KernelTime);
+ pInfo->SystemTime.Seconds = (unsigned long) (Value / 10000000L);
+ pInfo->SystemTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
+
+ pInfo->Fields |= osl_Process_CPUTIMES;
+ }
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
+{
+ return osl_joinProcessWithTimeout(Process, NULL);
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
+{
+ DWORD timeout = INFINITE;
+ oslProcessError osl_error = osl_Process_E_None;
+ DWORD ret;
+
+ if (NULL == Process)
+ return osl_Process_E_Unknown;
+
+ if (pTimeout)
+ timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L;
+
+ ret = WaitForSingleObject(((oslProcessImpl*)Process)->m_hProcess, timeout);
+
+ if (WAIT_FAILED == ret)
+ osl_error = osl_Process_E_Unknown;
+ else if (WAIT_TIMEOUT == ret)
+ osl_error = osl_Process_E_TimedOut;
+
+ return osl_error;
+}
+
+/***************************************************************************
+ * osl_bootstrap_getExecutableFile_Impl().
+ *
+ * @internal
+ * @see rtl_bootstrap
+ * @see #i37371#
+ *
+ ***************************************************************************/
+
+extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C()
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ DWORD buflen = 0;
+
+ if ((buflen = GetModuleFileNameW (0, ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols())) > 0)
+ {
+ rtl_uString * pAbsPath = 0;
+ rtl_uString_newFromStr_WithLength (&(pAbsPath), aBuffer, buflen);
+ if (pAbsPath)
+ {
+ /* Convert from path to url. */
+ if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
+ {
+ /* Success. */
+ result = osl_Process_E_None;
+ }
+ rtl_uString_release (pAbsPath);
+ }
+ }
+
+ return (result);
+}
+
+/***************************************************************************
+ * Command Line Arguments.
+ ***************************************************************************/
+
+struct CommandArgs_Impl
+{
+ sal_uInt32 m_nCount;
+ rtl_uString ** m_ppArgs;
+};
+
+static struct CommandArgs_Impl g_command_args =
+{
+ 0,
+ 0
+};
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable: 4100 )
+#endif
+static rtl_uString ** osl_createCommandArgs_Impl (int argc, char ** argv)
+{
+ rtl_uString ** ppArgs =
+ (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
+ if (ppArgs != 0)
+ {
+ int i;
+ int nArgs;
+ LPWSTR *wargv = CommandLineToArgvW( GetCommandLineW(), &nArgs );
+ OSL_ASSERT( nArgs == argc );
+ for (i = 0; i < nArgs; i++)
+ {
+ /* Convert to unicode */
+ rtl_uString_newFromStr( &(ppArgs[i]), reinterpret_cast<const sal_Unicode*>(wargv[i]) );
+ }
+ if (ppArgs[0] != 0)
+ {
+ /* Ensure absolute path */
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ DWORD dwResult = 0;
+
+ dwResult = SearchPath (
+ 0, reinterpret_cast<LPCWSTR>(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), 0);
+ if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols()))
+ {
+ /* Replace argv[0] with it's absolute path */
+ rtl_uString_newFromStr_WithLength(
+ &(ppArgs[0]), aBuffer, dwResult);
+ }
+ }
+ if (ppArgs[0] != 0)
+ {
+ /* Convert to FileURL, see @ osl_getExecutableFile() */
+ rtl_uString * pResult = 0;
+ osl_getFileURLFromSystemPath (ppArgs[0], &pResult);
+ if (pResult != 0)
+ {
+ rtl_uString_assign (&(ppArgs[0]), pResult);
+ rtl_uString_release (pResult);
+ }
+ }
+ }
+ return (ppArgs);
+
+}
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getExecutableFile( rtl_uString **ppustrFile )
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ osl_acquireMutex (*osl_getGlobalMutex());
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ {
+ /* CommandArgs set. Obtain arv[0]. */
+ rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
+ result = osl_Process_E_None;
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+
+ return (result);
+}
+
+/***************************************************************************/
+
+sal_uInt32 SAL_CALL osl_getCommandArgCount(void)
+{
+ sal_uInt32 result = 0;
+
+ osl_acquireMutex (*osl_getGlobalMutex());
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ {
+ /* We're not counting argv[0] here. */
+ result = g_command_args.m_nCount - 1;
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+
+ return (result);
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getCommandArg( sal_uInt32 nArg, rtl_uString **strCommandArg)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ osl_acquireMutex (*osl_getGlobalMutex());
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > (nArg + 1))
+ {
+ /* We're not counting argv[0] here. */
+ rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
+ result = osl_Process_E_None;
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+
+ return (result);
+}
+
+/***************************************************************************/
+
+void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
+{
+ OSL_ASSERT(argc > 0);
+ osl_acquireMutex (*osl_getGlobalMutex());
+ if (g_command_args.m_nCount == 0)
+ {
+ rtl_uString** ppArgs = osl_createCommandArgs_Impl (argc, argv);
+ if (ppArgs != 0)
+ {
+ g_command_args.m_nCount = argc;
+ g_command_args.m_ppArgs = ppArgs;
+ }
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+}
+
+/***************************************************************************
+ * Environment
+ ***************************************************************************/
+/*
+ #109941# because of a bug in the M$ unicows library we have to
+ allocate a buffer large enough to hold the requested environment
+ variable instead of testing for the required size. This wastes
+ some stack space, maybe we should revoke this work around if
+ unicows library is fixed.
+*/
+#define ENV_BUFFER_SIZE (32*1024-1)
+
+oslProcessError SAL_CALL osl_getEnvironment(rtl_uString *ustrVar, rtl_uString **ustrValue)
+{
+ WCHAR buff[ENV_BUFFER_SIZE];
+
+ if (GetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0)
+ {
+ rtl_uString_newFromStr(ustrValue, reinterpret_cast<const sal_Unicode*>(buff));
+ return osl_Process_E_None;
+ }
+ return osl_Process_E_Unknown;
+}
+
+/***************************************************************************
+ * Current Working Directory.
+ ***************************************************************************/
+
+extern "C" oslMutex g_CurrentDirectoryMutex;
+
+oslProcessError SAL_CALL osl_getProcessWorkingDir( rtl_uString **pustrWorkingDir )
+{
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ DWORD dwLen = 0;
+
+
+ osl_acquireMutex( g_CurrentDirectoryMutex );
+ dwLen = GetCurrentDirectory( aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer) );
+ osl_releaseMutex( g_CurrentDirectoryMutex );
+
+ if ( dwLen && dwLen < aBuffer.getBufSizeInSymbols() )
+ {
+ oslFileError eError;
+ rtl_uString *ustrTemp = NULL;;
+
+ rtl_uString_newFromStr_WithLength( &ustrTemp, aBuffer, dwLen );
+ eError = osl_getFileURLFromSystemPath( ustrTemp, pustrWorkingDir );
+
+ rtl_uString_release( ustrTemp );
+
+ if ( osl_File_E_None != eError )
+ return osl_Process_E_Unknown;
+ else
+ return osl_Process_E_None;
+ }
+ else
+ return osl_Process_E_Unknown;
+}
+
+/***************************************************************************
+ * Process Locale.
+ ***************************************************************************/
+
+extern "C" void _imp_getProcessLocale( rtl_Locale ** ppLocale );
+
+static rtl_Locale * g_theProcessLocale = NULL;
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ osl_acquireMutex( *osl_getGlobalMutex() );
+
+ /* determine the users default locale */
+ if( NULL == g_theProcessLocale )
+ _imp_getProcessLocale( &g_theProcessLocale );
+
+ /* or return the cached value */
+ *ppLocale = g_theProcessLocale;
+
+ osl_releaseMutex( *osl_getGlobalMutex() );
+ return osl_Process_E_None;
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
+{
+ osl_acquireMutex( *osl_getGlobalMutex() );
+
+ /* check if locale is supported */
+ if( RTL_TEXTENCODING_DONTKNOW == osl_getTextEncodingFromLocale( pLocale ) )
+ return osl_Process_E_Unknown;
+
+ /* just remember the locale here */
+ g_theProcessLocale = pLocale;
+
+ osl_releaseMutex( *osl_getGlobalMutex() );
+ return osl_Process_E_None;
+}
+
+/************************************************
+ * Portal send/receive interface implementation
+ ************************************************/
+
+static sal_Bool ReadPipe(oslPipe hPipe,
+ void* pBuffer,
+ sal_Int32 BytesToRead,
+ sal_Int32* nBytes)
+{
+ *nBytes = osl_receivePipe(hPipe, pBuffer, BytesToRead);
+ OSL_TRACE("tried to recieve %d, recieved %d.\n",
+ BytesToRead, *nBytes);
+ return (sal_Bool)((*nBytes >= 0) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
+}
+
+static sal_Bool WritePipe(oslPipe hPipe,
+ void* pBuffer,
+ sal_Int32 BytesToSend,
+ sal_Int32* nBytes)
+{
+ *nBytes = osl_sendPipe(hPipe, pBuffer, BytesToSend);
+ OSL_TRACE("tried to send %d, sent %d\n",
+ BytesToSend, *nBytes);
+ return (sal_Bool)((*nBytes == BytesToSend) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
+}
+
+sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe hPipe, oslSocket pSocket)
+{
+ sal_Bool bRet = sal_False;
+ sal_Int32 bytes = 0;
+
+ /* duplicate handle on this other side ->
+ receive remote process
+ duplicate handle and send it */
+ DWORD remoteProcessID = 0;
+ HANDLE fd = (HANDLE)pSocket->m_Socket;
+ oslDescriptorType code = osl_Process_TypeSocket;
+
+ OSL_TRACE("osl_sendResourcePipe: enter...");
+
+ if (ReadPipe(hPipe, &remoteProcessID, sizeof(remoteProcessID), &bytes))
+ {
+ HANDLE hRemoteProc = OpenProcess(PROCESS_DUP_HANDLE,
+ FALSE,
+ remoteProcessID);
+
+ if (hRemoteProc != (HANDLE)NULL)
+ {
+ HANDLE newFd;
+
+ if (DuplicateHandle(GetCurrentProcess(),
+ fd,
+ hRemoteProc,
+ &newFd,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ if (
+ WritePipe(hPipe, &code, sizeof(code), &bytes) &&
+ WritePipe(hPipe, &newFd, sizeof(fd), &bytes)
+ )
+ bRet = sal_True;
+ }
+
+ CloseHandle(hRemoteProc);
+ }
+ }
+
+ if (bRet)
+ {
+ sal_Int32 commitCode;
+ OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...\n");
+
+ if (
+ !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) ||
+ (commitCode <= 0)
+ )
+ bRet = sal_False;
+ }
+
+ OSL_TRACE("osl_sendResourcePipe: exit... %d\n", bRet);
+ return(bRet);
+}
+
+
+oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe)
+{
+ sal_Bool bRet = sal_False;
+ sal_Int32 bytes = 0;
+ sal_Int32 commitCode;
+ oslSocket pSocket = NULL;
+
+ /* duplicate handle on the other side ->
+ send my process id receive duplicated handle */
+ HANDLE fd = INVALID_HANDLE_VALUE;
+ DWORD myProcessID = GetCurrentProcessId();
+ oslDescriptorType code = osl_Process_TypeNone;
+
+ OSL_TRACE("osl_receiveResourcePipe: enter...\n");
+
+ if (
+ WritePipe(hPipe, &myProcessID, sizeof(myProcessID), &bytes) &&
+ ReadPipe(hPipe, &code, sizeof(code), &bytes) &&
+ ReadPipe(hPipe, &fd, sizeof(fd), &bytes)
+ )
+ {
+ if (code == osl_Process_TypeSocket)
+ {
+ pSocket = __osl_createSocketImpl((SOCKET)fd);
+ bRet = sal_True;
+ }
+ else
+ {
+ OSL_TRACE("osl_receiveResourcePipe: UKNOWN\n");
+ bRet = sal_False;
+ }
+ }
+
+ if (bRet)
+ commitCode = 1;
+ else
+ commitCode = 0;
+
+ WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes);
+
+ OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p\n", bRet, pSocket);
+
+ return pSocket;
+}
diff --git a/sal/osl/w32/procimpl.cxx b/sal/osl/w32/procimpl.cxx
new file mode 100644
index 000000000000..fc04d5b84a8f
--- /dev/null
+++ b/sal/osl/w32/procimpl.cxx
@@ -0,0 +1,606 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#define UNICODE
+#define _UNICODE
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# ifdef _MSC_VER
+# pragma warning(push,1) /* disable warnings within system headers */
+# endif
+# include <windows.h>
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif
+# include <tchar.h>
+# undef WIN32_LEAN_AND_MEAN
+#endif
+#include "procimpl.h"
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include "secimpl.h"
+#include "rtl/allocator.hxx"
+#include <osl/file.hxx>
+
+#include <list>
+#include <vector>
+#include <algorithm>
+#include <string>
+
+//#################################################
+extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle( HANDLE hFile, sal_uInt32 uFlags );
+
+//#################################################
+const sal_Unicode NAME_VALUE_SEPARATOR = TEXT('=');
+const sal_Char* SPACE = " ";
+const rtl::OUString ENV_COMSPEC = rtl::OUString::createFromAscii("COMSPEC");
+const rtl::OUString QUOTE = rtl::OUString::createFromAscii("\"");
+
+namespace /* private */
+{
+ //#################################################
+ typedef std::list<rtl::OUString, rtl::Allocator<rtl::OUString> > string_container_t;
+ typedef string_container_t::iterator string_container_iterator_t;
+ typedef string_container_t::const_iterator string_container_const_iterator_t;
+ typedef std::pair<string_container_iterator_t, string_container_iterator_t> iterator_pair_t;
+ typedef std::vector<sal_Unicode, rtl::Allocator<sal_Unicode> > environment_container_t;
+
+ //#################################################
+ /* Function object that compares two strings that are
+ expected to be environment variables in the form
+ "name=value". Only the 'name' part will be compared.
+ The comparison is in upper case and returns true
+ if the first of both strings is less than the
+ second one. */
+ struct less_environment_variable :
+ public std::binary_function<rtl::OUString, rtl::OUString, bool>
+ {
+ bool operator() (const rtl::OUString& lhs, const rtl::OUString& rhs) const
+ {
+ OSL_ENSURE((lhs.indexOf(NAME_VALUE_SEPARATOR) > -1) && \
+ (rhs.indexOf(NAME_VALUE_SEPARATOR) > -1), \
+ "Malformed environment variable");
+
+ // Windows compares environment variables uppercase
+ // so we do it, too
+ return (rtl_ustr_compare_WithLength(
+ lhs.toAsciiUpperCase().pData->buffer,
+ lhs.indexOf(NAME_VALUE_SEPARATOR),
+ rhs.toAsciiUpperCase().pData->buffer,
+ rhs.indexOf(NAME_VALUE_SEPARATOR)) < 0);
+ }
+ };
+
+ //#################################################
+ /* Function object used by for_each algorithm to
+ calculate the sum of the length of all strings
+ in a string container. */
+ class sum_of_string_lengths
+ {
+ public:
+ //--------------------------------
+ sum_of_string_lengths() : sum_(0) {}
+
+ //--------------------------------
+ void operator() (const rtl::OUString& string)
+ {
+ OSL_ASSERT(string.getLength());
+
+ // always include the terminating '\0'
+ if (string.getLength())
+ sum_ += string.getLength() + 1;
+ }
+
+ //--------------------------------
+ operator size_t () const
+ {
+ return sum_;
+ }
+ private:
+ size_t sum_;
+ };
+
+ //#################################################
+ inline size_t calc_sum_of_string_lengths(const string_container_t& string_cont)
+ {
+ return std::for_each(
+ string_cont.begin(), string_cont.end(), sum_of_string_lengths());
+ }
+
+ //#################################################
+ void read_environment(/*out*/ string_container_t* environment)
+ {
+ // GetEnvironmentStrings returns a sorted list, Windows
+ // sorts environment variables upper case
+ LPTSTR env = reinterpret_cast<LPTSTR>(GetEnvironmentStrings());
+ LPTSTR p = env;
+
+ while (size_t l = _tcslen(p))
+ {
+ environment->push_back(reinterpret_cast<const sal_Unicode*>(p));
+ p += l + 1;
+ }
+ FreeEnvironmentStrings(env);
+ }
+
+ //#################################################
+ /* the environment list must be sorted, new values
+ should either replace existing ones or should be
+ added to the list, environment variables will
+ be handled case-insensitive */
+ bool create_merged_environment(
+ rtl_uString* env_vars[],
+ sal_uInt32 env_vars_count,
+ /*in|out*/ string_container_t* merged_env)
+ {
+ OSL_ASSERT(env_vars && env_vars_count > 0 && merged_env);
+
+ read_environment(merged_env);
+
+ for (sal_uInt32 i = 0; i < env_vars_count; i++)
+ {
+ rtl::OUString env_var = rtl::OUString(env_vars[i]);
+
+ if (env_var.getLength() == 0)
+ return false;
+
+ iterator_pair_t iter_pair = std::equal_range(
+ merged_env->begin(),
+ merged_env->end(),
+ env_var,
+ less_environment_variable());
+
+ if (env_var.indexOf(NAME_VALUE_SEPARATOR) == -1)
+ {
+ merged_env->erase(iter_pair.first, iter_pair.second);
+ }
+ else
+ {
+ if (iter_pair.first != iter_pair.second) // found
+ *iter_pair.first = env_var;
+ else // not found
+ merged_env->insert(iter_pair.first, env_var);
+ }
+ }
+ return true;
+ }
+
+ //#################################################
+ /* Create a merged environment */
+ bool setup_process_environment(
+ rtl_uString* environment_vars[],
+ sal_uInt32 n_environment_vars,
+ /*in|out*/ environment_container_t& environment)
+ {
+ string_container_t merged_env;
+ if (!create_merged_environment(environment_vars, n_environment_vars, &merged_env))
+ return false;
+
+ // allocate enough space for the '\0'-separated environment strings and
+ // a final '\0'
+ environment.resize(calc_sum_of_string_lengths(merged_env) + 1);
+
+ string_container_const_iterator_t iter = merged_env.begin();
+ string_container_const_iterator_t iter_end = merged_env.end();
+
+ sal_uInt32 pos = 0;
+ for (/**/; iter != iter_end; ++iter)
+ {
+ rtl::OUString envv = *iter;
+
+ OSL_ASSERT(envv.getLength());
+
+ sal_uInt32 n = envv.getLength() + 1; // copy the final '\0', too
+ rtl_copyMemory(
+ reinterpret_cast<void*>(&environment[pos]),
+ reinterpret_cast<const void*>(envv.getStr()),
+ n * sizeof(sal_Unicode));
+ pos += n;
+ }
+ environment[pos] = 0; // append a final '\0'
+
+ return true;
+ }
+
+ //##########################################################
+ /* In contrast to the Win32 API function CreatePipe with
+ this function the caller is able to determine separately
+ which handle of the pipe is inheritable. */
+ bool create_pipe(
+ PHANDLE p_read_pipe,
+ bool b_read_pipe_inheritable,
+ PHANDLE p_write_pipe,
+ bool b_write_pipe_inheritable,
+ LPVOID p_security_descriptor = NULL,
+ DWORD pipe_size = 0)
+ {
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = p_security_descriptor;
+ sa.bInheritHandle = b_read_pipe_inheritable || b_write_pipe_inheritable;
+
+ BOOL bRet = FALSE;
+ HANDLE hTemp = NULL;
+
+ if (!b_read_pipe_inheritable && b_write_pipe_inheritable)
+ {
+ bRet = CreatePipe(&hTemp, p_write_pipe, &sa, pipe_size);
+
+ if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp,
+ GetCurrentProcess(), p_read_pipe, 0, FALSE,
+ DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle(hTemp);
+ CloseHandle(*p_read_pipe);
+ return false;
+ }
+ }
+ else if (b_read_pipe_inheritable && !b_write_pipe_inheritable)
+ {
+ bRet = CreatePipe(p_read_pipe, &hTemp, &sa, pipe_size);
+
+ if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp,
+ GetCurrentProcess(), p_write_pipe, 0, FALSE,
+ DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle(hTemp);
+ CloseHandle(*p_write_pipe);
+ return false;
+ }
+ }
+ else
+ {
+ bRet = CreatePipe(p_read_pipe, p_write_pipe, &sa, pipe_size);
+ }
+ return bRet;
+ }
+
+ //#########################################################
+ // Add a quote sign to the start and the end of a string
+ // if not already present
+ rtl::OUString quote_string(const rtl::OUString& string)
+ {
+ rtl::OUStringBuffer quoted;
+ if (string.indexOf(QUOTE) != 0)
+ quoted.append(QUOTE);
+
+ quoted.append(string);
+
+ if (string.lastIndexOf(QUOTE) != (string.getLength() - 1))
+ quoted.append(QUOTE);
+
+ return quoted.makeStringAndClear();
+ }
+
+ //##########################################################
+ // Returns the system path of the executable which can either
+ // be provided via the strImageName parameter or as first
+ // element of the strArguments list.
+ // The returned path will be quoted if it contains spaces.
+ rtl::OUString get_executable_path(
+ rtl_uString* image_name,
+ rtl_uString* cmdline_args[],
+ sal_uInt32 n_cmdline_args,
+ bool search_path)
+ {
+ rtl::OUString exe_name;
+
+ if (image_name)
+ exe_name = image_name;
+ else if (n_cmdline_args)
+ exe_name = rtl::OUString(cmdline_args[0]);
+
+ rtl::OUString exe_url = exe_name;
+ if (search_path)
+ osl_searchFileURL(exe_name.pData, NULL, &exe_url.pData);
+
+ rtl::OUString exe_path;
+ if (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(exe_url, exe_path))
+ return rtl::OUString();
+
+ if (exe_path.indexOf(' ') != -1)
+ exe_path = quote_string(exe_path);
+
+ return exe_path;
+ }
+
+ //##########################################################
+ rtl::OUString get_file_extension(const rtl::OUString& file_name)
+ {
+ sal_Int32 index = file_name.lastIndexOf('.');
+ if ((index != -1) && ((index + 1) < file_name.getLength()))
+ return file_name.copy(index + 1);
+
+ return rtl::OUString();
+ }
+
+ //##########################################################
+ bool is_batch_file(const rtl::OUString& file_name)
+ {
+ rtl::OUString ext = get_file_extension(file_name);
+ return (ext.equalsIgnoreAsciiCaseAscii("bat") ||
+ ext.equalsIgnoreAsciiCaseAscii("cmd") ||
+ ext.equalsIgnoreAsciiCaseAscii("btm"));
+ }
+
+ //##########################################################
+ rtl::OUString get_batch_processor()
+ {
+ rtl::OUString comspec;
+ osl_getEnvironment(ENV_COMSPEC.pData, &comspec.pData);
+
+ OSL_ASSERT(comspec.getLength());
+
+ /* check if comspec path contains blanks and quote it if any */
+ if (comspec.indexOf(' ') != -1)
+ comspec = quote_string(comspec);
+
+ return comspec;
+ }
+
+} // namespace private
+
+
+//#################################################
+oslProcessError SAL_CALL osl_executeProcess(
+ rtl_uString *strImageName,
+ rtl_uString *strArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *strDirectory,
+ rtl_uString *strEnvironmentVars[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess
+)
+{
+ return osl_executeProcess_WithRedirectedIO(
+ strImageName,
+ strArguments,
+ nArguments,
+ Options,
+ Security,
+ strDirectory,
+ strEnvironmentVars,
+ nEnvironmentVars,
+ pProcess,
+ NULL, NULL, NULL );
+}
+
+//#################################################
+oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrDirectory,
+ rtl_uString *ustrEnvironmentVars[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess,
+ oslFileHandle *pProcessInputWrite,
+ oslFileHandle *pProcessOutputRead,
+ oslFileHandle *pProcessErrorRead)
+{
+ rtl::OUString exe_path = get_executable_path(
+ ustrImageName, ustrArguments, nArguments, (Options & osl_Process_SEARCHPATH));
+
+ if (0 == exe_path.getLength())
+ return osl_Process_E_NotFound;
+
+ if (pProcess == NULL)
+ return osl_Process_E_InvalidError;
+
+ DWORD flags = NORMAL_PRIORITY_CLASS;
+ rtl::OUStringBuffer command_line;
+
+ if (is_batch_file(exe_path))
+ {
+ rtl::OUString batch_processor = get_batch_processor();
+
+ if (batch_processor.getLength())
+ {
+ /* cmd.exe does not work without a console window */
+ if (!(Options & osl_Process_WAIT) || (Options & osl_Process_DETACHED))
+ flags |= CREATE_NEW_CONSOLE;
+
+ command_line.append(batch_processor);
+ command_line.appendAscii(" /c ");
+ }
+ else
+ // should we return here in case of error?
+ return osl_Process_E_Unknown;
+ }
+
+ command_line.append(exe_path);
+
+ /* Add remaining arguments to command line. If ustrImageName is NULL
+ the first parameter is the name of the executable so we have to
+ start at 1 instead of 0 */
+ for (sal_uInt32 n = (NULL != ustrImageName) ? 0 : 1; n < nArguments; n++)
+ {
+ command_line.appendAscii(SPACE);
+
+ /* Quote arguments containing blanks */
+ if (rtl::OUString(ustrArguments[n]).indexOf(' ') != -1)
+ command_line.append(quote_string(ustrArguments[n]));
+ else
+ command_line.append(ustrArguments[n]);
+ }
+
+ environment_container_t environment;
+ LPVOID p_environment = NULL;
+
+ if (nEnvironmentVars && ustrEnvironmentVars)
+ {
+ if (!setup_process_environment(
+ ustrEnvironmentVars, nEnvironmentVars, environment))
+ return osl_Process_E_InvalidError;
+
+ flags |= CREATE_UNICODE_ENVIRONMENT;
+ p_environment = &environment[0];
+ }
+
+ rtl::OUString cwd;
+ if (ustrDirectory && ustrDirectory->length && (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(ustrDirectory, cwd)))
+ return osl_Process_E_InvalidError;
+
+ LPCWSTR p_cwd = (cwd.getLength()) ? reinterpret_cast<LPCWSTR>(cwd.getStr()) : NULL;
+
+ if ((Options & osl_Process_DETACHED) && !(flags & CREATE_NEW_CONSOLE))
+ flags |= DETACHED_PROCESS;
+
+ STARTUPINFO startup_info;
+ memset(&startup_info, 0, sizeof(STARTUPINFO));
+
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.dwFlags = STARTF_USESHOWWINDOW;
+ startup_info.lpDesktop = L"";
+
+ /* Create pipes for redirected IO */
+ HANDLE hInputRead = NULL;
+ HANDLE hInputWrite = NULL;
+ if (pProcessInputWrite && create_pipe(&hInputRead, true, &hInputWrite, false))
+ startup_info.hStdInput = hInputRead;
+
+ HANDLE hOutputRead = NULL;
+ HANDLE hOutputWrite = NULL;
+ if (pProcessOutputRead && create_pipe(&hOutputRead, false, &hOutputWrite, true))
+ startup_info.hStdOutput = hOutputWrite;
+
+ HANDLE hErrorRead = NULL;
+ HANDLE hErrorWrite = NULL;
+ if (pProcessErrorRead && create_pipe(&hErrorRead, false, &hErrorWrite, true))
+ startup_info.hStdError = hErrorWrite;
+
+ bool b_inherit_handles = false;
+ if (pProcessInputWrite || pProcessOutputRead || pProcessErrorRead)
+ {
+ startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ b_inherit_handles = true;
+ }
+
+ switch(Options & (osl_Process_NORMAL | osl_Process_HIDDEN | osl_Process_MINIMIZED | osl_Process_MAXIMIZED | osl_Process_FULLSCREEN))
+ {
+ case osl_Process_HIDDEN:
+ startup_info.wShowWindow = SW_HIDE;
+ flags |= CREATE_NO_WINDOW; // ignored for non-console
+ // applications; ignored on
+ // Win9x
+ break;
+
+ case osl_Process_MINIMIZED:
+ startup_info.wShowWindow = SW_MINIMIZE;
+ break;
+
+ case osl_Process_MAXIMIZED:
+ case osl_Process_FULLSCREEN:
+ startup_info.wShowWindow = SW_MAXIMIZE;
+ break;
+
+ default:
+ startup_info.wShowWindow = SW_NORMAL;
+ }
+
+ rtl::OUString cmdline = command_line.makeStringAndClear();
+ PROCESS_INFORMATION process_info;
+ BOOL bRet = FALSE;
+
+ if ((Security != NULL) && (((oslSecurityImpl*)Security)->m_hToken != NULL))
+ {
+ bRet = CreateProcessAsUser(
+ ((oslSecurityImpl*)Security)->m_hToken,
+ NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL,
+ b_inherit_handles, flags, p_environment, p_cwd,
+ &startup_info, &process_info);
+ }
+ else
+ {
+ bRet = CreateProcess(
+ NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL,
+ b_inherit_handles, flags, p_environment, p_cwd,
+ &startup_info, &process_info);
+ }
+
+ /* Now we can close the pipe ends that are used by the child process */
+
+ if (hInputRead)
+ CloseHandle(hInputRead);
+
+ if (hOutputWrite)
+ CloseHandle(hOutputWrite);
+
+ if (hErrorWrite)
+ CloseHandle(hErrorWrite);
+
+ if (bRet)
+ {
+ CloseHandle(process_info.hThread);
+
+ oslProcessImpl* pProcImpl = reinterpret_cast<oslProcessImpl*>(
+ rtl_allocateMemory(sizeof(oslProcessImpl)));
+
+ if (pProcImpl != NULL)
+ {
+ pProcImpl->m_hProcess = process_info.hProcess;
+ pProcImpl->m_IdProcess = process_info.dwProcessId;
+
+ *pProcess = (oslProcess)pProcImpl;
+
+ if (Options & osl_Process_WAIT)
+ WaitForSingleObject(pProcImpl->m_hProcess, INFINITE);
+
+ if (pProcessInputWrite)
+ *pProcessInputWrite = osl_createFileHandleFromOSHandle(hInputWrite, osl_File_OpenFlag_Write);
+
+ if (pProcessOutputRead)
+ *pProcessOutputRead = osl_createFileHandleFromOSHandle(hOutputRead, osl_File_OpenFlag_Read);
+
+ if (pProcessErrorRead)
+ *pProcessErrorRead = osl_createFileHandleFromOSHandle(hErrorRead, osl_File_OpenFlag_Read);
+
+ return osl_Process_E_None;
+ }
+ }
+
+ /* if an error occured we have to close the server side pipe ends too */
+
+ if (hInputWrite)
+ CloseHandle(hInputWrite);
+
+ if (hOutputRead)
+ CloseHandle(hOutputRead);
+
+ if (hErrorRead)
+ CloseHandle(hErrorRead);
+
+ return osl_Process_E_Unknown;
+}
diff --git a/sal/osl/w32/procimpl.h b/sal/osl/w32/procimpl.h
new file mode 100644
index 000000000000..b783f9b52ae2
--- /dev/null
+++ b/sal/osl/w32/procimpl.h
@@ -0,0 +1,47 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_PROCIMPL_H_
+#define _OSL_PROCIMPL_H_
+
+#include <osl/process.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslProcessImpl {
+ HANDLE m_hProcess;
+ DWORD m_IdProcess;
+} oslProcessImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/w32/profile.cxx b/sal/osl/w32/profile.cxx
new file mode 100644
index 000000000000..9f4ea5630e1f
--- /dev/null
+++ b/sal/osl/w32/profile.cxx
@@ -0,0 +1,2707 @@
+/*************************************************************************
+*
+* 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 "system.h"
+
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include <osl/diagnose.h>
+#include <osl/profile.h>
+#include <osl/process.h>
+#include <osl/file.h>
+#include <osl/util.h>
+#include <rtl/alloc.h>
+#include <algorithm>
+using std::min;
+static inline void copy_ustr_n( void *dest, const void *source, size_t length ) { rtl_copyMemory(dest, source, length*sizeof(sal_Unicode)); }
+
+#define LINES_INI 32
+#define LINES_ADD 10
+#define SECTIONS_INI 5
+#define SECTIONS_ADD 3
+#define ENTRIES_INI 5
+#define ENTRIES_ADD 3
+
+
+#define STR_INI_EXTENSION L".ini"
+#define STR_INI_METAHOME "?~"
+#define STR_INI_METASYS "?$"
+#define STR_INI_METACFG "?^"
+#define STR_INI_METAINS "?#"
+
+#define STR_INI_BOOLYES "yes"
+#define STR_INI_BOOLON "on"
+#define STR_INI_BOOLONE "1"
+#define STR_INI_BOOLNO "no"
+#define STR_INI_BOOLOFF "off"
+#define STR_INI_BOOLZERO "0"
+
+#define FLG_USER 0x00FF
+#define FLG_AUTOOPEN 0x0100
+#define FLG_MODIFIED 0x0200
+
+#define SVERSION_LOCATION STR_INI_METACFG
+#define SVERSION_FALLBACK STR_INI_METASYS
+#define SVERSION_NAME "sversion"
+#define SVERSION_SECTION "Versions"
+#define SVERSION_SOFFICE "StarOffice"
+#define SVERSION_PROFILE "soffice.ini"
+#define SVERSION_OPTION "userid:"
+#define SVERSION_DIRS { "bin", "program" }
+#define SVERSION_USER "user"
+
+#define DEFAULT_PMODE (_S_IREAD | _S_IWRITE)
+
+#define _BUILD_STR_(n) # n
+#define BUILD_STR(n) _BUILD_STR_(n)
+
+
+/*#define DEBUG_OSL_PROFILE 1*/
+/*#define TRACE_OSL_PROFILE 1*/
+
+
+/*****************************************************************************/
+/* Data Type Definition */
+/*****************************************************************************/
+
+typedef FILETIME osl_TStamp;
+
+typedef enum _osl_TLockMode
+{
+ un_lock, read_lock, write_lock
+} osl_TLockMode;
+
+typedef struct _osl_TFile
+{
+ HANDLE m_Handle;
+ sal_Char* m_pReadPtr;
+ sal_Char m_ReadBuf[512];
+/* sal_Char* m_pWritePtr; */
+/* sal_Char m_WriteBuf[512]; */
+ sal_Char* m_pWriteBuf;
+ sal_uInt32 m_nWriteBufLen;
+ sal_uInt32 m_nWriteBufFree;
+} osl_TFile;
+
+typedef struct _osl_TProfileEntry
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+} osl_TProfileEntry;
+
+typedef struct _osl_TProfileSection
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+ sal_uInt32 m_NoEntries;
+ sal_uInt32 m_MaxEntries;
+ osl_TProfileEntry* m_Entries;
+} osl_TProfileSection;
+
+
+/*
+ Profile-data structure hidden behind oslProfile:
+*/
+typedef struct _osl_TProfileImpl
+{
+ sal_uInt32 m_Flags;
+ osl_TFile* m_pFile;
+ osl_TStamp m_Stamp;
+ sal_uInt32 m_NoLines;
+ sal_uInt32 m_MaxLines;
+ sal_uInt32 m_NoSections;
+ sal_uInt32 m_MaxSections;
+ sal_Char** m_Lines;
+ rtl_uString *m_strFileName;
+ osl_TProfileSection* m_Sections;
+} osl_TProfileImpl;
+
+
+/*****************************************************************************/
+/* Static Module Function Declarations */
+/*****************************************************************************/
+
+static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags );
+static osl_TStamp closeFileImpl(osl_TFile* pFile);
+static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
+static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate);
+static osl_TStamp getFileStamp(osl_TFile* pFile);
+
+static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen);
+static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine);
+static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen);
+static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line);
+static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo);
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const sal_Char* Entry, sal_uInt32 Len);
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const sal_Char* Entry, sal_uInt32 Len);
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len);
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry);
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
+static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup);
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable);
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile);
+static sal_Bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile);
+
+static sal_Bool writeProfileImpl (osl_TFile* pFile);
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
+static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
+static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension);
+
+static sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName);
+
+/*****************************************************************************/
+/* Exported Module Functions */
+/*****************************************************************************/
+
+oslProfile SAL_CALL osl_openProfile(rtl_uString *strProfileName, sal_uInt32 Flags)
+{
+ osl_TFile* pFile = NULL;
+ osl_TProfileImpl* pProfile;
+ rtl_uString *FileName=NULL;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_openProfile\n");
+#endif
+ OSL_VERIFY(strProfileName);
+
+ if (rtl_uString_getLength(strProfileName) == 0 )
+ {
+ OSL_VERIFY(osl_getProfileName(NULL, NULL, &FileName));
+ }
+ else
+ {
+ rtl_uString_assign(&FileName, strProfileName);
+ }
+
+
+ osl_getSystemPathFromFileURL(FileName, &FileName);
+
+
+#ifdef DEBUG_OSL_PROFILE
+ Flags=osl_Profile_FLUSHWRITE;
+
+ // OSL_TRACE("opening '%s'\n",FileName);
+ if ( Flags == osl_Profile_DEFAULT )
+ {
+ OSL_TRACE("with osl_Profile_DEFAULT \n");
+ }
+ if ( Flags & osl_Profile_SYSTEM )
+ {
+ OSL_TRACE("with osl_Profile_SYSTEM \n");
+ }
+ if ( Flags & osl_Profile_READLOCK )
+ {
+ OSL_TRACE("with osl_Profile_READLOCK \n");
+ }
+ if ( Flags & osl_Profile_WRITELOCK )
+ {
+ OSL_TRACE("with osl_Profile_WRITELOCK \n");
+ }
+/* if ( Flags & osl_Profile_READWRITE ) */
+/* { */
+/* OSL_TRACE("with osl_Profile_READWRITE \n"); */
+/* } */
+ if ( Flags & osl_Profile_FLUSHWRITE )
+ {
+ OSL_TRACE("with osl_Profile_FLUSHWRITE \n");
+ }
+#endif
+
+ if ( (! (Flags & osl_Profile_SYSTEM)) && ( (pFile = openFileImpl(FileName, Flags) ) == NULL ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [not opened]\n");
+#endif
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return (NULL);
+ }
+
+
+ pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
+
+
+ pProfile->m_Flags = Flags & FLG_USER;
+ osl_getSystemPathFromFileURL(strProfileName, &pProfile->m_strFileName);
+// rtl_uString_assign(&pProfile->m_strFileName, strProfileName);
+
+ if (Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ))
+ pProfile->m_pFile = pFile;
+
+ pProfile->m_Stamp = getFileStamp(pFile);
+
+ loadProfile(pFile, pProfile);
+
+ if (pProfile->m_pFile == NULL)
+ closeFileImpl(pFile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [ok]\n");
+#endif
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return (pProfile);
+}
+
+sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_closeProfile\n");
+#endif
+
+ if ( Profile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ pProfile = acquireProfile(Profile,sal_True);
+
+ if ( pProfile != 0 )
+ {
+ if ( !( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
+ {
+/* if (pProfile->m_pFile == NULL) */
+/* pProfile->m_pFile = openFileImpl(pProfile->m_Filename, sal_True); */
+
+ storeProfile(pProfile, sal_False);
+ }
+ }
+ else
+ {
+ pProfile = acquireProfile(Profile,sal_False);
+ }
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [pProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (pProfile->m_pFile != NULL)
+ closeFileImpl(pProfile->m_pFile);
+ }
+
+ pProfile->m_pFile = NULL;
+ rtl_uString_release(pProfile->m_strFileName);
+ pProfile->m_strFileName = NULL;
+
+ /* release whole profile data types memory */
+ if ( pProfile->m_NoLines > 0)
+ {
+ unsigned int index=0;
+ if ( pProfile->m_Lines != 0 )
+ {
+ for ( index = 0 ; index < pProfile->m_NoLines ; ++index)
+ {
+ if ( pProfile->m_Lines[index] != 0 )
+ {
+ free(pProfile->m_Lines[index]);
+ }
+ }
+ free(pProfile->m_Lines);
+ }
+ if ( pProfile->m_Sections != 0 )
+ {
+ /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
+ for ( index = 0 ; index < pProfile->m_NoSections ; ++index )
+ {
+ if ( pProfile->m_Sections[index].m_Entries != 0 )
+ {
+ free(pProfile->m_Sections[index].m_Entries);
+ }
+ }
+ free(pProfile->m_Sections);
+ }
+
+ }
+ free(pProfile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
+ osl_TFile* pFile;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_flushProfile()\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [pProfile == 0]\n");
+#endif
+ return sal_False;
+ }
+
+ pFile = pProfile->m_pFile;
+ if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [invalid file]\n");
+#endif
+ return sal_False;
+ }
+
+ if ( pProfile->m_Flags & FLG_MODIFIED )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("swapping to storeprofile\n");
+#endif
+ bRet = storeProfile(pProfile,sal_False);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [ok]\n");
+#endif
+ return bRet;
+}
+
+static sal_Bool writeProfileImpl(osl_TFile* pFile)
+{
+ DWORD BytesWritten=0;
+ BOOL bRet;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileImpl()\n");
+#endif
+
+ if ( !( pFile != 0 && pFile->m_Handle != INVALID_HANDLE_VALUE ) || ( pFile->m_pWriteBuf == 0 ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileImpl() [invalid args]\n");
+#endif
+ return sal_False;
+ }
+
+#ifdef DEBUG_OSL_PROFILE
+/* OSL_TRACE("File Buffer in writeProfileImpl '%s' size == '%i' '%i'(%i)\n",
+ pFile->m_pWriteBuf,pFile->m_nWriteBufLen,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/
+#endif
+
+ bRet=WriteFile(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree,&BytesWritten,NULL);
+
+ if ( bRet == 0 || BytesWritten <= 0 )
+ {
+ OSL_ENSURE(bRet,"WriteFile failed!!!");
+
+ OSL_TRACE("write failed '%s'\n",strerror(errno));
+
+/* OSL_TRACE("Out osl_writeProfileImpl() [write '%s']\n",strerror(errno));*/
+ return (sal_False);
+ }
+
+ free(pFile->m_pWriteBuf);
+ pFile->m_pWriteBuf=0;
+ pFile->m_nWriteBufLen=0;
+ pFile->m_nWriteBufFree=0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileImpl() [ok]\n");
+#endif
+ return sal_True;
+}
+
+
+sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Char* pszString, sal_uInt32 MaxLen,
+ const sal_Char* pszDefault)
+{
+ sal_uInt32 NoEntry;
+ const sal_Char* pStr = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileString\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pProfile==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries) &&
+ ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
+ '=')) != NULL))
+ pStr++;
+ else
+ pStr = pszDefault;
+
+ if ( pStr != 0 )
+ {
+ pStr = stripBlanks(pStr, NULL);
+ MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
+ pStr = stripBlanks(pStr, &MaxLen);
+ strncpy(pszString, pStr, MaxLen);
+ pszString[MaxLen] = '\0';
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ GetPrivateProfileString(pszSection, pszEntry, pszDefault, pszString, MaxLen, aFileName);
+ }
+
+ releaseProfile(pProfile);
+
+ if ( pStr == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pStr==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [ok]\n");
+#endif
+
+
+
+
+ return (sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Default)
+{
+ sal_Char Line[32];
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileBool\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ if ((stricmp(Line, STR_INI_BOOLYES) == 0) ||
+ (stricmp(Line, STR_INI_BOOLON) == 0) ||
+ (stricmp(Line, STR_INI_BOOLONE) == 0))
+ Default = sal_True;
+ else
+ if ((stricmp(Line, STR_INI_BOOLNO) == 0) ||
+ (stricmp(Line, STR_INI_BOOLOFF) == 0) ||
+ (stricmp(Line, STR_INI_BOOLZERO) == 0))
+ Default = sal_False;
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileBool [ok]\n");
+#endif
+
+ return (Default);
+}
+
+
+sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Default)
+{
+ sal_uInt32 i;
+ sal_Char Line[256];
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileIdent\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ i = 0;
+ while (Strings[i] != NULL)
+ {
+ if (stricmp(Line, Strings[i]) == 0)
+ {
+ Default = i + FirstId;
+ break;
+ }
+ i++;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileIdent [ok]\n");
+#endif
+ return (Default);
+}
+
+sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ const sal_Char* pszString)
+{
+ sal_uInt32 i;
+ sal_Bool bRet = sal_False;
+ sal_uInt32 NoEntry;
+ const sal_Char* pStr;
+ sal_Char Line[4096];
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileString\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [pProfile==0]\n");
+#endif
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
+ {
+ Line[0] = '\0';
+ addLine(pProfile, Line);
+
+ Line[0] = '[';
+ strcpy(&Line[1], pszSection);
+ Line[1 + strlen(pszSection)] = ']';
+ Line[2 + strlen(pszSection)] = '\0';
+
+ if (((pStr = addLine(pProfile, Line)) == NULL) ||
+ (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
+ {
+ releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not added]\n");
+#endif
+ return (sal_False);
+ }
+
+ pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
+ NoEntry = pSec->m_NoEntries;
+ }
+
+ Line[0] = '\0';
+ strcpy(&Line[0], pszEntry);
+ Line[0 + strlen(pszEntry)] = '=';
+ strcpy(&Line[1 + strlen(pszEntry)], pszString);
+
+ if (NoEntry >= pSec->m_NoEntries)
+ {
+ if (pSec->m_NoEntries > 0)
+ i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
+ else
+ i = pSec->m_Line + 1;
+
+ if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
+ (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
+ {
+ releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not inserted]\n");
+#endif
+ return (sal_False);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ else
+ {
+ i = pSec->m_Entries[NoEntry].m_Line;
+ free(pProfile->m_Lines[i]);
+ pProfile->m_Lines[i] = strdup(Line);
+ setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ WritePrivateProfileString(pszSection, pszEntry, pszString, aFileName);
+ }
+
+ bRet = releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [ok]\n");
+#endif
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Value)
+{
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileBool\n");
+#endif
+
+ if (Value)
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileBool [ok]\n");
+#endif
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Value)
+{
+ int i, n;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileIdent\n");
+#endif
+
+ for (n = 0; Strings[n] != NULL; n++);
+
+ if ((i = Value - FirstId) >= n)
+ bRet=sal_False;
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileIdent\n");
+#endif
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
+ const sal_Char *pszSection, const sal_Char *pszEntry)
+{
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_removeProfileEntry\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries))
+ {
+ removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
+ removeEntry(pSec, NoEntry);
+ if (pSec->m_NoEntries == 0)
+ {
+ removeLine(pProfile, pSec->m_Line);
+
+ /* remove any empty separation line */
+ if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
+ removeLine(pProfile, pSec->m_Line - 1);
+
+ removeSection(pProfile, pSec);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ WritePrivateProfileString(pszSection, pszEntry, NULL, aFileName);
+ }
+
+ bRet = releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [ok]\n");
+#endif
+ return bRet;
+}
+
+
+sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const sal_Char *pszSection,
+ sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_getProfileSectionEntries\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]\n");
+#endif
+
+
+ return (0);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
+ n += pSec->m_Entries[i].m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ n += pSec->m_Entries[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ n = 0;
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ n = GetPrivateProfileString(pszSection, NULL, NULL, pszBuffer, MaxLen, aFileName);
+ }
+
+ releaseProfile(pProfile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [ok]\n");
+#endif
+
+ return (n);
+}
+
+
+sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName)
+{
+ sal_Bool bFailed;
+ ::osl::LongPathBuffer< sal_Unicode > aFile( MAX_LONG_PATH );
+ ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
+ sal_uInt32 nFileLen = 0;
+ sal_uInt32 nPathLen = 0;
+
+ rtl_uString * strTmp = NULL;
+ oslFileError nError;
+
+ /* build file name */
+ if (strName && strName->length)
+ {
+ if( ::sal::static_int_cast< sal_uInt32 >( strName->length ) >= aFile.getBufSizeInSymbols() )
+ return sal_False;
+
+ copy_ustr_n( aFile, strName->buffer, strName->length+1);
+ nFileLen = strName->length;
+
+ if (rtl_ustr_indexOfChar( aFile, L'.' ) == -1)
+ {
+ if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
+ return sal_False;
+
+ /* add default extension */
+ copy_ustr_n( aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1 );
+ nFileLen += wcslen(STR_INI_EXTENSION);
+ }
+ }
+ else
+ {
+ rtl_uString *strProgName = NULL;
+ sal_Unicode *pProgName;
+ sal_Int32 nOffset = 0;
+ sal_Int32 nLen;
+ sal_Int32 nPos;
+
+ if (osl_getExecutableFile(&strProgName) != osl_Process_E_None)
+ return sal_False;
+
+ /* remove path and extension from filename */
+ pProgName = strProgName->buffer;
+ nLen = strProgName->length ;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'/' )) != -1)
+ nOffset = nPos + 1;
+ else if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L':' )) != -1)
+ nOffset = nPos + 1;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'.' )) != -1 )
+ nLen -= 4;
+
+ if ((nFileLen = nLen - nOffset) >= aFile.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aFile, pProgName + nOffset, nFileLen);
+
+ if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
+ return sal_False;
+
+ /* add default extension */
+ copy_ustr_n(aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1);
+ nFileLen += wcslen(STR_INI_EXTENSION);
+
+ rtl_uString_release( strProgName );
+ }
+
+ if (aFile[0] == 0)
+ return sal_False;
+
+ /* build directory path */
+ if (strPath && strPath->length)
+ {
+ sal_Unicode *pPath = rtl_uString_getStr(strPath);
+ sal_Int32 nLen = rtl_uString_getLength(strPath);
+
+ if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAHOME) , STR_INI_METAHOME) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)] == '/')))
+ {
+ rtl_uString * strHome = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getHomeDir(security, &strHome);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+
+ if ( ::sal::static_int_cast< sal_uInt32 >( strHome->length ) >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n( aPath, strHome->buffer, strHome->length+1);
+ nPathLen = strHome->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METAHOME))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strHome);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METACFG), STR_INI_METACFG) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METACFG)] == '/')))
+ {
+ rtl_uString * strConfig = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfig);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+
+ if ( ::sal::static_int_cast< sal_uInt32 >( strConfig->length ) >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n( aPath, strConfig->buffer, strConfig->length+1 );
+ nPathLen = strConfig->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METACFG))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strConfig);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METASYS), STR_INI_METASYS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METASYS)] == '/')))
+ {
+ if (((nPathLen = GetWindowsDirectoryW(::osl::mingw_reinterpret_cast<LPWSTR>(aPath), aPath.getBufSizeInSymbols())) == 0) || (nPathLen >= aPath.getBufSizeInSymbols()))
+ return (sal_False);
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METASYS))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAINS), STR_INI_METAINS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAINS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '/') ||
+ (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '"') ) )
+ {
+ if (! lookupProfile(pPath + RTL_CONSTASCII_LENGTH(STR_INI_METAINS), aFile, aPath))
+ return (sal_False);
+
+ nPathLen = rtl_ustr_getLength(aPath);
+ }
+
+ else if( ::sal::static_int_cast< sal_uInt32 >( nLen ) < aPath.getBufSizeInSymbols())
+ {
+ copy_ustr_n(aPath, pPath, nLen+1);
+ nPathLen = rtl_ustr_getLength(aPath);
+ }
+ else
+ return sal_False;
+ }
+ else
+ {
+ rtl_uString * strConfigDir = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfigDir);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+ if ( ::sal::static_int_cast< sal_uInt32 >( strConfigDir->length ) >= aPath.getBufSizeInSymbols() )
+ return sal_False;
+
+ copy_ustr_n(aPath, strConfigDir->buffer, strConfigDir->length+1);
+ nPathLen = strConfigDir->length;
+ }
+
+ if (nPathLen && (aPath[nPathLen - 1] != L'/') && (aPath[nPathLen - 1] != L'\\'))
+ {
+ aPath[nPathLen++] = L'\\';
+ aPath[nPathLen] = 0;
+ }
+
+ if (nPathLen + nFileLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ /* append file name */
+ copy_ustr_n(aPath + nPathLen, aFile, nFileLen+1);
+ nPathLen += nFileLen;
+
+ /* copy filename */
+ rtl_uString_newFromStr_WithLength(&strTmp, aPath, nPathLen);
+ nError = osl_getFileURLFromSystemPath(strTmp, strProfileName);
+ rtl_uString_release(strTmp);
+
+ return (sal_Bool) (nError == osl_File_E_None);
+}
+
+
+sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ return (0);
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if ((n + pSec->m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
+ pSec->m_Len);
+ n += pSec->m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ n += pProfile->m_Sections[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ n = GetPrivateProfileSectionNames(pszBuffer, MaxLen, aFileName);
+ }
+
+ releaseProfile(pProfile);
+
+ return (n);
+}
+
+
+
+
+/*****************************************************************************/
+/* Static Module Functions */
+/*****************************************************************************/
+
+static osl_TStamp getFileStamp(osl_TFile* pFile)
+{
+ FILETIME FileTime;
+
+ if ((pFile->m_Handle == INVALID_HANDLE_VALUE) ||
+ (! GetFileTime(pFile->m_Handle, NULL, NULL, &FileTime)))
+ memset(&FileTime, 0, sizeof(FileTime));
+
+ return (FileTime);
+}
+
+
+
+static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
+{
+ sal_Bool status = sal_False;
+ OVERLAPPED Overlapped;
+
+ if (pFile->m_Handle == INVALID_HANDLE_VALUE)
+ return (sal_False);
+
+ memset(&Overlapped, 0, sizeof(Overlapped));
+
+ switch (eMode)
+ {
+ case un_lock:
+ status = (sal_Bool) UnlockFileEx(
+ pFile->m_Handle, 0, 0xFFFFFFFF, 0, &Overlapped);
+ break;
+
+ case read_lock:
+ status = (sal_Bool) LockFileEx(
+ pFile->m_Handle, 0, 0, 0xFFFFFFFF, 0, &Overlapped);
+ break;
+
+ case write_lock:
+ status = (sal_Bool) LockFileEx(
+ pFile->m_Handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 0xFFFFFFFF, 0,
+ &Overlapped);
+ break;
+ }
+
+ return (status);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags )
+{
+ osl_TFile* pFile = reinterpret_cast< osl_TFile*>( calloc( 1, sizeof(osl_TFile) ) );
+ sal_Bool bWriteable = sal_False;
+
+/* if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE | osl_Profile_READWRITE ) )*/
+ if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("setting bWriteable to TRUE\n");
+#endif
+ bWriteable=sal_True;
+ }
+
+ if (! bWriteable)
+ {
+#if 0
+//#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("opening '%s' read only\n",pszFilename);
+#endif
+
+ pFile->m_Handle = CreateFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strFileName )), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ /* mfe: argghh!!! do not check if the file could be openend */
+ /* default mode expects it that way!!! */
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("opening '%s' read/write\n",pszFilename);
+#endif
+
+ if ((pFile->m_Handle = CreateFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strFileName )), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
+ == INVALID_HANDLE_VALUE)
+ {
+ free(pFile);
+ return (NULL);
+ }
+ }
+
+ pFile->m_pWriteBuf=0;
+ pFile->m_nWriteBufFree=0;
+ pFile->m_nWriteBufLen=0;
+
+ if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("locking '%s' file\n",pszFilename);
+#endif
+
+ lockFile(pFile, bWriteable ? write_lock : read_lock);
+ }
+
+ /* mfe: new WriteBuf obsolete */
+/* pFile->m_pWritePtr = pFile->m_Buf;*/
+/* pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);*/
+
+ return (pFile);
+}
+
+
+
+
+
+
+
+
+
+static osl_TStamp closeFileImpl(osl_TFile* pFile)
+{
+ osl_TStamp stamp = {0, 0};
+
+ if ( pFile == 0 )
+ {
+ return stamp;
+ }
+
+ if (pFile->m_Handle != INVALID_HANDLE_VALUE)
+ {
+ /* mfe: new WriteBuf obsolete */
+ /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
+/* if (pFile->m_pWritePtr > pFile->m_Buf)*/
+/* {*/
+/* DWORD Bytes;*/
+
+/* WriteFile(pFile->m_Handle, pFile->m_WriteBuf,*/
+/* pFile->m_pWritePtr - pFile->m_WriteBuf,*/
+/* &Bytes, NULL);*/
+/* }*/
+
+ stamp = getFileStamp(pFile);
+
+ lockFile(pFile, un_lock);
+
+ CloseHandle(pFile->m_Handle);
+ pFile->m_Handle = INVALID_HANDLE_VALUE;
+ }
+
+ if ( pFile->m_pWriteBuf != 0 )
+ {
+ free(pFile->m_pWriteBuf);
+ }
+
+ free(pFile);
+
+ return(stamp);
+}
+
+
+
+
+
+
+
+
+static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate)
+{
+ if (pFile->m_Handle != INVALID_HANDLE_VALUE)
+ {
+ /* mfe: new WriteBuf obsolete */
+ /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
+/* if (pFile->m_pWritePtr > pFile->m_WriteBuf)*/
+/* {*/
+/* DWORD Bytes;*/
+
+/* WriteFile(pFile->m_Handle, pFile->m_WriteBuf,*/
+/* pFile->m_pWritePtr - pFile->m_WriteBuf,*/
+/* &Bytes, NULL);*/
+
+/* pFile->m_pWritePtr = pFile->m_WriteBuf;*/
+/* }*/
+
+ pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ SetFilePointer(pFile->m_Handle, 0, NULL, FILE_BEGIN);
+
+ if (bTruncate)
+ SetEndOfFile(pFile->m_Handle);
+ }
+
+ return (sal_True);
+}
+
+
+
+
+
+
+
+
+
+
+static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen)
+{
+ DWORD Max;
+ size_t Free, Bytes;
+ sal_Char* pChr;
+ sal_Char* pLine = (sal_Char *)pszLine;
+
+ if (pFile->m_Handle == INVALID_HANDLE_VALUE)
+ return (sal_False);
+
+ MaxLen -= 1;
+
+ do
+ {
+ Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
+
+ if (Bytes <= 1)
+ {
+ /* refill buffer */
+ memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
+ pFile->m_pReadPtr = pFile->m_ReadBuf;
+
+ Free = sizeof(pFile->m_ReadBuf) - Bytes;
+
+ if (! ReadFile(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free, &Max, NULL))
+ {
+ *pLine = '\0';
+ return (sal_False);
+ }
+
+ if (Max < Free)
+ {
+ if ((Max == 0) && (pLine == pszLine))
+ {
+ *pLine = '\0';
+ return (sal_False);
+ }
+
+ pFile->m_ReadBuf[Bytes + Max] = '\0';
+ }
+ }
+
+ for (pChr = pFile->m_pReadPtr;
+ (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
+ (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
+ pChr++);
+
+ Max = min(pChr - pFile->m_pReadPtr, MaxLen);
+ memcpy(pLine, pFile->m_pReadPtr, Max);
+ MaxLen -= Max;
+ pLine += Max;
+
+ if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
+ {
+ if (*pChr != '\0')
+ {
+ if ((pChr[0] == '\r') && (pChr[1] == '\n'))
+ pChr += 2;
+ else
+ pChr += 1;
+ }
+
+ if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
+ (*pChr == '\0'))
+ pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ *pLine = '\0';
+
+ /* setting MaxLen to -1 indicates terminating read loop */
+ MaxLen = -1;
+ }
+
+ pFile->m_pReadPtr = pChr;
+ }
+ while (MaxLen > 0);
+
+ return (sal_True);
+}
+
+
+
+
+
+
+
+
+
+
+static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine)
+{
+ unsigned int Len = strlen(pszLine);
+
+#ifdef DEBUG_OSL_PROFILE
+ int strLen=0;
+#endif
+
+ if ( pFile == 0 || pFile->m_Handle < 0 )
+ {
+ return (sal_False);
+ }
+
+ if ( pFile->m_pWriteBuf == 0 )
+ {
+ pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
+ pFile->m_nWriteBufLen = Len+3;
+ pFile->m_nWriteBufFree = Len+3;
+ }
+ else
+ {
+ if ( pFile->m_nWriteBufFree <= Len + 3 )
+ {
+ sal_Char* pTmp;
+
+ pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
+ if ( pTmp == 0 )
+ {
+ return sal_False;
+ }
+ pFile->m_pWriteBuf = pTmp;
+ pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
+ pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
+ memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
+ }
+ }
+
+
+
+ memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
+#ifdef DEBUG_OSL_PROFILE
+ strLen = strlen(pFile->m_pWriteBuf);
+#endif
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\r';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\n';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 2]='\0';
+
+ pFile->m_nWriteBufFree-=Len+2;
+
+#ifdef DEBUG_OSL_PROFILE
+/* OSL_TRACE("File Buffer in _putLine '%s' '%i'(%i)\n",pFile->m_pWriteBuf,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/
+#endif
+
+ return (sal_True);
+}
+
+/* platform specific end */
+
+
+static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen)
+{
+ if ( (pLen != NULL) && ( *pLen != 0 ) )
+ {
+ while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
+ (*pLen)--;
+
+ while ((*String == ' ') || (*String == '\t'))
+ {
+ String++;
+ (*pLen)--;
+ }
+ }
+ else
+ while ((*String == ' ') || (*String == '\t'))
+ String++;
+
+ return (String);
+}
+
+static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ unsigned int index=0;
+ unsigned int oldmax=pProfile->m_MaxLines;
+
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines, pProfile->m_MaxLines * sizeof(sal_Char *));
+
+ for ( index = oldmax ; index < pProfile->m_MaxLines ; ++index )
+ {
+ pProfile->m_Lines[index]=0;
+ }
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+
+ }
+
+ if ( pProfile->m_Lines != 0 && pProfile->m_Lines[pProfile->m_NoLines] != 0 )
+ {
+ free(pProfile->m_Lines[pProfile->m_NoLines]);
+ }
+ pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
+
+ return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
+}
+
+static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
+ pProfile->m_MaxLines * sizeof(sal_Char *));
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines],
+ 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(sal_Char*));
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+ }
+
+ LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
+
+ if (LineNo < pProfile->m_NoLines)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
+ (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
+
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line >= LineNo)
+ pSec->m_Line++;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line >= LineNo)
+ pSec->m_Entries[n].m_Line++;
+ }
+ }
+
+ pProfile->m_NoLines++;
+
+ pProfile->m_Lines[LineNo] = strdup(Line);
+
+ return (pProfile->m_Lines[LineNo]);
+}
+
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
+{
+ if (LineNo < pProfile->m_NoLines)
+ {
+ free(pProfile->m_Lines[LineNo]);
+ pProfile->m_Lines[LineNo]=0;
+ if (pProfile->m_NoLines - LineNo > 1)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
+ (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
+ 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(sal_Char*));
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line > LineNo)
+ pSec->m_Line--;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line > LineNo)
+ pSec->m_Entries[n].m_Line--;
+ }
+ }
+ else
+ {
+ pProfile->m_Lines[LineNo] = 0;
+ }
+
+ pProfile->m_NoLines--;
+ }
+
+ return;
+}
+
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const sal_Char* Entry, sal_uInt32 Len)
+{
+ Entry = stripBlanks(Entry, &Len);
+ pSection->m_Entries[NoEntry].m_Line = Line;
+ pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
+ pSection->m_Entries[NoEntry].m_Len = Len;
+
+ return;
+}
+
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const sal_Char* Entry, sal_uInt32 Len)
+{
+ if (pSection != NULL)
+ {
+ if (pSection->m_NoEntries >= pSection->m_MaxEntries)
+ {
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_MaxEntries = ENTRIES_INI;
+ pSection->m_Entries = (osl_TProfileEntry *)malloc(
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+ else
+ {
+ pSection->m_MaxEntries += ENTRIES_ADD;
+ pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_NoEntries = 0;
+ pSection->m_MaxEntries = 0;
+ return (sal_False);
+ }
+ }
+
+ pSection->m_NoEntries++;
+
+ Entry = stripBlanks(Entry, &Len);
+ setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
+ Entry, Len);
+
+ return (sal_True);
+ }
+
+ return (sal_False);
+}
+
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
+{
+ if (NoEntry < pSection->m_NoEntries)
+ {
+ if (pSection->m_NoEntries - NoEntry > 1)
+ {
+ memmove(&pSection->m_Entries[NoEntry],
+ &pSection->m_Entries[NoEntry + 1],
+ (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
+ }
+
+ pSection->m_NoEntries--;
+ }
+
+ return;
+}
+
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
+{
+ if (pProfile->m_NoSections >= pProfile->m_MaxSections)
+ {
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_MaxSections = SECTIONS_INI;
+ pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ memset(pProfile->m_Sections,0,pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ }
+ else
+ {
+ unsigned int index=0;
+ unsigned int oldmax=pProfile->m_MaxSections;
+
+ pProfile->m_MaxSections += SECTIONS_ADD;
+ pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
+ pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ for ( index = oldmax ; index < pProfile->m_MaxSections ; ++index )
+ {
+ pProfile->m_Sections[index].m_Entries=0;
+ }
+ }
+
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_NoSections = 0;
+ pProfile->m_MaxSections = 0;
+ return (sal_False);
+ }
+ }
+
+ pProfile->m_NoSections++;
+
+ if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != 0 )
+ {
+ free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
+ }
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
+
+ Section = (sal_Char *)stripBlanks(Section, &Len);
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
+
+ return (sal_True);
+}
+
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
+{
+ sal_uInt32 Section;
+
+ if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
+ {
+ free (pSection->m_Entries);
+ pSection->m_Entries=0;
+ if (pProfile->m_NoSections - Section > 1)
+ {
+ memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
+ (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
+
+ memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
+ 0,
+ (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = 0;
+ }
+ else
+ {
+ pSection->m_Entries = 0;
+ }
+
+ pProfile->m_NoSections--;
+ }
+
+ return;
+}
+
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry)
+{
+static sal_uInt32 Sect = 0;
+ sal_uInt32 i, n;
+ sal_uInt32 Len;
+ const sal_Char* pStr;
+ osl_TProfileSection* pSec = NULL;
+
+ Len = strlen(Section);
+ Section = (sal_Char *)stripBlanks(Section, &Len);
+
+ n = Sect;
+
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ n %= pProfile->m_NoSections;
+ pSec = &pProfile->m_Sections[n];
+ if ((Len == pSec->m_Len) &&
+ (strnicmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
+ == 0))
+ break;
+ n++;
+ }
+
+ Sect = n;
+
+ if (i < pProfile->m_NoSections)
+ {
+ Len = strlen(Entry);
+ Entry = stripBlanks(Entry, &Len);
+
+ *pNoEntry = pSec->m_NoEntries;
+
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset];
+ if ((Len == pSec->m_Entries[i].m_Len) &&
+ (strnicmp(Entry, pStr, pSec->m_Entries[i].m_Len)
+ == 0))
+ {
+ *pNoEntry = i;
+ break;
+ }
+ }
+ }
+ else
+ pSec = NULL;
+
+ return (pSec);
+}
+
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
+{
+ sal_uInt32 i;
+ sal_Char* pStr;
+ sal_Char* pChar;
+ sal_Char Line[4096];
+
+ pProfile->m_NoLines = 0;
+ pProfile->m_NoSections = 0;
+
+ OSL_VERIFY(rewindFile(pFile, sal_False));
+
+ while (getLine(pFile, Line, sizeof(Line)))
+ {
+ if (! addLine(pProfile, Line))
+ return (sal_False);
+ }
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
+
+ if ((*pStr == '\0') || (*pStr == ';'))
+ continue;
+
+ if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
+ ((pChar - pStr) <= 2))
+ {
+ /* insert entry */
+
+ if (pProfile->m_NoSections < 1)
+ continue;
+
+ if ((pChar = strchr(pStr, '=')) == NULL)
+ pChar = pStr + strlen(pStr);
+
+ if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
+ i, pStr, pChar - pStr))
+ return (sal_False);
+ }
+ else
+ {
+ /* new section */
+
+ if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
+ return (sal_False);
+ }
+ }
+
+ return (sal_True);
+}
+
+
+
+
+
+static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup)
+{
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In storeProfile\n");
+#endif
+
+ if (pProfile->m_Lines != NULL)
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ {
+ sal_uInt32 i;
+
+ osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
+
+ if ( pTmpFile == 0 )
+ {
+ return sal_False;
+ }
+
+ OSL_VERIFY(rewindFile(pTmpFile, sal_True));
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ OSL_VERIFY(putLine(pTmpFile, pProfile->m_Lines[i]));
+ }
+
+ if ( ! writeProfileImpl(pTmpFile) )
+ {
+ if ( pTmpFile->m_pWriteBuf != 0 )
+ {
+ free(pTmpFile->m_pWriteBuf);
+ }
+
+ pTmpFile->m_pWriteBuf=0;
+ pTmpFile->m_nWriteBufLen=0;
+ pTmpFile->m_nWriteBufFree=0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out storeProfile [not flushed]\n");
+#endif
+ closeFileImpl(pTmpFile);
+
+ return sal_False;
+ }
+
+ pProfile->m_Flags &= ~FLG_MODIFIED;
+
+ closeFileImpl(pProfile->m_pFile);
+ closeFileImpl(pTmpFile);
+
+ osl_ProfileSwapProfileNames(pProfile);
+
+/* free(pProfile->m_pFile);*/
+/* free(pTmpFile);*/
+
+ pProfile->m_pFile = openFileImpl(pProfile->m_strFileName,pProfile->m_Flags);
+
+ }
+
+ if (bCleanup)
+ {
+ while (pProfile->m_NoLines > 0)
+ removeLine(pProfile, pProfile->m_NoLines - 1);
+
+ free(pProfile->m_Lines);
+ pProfile->m_Lines = NULL;
+ pProfile->m_MaxLines = 0;
+
+ while (pProfile->m_NoSections > 0)
+ removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
+
+ free(pProfile->m_Sections);
+ pProfile->m_Sections = NULL;
+ pProfile->m_MaxSections = 0;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out storeProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
+{
+ osl_TFile* pFile=0;
+ rtl_uString* ustrExtension=0;
+ rtl_uString* ustrTmpName=0;
+ oslProfileOption PFlags=0;
+
+ rtl_uString_newFromAscii(&ustrExtension,"tmp");
+
+
+ /* generate tmp profilename */
+ ustrTmpName=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+
+ if ( ustrTmpName == 0 )
+ {
+ return 0;
+ }
+
+
+ if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
+ {
+ PFlags |= osl_Profile_WRITELOCK;
+ }
+
+ /* open this file */
+ pFile = openFileImpl(ustrTmpName,pProfile->m_Flags | PFlags);
+
+
+ /* return new pFile */
+ return pFile;
+}
+
+
+static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
+{
+ sal_Bool bRet = sal_False;
+
+ rtl_uString* ustrBakFile=0;
+ rtl_uString* ustrTmpFile=0;
+ rtl_uString* ustrIniFile=0;
+ rtl_uString* ustrExtension=0;
+
+
+ rtl_uString_newFromAscii(&ustrExtension,"bak");
+
+ ustrBakFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=0;
+
+
+ rtl_uString_newFromAscii(&ustrExtension,"ini");
+
+ ustrIniFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=0;
+
+
+ rtl_uString_newFromAscii(&ustrExtension,"tmp");
+
+ ustrTmpFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=0;
+
+
+ /* unlink bak */
+ DeleteFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrBakFile )) );
+
+ /* rename ini bak */
+ MoveFileExW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrIniFile )), reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrBakFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
+
+ /* rename tmp ini */
+ MoveFileExW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrTmpFile )), reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrIniFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
+
+ return bRet;
+}
+
+
+static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension)
+{
+ rtl_uString* ustrNewFileName=0;
+ rtl_uString* ustrOldExtension = 0;
+ sal_Unicode* pExtensionBuf = 0;
+ sal_Unicode* pFileNameBuf = 0;
+ sal_Int32 nIndex = -1;
+
+ pFileNameBuf = rtl_uString_getStr(ustrFileName);
+
+ rtl_uString_newFromAscii(&ustrOldExtension,".");
+
+ pExtensionBuf = rtl_uString_getStr(ustrOldExtension);
+
+ nIndex = rtl_ustr_lastIndexOfChar(pFileNameBuf,*pExtensionBuf);
+
+ rtl_uString_newReplaceStrAt(&ustrNewFileName,
+ ustrFileName,
+ nIndex+1,
+ 3,
+ ustrExtension);
+
+ return ustrNewFileName;
+}
+
+
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+ oslProfileOption PFlags=0;
+
+
+ if ( bWriteable )
+ {
+/* PFlags = osl_Profile_DEFAULT | osl_Profile_READWRITE; */
+ PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
+ }
+ else
+ {
+ PFlags = osl_Profile_DEFAULT;
+ }
+
+
+ if (pProfile == NULL)
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("AUTOOPEN MODE\n");
+#endif
+
+
+
+ if ( ( pProfile = (osl_TProfileImpl*)osl_openProfile( NULL, PFlags ) ) != NULL )
+ {
+ pProfile->m_Flags |= FLG_AUTOOPEN;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("try to acquire\n");
+#endif
+
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ osl_TStamp Stamp;
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("DEFAULT MODE\n");
+#endif
+ pProfile->m_pFile = openFileImpl(
+ pProfile->m_strFileName, pProfile->m_Flags | PFlags);
+ if (!pProfile->m_pFile)
+ return NULL;
+
+ Stamp = getFileStamp(pProfile->m_pFile);
+
+ if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
+ {
+ pProfile->m_Stamp = Stamp;
+
+ loadProfile(pProfile->m_pFile, pProfile);
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("READ/WRITELOCK MODE\n");
+#endif
+
+
+ /* A readlock file could not be written */
+ if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
+ {
+ return (NULL);
+ }
+ }
+ }
+ }
+
+ return (pProfile);
+}
+
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile)
+{
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In releaseProfile\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (pProfile->m_Flags & FLG_AUTOOPEN)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [AUTOOPEN]\n");
+#endif
+ return (osl_closeProfile((oslProfile)pProfile));
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("DEFAULT MODE\n");
+#endif
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ storeProfile(pProfile, sal_False);
+
+ closeFileImpl(pProfile->m_pFile);
+ pProfile->m_pFile = NULL;
+ }
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+static sal_Bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile)
+{
+ sal_Char *pChr, *pStr;
+ sal_Char Buffer[4096] = "";
+ sal_Char Product[132] = "";
+
+ ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
+ aPath[0] = 0;
+ DWORD dwPathLen = 0;
+
+ if (*strPath == L'"')
+ {
+ int i = 0;
+
+ strPath++;
+
+ while ((strPath[i] != L'"') && (strPath[i] != L'\0'))
+ i++;
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(strPath), i, Product, sizeof(Product), NULL, NULL);
+ Product[i] = '\0';
+ strPath += i;
+
+ if (*strPath == L'"')
+ strPath++;
+
+ if ( (*strPath == L'/') || (*strPath == L'\\') )
+ {
+ strPath++;
+ }
+ }
+
+ else
+ {
+ /* if we have not product identfication, do a special handling for soffice.ini */
+ if (rtl_ustr_ascii_compare(strFile, SVERSION_PROFILE) == 0)
+ {
+ rtl_uString * strSVProfile = NULL;
+ rtl_uString * strSVFallback = NULL;
+ rtl_uString * strSVLocation = NULL;
+ rtl_uString * strSVName = NULL;
+ ::osl::LongPathBuffer< sal_Char > aDir( MAX_LONG_PATH );
+ oslProfile hProfile;
+
+ rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
+ rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
+ rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if (osl_getProfileName( strSVFallback, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_getProfileSectionEntries(
+ hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(
+ pChr, SVERSION_SOFFICE,
+ sizeof(SVERSION_SOFFICE) - 1)
+ == 0)
+ && (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, pChr, aDir,
+ aDir.getBufSizeInSymbols(), "");
+
+ /* check for existence of path */
+ if (access(aDir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+ rtl_uString_release(strSVProfile);
+ strSVProfile = NULL;
+ }
+
+ /* open sversion.ini in the users directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if ((strcmp(SVERSION_LOCATION, SVERSION_FALLBACK) != 0) &&
+ (osl_getProfileName(strSVLocation, strSVName, &strSVProfile)))
+ {
+ hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_getProfileSectionEntries(
+ hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(
+ pChr, SVERSION_SOFFICE,
+ sizeof(SVERSION_SOFFICE) - 1)
+ == 0)
+ && (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, pChr, aDir,
+ aDir.getBufSizeInSymbols(), "");
+
+ /* check for existence of path */
+ if (access(aDir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+ rtl_uString_release(strSVProfile);
+ }
+
+ rtl_uString_release(strSVFallback);
+ rtl_uString_release(strSVLocation);
+ rtl_uString_release(strSVName);
+
+ /* remove any trailing build number */
+ if ((pChr = strrchr(Product, '/')) != NULL)
+ *pChr = '\0';
+ }
+ }
+
+ /* if we have an userid option eg. "-userid:rh[/usr/home/rh/staroffice]",
+ this will supercede all other locations */
+ {
+ sal_uInt32 n, nArgs = osl_getCommandArgCount();
+
+ for (n = 0; n < nArgs; n++)
+ {
+ rtl_uString * strCommandArg = NULL;
+
+ if ((osl_getCommandArg( n, &strCommandArg ) == osl_Process_E_None) &&
+ ((strCommandArg->buffer[0] == L'-') || (strCommandArg->buffer[0] == L'+')) &&
+ (rtl_ustr_ascii_compare_WithLength(strCommandArg->buffer, RTL_CONSTASCII_LENGTH(SVERSION_OPTION), SVERSION_OPTION)))
+ {
+ sal_Unicode *pCommandArg = strCommandArg->buffer + RTL_CONSTASCII_LENGTH(SVERSION_OPTION);
+ sal_Int32 nStart, nEnd;
+
+ if (((nStart = rtl_ustr_indexOfChar(pCommandArg, L'[')) != -1) &&
+ ((nEnd = rtl_ustr_indexOfChar(pCommandArg + nStart + 1, L']')) != -1))
+ {
+ dwPathLen = nEnd;
+ copy_ustr_n(aPath, pCommandArg + nStart + 1, dwPathLen);
+ aPath[dwPathLen] = 0;
+
+ /* build full path */
+ if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ copy_ustr_n(aPath + dwPathLen++, L"/", 2);
+ }
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+ int n;
+
+ if ((n = WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL)) > 0)
+ {
+ strcpy(aTmpPath + n, SVERSION_USER);
+ if (access(aTmpPath, 0) >= 0)
+ {
+ dwPathLen += MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, reinterpret_cast<LPWSTR>(aPath + dwPathLen), aPath.getBufSizeInSymbols() - dwPathLen );
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (dwPathLen == 0)
+ {
+ rtl_uString * strExecutable = NULL;
+ rtl_uString * strTmp = NULL;
+ sal_Int32 nPos;
+
+ /* try to find the file in the directory of the executbale */
+ if (osl_getExecutableFile(&strTmp) != osl_Process_E_None)
+ return (sal_False);
+
+ /* convert to native path */
+ if (osl_getSystemPathFromFileURL(strTmp, &strExecutable) != osl_File_E_None)
+ {
+ rtl_uString_release(strTmp);
+ return sal_False;
+ }
+
+ rtl_uString_release(strTmp);
+
+ /* seperate path from filename */
+ if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L'\\')) == -1)
+ {
+ if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L':')) == -1)
+ {
+ return sal_False;
+ }
+ else
+ {
+ copy_ustr_n(aPath, strExecutable->buffer, nPos);
+ aPath[nPos] = 0;
+ dwPathLen = nPos;
+ }
+ }
+ else
+ {
+ copy_ustr_n(aPath, strExecutable->buffer, nPos);
+ dwPathLen = nPos;
+ aPath[dwPathLen] = 0;
+ }
+
+ /* if we have no product identification use the executable file name */
+ if (*Product == 0)
+ {
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(strExecutable->buffer + nPos + 1), -1, Product, sizeof(Product), NULL, NULL);
+
+ /* remove extension */
+ if ((pChr = strrchr(Product, '.')) != NULL)
+ *pChr = '\0';
+ }
+
+ rtl_uString_release(strExecutable);
+
+ /* remember last subdir */
+ nPos = rtl_ustr_lastIndexOfChar(aPath, L'\\');
+
+ copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL);
+
+ /* if file not exists, remove any specified subdirectories
+ like "bin" or "program" */
+
+ if (((access(aTmpPath, 0) < 0) && (nPos != -1)) || (*strPath == 0))
+ {
+ static sal_Char *SubDirs[] = SVERSION_DIRS;
+
+ int i = 0;
+ pStr = aTmpPath + nPos;
+
+ for (i = 0; i < (sizeof(SubDirs) / sizeof(SubDirs[0])); i++)
+ if (strnicmp(pStr + 1, SubDirs[i], strlen(SubDirs[i])) == 0)
+ {
+ if ( *strPath == 0)
+ {
+ strcpy(pStr + 1,SVERSION_USER);
+ if ( access(aTmpPath, 0) < 0 )
+ {
+ *(pStr+1)='\0';
+ }
+ else
+ {
+ dwPathLen = nPos + MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, reinterpret_cast<LPWSTR>(aPath + nPos + 1), aPath.getBufSizeInSymbols() - (nPos + 1) );
+ }
+ }
+ else
+ {
+ copy_ustr_n(aPath + nPos + 1, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen = nPos + 1 + rtl_ustr_getLength(strPath);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ aPath[dwPathLen++] = L'\\';
+ aPath[dwPathLen] = 0;
+ }
+
+ copy_ustr_n(aPath + dwPathLen, strFile, rtl_ustr_getLength(strFile)+1);
+
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL);
+
+ if ((access(aTmpPath, 0) < 0) && (strlen(Product) > 0))
+ {
+ rtl_uString * strSVFallback = NULL;
+ rtl_uString * strSVProfile = NULL;
+ rtl_uString * strSVLocation = NULL;
+ rtl_uString * strSVName = NULL;
+ oslProfile hProfile;
+
+ rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
+ rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
+ rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if (osl_getProfileName(strSVLocation, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(
+ strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, Product, Buffer,
+ sizeof(Buffer), "");
+ osl_closeProfile(hProfile);
+
+ /* if not found, try the fallback */
+ if ((strlen(Buffer) <= 0)
+ && (strcmp(SVERSION_LOCATION, SVERSION_FALLBACK)
+ != 0))
+ {
+ if (osl_getProfileName(
+ strSVFallback, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(
+ strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, Product,
+ Buffer, sizeof(Buffer), "");
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+
+ if (strlen(Buffer) > 0)
+ {
+ dwPathLen = MultiByteToWideChar(
+ CP_ACP, 0, Buffer, -1, ::osl::mingw_reinterpret_cast<LPWSTR>(aPath), aPath.getBufSizeInSymbols() );
+ dwPathLen -=1;
+
+ /* build full path */
+ if ((aPath[dwPathLen - 1] != L'/')
+ && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
+ }
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+ int n;
+
+ if ((n = WideCharToMultiByte(
+ CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath,
+ aTmpPath.getBufSizeInSymbols(), NULL, NULL))
+ > 0)
+ {
+ strcpy(aTmpPath + n, SVERSION_USER);
+ if (access(aTmpPath, 0) >= 0)
+ {
+ dwPathLen += MultiByteToWideChar(
+ CP_ACP, 0, SVERSION_USER, -1,
+ reinterpret_cast<LPWSTR>(aPath + dwPathLen),
+ aPath.getBufSizeInSymbols() - dwPathLen );
+ }
+ }
+ }
+ }
+ }
+
+ rtl_uString_release(strSVProfile);
+ }
+
+ rtl_uString_release(strSVFallback);
+ rtl_uString_release(strSVLocation);
+ rtl_uString_release(strSVName);
+ }
+ }
+
+ aPath[dwPathLen] = 0;
+ }
+
+ /* copy filename */
+ copy_ustr_n(strProfile, aPath, dwPathLen+1);
+
+ return sal_True;
+}
+
+
diff --git a/sal/osl/w32/salinit.cxx b/sal/osl/w32/salinit.cxx
new file mode 100644
index 000000000000..aea584f67970
--- /dev/null
+++ b/sal/osl/w32/salinit.cxx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "system.h"
+#include <osl/process.h>
+#include <sal/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Prototypes for initialization and deinitialization of SAL library
+
+void SAL_CALL sal_detail_initialize(int argc, char ** argv)
+{
+ WSADATA wsaData;
+ int error;
+ WORD wVersionRequested;
+
+ wVersionRequested = MAKEWORD(1, 1);
+
+ error = WSAStartup(wVersionRequested, &wsaData);
+ if ( 0 == error )
+ {
+ WORD wMajorVersionRequired = 1;
+ WORD wMinorVersionRequired = 1;
+
+ if ((LOBYTE(wsaData.wVersion) < wMajorVersionRequired) ||
+ (LOBYTE(wsaData.wVersion) == wMajorVersionRequired) &&
+ ((HIBYTE(wsaData.wVersion) < wMinorVersionRequired)))
+ {
+ // How to handle a very unlikely error ???
+ }
+ }
+ else
+ {
+ // How to handle a very unlikely error ???
+ }
+
+ osl_setCommandArgs(argc, argv);
+}
+
+void SAL_CALL sal_detail_deinitialize()
+{
+ if ( SOCKET_ERROR == WSACleanup() )
+ {
+ // We should never reach this point or we did wrong elsewhere
+ }
+}
+
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sal/osl/w32/secimpl.h b/sal/osl/w32/secimpl.h
new file mode 100644
index 000000000000..97a9d9c44f9e
--- /dev/null
+++ b/sal/osl/w32/secimpl.h
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SECURITYIMPL_H_
+#define _OSL_SECURITYIMPL_H_
+
+#include <winnetwk.h>
+
+#include <osl/security.h>
+
+#define USER_BUFFER_SIZE 256
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslSecurityImpl {
+ HANDLE m_hProfile;
+ HANDLE m_hToken;
+ sal_Unicode m_User[USER_BUFFER_SIZE];
+/* ts: Erweiterung um Fileserver-login */
+ NETRESOURCEW *m_pNetResource;
+} oslSecurityImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/w32/security.c b/sal/osl/w32/security.c
new file mode 100644
index 000000000000..237ea67dc949
--- /dev/null
+++ b/sal/osl/w32/security.c
@@ -0,0 +1,991 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include <osl/security.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <systools/win32/uwinapi.h>
+#include "secimpl.h"
+
+/*****************************************************************************/
+/* Data Type Definition */
+/*****************************************************************************/
+
+
+/* Data for use in (un)LoadProfile Functions */
+/* Declarations based on USERENV.H for Windows 2000 Beta 2 */
+#define PI_NOUI 0x00000001 // Prevents displaying of messages
+#define PI_APPLYPOLICY 0x00000002 // Apply NT4 style policy
+
+typedef struct _PROFILEINFOW {
+ DWORD dwSize; // Must be set to sizeof(PROFILEINFO)
+ DWORD dwFlags; // See flags above
+ LPWSTR lpUserName; // User name (required)
+ LPWSTR lpProfilePath; // Roaming profile path
+ LPWSTR lpDefaultPath; // Default user profile path
+ LPWSTR lpServerName; // Validating DC name in netbios format
+ LPWSTR lpPolicyPath; // Path to the NT4 style policy file
+ HANDLE hProfile; // Registry key handle - filled by function
+} PROFILEINFOW, FAR * LPPROFILEINFOW;
+
+/* Typedefs for function pointers in USERENV.DLL */
+typedef BOOL (STDMETHODCALLTYPE FAR * LPFNLOADUSERPROFILE) (
+ HANDLE hToken,
+ LPPROFILEINFOW lpProfileInfo
+);
+
+typedef BOOL (STDMETHODCALLTYPE FAR * LPFNUNLOADUSERPROFILE) (
+ HANDLE hToken,
+ HANDLE hProfile
+);
+
+typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) (
+ HANDLE hToken,
+ LPTSTR lpProfileDir,
+ LPDWORD lpcchSize
+);
+
+/* To get an impersonation token we need to create an impersonation
+ duplicate so every access token has to be created with duplicate
+ access rights */
+
+#define TOKEN_DUP_QUERY (TOKEN_QUERY|TOKEN_DUPLICATE)
+
+/*****************************************************************************/
+/* Static Module Function Declarations */
+/*****************************************************************************/
+
+static sal_Bool isWNT(void);
+static sal_Bool GetSpecialFolder(rtl_uString **strPath,int nFolder);
+static BOOL Privilege(LPTSTR pszPrivilege, BOOL bEnable);
+static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName, sal_Bool bIncludeDomain);
+
+/*****************************************************************************/
+/* Exported Module Functions */
+/*****************************************************************************/
+
+oslSecurity SAL_CALL osl_getCurrentSecurity(void)
+{
+ oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
+
+ pSecImpl->m_pNetResource = NULL;
+ pSecImpl->m_User[0] = '\0';
+ pSecImpl->m_hToken = NULL;
+ pSecImpl->m_hProfile = NULL;
+
+ return ((oslSecurity)pSecImpl);
+}
+
+oslSecurityError SAL_CALL osl_loginUser( rtl_uString *strUserName, rtl_uString *strPasswd, oslSecurity *pSecurity )
+{
+ oslSecurityError ret;
+
+ if (!isWNT())
+ {
+ *pSecurity = osl_getCurrentSecurity();
+ ret = osl_Security_E_None;
+ }
+ else
+ {
+ sal_Unicode* strUser;
+ sal_Unicode* strDomain = _wcsdup(rtl_uString_getStr(strUserName));
+ HANDLE hUserToken;
+
+ #if OSL_DEBUG_LEVEL > 0
+ LUID luid;
+ #endif
+
+ if (NULL != (strUser = wcschr(strDomain, L'/')))
+ *strUser++ = L'\0';
+ else
+ {
+ strUser = strDomain;
+ strDomain = NULL;
+ }
+
+ // this process must have the right: 'act as a part of operatingsystem'
+ OSL_ASSERT(LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid));
+
+ if (LogonUserW(strUser, strDomain ? strDomain : L"", rtl_uString_getStr(strPasswd),
+ LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
+ &hUserToken))
+ {
+ oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
+
+ pSecImpl->m_pNetResource = NULL;
+ pSecImpl->m_hToken = hUserToken;
+ pSecImpl->m_hProfile = NULL;
+ wcscpy(pSecImpl->m_User, strUser);
+
+ *pSecurity = (oslSecurity)pSecImpl;
+ ret = osl_Security_E_None;
+ }
+ else
+ ret = osl_Security_E_UserUnknown;
+
+ if (strDomain)
+ free(strDomain);
+ else
+ free(strUser);
+ }
+
+ return ret;
+}
+
+oslSecurityError SAL_CALL osl_loginUserOnFileServer(rtl_uString *strUserName,
+ rtl_uString *strPasswd,
+ rtl_uString *strFileServer,
+ oslSecurity *pSecurity)
+{
+ oslSecurityError ret;
+ DWORD err;
+ NETRESOURCEW netResource;
+ sal_Unicode* remoteName;
+ sal_Unicode* userName;
+
+ remoteName = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 4);
+ userName = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 2);
+
+ wcscpy(remoteName, L"\\\\");
+ wcscat(remoteName, rtl_uString_getStr(strFileServer));
+ wcscat(remoteName, L"\\");
+ wcscat(remoteName, rtl_uString_getStr(strUserName));
+
+ wcscpy(userName, rtl_uString_getStr(strFileServer));
+ wcscat(userName, L"\\");
+ wcscat(userName, rtl_uString_getStr(strUserName));
+
+ netResource.dwScope = RESOURCE_GLOBALNET;
+ netResource.dwType = RESOURCETYPE_DISK;
+ netResource.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+ netResource.dwUsage = RESOURCEUSAGE_CONNECTABLE;
+ netResource.lpLocalName = NULL;
+ netResource.lpRemoteName = remoteName;
+ netResource.lpComment = NULL;
+ netResource.lpProvider = NULL;
+
+ err = WNetAddConnection2W(&netResource, rtl_uString_getStr(strPasswd), userName, 0);
+
+ if ((err == NO_ERROR) || (err == ERROR_ALREADY_ASSIGNED))
+ {
+ oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
+
+ pSecImpl->m_pNetResource = malloc(sizeof(NETRESOURCE));
+ *pSecImpl->m_pNetResource = netResource;
+
+ pSecImpl->m_hToken = NULL;
+ pSecImpl->m_hProfile = NULL;
+ wcscpy(pSecImpl->m_User, rtl_uString_getStr(strUserName));
+
+ *pSecurity = (oslSecurity)pSecImpl;
+
+ ret = osl_Security_E_None;
+ }
+ else
+ ret = osl_Security_E_UserUnknown;
+
+ free(remoteName);
+ free(userName);
+
+ return ret;
+}
+
+
+static BOOL WINAPI CheckTokenMembership_Stub( HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember )
+{
+ typedef BOOL (WINAPI *CheckTokenMembership_PROC)( HANDLE, PSID, PBOOL );
+
+ static HMODULE hModule = NULL;
+ static CheckTokenMembership_PROC pCheckTokenMembership = NULL;
+
+ if ( !hModule )
+ {
+ /* SAL is always linked against ADVAPI32 so we can rely on that it is already mapped */
+
+ hModule = GetModuleHandleA( "ADVAPI32.DLL" );
+
+ pCheckTokenMembership = (CheckTokenMembership_PROC)GetProcAddress( hModule, "CheckTokenMembership" );
+ }
+
+ if ( pCheckTokenMembership )
+ return pCheckTokenMembership( TokenHandle, SidToCheck, IsMember );
+ else
+ {
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+ return FALSE;
+ }
+
+}
+
+
+sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
+{
+ if (Security != NULL)
+ {
+ /* ts: on Window 95 systems any user seems to be an adminstrator */
+ if (!isWNT())
+ {
+ return(sal_True);
+ }
+ else
+ {
+ HANDLE hImpersonationToken = NULL;
+ PSID psidAdministrators;
+ SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
+ sal_Bool bSuccess = sal_False;
+
+
+ /* If Security contains an access token we need to duplicate it to an impersonation
+ access token. NULL works with CheckTokenMembership() as the current effective
+ impersonation token
+ */
+
+ if ( ((oslSecurityImpl*)Security)->m_hToken )
+ {
+ if ( !DuplicateToken (((oslSecurityImpl*)Security)->m_hToken, SecurityImpersonation, &hImpersonationToken) )
+ return sal_False;
+ }
+
+ /* CheckTokenMembership() can be used on W2K and higher (NT4 no longer supported by OOo)
+ and also works on Vista to retrieve the effective user rights. Just checking for
+ membership of Administrators group is not enough on Vista this would require additional
+ complicated checks as described in KB arcticle Q118626: http://support.microsoft.com/kb/118626/en-us
+ */
+
+ if (AllocateAndInitializeSid(&siaNtAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &psidAdministrators))
+ {
+ BOOL fSuccess = FALSE;
+
+ if ( CheckTokenMembership_Stub( hImpersonationToken, psidAdministrators, &fSuccess ) && fSuccess )
+ bSuccess = sal_True;
+
+ FreeSid(psidAdministrators);
+ }
+
+ if ( hImpersonationToken )
+ CloseHandle( hImpersonationToken );
+
+ return (bSuccess);
+ }
+ }
+ else
+ return (sal_False);
+}
+
+
+void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
+{
+ if (Security)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ if (pSecImpl->m_pNetResource != NULL)
+ {
+ WNetCancelConnection2W(pSecImpl->m_pNetResource->lpRemoteName, 0, sal_True);
+
+ free(pSecImpl->m_pNetResource->lpRemoteName);
+ free(pSecImpl->m_pNetResource);
+ }
+
+ if (pSecImpl->m_hToken)
+ CloseHandle(pSecImpl->m_hToken);
+
+ if ( pSecImpl->m_hProfile )
+ CloseHandle(pSecImpl->m_hProfile);
+
+ free (pSecImpl);
+ }
+}
+
+
+sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **strIdent)
+{
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ HANDLE hAccessToken = pSecImpl->m_hToken;
+
+ if (hAccessToken == NULL)
+ OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
+
+ if (hAccessToken)
+ {
+ sal_Char *Ident;
+ DWORD nInfoBuffer = 512;
+ UCHAR* pInfoBuffer = malloc(nInfoBuffer);
+
+
+ while (!GetTokenInformation(hAccessToken, TokenUser,
+ pInfoBuffer, nInfoBuffer, &nInfoBuffer))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
+ else
+ {
+ free(pInfoBuffer);
+ pInfoBuffer = NULL;
+ break;
+ }
+ }
+
+ if (pSecImpl->m_hToken == NULL)
+ CloseHandle(hAccessToken);
+
+ if (pInfoBuffer)
+ {
+ PSID pSid = ((PTOKEN_USER)pInfoBuffer)->User.Sid;
+ PSID_IDENTIFIER_AUTHORITY psia;
+ DWORD dwSubAuthorities;
+ DWORD dwSidRev=SID_REVISION;
+ DWORD dwCounter;
+ DWORD dwSidSize;
+
+ /* obtain SidIdentifierAuthority */
+ psia=GetSidIdentifierAuthority(pSid);
+
+ /* obtain sidsubauthority count */
+ dwSubAuthorities=min(*GetSidSubAuthorityCount(pSid), 5);
+
+ /* buffer length: S-SID_REVISION- + identifierauthority- + subauthorities- + NULL */
+ Ident=malloc(88*sizeof(sal_Char));
+
+ /* prepare S-SID_REVISION- */
+ dwSidSize=wsprintf(Ident, TEXT("S-%lu-"), dwSidRev);
+
+ /* prepare SidIdentifierAuthority */
+ if ((psia->Value[0] != 0) || (psia->Value[1] != 0))
+ {
+ dwSidSize+=wsprintf(Ident + strlen(Ident),
+ TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
+ (USHORT)psia->Value[0],
+ (USHORT)psia->Value[1],
+ (USHORT)psia->Value[2],
+ (USHORT)psia->Value[3],
+ (USHORT)psia->Value[4],
+ (USHORT)psia->Value[5]);
+ }
+ else
+ {
+ dwSidSize+=wsprintf(Ident + strlen(Ident),
+ TEXT("%lu"),
+ (ULONG)(psia->Value[5] ) +
+ (ULONG)(psia->Value[4] << 8) +
+ (ULONG)(psia->Value[3] << 16) +
+ (ULONG)(psia->Value[2] << 24) );
+ }
+
+ /* loop through SidSubAuthorities */
+ for (dwCounter=0; dwCounter < dwSubAuthorities; dwCounter++)
+ {
+ dwSidSize+=wsprintf(Ident + dwSidSize, TEXT("-%lu"),
+ *GetSidSubAuthority(pSid, dwCounter) );
+ }
+
+ rtl_uString_newFromAscii( strIdent, Ident );
+
+ free(pInfoBuffer);
+ free(Ident);
+
+ return (sal_True);
+ }
+ }
+ else
+ {
+ DWORD needed=0;
+ sal_Unicode *Ident;
+
+ WNetGetUserA(NULL, NULL, &needed);
+ needed = max( 16 , needed );
+ Ident=malloc(needed*sizeof(sal_Unicode));
+
+ if (WNetGetUserW(NULL, Ident, &needed) != NO_ERROR)
+ {
+ wcscpy(Ident, L"unknown");
+ Ident[7] = L'\0';
+ }
+
+ rtl_uString_newFromStr( strIdent, Ident);
+
+ free(Ident);
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+
+sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **strName)
+{
+ return getUserNameImpl(Security, strName, sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ rtl_uString *ustrSysDir = NULL;
+ sal_Bool bSuccess = sal_False;
+
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ if (pSecImpl->m_pNetResource != NULL)
+ {
+ rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName);
+
+ bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory ));
+ }
+ else
+ {
+#if 0
+ if (pSecImpl->m_hToken)
+ {
+ DWORD nInfoBuffer = 512;
+ UCHAR* pInfoBuffer = malloc(nInfoBuffer);
+
+ while (!GetTokenInformation(pSecImpl->m_hToken, TokenUser,
+ pInfoBuffer, nInfoBuffer, &nInfoBuffer))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
+ else
+ {
+ free(pInfoBuffer);
+ pInfoBuffer = NULL;
+ break;
+ }
+ }
+
+ /* not implemented */
+ OSL_ASSERT(sal_False);
+
+ if (pInfoBuffer)
+ {
+ /* if (EqualSid() ... */
+
+ }
+ }
+ else
+#endif
+
+ bSuccess = (sal_Bool)(GetSpecialFolder(&ustrSysDir, CSIDL_PERSONAL) &&
+ (osl_File_E_None == osl_getFileURLFromSystemPath(ustrSysDir, pustrDirectory)));
+ }
+ }
+
+ if ( ustrSysDir )
+ rtl_uString_release( ustrSysDir );
+
+ return bSuccess;
+}
+
+sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ sal_Bool bSuccess = sal_False;
+
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ if (pSecImpl->m_pNetResource != NULL)
+ {
+ rtl_uString *ustrSysDir = NULL;
+
+ rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName);
+ bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory));
+
+ if ( ustrSysDir )
+ rtl_uString_release( ustrSysDir );
+ }
+ else
+ {
+ if (pSecImpl->m_hToken)
+ {
+ /* not implemented */
+ OSL_ASSERT(sal_False);
+ }
+ else
+ {
+ rtl_uString *ustrFile = NULL;
+ sal_Unicode sFile[_MAX_PATH];
+
+ if ( !GetSpecialFolder( &ustrFile, CSIDL_APPDATA) )
+ {
+ OSL_VERIFY(GetWindowsDirectoryW(sFile, _MAX_DIR) > 0);
+
+ rtl_uString_newFromStr( &ustrFile, sFile);
+ }
+
+ bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath(ustrFile, pustrDirectory));
+
+ if ( ustrFile )
+ rtl_uString_release( ustrFile );
+ }
+ }
+ }
+
+ return bSuccess;
+}
+
+
+sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
+{
+ /* CreateProcessAsUser does not load the specified user's profile
+ into the HKEY_USERS registry key. This means that access to information
+ in the HKEY_CURRENT_USER registry key may not produce results consistent
+ with a normal interactive logon.
+ It is your responsibility to load the user's registry hive into HKEY_USERS
+ with the LoadUserProfile function before calling CreateProcessAsUser.
+ */
+ BOOL bOk = FALSE;
+
+ RegCloseKey(HKEY_CURRENT_USER);
+
+ if (Privilege(SE_RESTORE_NAME, TRUE))
+ {
+ HMODULE hUserEnvLib = NULL;
+ LPFNLOADUSERPROFILE fLoadUserProfile = NULL;
+ LPFNUNLOADUSERPROFILE fUnloadUserProfile = NULL;
+ HANDLE hAccessToken = ((oslSecurityImpl*)Security)->m_hToken;
+ DWORD nError = 0;
+
+ /* try to create user profile */
+ if ( !hAccessToken )
+ {
+ /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
+ */
+ HANDLE hProcess = GetCurrentProcess();
+
+ if (hProcess != NULL)
+ {
+ OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
+ CloseHandle(hProcess);
+ }
+ }
+
+ hUserEnvLib = LoadLibraryA("userenv.dll");
+
+ if (hUserEnvLib)
+ {
+ fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileW");
+ fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile");
+
+ if (fLoadUserProfile && fUnloadUserProfile)
+ {
+ rtl_uString *buffer = 0;
+ PROFILEINFOW pi;
+
+ getUserNameImpl(Security, &buffer, sal_False);
+
+ ZeroMemory( &pi, sizeof(pi) );
+ pi.dwSize = sizeof(pi);
+ pi.lpUserName = rtl_uString_getStr(buffer);
+ pi.dwFlags = PI_NOUI;
+
+ if (fLoadUserProfile(hAccessToken, &pi))
+ {
+ fUnloadUserProfile(hAccessToken, pi.hProfile);
+
+ bOk = TRUE;
+ }
+ else
+ nError = GetLastError();
+
+ rtl_uString_release(buffer);
+ }
+
+ FreeLibrary(hUserEnvLib);
+ }
+
+ if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken))
+ CloseHandle(hAccessToken);
+ }
+
+ return (sal_Bool)bOk;
+}
+
+
+void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
+{
+ if ( ((oslSecurityImpl*)Security)->m_hProfile != NULL )
+ {
+ HMODULE hUserEnvLib = NULL;
+ LPFNLOADUSERPROFILE fLoadUserProfile = NULL;
+ LPFNUNLOADUSERPROFILE fUnloadUserProfile = NULL;
+ BOOL bOk = FALSE;
+ HANDLE hAccessToken = ((oslSecurityImpl*)Security)->m_hToken;
+
+ if ( !hAccessToken )
+ {
+ /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
+ */
+ HANDLE hProcess = GetCurrentProcess();
+
+ if (hProcess != NULL)
+ {
+ OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
+ CloseHandle(hProcess);
+ }
+ }
+
+ hUserEnvLib = LoadLibrary("userenv.dll");
+
+ if (hUserEnvLib)
+ {
+ fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileA");
+ fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile");
+
+ if (fLoadUserProfile && fUnloadUserProfile)
+ {
+ /* unloading the user profile */
+ if (fLoadUserProfile && fUnloadUserProfile)
+ bOk = fUnloadUserProfile(hAccessToken, ((oslSecurityImpl*)Security)->m_hProfile);
+
+ if (hUserEnvLib)
+ FreeLibrary(hUserEnvLib);
+ }
+ }
+
+ ((oslSecurityImpl*)Security)->m_hProfile;
+
+ if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken))
+ {
+ CloseHandle(hAccessToken);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* Static Module Functions */
+/*****************************************************************************/
+
+
+static sal_Bool GetSpecialFolder(rtl_uString **strPath, int nFolder)
+{
+ sal_Bool bRet = sal_False;
+ HINSTANCE hLibrary;
+ sal_Char PathA[_MAX_PATH];
+ sal_Unicode PathW[_MAX_PATH];
+
+ if ((hLibrary = LoadLibrary("shell32.dll")) != NULL)
+ {
+ BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL);
+ BOOL (WINAPI *pSHGetSpecialFolderPathW)(HWND, LPWSTR, int, BOOL);
+
+ pSHGetSpecialFolderPathA = (BOOL (WINAPI *)(HWND, LPSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathA");
+ pSHGetSpecialFolderPathW = (BOOL (WINAPI *)(HWND, LPWSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathW");
+
+ if (pSHGetSpecialFolderPathA)
+ {
+ if (pSHGetSpecialFolderPathA(GetActiveWindow(), PathA, nFolder, TRUE))
+ {
+ rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(*strPath != NULL);
+ bRet = sal_True;
+ }
+ }
+ else if (pSHGetSpecialFolderPathW)
+ {
+ if (pSHGetSpecialFolderPathW(GetActiveWindow(), PathW, nFolder, TRUE))
+ {
+ rtl_uString_newFromStr( strPath, PathW);
+ bRet = sal_True;
+ }
+ }
+ else
+ {
+ HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *) = (HRESULT (WINAPI *)(HWND, int, LPITEMIDLIST *))GetProcAddress(hLibrary, "SHGetSpecialFolderLocation");
+ BOOL (WINAPI *pSHGetPathFromIDListA)(LPCITEMIDLIST, LPSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListA");
+ BOOL (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPWSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListW");
+ HRESULT (WINAPI *pSHGetMalloc)(LPMALLOC *) = (HRESULT (WINAPI *)(LPMALLOC *))GetProcAddress(hLibrary, "SHGetMalloc");
+
+
+ if (pSHGetSpecialFolderLocation && (pSHGetPathFromIDListA || pSHGetPathFromIDListW ) && pSHGetMalloc )
+ {
+ LPITEMIDLIST pidl;
+ LPMALLOC pMalloc;
+ HRESULT hr;
+
+ hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl);
+
+ /* Get SHGetSpecialFolderLocation fails if directory does not exists. */
+ /* If it fails we try to create the directory and redo the call */
+ if (! SUCCEEDED(hr))
+ {
+ HKEY hRegKey;
+
+ if (RegOpenKey(HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
+ &hRegKey) == ERROR_SUCCESS)
+ {
+ LONG lRet;
+ DWORD lSize = elementsof(PathA);
+ DWORD Type = REG_SZ;
+
+ switch (nFolder)
+ {
+ case CSIDL_APPDATA:
+ lRet = RegQueryValueEx(hRegKey, "AppData", NULL, &Type, (LPBYTE)PathA, &lSize);
+ break;
+
+ case CSIDL_PERSONAL:
+ lRet = RegQueryValueEx(hRegKey, "Personal", NULL, &Type, (LPBYTE)PathA, &lSize);
+ break;
+
+ default:
+ lRet = -1l;
+ }
+
+ if ((lRet == ERROR_SUCCESS) && (Type == REG_SZ))
+ {
+ if (_access(PathA, 0) < 0)
+ CreateDirectory(PathA, NULL);
+
+ hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl);
+ }
+
+ RegCloseKey(hRegKey);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (pSHGetPathFromIDListW && pSHGetPathFromIDListW(pidl, PathW))
+ {
+ /* if directory does not exist, create it */
+ if (_waccess(PathW, 0) < 0)
+ CreateDirectoryW(PathW, NULL);
+
+ rtl_uString_newFromStr( strPath, PathW);
+ bRet = sal_True;
+ }
+ else if (pSHGetPathFromIDListA && pSHGetPathFromIDListA(pidl, PathA))
+ {
+ /* if directory does not exist, create it */
+ if (_access(PathA, 0) < 0)
+ CreateDirectoryA(PathA, NULL);
+
+ rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(*strPath != NULL);
+ bRet = sal_True;
+ }
+ }
+
+ if (SUCCEEDED(pSHGetMalloc(&pMalloc)))
+ {
+ pMalloc->lpVtbl->Free(pMalloc, pidl);
+ pMalloc->lpVtbl->Release(pMalloc);
+ }
+ }
+ }
+ }
+
+ FreeLibrary(hLibrary);
+
+ return (bRet);
+}
+
+
+static sal_Bool isWNT(void)
+{
+ static sal_Bool isInit = sal_False;
+ static sal_Bool isWNT = sal_False;
+
+ if (!isInit)
+ {
+ OSVERSIONINFO VersionInformation =
+
+ {
+ sizeof(OSVERSIONINFO),
+ 0,
+ 0,
+ 0,
+ 0,
+ "",
+ };
+
+ if (
+ GetVersionEx(&VersionInformation) &&
+ (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ )
+ {
+ isWNT = sal_True;
+ }
+
+ isInit = sal_True;
+ }
+
+ return(isWNT);
+}
+
+static BOOL Privilege(LPTSTR strPrivilege, BOOL bEnable)
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tp;
+
+ /*
+ obtain the processes token
+ */
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_DUP_QUERY, &hToken))
+ return FALSE;
+
+ /*
+ get the luid
+ */
+ if (!LookupPrivilegeValue(NULL, strPrivilege, &tp.Privileges[0].Luid))
+ return FALSE;
+
+ tp.PrivilegeCount = 1;
+
+ if (bEnable)
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ else
+ tp.Privileges[0].Attributes = 0;
+
+ /*
+ enable or disable the privilege
+ */
+ if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
+ return FALSE;
+
+ if (!CloseHandle(hToken))
+ return FALSE;
+
+ return TRUE;
+}
+
+static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName, sal_Bool bIncludeDomain)
+{
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ HANDLE hAccessToken = pSecImpl->m_hToken;
+
+ if (hAccessToken == NULL)
+ OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
+
+ if (hAccessToken)
+ {
+ DWORD nInfoBuffer = 512;
+ UCHAR* pInfoBuffer = malloc(nInfoBuffer);
+
+ while (!GetTokenInformation(hAccessToken, TokenUser,
+ pInfoBuffer, nInfoBuffer, &nInfoBuffer))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
+ else
+ {
+ free(pInfoBuffer);
+ pInfoBuffer = NULL;
+ break;
+ }
+ }
+
+ if (pSecImpl->m_hToken == NULL)
+ CloseHandle(hAccessToken);
+
+ if (pInfoBuffer)
+ {
+ sal_Unicode UserName[128];
+ sal_Unicode DomainName[128];
+ sal_Unicode Name[257];
+ DWORD nUserName = sizeof(UserName);
+ DWORD nDomainName = sizeof(DomainName);
+ SID_NAME_USE sUse;
+
+ if (LookupAccountSidW(NULL, ((PTOKEN_USER)pInfoBuffer)->User.Sid,
+ UserName, &nUserName,
+ DomainName, &nDomainName, &sUse))
+ {
+ if (bIncludeDomain)
+ {
+ wcscpy(Name, DomainName);
+ wcscat(Name, L"/");
+ wcscat(Name, UserName);
+ }
+ else
+ {
+ wcscpy(Name, UserName);
+ }
+ }
+ rtl_uString_newFromStr( strName, Name);
+
+ free(pInfoBuffer);
+
+ return (sal_True);
+ }
+ }
+ else
+ {
+ DWORD needed=0;
+ sal_Unicode *pNameW=NULL;
+
+ WNetGetUserW(NULL, NULL, &needed);
+ pNameW = malloc (needed*sizeof(sal_Unicode));
+
+ if (WNetGetUserW(NULL, pNameW, &needed) == NO_ERROR)
+ {
+ rtl_uString_newFromStr( strName, pNameW);
+
+ if (pNameW)
+ free(pNameW);
+ return (sal_True);
+ }
+ else
+ if (wcslen(pSecImpl->m_User) > 0)
+ {
+ rtl_uString_newFromStr( strName, pSecImpl->m_pNetResource->lpRemoteName);
+
+ if (pNameW)
+ free(pNameW);
+
+ return (sal_True);
+ }
+
+ if (pNameW)
+ free(pNameW);
+ }
+ }
+
+ return sal_False;
+}
+
diff --git a/sal/osl/w32/semaphor.c b/sal/osl/w32/semaphor.c
new file mode 100644
index 000000000000..e16a73d998fa
--- /dev/null
+++ b/sal/osl/w32/semaphor.c
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/semaphor.h>
+
+/*
+ Implemetation notes:
+ The void* represented by oslSemaphore is used
+ to store a WIN32 HANDLE.
+*/
+
+
+/*****************************************************************************/
+/* osl_createSemaphore */
+/*****************************************************************************/
+oslSemaphore SAL_CALL osl_createSemaphore(sal_uInt32 initialCount)
+{
+ oslSemaphore Semaphore;
+
+ Semaphore= CreateSemaphore(0, initialCount, INT_MAX, 0);
+
+ /* create failed? */
+ if((HANDLE)Semaphore == INVALID_HANDLE_VALUE)
+ {
+ Semaphore= 0;
+ }
+
+ return Semaphore;
+}
+
+/*****************************************************************************/
+/* osl_destroySemaphore */
+/*****************************************************************************/
+void SAL_CALL osl_destroySemaphore(oslSemaphore Semaphore)
+{
+
+
+ if(Semaphore != 0)
+ {
+ CloseHandle((HANDLE)Semaphore);
+ }
+
+}
+
+/*****************************************************************************/
+/* osl_acquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireSemaphore(oslSemaphore Semaphore)
+{
+ OSL_ASSERT(Semaphore != 0);
+
+ switch ( WaitForSingleObject( (HANDLE)Semaphore, INFINITE ) )
+ {
+ case WAIT_OBJECT_0:
+ return sal_True;
+
+ default:
+ return (sal_False);
+ }
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireSemaphore(oslSemaphore Semaphore)
+{
+ OSL_ASSERT(Semaphore != 0);
+ return (sal_Bool)(WaitForSingleObject((HANDLE)Semaphore, 0) == WAIT_OBJECT_0);
+}
+
+
+/*****************************************************************************/
+/* osl_releaseSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseSemaphore(oslSemaphore Semaphore)
+{
+ OSL_ASSERT(Semaphore != 0);
+
+ /* increase count by one, not interested in previous count */
+ return (sal_Bool)(ReleaseSemaphore((HANDLE)Semaphore, 1, NULL) != FALSE);
+}
+
+
+
diff --git a/sal/osl/w32/signal.cxx b/sal/osl/w32/signal.cxx
new file mode 100644
index 000000000000..f893f7520d40
--- /dev/null
+++ b/sal/osl/w32/signal.cxx
@@ -0,0 +1,436 @@
+/*************************************************************************
+*
+* 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.
+*
+************************************************************************/
+
+/* system headers */
+#include "system.h"
+#include <tchar.h>
+
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+#ifndef __MINGW32__
+#include <DbgHelp.h>
+#endif
+#include <ErrorRep.h>
+#include <systools/win32/uwinapi.h>
+
+typedef struct _oslSignalHandlerImpl
+{
+ oslSignalHandlerFunction Handler;
+ void* pData;
+ struct _oslSignalHandlerImpl* pNext;
+} oslSignalHandlerImpl;
+
+static sal_Bool bErrorReportingEnabled = sal_True;
+static sal_Bool bInitSignal = sal_False;
+static oslMutex SignalListMutex;
+static oslSignalHandlerImpl* SignalList;
+
+static long WINAPI SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP);
+
+static sal_Bool InitSignal(void)
+{
+ HMODULE hFaultRep;
+
+ SignalListMutex = osl_createMutex();
+
+ SetUnhandledExceptionFilter(SignalHandlerFunction);
+
+ hFaultRep = LoadLibrary( "faultrep.dll" );
+ if ( hFaultRep )
+ {
+#ifdef __MINGW32__
+typedef BOOL (WINAPI *pfn_ADDEREXCLUDEDAPPLICATIONW)(LPCWSTR);
+#endif
+ pfn_ADDEREXCLUDEDAPPLICATIONW pfn = (pfn_ADDEREXCLUDEDAPPLICATIONW)GetProcAddress( hFaultRep, "AddERExcludedApplicationW" );
+ if ( pfn )
+ pfn( L"SOFFICE.EXE" );
+ FreeLibrary( hFaultRep );
+ }
+
+ return sal_True;
+}
+
+static sal_Bool DeInitSignal(void)
+{
+ SetUnhandledExceptionFilter(NULL);
+
+ osl_destroyMutex(SignalListMutex);
+
+ return sal_False;
+}
+
+static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo)
+{
+ oslSignalHandlerImpl* pHandler = SignalList;
+ oslSignalAction Action = osl_Signal_ActCallNextHdl;
+
+ while (pHandler != NULL)
+ {
+ if ((Action = pHandler->Handler(pHandler->pData, pInfo)) != osl_Signal_ActCallNextHdl)
+ break;
+
+ pHandler = pHandler->pNext;
+ }
+
+ return Action;
+}
+
+/*****************************************************************************/
+/* SignalHandlerFunction */
+/*****************************************************************************/
+
+#define REPORTENV_PARAM "-crashreportenv:"
+#define REPORTENV_PARAM2 "/crashreportenv:"
+
+static BOOL ReportCrash( LPEXCEPTION_POINTERS lpEP )
+{
+ BOOL fSuccess = FALSE;
+ BOOL fAutoReport = FALSE;
+ TCHAR szBuffer[1024];
+ ::osl::LongPathBuffer< sal_Char > aPath( MAX_LONG_PATH );
+ LPTSTR lpFilePart;
+ PROCESS_INFORMATION ProcessInfo;
+ STARTUPINFO StartupInfo;
+ int argi;
+
+ if ( !bErrorReportingEnabled )
+ return FALSE;
+
+ /* Check if crash reporter was disabled by command line */
+
+ for ( argi = 1; argi < __argc; argi++ )
+ {
+ if (
+ 0 == stricmp( __argv[argi], "-nocrashreport" ) ||
+ 0 == stricmp( __argv[argi], "/nocrashreport" )
+ )
+ return FALSE;
+ else if (
+ 0 == stricmp( __argv[argi], "-autocrashreport" ) ||
+ 0 == stricmp( __argv[argi], "/autocrashreport" )
+ )
+ fAutoReport = TRUE;
+ else if (
+ 0 == strnicmp( __argv[argi], REPORTENV_PARAM, strlen(REPORTENV_PARAM) ) ||
+ 0 == strnicmp( __argv[argi], REPORTENV_PARAM2, strlen(REPORTENV_PARAM2) )
+ )
+ {
+ const char *envparam = __argv[argi] + strlen(REPORTENV_PARAM);
+ const char *delim = strchr(envparam, '=' );
+
+ if ( delim )
+ {
+ CHAR *lpVariable;
+ CHAR *lpValue;
+ const char *variable = envparam;
+ size_t variable_len = delim - envparam;
+ const char *value = delim + 1;
+ size_t value_len = strlen(envparam) - variable_len - 1;
+
+ if ( '\"' == *value )
+ {
+ const char *quote;
+
+ value++;
+ value_len--;
+
+ quote = strchr( value, '\"' );
+ if ( quote )
+ value_len = quote - value;
+ }
+
+ lpVariable = reinterpret_cast< CHAR* >( _alloca( variable_len + 1 ) );
+ memcpy( lpVariable, variable, variable_len );
+ lpVariable[variable_len] = 0;
+
+ lpValue = reinterpret_cast< CHAR* >( _alloca( value_len + 1) );
+ memcpy( lpValue, value, value_len );
+ lpValue[value_len] = 0;
+
+ SetEnvironmentVariable( lpVariable, lpValue );
+ }
+ }
+ }
+
+ if ( SearchPath( NULL, TEXT( "crashrep.exe" ), NULL, aPath.getBufSizeInSymbols(), aPath, &lpFilePart ) )
+ {
+ ZeroMemory( &StartupInfo, sizeof(StartupInfo) );
+ StartupInfo.cb = sizeof(StartupInfo.cb);
+
+
+ sntprintf( szBuffer, elementsof(szBuffer),
+ _T("%s -p %u -excp 0x%p -t %u%s"),
+ aPath,
+ GetCurrentProcessId(),
+ lpEP,
+ GetCurrentThreadId(),
+ fAutoReport ? _T(" -noui -send") : _T(" -noui") );
+
+ if (
+ CreateProcess(
+ NULL,
+ szBuffer,
+ NULL,
+ NULL,
+ FALSE,
+#ifdef UNICODE
+ CREATE_UNICODE_ENVIRONMENT,
+#else
+ 0,
+#endif
+ NULL, NULL, &StartupInfo, &ProcessInfo )
+ )
+ {
+ DWORD dwExitCode;
+
+ WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
+ if ( GetExitCodeProcess( ProcessInfo.hProcess, &dwExitCode ) && 0 == dwExitCode )
+
+ fSuccess = TRUE;
+
+ }
+ }
+
+ return fSuccess;
+}
+
+/*****************************************************************************/
+/* SignalHandlerFunction */
+/*****************************************************************************/
+
+static BOOL WINAPI IsWin95A(void)
+{
+ OSVERSIONINFO ovi;
+
+ ZeroMemory( &ovi, sizeof(ovi) );
+ ovi.dwOSVersionInfoSize = sizeof(ovi);
+
+ if ( GetVersionEx( &ovi ) )
+ /* See MSDN January 2000 documentation of GetVersionEx */
+ return (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
+ (ovi.dwMajorVersion <= 4) &&
+ (ovi.dwMinorVersion == 0) &&
+ (ovi.dwBuildNumber == 0x040003B6);
+
+ /* Something wrent wrong. So assume we have an older operating prior Win95 */
+
+ return TRUE;
+}
+
+/* magic Microsoft C++ compiler exception constant */
+#define EXCEPTION_MSC_CPP_EXCEPTION 0xe06d7363
+
+static long WINAPI SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP)
+{
+ static sal_Bool bNested = sal_False;
+ sal_Bool bRaiseCrashReporter = sal_False;
+ oslSignalInfo Info;
+ oslSignalAction Action;
+
+ Info.UserSignal = lpEP->ExceptionRecord->ExceptionCode;
+ Info.UserData = NULL;
+
+ switch (lpEP->ExceptionRecord->ExceptionCode)
+ {
+ /* Transform unhandled exceptions into access violations.
+ Microsoft C++ compiler (add more for other compilers if necessary).
+ */
+ case EXCEPTION_MSC_CPP_EXCEPTION:
+ case EXCEPTION_ACCESS_VIOLATION:
+ Info.Signal = osl_Signal_AccessViolation;
+ bRaiseCrashReporter = sal_True;
+ break;
+
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ Info.Signal = osl_Signal_IntegerDivideByZero;
+ bRaiseCrashReporter = sal_True;
+ break;
+
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ Info.Signal = osl_Signal_FloatDivideByZero;
+ bRaiseCrashReporter = sal_True;
+ break;
+
+ case EXCEPTION_BREAKPOINT:
+ Info.Signal = osl_Signal_DebugBreak;
+ break;
+
+ default:
+ Info.Signal = osl_Signal_System;
+ bRaiseCrashReporter = sal_True;
+ break;
+ }
+
+ if ( !bNested )
+ {
+ bNested = sal_True;
+
+ if ( bRaiseCrashReporter && ReportCrash( lpEP ) || IsWin95A() )
+ {
+ CallSignalHandler(&Info);
+ Action = osl_Signal_ActKillApp;
+ }
+ else
+ Action = CallSignalHandler(&Info);
+ }
+ else
+ Action = osl_Signal_ActKillApp;
+
+
+ switch ( Action )
+ {
+ case osl_Signal_ActCallNextHdl:
+ return (EXCEPTION_CONTINUE_SEARCH);
+
+ case osl_Signal_ActAbortApp:
+ return (EXCEPTION_EXECUTE_HANDLER);
+
+ case osl_Signal_ActKillApp:
+ SetErrorMode(SEM_NOGPFAULTERRORBOX);
+ exit(255);
+ break;
+ default:
+ break;
+ }
+
+ return (EXCEPTION_CONTINUE_EXECUTION);
+}
+
+/*****************************************************************************/
+/* osl_addSignalHandler */
+/*****************************************************************************/
+oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
+{
+ oslSignalHandlerImpl* pHandler;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ pHandler = reinterpret_cast< oslSignalHandlerImpl* >( calloc( 1, sizeof(oslSignalHandlerImpl) ) );
+
+ if (pHandler != NULL)
+ {
+ pHandler->Handler = Handler;
+ pHandler->pData = pData;
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler->pNext = SignalList;
+ SignalList = pHandler;
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (pHandler);
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_removeSignalHandler */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
+{
+ oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler = SignalList;
+
+ while (pHandler != NULL)
+ {
+ if (pHandler == Handler)
+ {
+ if (pPrevious)
+ pPrevious->pNext = pHandler->pNext;
+ else
+ SignalList = pHandler->pNext;
+
+ osl_releaseMutex(SignalListMutex);
+
+ if (SignalList == NULL)
+ bInitSignal = DeInitSignal();
+
+ free(pHandler);
+
+ return (sal_True);
+ }
+
+ pPrevious = pHandler;
+ pHandler = pHandler->pNext;
+ }
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_raiseSignal */
+/*****************************************************************************/
+oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
+{
+ oslSignalInfo Info;
+ oslSignalAction Action;
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ Info.Signal = osl_Signal_User;
+ Info.UserSignal = UserSignal;
+ Info.UserData = UserData;
+
+ Action = CallSignalHandler(&Info);
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (Action);
+}
+
+/*****************************************************************************/
+/* osl_setErrorReporting */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
+{
+ sal_Bool bOld = bErrorReportingEnabled;
+ bErrorReportingEnabled = bEnable;
+
+ return bOld;
+}
diff --git a/sal/osl/w32/socket.cxx b/sal/osl/w32/socket.cxx
new file mode 100644
index 000000000000..191c31fb986a
--- /dev/null
+++ b/sal/osl/w32/socket.cxx
@@ -0,0 +1,2190 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "system.h"
+
+#include <osl/socket.h>
+#include <osl/diagnose.h>
+#include <rtl/alloc.h>
+
+#include "sockimpl.h"
+
+extern "C" {
+
+/* defines for shutdown */
+#ifdef GCC
+# define SD_RECEIVE 0
+# define SD_SEND 1
+# define SD_BOTH 2
+#endif
+
+/*
+ oslSocketAddr is a pointer to a Berkeley struct sockaddr.
+ I refrained from using sockaddr_in because of possible further
+ extensions of this socket-interface (IP-NG?).
+ The intention was to hide all Berkeley data-structures from
+ direct access past the osl-interface.
+
+ The current implementation is internet (IP) centered. All
+ the constructor-functions (osl_create...) take parameters
+ that will probably make sense only in the IP-environment
+ (e.g. because of using the dotted-Addr-format).
+
+ If the interface will be extended to host other protocol-
+ families, I expect no externally visible changes in the
+ existing functions. You'll probably need only new
+ constructor-functions who take the different Addr
+ formats into consideration (maybe a long dotted Addr
+ or whatever).
+*/
+
+/*
+ _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr
+ are the same! I don't like it very much but see no other easy way to
+ conceal the struct sockaddr from the eyes of the user.
+*/
+
+#define OSL_INVALID_SOCKET INVALID_SOCKET /* WIN32 */
+#define OSL_SOCKET_ERROR SOCKET_ERROR /* WIN32 */
+
+/*****************************************************************************/
+/* enum oslAddrFamily */
+/*****************************************************************************/
+
+/* map */
+static DWORD FamilyMap[]= {
+ AF_INET, /* osl_Socket_FamilyInet */
+ AF_IPX, /* osl_Socket_FamilyIpx */
+ 0 /* osl_Socket_FamilyInvalid */
+};
+
+/* reverse map */
+static oslAddrFamily osl_AddrFamilyFromNative(DWORD nativeType)
+{
+ oslAddrFamily i= (oslAddrFamily) 0;
+ while(i != osl_Socket_FamilyInvalid)
+ {
+ if(FamilyMap[i] == nativeType)
+ return i;
+ i = (oslAddrFamily) ( (int)i + 1);
+ }
+ return i;
+}
+
+/* macros */
+#define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
+#define FAMILY_TO_NATIVE(x) (short)FamilyMap[x]
+
+/*****************************************************************************/
+/* enum oslProtocol */
+/*****************************************************************************/
+
+/* map */
+static DWORD ProtocolMap[]= {
+ 0, /* osl_Socket_FamilyInet */
+ NSPROTO_IPX, /* osl_Socket_FamilyIpx */
+ NSPROTO_SPX, /* osl_Socket_ProtocolSpx */
+ NSPROTO_SPXII, /* osl_Socket_ProtocolSpx_ii */
+ 0 /* osl_Socket_ProtocolInvalid */
+};
+
+/* macros */
+#define PROTOCOL_FROM_NATIVE(y) osl_ProtocolFromNative(y)
+#define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
+
+/*****************************************************************************/
+/* enum oslSocketType */
+/*****************************************************************************/
+
+/* map */
+static DWORD TypeMap[]= {
+ SOCK_STREAM, /* osl_Socket_TypeStream */
+ SOCK_DGRAM, /* osl_Socket_TypeDgram */
+ SOCK_RAW, /* osl_Socket_TypeRaw */
+ SOCK_RDM, /* osl_Socket_TypeRdm */
+ SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */
+ 0 /* osl_Socket_TypeInvalid */
+};
+
+/* reverse map */
+static oslSocketType osl_SocketTypeFromNative(DWORD nativeType)
+{
+ oslSocketType i= (oslSocketType)0;
+ while(i != osl_Socket_TypeInvalid)
+ {
+ if(TypeMap[i] == nativeType)
+ return i;
+ i = (oslSocketType)((int)i+1);
+ }
+ return i;
+}
+
+/* macros */
+#define TYPE_TO_NATIVE(x) TypeMap[x]
+#define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketOption */
+/*****************************************************************************/
+
+/* map */
+static DWORD OptionMap[]= {
+ SO_DEBUG, /* osl_Socket_OptionDebug */
+ SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */
+ SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */
+ SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */
+ SO_DONTROUTE, /* osl_Socket_OptionDontRoute */
+ SO_BROADCAST, /* osl_Socket_OptionBroadcast */
+ SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */
+ SO_LINGER, /* osl_Socket_OptionLinger */
+ SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */
+ SO_SNDBUF, /* osl_Socket_OptionSndBuf */
+ SO_RCVBUF, /* osl_Socket_OptionRcvBuf */
+ SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */
+ SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */
+ SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */
+ SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */
+ SO_ERROR, /* osl_Socket_OptionError */
+ SO_TYPE, /* osl_Socket_OptionType */
+ TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */
+ 0 /* osl_Socket_OptionInvalid */
+};
+
+/* macros */
+#define OPTION_TO_NATIVE(x) OptionMap[x]
+#define OPTION_FROM_NATIVE(y) osl_SocketOptionFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketOptionLevel */
+/*****************************************************************************/
+
+static DWORD OptionLevelMap[]= {
+ SOL_SOCKET, /* osl_Socket_LevelSocket */
+ IPPROTO_TCP, /* osl_Socket_LevelTcp */
+ 0 /* osl_invalid_SocketLevel */
+};
+
+/* macros */
+#define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
+#define OPTION_LEVEL_FROM_NATIVE(y) osl_SocketOptionLevelFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketMsgFlag */
+/*****************************************************************************/
+
+static DWORD SocketMsgFlagMap[]= {
+ 0, /* osl_Socket_MsgNormal */
+ MSG_OOB, /* osl_Socket_MsgOOB */
+ MSG_PEEK, /* osl_Socket_MsgPeek */
+ MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */
+ MSG_MAXIOVLEN /* osl_Socket_MsgMaxIOVLen */
+};
+
+/* macros */
+#define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
+#define MSG_FLAG_FROM_NATIVE(y) osl_SocketMsgFlagFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketDirection */
+/*****************************************************************************/
+
+static DWORD SocketDirection[]= {
+ SD_RECEIVE, /* osl_Socket_DirRead */
+ SD_SEND, /* osl_Socket_DirWrite */
+ SD_BOTH /* osl_Socket_DirReadwrite */
+};
+
+/* macros */
+#define DIRECTION_TO_NATIVE(x) SocketDirection[x]
+#define DIRECTION_FROM_NATIVE(y) osl_SocketDirectionFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketError */
+/*****************************************************************************/
+
+static int SocketError[]= {
+
+ 0, /* no error */
+ WSAENOTSOCK, /* Socket operation on non-socket */
+ WSAEDESTADDRREQ, /* Destination address required */
+ WSAEMSGSIZE, /* Message too long */
+ WSAEPROTOTYPE, /* Protocol wrong type for socket */
+ WSAENOPROTOOPT, /* Protocol not available */
+ WSAEPROTONOSUPPORT, /* Protocol not supported */
+ WSAESOCKTNOSUPPORT, /* Socket type not supported */
+ WSAEOPNOTSUPP, /* Operation not supported on socket */
+ WSAEPFNOSUPPORT, /* Protocol family not supported */
+ WSAEAFNOSUPPORT, /* Address family not supported by */
+ /* protocol family */
+ WSAEADDRINUSE, /* Address already in use */
+ WSAEADDRNOTAVAIL, /* Can't assign requested address */
+ WSAENETDOWN, /* Network is down */
+ WSAENETUNREACH, /* Network is unreachable */
+ WSAENETRESET, /* Network dropped connection because */
+ /* of reset */
+ WSAECONNABORTED, /* Software caused connection abort */
+ WSAECONNRESET, /* Connection reset by peer */
+ WSAENOBUFS, /* No buffer space available */
+ WSAEISCONN, /* Socket is already connected */
+ WSAENOTCONN, /* Socket is not connected */
+ WSAESHUTDOWN, /* Can't send after socket shutdown */
+ WSAETOOMANYREFS, /* Too many references: can't splice */
+ WSAETIMEDOUT, /* Connection timed out */
+ WSAECONNREFUSED, /* Connection refused */
+ WSAEHOSTDOWN, /* Host is down */
+ WSAEHOSTUNREACH, /* No route to host */
+ WSAEWOULDBLOCK, /* call would block on non-blocking socket */
+ WSAEALREADY, /* operation already in progress */
+ WSAEINPROGRESS /* operation now in progress */
+};
+
+/* reverse map */
+static oslSocketError osl_SocketErrorFromNative(int nativeType)
+{
+ oslSocketError i= (oslSocketError)0;
+
+ while(i != osl_Socket_E_InvalidError)
+ {
+ if(SocketError[i] == nativeType)
+ return i;
+
+ i = (oslSocketError)( (int) i + 1);
+ }
+ return i;
+}
+
+/* macros */
+#define ERROR_TO_NATIVE(x) SocketError[x]
+#define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
+
+/*****************************************************************************/
+/* oslSocketDialupImpl */
+/*****************************************************************************/
+static oslSocketDialupImpl *pDialupImpl = NULL;
+
+#if 0 /* INTERNAL DEBUG ONLY */
+BOOL WINAPI __osl_autodial_Impl (DWORD dwFlags, DWORD dwReserved)
+{
+ return 0;
+}
+
+BOOL WINAPI __osl_autodialHangup_Impl (DWORD dwReserved)
+{
+ return 1;
+}
+
+BOOL WINAPI __osl_getConnectedState_Impl (LPDWORD lpdwFlags, DWORD dwReserved)
+{
+ if (lpdwFlags)
+ *lpdwFlags = 0;
+ return 0;
+}
+#endif /* INTERNAL DEBUG ONLY */
+
+/*
+ * __osl_createSocketDialupImpl.
+ */
+static oslSocketDialupImpl* __osl_createSocketDialupImpl (void)
+{
+ oslSocketDialupImpl *pImpl;
+ pImpl = (oslSocketDialupImpl*)rtl_allocateZeroMemory( sizeof (oslSocketDialupImpl));
+
+ InitializeCriticalSection (&pImpl->m_hMutex);
+
+ return (pImpl);
+}
+
+/*
+ * __osl_initSocketDialupImpl.
+ */
+static void __osl_initSocketDialupImpl (oslSocketDialupImpl *pImpl)
+{
+#ifdef SOCKET_USE_AUTODIAL
+ if (pImpl)
+ {
+ HINSTANCE hModule;
+
+ EnterCriticalSection (&pImpl->m_hMutex);
+
+ hModule = LoadLibrary (INTERNET_MODULE_NAME);
+ if (!(hModule <= (HINSTANCE)HINSTANCE_ERROR))
+ {
+ pImpl->m_pfnAttemptConnect = (INTERNETATTEMPTCONNECT)
+ (GetProcAddress (hModule, "InternetAttemptConnect"));
+ pImpl->m_pfnAutodial = (INTERNETAUTODIAL)
+ (GetProcAddress (hModule, "InternetAutodial"));
+ pImpl->m_pfnAutodialHangup = (INTERNETAUTODIALHANGUP)
+ (GetProcAddress (hModule, "InternetAutodialHangup"));
+ pImpl->m_pfnGetConnectedState = (INTERNETGETCONNECTEDSTATE)
+ (GetProcAddress (hModule, "InternetGetConnectedState"));
+ pImpl->m_hModule = hModule;
+ }
+
+ LeaveCriticalSection (&pImpl->m_hMutex);
+ }
+#else
+ pImpl = pImpl; /* avoid warnings */
+#endif
+}
+
+/*
+ * __osl_destroySocketDialupImpl.
+ */
+static void __osl_destroySocketDialupImpl (oslSocketDialupImpl *pImpl)
+{
+ if (pImpl)
+ {
+ EnterCriticalSection (&pImpl->m_hMutex);
+
+ if (pImpl->m_dwFlags & INTERNET_CONNECTION_HANGUP)
+ {
+ if (pImpl->m_pfnAutodialHangup)
+ {
+ (pImpl->m_pfnAutodialHangup)(0);
+ pImpl->m_dwFlags &= ~INTERNET_CONNECTION_HANGUP;
+ }
+ }
+
+ if (pImpl->m_hModule)
+ FreeLibrary (pImpl->m_hModule);
+
+ LeaveCriticalSection (&pImpl->m_hMutex);
+ DeleteCriticalSection (&pImpl->m_hMutex);
+
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*
+ * __osl_querySocketDialupImpl.
+ */
+static sal_Bool __osl_querySocketDialupImpl (void)
+{
+ sal_Bool result;
+
+ if (pDialupImpl == NULL)
+ {
+ pDialupImpl = __osl_createSocketDialupImpl();
+ __osl_initSocketDialupImpl (pDialupImpl);
+ }
+
+ EnterCriticalSection (&pDialupImpl->m_hMutex);
+
+ result = sal_True;
+ if (pDialupImpl->m_pfnGetConnectedState)
+ {
+ DWORD dwFlags = 0;
+
+ result = (sal_Bool)(pDialupImpl->m_pfnGetConnectedState)(&dwFlags, 0);
+ pDialupImpl->m_dwFlags |= dwFlags;
+ }
+
+ LeaveCriticalSection (&pDialupImpl->m_hMutex);
+ return (result);
+}
+
+/*
+ * __osl_attemptSocketDialupImpl.
+ */
+static sal_Bool __osl_attemptSocketDialupImpl (void)
+{
+ sal_Bool result;
+
+ if (pDialupImpl == NULL)
+ {
+ pDialupImpl = __osl_createSocketDialupImpl();
+ __osl_initSocketDialupImpl (pDialupImpl);
+ }
+
+ EnterCriticalSection (&pDialupImpl->m_hMutex);
+
+ result = __osl_querySocketDialupImpl();
+ if (!result)
+ {
+ result = sal_True;
+ if (pDialupImpl->m_pfnAutodial)
+ {
+ result = (sal_Bool)(pDialupImpl->m_pfnAutodial)(0, 0);
+ if (result)
+ pDialupImpl->m_dwFlags |= INTERNET_CONNECTION_HANGUP;
+ else
+ WSASetLastError (WSAENETDOWN);
+ }
+ }
+
+ LeaveCriticalSection (&pDialupImpl->m_hMutex);
+ return (result);
+}
+
+/*****************************************************************************/
+/* oslSocketImpl */
+/*****************************************************************************/
+static sal_uInt32 g_nSocketImpl = 0;
+
+#if OSL_DEBUG_LEVEL > 1
+static sal_uInt32 g_nSocketAddr = 0;
+struct LeakWarning
+{
+ ~LeakWarning()
+ {
+ if( g_nSocketImpl )
+ OSL_TRACE( "sal_socket: %d socket instances leak\n" , g_nSocketImpl );
+ if( g_nSocketAddr )
+ OSL_TRACE( "sal_socket: %d socket address instances leak\n" , g_nSocketAddr );
+ }
+};
+LeakWarning socketWarning;
+#endif
+
+/*
+ * __osl_createSocketImpl.
+ */
+oslSocket __osl_createSocketImpl(SOCKET Socket)
+{
+ oslSocket pSockImpl = (oslSocket) rtl_allocateZeroMemory( sizeof(struct oslSocketImpl));
+ pSockImpl->m_Socket = Socket;
+ pSockImpl->m_nRefCount = 1;
+
+ g_nSocketImpl++;
+
+ return (pSockImpl);
+}
+
+/*
+ * __osl_destroySocketImpl.
+ */
+void __osl_destroySocketImpl(oslSocketImpl *pImpl)
+{
+ if (pImpl)
+ {
+ if (--g_nSocketImpl == 0)
+ {
+ __osl_destroySocketDialupImpl (pDialupImpl);
+ pDialupImpl = NULL;
+ }
+ rtl_freeMemory (pImpl);
+ }
+}
+/*****************************************************************************/
+static oslSocketAddr __osl_createSocketAddr( )
+{
+ oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl ));
+ pAddr->m_nRefCount = 1;
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr ++;
+#endif
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrWithFamily(
+ oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
+{
+ OSL_ASSERT( family == osl_Socket_FamilyInet );
+
+ oslSocketAddr pAddr = __osl_createSocketAddr();
+ switch( family )
+ {
+ case osl_Socket_FamilyInet:
+ {
+ struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
+ pInetAddr->sin_addr.s_addr = nAddr;
+ pInetAddr->sin_port = (sal_uInt16)(port&0xffff);
+ break;
+ }
+ default:
+ pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
+ }
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
+{
+ oslSocketAddr pAddr = __osl_createSocketAddr();
+ memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( sockaddr ) );
+ return pAddr;
+}
+
+static void __osl_destroySocketAddr( oslSocketAddr addr )
+{
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr --;
+#endif
+ rtl_freeMemory( addr );
+}
+/*****************************************************************************/
+/* osl_createEmptySocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
+{
+ oslSocketAddr pAddr = 0;
+
+ /* is it an internet-Addr? */
+ if (Family == osl_Socket_FamilyInet)
+ {
+ pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
+ }
+ else
+ {
+ pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 );
+ }
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_copySocketAddr */
+/*****************************************************************************/
+// @deprecated, to be removed
+oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
+{
+ oslSocketAddr pCopy = 0;
+ if (Addr)
+ {
+ pCopy = __osl_createSocketAddr();
+
+ if (pCopy)
+ memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
+ }
+ return pCopy;
+}
+
+/*****************************************************************************/
+/* osl_isEqualSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isEqualSocketAddr(oslSocketAddr Addr1, oslSocketAddr Addr2)
+{
+ struct sockaddr* pAddr1= &(Addr1->m_sockaddr);
+ struct sockaddr* pAddr2= &(Addr2->m_sockaddr);
+
+ OSL_ASSERT(pAddr1);
+ OSL_ASSERT(pAddr2);
+
+ if (pAddr1->sa_family == pAddr2->sa_family)
+ {
+ switch (pAddr1->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1;
+ struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2;
+
+ if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
+ (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
+ (pInetAddr1->sin_port == pInetAddr2->sin_port))
+ return (sal_True);
+ }
+
+ default:
+ {
+ return (memcmp(pAddr1, Addr2, sizeof(struct sockaddr)) == 0);
+ }
+ }
+ }
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_createInetBroadcastAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
+ rtl_uString *strDottedAddr,
+ sal_Int32 Port)
+{
+ sal_uInt32 nAddr = OSL_INADDR_NONE;
+
+ if (strDottedAddr && strDottedAddr->length)
+ {
+ /* Dotted host address for limited broadcast */
+ rtl_String *pDottedAddr = NULL;
+
+ rtl_uString2String (
+ &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ nAddr = inet_addr (pDottedAddr->buffer);
+ rtl_string_release (pDottedAddr);
+ }
+
+ if (nAddr != OSL_INADDR_NONE)
+ {
+ /* Limited broadcast */
+ nAddr = ntohl(nAddr);
+ if (IN_CLASSA(nAddr))
+ {
+ nAddr &= IN_CLASSA_NET;
+ nAddr |= IN_CLASSA_HOST;
+ }
+ else if (IN_CLASSB(nAddr))
+ {
+ nAddr &= IN_CLASSB_NET;
+ nAddr |= IN_CLASSB_HOST;
+ }
+ else if (IN_CLASSC(nAddr))
+ {
+ nAddr &= IN_CLASSC_NET;
+ nAddr |= IN_CLASSC_HOST;
+ }
+ else
+ {
+ /* No broadcast in class D */
+ return ((oslSocketAddr)NULL);
+ }
+ nAddr = htonl(nAddr);
+ }
+
+ oslSocketAddr pAddr =
+ __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons( (sal_uInt16) Port), nAddr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createInetSocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetSocketAddr (
+ rtl_uString *strDottedAddr,
+ sal_Int32 Port)
+{
+ DWORD Addr;
+ rtl_String *pDottedAddr=NULL;
+
+ rtl_uString2String(
+ &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ Addr= inet_addr (pDottedAddr->buffer);
+ rtl_string_release (pDottedAddr);
+
+ oslSocketAddr pAddr = 0;
+ if(Addr != -1)
+ {
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons( (sal_uInt16)Port), Addr );
+ }
+ return pAddr;
+}
+
+oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
+{
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( pByteSeq );
+
+ oslSocketResult res = osl_Socket_Error;
+ if( pAddr && pByteSeq )
+ {
+ OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
+ OSL_ASSERT( pByteSeq->nElements == 4 );
+ struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+/** Returns the addr field in the struct sockaddr. ppByteSeq is in network byteorder. *ppByteSeq may
+ either be 0 or contain a constructed sal_Sequence.
+ */
+oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
+{
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( ppByteSeq );
+
+ oslSocketResult res = osl_Socket_Error;
+ if( pAddr && ppByteSeq )
+ {
+ struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4);
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+/*****************************************************************************/
+/* oslHostAddr */
+/*****************************************************************************/
+struct oslHostAddrImpl {
+ rtl_uString *pHostName;
+ oslSocketAddr pSockAddr;
+} ;
+
+static oslHostAddr __osl_hostentToHostAddr (const struct hostent *he)
+{
+ oslHostAddr pAddr= NULL;
+ oslSocketAddr pSocketAddr = 0;
+
+ rtl_uString *cn= NULL;
+
+ if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL))
+ return ((oslHostAddr)NULL);
+
+ rtl_string2UString(
+ &cn, he->h_name, strlen(he->h_name),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(cn != 0);
+
+ pSocketAddr = __osl_createSocketAddr();
+
+ if (pSocketAddr == NULL)
+ {
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pSocketAddr->m_sockaddr.sa_family = he->h_addrtype;
+ if (pSocketAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ struct sockaddr_in *sin= (struct sockaddr_in *)&(pSocketAddr->m_sockaddr);
+ memcpy (
+ &(sin->sin_addr.s_addr),
+ he->h_addr_list[0],
+ he->h_length);
+ }
+ else
+ {
+ /* unknown address family */
+ /* future extensions for new families might be implemented here */
+
+ OSL_TRACE("_osl_hostentToHostAddr(): unknown address family.\n");
+ OSL_ASSERT(sal_False);
+
+ __osl_destroySocketAddr( pSocketAddr );
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr= (oslHostAddr )rtl_allocateMemory (sizeof (struct oslHostAddrImpl));
+
+ if (pAddr == NULL)
+ {
+ __osl_destroySocketAddr( pSocketAddr );
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr->pHostName= cn;
+ pAddr->pSockAddr= pSocketAddr;
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddr (
+ rtl_uString *strHostname,
+ const oslSocketAddr pSocketAddr)
+{
+ oslHostAddr pAddr;
+ rtl_uString *cn= NULL;
+
+ if ((strHostname == NULL) || (strHostname->length == 0) || (pSocketAddr == NULL))
+ return ((oslHostAddr)NULL);
+
+ rtl_uString_newFromString( &cn, strHostname);
+
+ if ( ! pSocketAddr )
+ {
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr= (oslHostAddr)rtl_allocateMemory (sizeof (struct oslHostAddrImpl));
+
+ if (pAddr == NULL)
+ {
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr->pHostName= cn;
+ pAddr->pSockAddr= osl_copySocketAddr( pSocketAddr );
+
+ return ((oslHostAddr)pAddr);
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByName */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *strHostname)
+{
+ if ((strHostname == NULL) || (strHostname->length == 0))
+ return ((oslHostAddr)NULL);
+
+ if (__osl_attemptSocketDialupImpl())
+ {
+ struct hostent *he;
+ rtl_String *Hostname= NULL;
+
+ rtl_uString2String(
+ &Hostname, strHostname->buffer, strHostname->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ he= gethostbyname (Hostname->buffer);
+
+ rtl_string_release (Hostname);
+ return __osl_hostentToHostAddr (he);
+ }
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByAddr(const oslSocketAddr pAddr)
+{
+ if (pAddr == NULL)
+ return ((oslHostAddr)NULL);
+
+ if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr);
+
+ if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
+ return ((oslHostAddr)NULL);
+
+ if (__osl_attemptSocketDialupImpl())
+ {
+ struct hostent *he;
+ he= gethostbyaddr ((const sal_Char *)&(sin->sin_addr),
+ sizeof (sin->sin_addr),
+ sin->sin_family);
+ return __osl_hostentToHostAddr (he);
+ }
+ }
+
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_copyHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_copyHostAddr(const oslHostAddr Addr)
+{
+ oslHostAddr pAddr= (oslHostAddr)Addr;
+
+ if (pAddr)
+ return osl_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
+ else
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_getHostnameOfHostAddr(
+ const oslHostAddr pAddr, rtl_uString **strHostname)
+{
+ if (pAddr)
+ rtl_uString_assign (strHostname, pAddr->pHostName);
+ else
+ rtl_uString_new (strHostname);
+}
+
+/*****************************************************************************/
+/* osl_getSocketAddrOfHostAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr(const oslHostAddr pAddr)
+{
+ if (pAddr)
+ return (const oslSocketAddr)(pAddr->pSockAddr);
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_destroyHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroyHostAddr(oslHostAddr pAddr)
+{
+ if (pAddr)
+ {
+ if (pAddr->pHostName)
+ rtl_uString_release (pAddr->pHostName);
+ if (pAddr->pSockAddr)
+ osl_destroySocketAddr( pAddr->pSockAddr );
+
+ rtl_freeMemory (pAddr);
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLocalHostname */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getLocalHostname (rtl_uString **strLocalHostname)
+{
+ static sal_Unicode LocalHostname[256] = {0};
+
+ if (rtl_ustr_getLength(LocalHostname) == 0)
+ {
+ sal_Char Host[256]= "";
+ if (gethostname(Host, sizeof(Host)) == 0)
+ {
+ /* check if we have an FQDN */
+ if (strchr(Host, '.') == NULL)
+ {
+ oslHostAddr pAddr;
+ rtl_uString *hostName= NULL;
+
+ rtl_string2UString(
+ &hostName, Host, strlen(Host),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(hostName != 0);
+
+ /* no, determine it via dns */
+ pAddr = osl_createHostAddrByName(hostName);
+ rtl_uString_release (hostName);
+
+ if (pAddr && pAddr->pHostName)
+ memcpy(LocalHostname, pAddr->pHostName->buffer, sizeof(sal_Unicode)*(rtl_ustr_getLength(pAddr->pHostName->buffer)+1));
+ else
+ memset(LocalHostname, 0, sizeof(LocalHostname));
+
+ osl_destroyHostAddr ((oslHostAddr)pAddr);
+ }
+ }
+ }
+
+ if (rtl_ustr_getLength(LocalHostname) > 0)
+ {
+ rtl_uString_newFromStr (strLocalHostname, LocalHostname);
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_resolveHostname */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString* strHostname)
+{
+ oslHostAddr pAddr=
+ (oslHostAddr )osl_createHostAddrByName (strHostname);
+ if (pAddr)
+ {
+ oslSocketAddr SockAddr = osl_copySocketAddr( pAddr->pSockAddr );
+ osl_destroyHostAddr(pAddr);
+ return (SockAddr);
+ }
+ return ((oslSocketAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getServicePort */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getServicePort (
+ rtl_uString* strServicename,
+ rtl_uString* strProtocol)
+{
+ struct servent* ps;
+
+ rtl_String *str_Servicename=NULL;
+ rtl_String *str_Protocol=NULL;
+
+ rtl_uString2String(
+ &str_Servicename,
+ rtl_uString_getStr(strServicename),
+ rtl_uString_getLength(strServicename),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ rtl_uString2String(
+ &str_Protocol,
+ rtl_uString_getStr(strProtocol),
+ rtl_uString_getLength(strProtocol),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ ps= getservbyname(
+ rtl_string_getStr(str_Servicename),
+ rtl_string_getStr(str_Protocol));
+
+ rtl_string_release( str_Servicename );
+ rtl_string_release( str_Protocol );
+
+ if (ps != 0)
+ return ntohs(ps->s_port);
+
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
+{
+ __osl_destroySocketAddr( pAddr );
+}
+
+/*****************************************************************************/
+/* osl_getFamilyOfSocketAddr */
+/*****************************************************************************/
+oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
+{
+ if (pAddr)
+ return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
+ else
+ return osl_Socket_FamilyInvalid;
+}
+
+/*****************************************************************************/
+/* osl_getInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
+{
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ if ( (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)))
+ return ntohs(pSystemInetAddr->sin_port);
+ }
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_setInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setInetPortOfSocketAddr (
+ oslSocketAddr pAddr,
+ sal_Int32 Port)
+{
+ if (pAddr == NULL)
+ return sal_False;
+
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ return sal_False;
+
+ pSystemInetAddr->sin_port= htons((short)Port);
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr (
+ oslSocketAddr Addr,
+ rtl_uString **strHostName)
+{
+ oslHostAddr pAddr= osl_createHostAddrByAddr (Addr);
+
+ if (pAddr)
+ {
+ rtl_uString_newFromString(strHostName, pAddr->pHostName);
+
+ osl_destroyHostAddr(pAddr);
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_getDottedInetAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr (
+ oslSocketAddr pAddr,
+ rtl_uString **strDottedInetAddr)
+{
+ sal_Char *pDotted;
+
+ if (pAddr == NULL)
+ return osl_Socket_Error;
+
+ struct sockaddr_in *pSystemInetAddr = (struct sockaddr_in*) &(pAddr->m_sockaddr);
+ if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ return osl_Socket_Error;
+
+ pDotted = inet_ntoa (pSystemInetAddr->sin_addr);
+ rtl_string2UString(
+ strDottedInetAddr, pDotted, strlen (pDotted),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(*strDottedInetAddr != 0);
+
+ return osl_Socket_Ok;
+}
+
+/*****************************************************************************/
+/* osl_createSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_createSocket (
+ oslAddrFamily Family,
+ oslSocketType Type,
+ oslProtocol Protocol)
+{
+ /* alloc memory */
+ oslSocket pSocket = __osl_createSocketImpl(0);
+
+ if (pSocket == NULL)
+ return 0;
+
+ /* create socket */
+ pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
+ TYPE_TO_NATIVE(Type),
+ PROTOCOL_TO_NATIVE(Protocol));
+
+ /* creation failed => free memory */
+ if(pSocket->m_Socket == OSL_INVALID_SOCKET)
+ {
+ __osl_destroySocketImpl(pSocket);
+ pSocket= 0;
+ }
+ else
+ {
+ pSocket->m_Flags = 0;
+ pSocket->m_CloseCallback = NULL;
+ pSocket->m_CallbackArg = NULL;
+ }
+
+ return pSocket;
+}
+
+void SAL_CALL osl_acquireSocket( oslSocket pSocket )
+{
+ osl_incrementInterlockedCount( &(pSocket->m_nRefCount) );
+}
+
+void SAL_CALL osl_releaseSocket( oslSocket pSocket )
+{
+ if( pSocket && 0 == osl_decrementInterlockedCount( &(pSocket->m_nRefCount) ) )
+ {
+ osl_closeSocket( pSocket );
+ __osl_destroySocketImpl( pSocket );
+ }
+}
+
+/*****************************************************************************/
+/* osl_closeSocket */
+/*****************************************************************************/
+void SAL_CALL osl_closeSocket(oslSocket pSocket)
+{
+ /* socket already invalid */
+ if(pSocket==0)
+ return;
+
+ /* close */
+ closesocket(pSocket->m_Socket);
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+
+ /* registrierten Callback ausfuehren */
+ if (pSocket->m_CloseCallback != NULL)
+ {
+ pSocket->m_CloseCallback(pSocket->m_CallbackArg);
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLocalAddrOfSocket */
+/* Note that I rely on the fact that oslSocketAddr and struct sockaddr */
+/* are the same! I don't like it very much but see no other easy way */
+/* to conceal the struct sockaddr from the eyes of the user. */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
+{
+ struct sockaddr Addr;
+ int AddrLen;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocketAddr)NULL);
+
+ AddrLen= sizeof(struct sockaddr);
+
+ if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
+ return ((oslSocketAddr)NULL);
+
+ oslSocketAddr pAddr = __osl_createSocketAddrFromSystem( &Addr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_getPeerAddrOfSocket */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
+{
+ struct sockaddr Addr;
+ int AddrLen;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocketAddr)NULL);
+
+ AddrLen= sizeof(struct sockaddr);
+
+ if (getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
+ return ((oslSocketAddr)NULL);
+
+ oslSocketAddr pAddr = __osl_createSocketAddrFromSystem( &Addr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_bindAddrToSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_bindAddrToSocket ( oslSocket pSocket, oslSocketAddr pAddr)
+{
+ OSL_ASSERT( pAddr );
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (bind(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR);
+}
+
+/*****************************************************************************/
+/* osl_connectSocketTo */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_connectSocketTo (
+ oslSocket pSocket,
+ oslSocketAddr pAddr,
+ const TimeValue* pTimeout)
+{
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ if (pAddr == NULL) /* EDESTADDRREQ */
+ return osl_Socket_Error;
+
+ if (!__osl_attemptSocketDialupImpl()) /* ENETDOWN */
+ return osl_Socket_Error;
+
+ if (pTimeout == NULL)
+ {
+ if(connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) == OSL_SOCKET_ERROR)
+ return osl_Socket_Error;
+ else
+ return osl_Socket_Ok;
+ }
+ else
+ {
+ fd_set fds;
+ int error;
+ struct timeval tv;
+ unsigned long Param;
+ oslSocketResult Result= osl_Socket_Ok;
+
+ if (pSocket->m_Flags & OSL_SOCKET_FLAGS_NONBLOCKING)
+ {
+ if (connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) == OSL_SOCKET_ERROR)
+ {
+ switch (WSAGetLastError())
+ {
+ case WSAEWOULDBLOCK:
+ case WSAEINPROGRESS:
+ return osl_Socket_InProgress;
+
+ default:
+ return osl_Socket_Error;
+ }
+ }
+ else
+ return osl_Socket_Ok;
+ }
+
+ /* set socket temporarily to non-blocking */
+ Param= 1;
+ OSL_VERIFY(ioctlsocket(
+ pSocket->m_Socket, FIONBIO, &Param) != OSL_SOCKET_ERROR);
+
+ /* initiate connect */
+ if (connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ {
+ /* immediate connection */
+
+ Param= 0;
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param);
+
+ return osl_Socket_Ok;
+ }
+ else
+ {
+ error = WSAGetLastError();
+
+ /* really an error or just delayed? */
+ if (error != WSAEWOULDBLOCK && error != WSAEINPROGRESS)
+ {
+ Param= 0;
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param);
+
+ return osl_Socket_Error;
+ }
+ }
+
+ /* prepare select set for socket */
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ /* divide milliseconds into seconds and microseconds */
+ tv.tv_sec= pTimeout->Seconds;
+ tv.tv_usec= pTimeout->Nanosec / 1000L;
+
+ /* select */
+ error= select(pSocket->m_Socket+1,
+ 0,
+ &fds,
+ 0,
+ &tv);
+
+ if (error > 0) /* connected */
+ {
+ OSL_POSTCOND(
+ FD_ISSET(pSocket->m_Socket, &fds),
+ "osl_connectSocketTo(): select returned but socket not set\n");
+
+ Result= osl_Socket_Ok;
+
+ }
+ else if(error < 0) /* error */
+ {
+ /* errno == EBADF: most probably interrupted by close() */
+ if(WSAGetLastError() == WSAEBADF)
+ {
+ /* do not access pSockImpl because it is about to be or */
+ /* already destroyed */
+ return osl_Socket_Interrupted;
+ }
+ else
+ Result= osl_Socket_Error;
+
+ }
+ else /* timeout */
+ Result= osl_Socket_TimedOut;
+
+
+ /* clean up */
+ Param= 0;
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param);
+
+ return Result;
+ }
+}
+
+/*****************************************************************************/
+/* osl_listenOnSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_listenOnSocket (
+ oslSocket pSocket,
+ sal_Int32 MaxPendingConnections)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (listen(pSocket->m_Socket,
+ MaxPendingConnections == -1 ?
+ SOMAXCONN :
+ MaxPendingConnections) != OSL_SOCKET_ERROR);
+}
+
+/*****************************************************************************/
+/* osl_acceptConnectionOnSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_acceptConnectionOnSocket (
+ oslSocket pSocket,
+ oslSocketAddr* ppAddr)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocket)NULL);
+
+ SOCKET Connection;
+ if(ppAddr)
+ {
+ if( *ppAddr )
+ {
+ osl_destroySocketAddr( *ppAddr );
+ *ppAddr = 0;
+ }
+ int AddrLen= sizeof(struct sockaddr);
+
+ /* user wants to know peer Addr */
+ struct sockaddr Addr;
+
+ Connection= accept(pSocket->m_Socket, &Addr, &AddrLen);
+ OSL_ASSERT(AddrLen == sizeof(struct sockaddr));
+
+ if(Connection != OSL_SOCKET_ERROR)
+ *ppAddr= __osl_createSocketAddrFromSystem(&Addr);
+ else
+ *ppAddr = NULL;
+ }
+ else
+ {
+ /* user is not interested in peer-addr */
+ Connection= accept(pSocket->m_Socket, 0, 0);
+ }
+
+ /* accept failed? */
+ if(Connection == OSL_SOCKET_ERROR)
+ return ((oslSocket)NULL);
+
+ /* alloc memory */
+ oslSocket pConnectionSocket;
+ pConnectionSocket= __osl_createSocketImpl(Connection);
+
+ pConnectionSocket->m_Flags = 0;
+ pConnectionSocket->m_CloseCallback = NULL;
+ pConnectionSocket->m_CallbackArg = NULL;
+
+ return pConnectionSocket;
+}
+
+/*****************************************************************************/
+/* osl_receiveSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveSocket (
+ oslSocket pSocket,
+ void* pBuffer,
+ sal_uInt32 BytesToRead,
+ oslSocketMsgFlag Flag)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ return recv(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToRead,
+ MSG_FLAG_TO_NATIVE(Flag));
+}
+
+/*****************************************************************************/
+/* osl_receiveFromSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveFromSocket (
+ oslSocket pSocket,
+ oslSocketAddr SenderAddr,
+ void* pBuffer,
+ sal_uInt32 BufferSize,
+ oslSocketMsgFlag Flag)
+{
+ struct sockaddr *pSystemSockAddr = 0;
+ int AddrLen = 0;
+ if( SenderAddr )
+ {
+ AddrLen = sizeof( struct sockaddr );
+ pSystemSockAddr = &(SenderAddr->m_sockaddr);
+ }
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ return recvfrom(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BufferSize,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ &AddrLen);
+}
+
+/*****************************************************************************/
+/* osl_sendSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendSocket (
+ oslSocket pSocket,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ return send(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag));
+}
+
+/*****************************************************************************/
+/* osl_sendToSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendToSocket (
+ oslSocket pSocket,
+ oslSocketAddr ReceiverAddr,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ /* ReceiverAddr might be 0 when used on a connected socket. */
+ /* Then sendto should behave like send. */
+
+ struct sockaddr *pSystemSockAddr = 0;
+ if( ReceiverAddr )
+ pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
+
+ return sendto(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ pSystemSockAddr == 0 ? 0 : sizeof(struct sockaddr));
+}
+
+/*****************************************************************************/
+/* osl_readSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_readSocket( oslSocket pSocket, void *pBuffer, sal_Int32 n )
+{
+ sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer;
+
+ OSL_ASSERT( pSocket);
+
+ /* loop until all desired bytes were read or an error occured */
+ sal_uInt32 BytesRead= 0;
+ sal_uInt32 BytesToRead= n;
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receiveSocket(pSocket,
+ Ptr,
+ BytesToRead,
+ osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ Ptr += RetVal;
+ }
+
+ return BytesRead;
+}
+
+/*****************************************************************************/
+/* osl_writeSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_writeSocket( oslSocket pSocket, const void *pBuffer, sal_Int32 n )
+{
+ OSL_ASSERT( pSocket );
+
+ /* loop until all desired bytes were send or an error occured */
+ sal_uInt32 BytesSend= 0;
+ sal_uInt32 BytesToSend= n;
+ sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer;
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToSend -= RetVal;
+ BytesSend += RetVal;
+ Ptr += RetVal;
+
+ }
+ return BytesSend;
+}
+
+
+/*****************************************************************************/
+/* osl_isReceiveReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isReceiveReady (
+ oslSocket pSocket,
+ const TimeValue* pTimeout)
+{
+ fd_set fds;
+ struct timeval tv;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */
+ &fds, /* check read operations */
+ 0, /* check write ops */
+ 0, /* ckeck for OOB */
+ (pTimeout) ? &tv : 0)==1); /* use timeout? */
+}
+
+/*****************************************************************************/
+/* osl_isSendReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isSendReady (
+ oslSocket pSocket,
+ const TimeValue* pTimeout)
+{
+ fd_set fds;
+ struct timeval tv;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */
+ 0, /* check read operations */
+ &fds, /* check write ops */
+ 0, /* ckeck for OOB */
+ (pTimeout) ? &tv : 0)==1); /* use timeout? */
+}
+
+/*****************************************************************************/
+/* osl_isExceptionPending */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isExceptionPending (
+ oslSocket pSocket,
+ const TimeValue* pTimeout)
+{
+ fd_set fds;
+ struct timeval tv;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */
+ 0, /* check read operations */
+ 0, /* check write ops */
+ &fds, /* ckeck for OOB */
+ (pTimeout) ? &tv : 0)==1); /* use timeout? */
+}
+
+/*****************************************************************************/
+/* osl_shutdownSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_shutdownSocket (
+ oslSocket pSocket,
+ oslSocketDirection Direction)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction))==0);
+}
+
+/*****************************************************************************/
+/* osl_getSocketOption */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getSocketOption (
+ oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ if (getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ (int*)&BufferLen) == -1)
+ {
+ return -1;
+ }
+
+ return (sal_Int32)BufferLen;
+}
+
+/*****************************************************************************/
+/* osl_setSocketOption */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setSocketOption (
+ oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return(setsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ BufferLen) == 0);
+}
+
+/*****************************************************************************/
+/* osl_enableNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_enableNonBlockingMode ( oslSocket pSocket, sal_Bool On)
+{
+ unsigned long Param= On ? 1 : 0;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ pSocket->m_Flags = Param ?
+ (pSocket->m_Flags | OSL_SOCKET_FLAGS_NONBLOCKING) :
+ (pSocket->m_Flags & ~OSL_SOCKET_FLAGS_NONBLOCKING) ;
+
+ return (
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param) != OSL_SOCKET_ERROR);
+}
+
+/*****************************************************************************/
+/* osl_isNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (sal_Bool)((pSocket->m_Flags & OSL_SOCKET_FLAGS_NONBLOCKING) != 0);
+}
+
+/*****************************************************************************/
+/* osl_getSocketType */
+/*****************************************************************************/
+oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
+{
+ int Type=0;
+ int TypeSize= sizeof(Type);
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_TypeInvalid;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
+ OPTION_TO_NATIVE(osl_Socket_OptionType),
+ (sal_Char *)&Type,
+ &TypeSize) == -1)
+ {
+ /* error */
+ return osl_Socket_TypeInvalid;
+ }
+
+ return TYPE_FROM_NATIVE(Type);
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketErrorDescription */
+/*****************************************************************************/
+void SAL_CALL osl_getLastSocketErrorDescription (
+ oslSocket /*Socket*/,
+ rtl_uString **strError)
+{
+ int error;
+
+ switch(error = WSAGetLastError())
+ {
+ case WSAENOTSOCK:
+ rtl_uString_newFromAscii (strError, "WSAENOTSOCK, Socket operation on non-socket. A socket created in one process is used by another process.");
+ break;
+
+ case WSAEDESTADDRREQ:
+ rtl_uString_newFromAscii (strError, "WSAEDESTADDRREQ, Destination Addr required");
+ break;
+
+ case WSAEMSGSIZE:
+ rtl_uString_newFromAscii (strError, "WSAEMSGSIZE, Message too long");
+ break;
+
+ case WSAEPROTOTYPE:
+ rtl_uString_newFromAscii (strError, "WSAEPROTOTYPE, Protocol wrong type for socket");
+ break;
+
+ case WSAENOPROTOOPT:
+ rtl_uString_newFromAscii (strError, "WSAENOPROTOOPT, Protocol not available");
+ break;
+
+ case WSAEPROTONOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSAEPROTONOSUPPORT, Protocol not supported");
+ break;
+
+ case WSAESOCKTNOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSAESOCKTNOSUPPORT, Socket type not supported");
+ break;
+
+ case WSAEOPNOTSUPP:
+ rtl_uString_newFromAscii (strError, "WSAEOPNOTSUPP, Operation not supported on socket");
+ break;
+
+ case WSAEPFNOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSAEPFNOSUPPORT, Protocol family not supported");
+ break;
+
+ case WSAEAFNOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSEAFNOSUPPORT, Addr family not supported by protocol family");
+ break;
+
+ case WSAEADDRINUSE:
+ rtl_uString_newFromAscii (strError, "WSAEADDRINUSE, Triggered by bind() because a process went down without closing a socket.");
+ break;
+
+ case WSAEADDRNOTAVAIL:
+ rtl_uString_newFromAscii (strError, "WSAEADDRNOTAVAIL, Can't assign requested Addr");
+ break;
+
+ case WSAENETDOWN:
+ rtl_uString_newFromAscii (strError, "WSAENETDOWN, Network is down");
+ break;
+
+ case WSAENETUNREACH:
+ rtl_uString_newFromAscii (strError, "WSAENETUNREACH, Network is unreachable");
+ break;
+
+ case WSAENETRESET:
+ rtl_uString_newFromAscii (strError, "WSAENETRESET, Network dropped connection or reset");
+ break;
+
+ case WSAECONNABORTED:
+ rtl_uString_newFromAscii (strError, "WSAECONNABORTED, Software caused connection abort");
+ break;
+
+ case WSAECONNRESET:
+ rtl_uString_newFromAscii (strError, "WSAECONNRESET, Connection reset by peer");
+ break;
+
+ case WSAENOBUFS:
+ rtl_uString_newFromAscii (strError, "WSAENOBUFS, No buffer space available.");
+ break;
+
+ case WSAEISCONN:
+ rtl_uString_newFromAscii (strError, "WSAEISCONN, Socket is already connected");
+ break;
+
+ case WSAENOTCONN:
+ rtl_uString_newFromAscii (strError, "WSAENOTCONN, Socket is not connected");
+ break;
+
+ case WSAESHUTDOWN:
+ rtl_uString_newFromAscii (strError, "WSAESHUTDOWN, Can't send after socket shutdown");
+ break;
+
+ case WSAETIMEDOUT:
+ rtl_uString_newFromAscii (strError, "WSAETIMEDOUT, Connection timed out");
+ break;
+
+ case WSAECONNREFUSED:
+ rtl_uString_newFromAscii (strError, "WSAECONNREFUSED, Connection refused");
+ break;
+
+ case WSAEHOSTDOWN:
+ rtl_uString_newFromAscii (strError, "WSAEHOSTDOWN, Networking subsystem not started");
+ break;
+
+ case WSAEHOSTUNREACH:
+ rtl_uString_newFromAscii (strError, "WSAEHOSTUNREACH, No route to host");
+ break;
+
+ case WSAEWOULDBLOCK:
+ rtl_uString_newFromAscii (strError, "WSAEWOULDBLOCK, Operation would block");
+ break;
+
+ case WSAEINPROGRESS:
+ rtl_uString_newFromAscii (strError, "WSAEINPROGRESS, Operation now in progress");
+ break;
+
+ case WSAEALREADY:
+ rtl_uString_newFromAscii (strError, "WSAEALREADY, Operation already in progress");
+ break;
+
+ case WSAEINTR:
+ rtl_uString_newFromAscii (strError, "WSAEALREADY, Operation was interrupted");
+ break;
+
+ case WSAEBADF:
+ rtl_uString_newFromAscii (strError, "WSAEBADF, Bad file number");
+ break;
+
+ case WSAEACCES:
+ rtl_uString_newFromAscii (strError, "WSAEACCES, Access is denied");
+ break;
+
+ case WSAEFAULT:
+ rtl_uString_newFromAscii (strError, "WSAEFAULT, Bad memory Addr");
+ break;
+
+ case WSAEINVAL:
+ rtl_uString_newFromAscii (strError, "WSAEINVAL, The socket has not been bound with bind() or is already connected");
+ break;
+
+ case WSAEMFILE:
+ rtl_uString_newFromAscii (strError, "WSAEMFILE, No more file descriptors are available");
+ break;
+
+ case WSAETOOMANYREFS:
+ rtl_uString_newFromAscii (strError, "WSAETOOMANYREFS, Undocumented WinSock error");
+ break;
+
+ case WSAENAMETOOLONG:
+ rtl_uString_newFromAscii (strError, "WSAENAMETOOLONG, Undocumented WinSock error");
+ break;
+
+ case WSAENOTEMPTY:
+ rtl_uString_newFromAscii (strError, "WSAENOTEMPTY, Undocumented WinSock error");
+ break;
+
+ case WSAEPROCLIM:
+ rtl_uString_newFromAscii (strError, "WSAEPROCLIM, Undocumented WinSock error");
+ break;
+
+ case WSAEUSERS:
+ rtl_uString_newFromAscii (strError, "WSAEUSERS, Undocumented WinSock error");
+ break;
+
+ case WSAEDQUOT:
+ rtl_uString_newFromAscii (strError, "WSAEDQUOT, Undocumented WinSock error");
+ break;
+
+ case WSAESTALE:
+ rtl_uString_newFromAscii (strError, "WSAESTALE, Undocumented WinSock error");
+ break;
+
+ case WSAEREMOTE:
+ rtl_uString_newFromAscii (strError, "WSAEREMOTE, Undocumented WinSock error");
+ break;
+
+ case WSAEDISCON:
+ rtl_uString_newFromAscii (strError, "WSAEDISCON, Circuit was gracefully terminated");
+ break;
+
+ case WSASYSNOTREADY:
+ rtl_uString_newFromAscii (strError, "WSASYSNOTREADY, The underlying network subsystem is not ready for network communication");
+ break;
+
+ case WSAVERNOTSUPPORTED:
+ rtl_uString_newFromAscii (strError, "WSAVERNOTSUPPORTED, The version of Windows Sockets API support requested is not provided by this particular Windows Sockets implementation");
+ break;
+
+ case WSANOTINITIALISED:
+ rtl_uString_newFromAscii (strError, "WSANOTINITIALISED, WSAStartup() has not been called");
+ break;
+
+ case WSAHOST_NOT_FOUND:
+ rtl_uString_newFromAscii (strError, "WSAHOST_NOT_FOUND, Authoritative answer host not found");
+ break;
+
+ case WSATRY_AGAIN:
+ rtl_uString_newFromAscii (strError, "WSATRY_AGAIN, Non-authoritative answer host not found or SERVERFAIL");
+ break;
+
+ case WSANO_RECOVERY:
+ rtl_uString_newFromAscii (strError, "WSANO_RECOVERY, Non recoverable errors, FORMERR, REFUSED, NOTIMP");
+ break;
+
+ case WSANO_DATA:
+ rtl_uString_newFromAscii (strError, "WSANO_DATA or WSANO_ADDRESS, Valid name, no data record of requested type");
+ break;
+
+ default:
+ {
+ sal_Unicode message[128];
+
+ wsprintfW(reinterpret_cast<LPWSTR>(message), L"Unknown WinSock Error Number %d", error);
+ rtl_uString_newFromStr (strError, message);
+ }
+
+ return;
+
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketError */
+/*****************************************************************************/
+oslSocketError SAL_CALL osl_getLastSocketError(oslSocket /*Socket*/)
+{
+ return ERROR_FROM_NATIVE(WSAGetLastError());
+}
+
+/*****************************************************************************/
+/* SocketSet */
+/*****************************************************************************/
+typedef struct _TSocketSetImpl
+{
+ fd_set m_Set; /* the set of descriptors */
+
+} TSocketSetImpl;
+
+/*****************************************************************************/
+/* osl_createSocketSet */
+/*****************************************************************************/
+oslSocketSet SAL_CALL osl_createSocketSet()
+{
+ TSocketSetImpl* pSet;
+
+ pSet = (TSocketSetImpl*) rtl_allocateMemory(sizeof(TSocketSetImpl));
+
+ if(pSet)
+ {
+ FD_ZERO(&pSet->m_Set);
+ }
+
+ return (oslSocketSet)pSet;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketSet (oslSocketSet Set)
+{
+ if(Set)
+ rtl_freeMemory(Set);
+}
+
+/*****************************************************************************/
+/* osl_clearSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_clearSocketSet (oslSocketSet Set)
+{
+ TSocketSetImpl* pSet;
+
+ pSet= (TSocketSetImpl*)Set;
+
+ if (pSet)
+ FD_ZERO(&pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_addToSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_addToSocketSet (
+ oslSocketSet Set,
+ oslSocket Socket)
+{
+ TSocketSetImpl* pSet;
+ oslSocketImpl* pSockImpl;
+
+ pSet= (TSocketSetImpl*)Set;
+ pSockImpl= (oslSocketImpl*)Socket;
+
+ if (pSet && pSockImpl)
+ FD_SET(pSockImpl->m_Socket, &pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_removeFromSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_removeFromSocketSet (
+ oslSocketSet Set,
+ oslSocket Socket)
+{
+ TSocketSetImpl* pSet;
+ oslSocketImpl* pSockImpl;
+
+ pSet= (TSocketSetImpl*)Set;
+ pSockImpl= (oslSocketImpl*)Socket;
+
+ if (pSet && pSockImpl)
+ FD_CLR(pSockImpl->m_Socket, &pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_isInSocketSet */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isInSocketSet (
+ oslSocketSet Set,
+ oslSocket Socket)
+{
+ TSocketSetImpl* pSet;
+ oslSocketImpl* pSockImpl;
+
+ pSet= (TSocketSetImpl*)Set;
+ pSockImpl= (oslSocketImpl*)Socket;
+
+ if (pSet && pSockImpl)
+ return (FD_ISSET(pSockImpl->m_Socket, &pSet->m_Set) != 0);
+ else
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_demultiplexSocketEvents */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_demultiplexSocketEvents (
+ oslSocketSet IncomingSet,
+ oslSocketSet OutgoingSet,
+ oslSocketSet OutOfBandSet,
+ const TimeValue* pTimeout)
+{
+ int MaxHandle= 0;
+ struct timeval tv;
+ TSocketSetImpl* pInSet;
+ TSocketSetImpl* pOutSet;
+ TSocketSetImpl* pOOBSet;
+
+ if(pTimeout)
+ {
+ /* divide milliseconds into seconds and microseconds */
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ /* map opaque data to impl-types */
+ pInSet= (TSocketSetImpl*)IncomingSet;
+ pOutSet= (TSocketSetImpl*)OutgoingSet;
+ pOOBSet= (TSocketSetImpl*)OutOfBandSet;
+
+ return select(MaxHandle, /* redundant in WIN32 */
+ pInSet ? &pInSet->m_Set : 0,
+ pOutSet ? &pOutSet->m_Set : 0,
+ pOOBSet ? &pOOBSet->m_Set : 0,
+ pTimeout ? &tv : 0);
+}
+
+}
diff --git a/sal/osl/w32/sockimpl.h b/sal/osl/w32/sockimpl.h
new file mode 100644
index 000000000000..d1278ee8e6ac
--- /dev/null
+++ b/sal/osl/w32/sockimpl.h
@@ -0,0 +1,108 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SOCKETIMPL_H_
+#define _OSL_SOCKETIMPL_H_
+
+#include <osl/socket.h>
+#include <osl/interlck.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+/* oslSocketImpl */
+/*****************************************************************************/
+#define OSL_SOCKET_FLAGS_NONBLOCKING 0x0001
+
+typedef void* (SAL_CALL * oslCloseCallback) (void*);
+
+struct oslSocketImpl {
+ oslInterlockedCount m_nRefCount;
+ SOCKET m_Socket;
+ int m_Flags;
+ oslCloseCallback m_CloseCallback;
+ void* m_CallbackArg;
+};
+
+struct oslSocketAddrImpl
+{
+ struct sockaddr m_sockaddr;
+ oslInterlockedCount m_nRefCount;
+};
+
+oslSocket __osl_createSocketImpl(SOCKET Socket);
+void __osl_destroySocketImpl(oslSocket pImpl);
+
+/*****************************************************************************/
+/* oslSocketDialupImpl */
+/*****************************************************************************/
+#define INTERNET_MODULE_NAME "wininet.dll"
+
+#define INTERNET_CONNECTION_MODEM 0x00000001L
+#define INTERNET_CONNECTION_LAN 0x00000002L
+#define INTERNET_CONNECTION_HANGUP 0x80000000L
+
+typedef DWORD (WINAPI *INTERNETATTEMPTCONNECT) (
+ DWORD dwReserved);
+typedef BOOL (WINAPI *INTERNETAUTODIAL) (
+ DWORD dwFlags, DWORD dwReserved);
+typedef BOOL (WINAPI *INTERNETAUTODIALHANGUP) (
+ DWORD dwReserved);
+typedef BOOL (WINAPI *INTERNETGETCONNECTEDSTATE) (
+ LPDWORD lpdwFlags, DWORD dwReserved);
+
+typedef struct osl_socket_dialup_impl_st
+{
+ CRITICAL_SECTION m_hMutex;
+ HINSTANCE m_hModule;
+ INTERNETATTEMPTCONNECT m_pfnAttemptConnect;
+ INTERNETAUTODIAL m_pfnAutodial;
+ INTERNETAUTODIALHANGUP m_pfnAutodialHangup;
+ INTERNETGETCONNECTEDSTATE m_pfnGetConnectedState;
+ DWORD m_dwFlags;
+} oslSocketDialupImpl;
+
+static oslSocketDialupImpl* __osl_createSocketDialupImpl (void);
+static void __osl_initSocketDialupImpl (oslSocketDialupImpl *pImpl);
+static void __osl_destroySocketDialupImpl (oslSocketDialupImpl *pImpl);
+
+static sal_Bool __osl_querySocketDialupImpl (void);
+static sal_Bool __osl_attemptSocketDialupImpl (void);
+
+/*****************************************************************************/
+/* The End */
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/sal/osl/w32/system.h b/sal/osl/w32/system.h
new file mode 100644
index 000000000000..1bd86994e6ce
--- /dev/null
+++ b/sal/osl/w32/system.h
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#if OSL_DEBUG_LEVEL == 0
+# define NO_DEBUG_CRT
+#endif
+
+#ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0400
+# define _CTYPE_DISABLE_MACROS /* wg. dynamischer C-Runtime MH */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <limits.h>
+#include <process.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <share.h>
+#include <direct.h>
+
+/* Must define this else build breaks because Winsock2.h
+ includes Windows.h and without WIN32_LEAN_AND_MEAN
+ also includes mswsock.h which needs a forward typedef
+ of SOCKET ...
+*/
+#define WIN32_LEAN_AND_MEAN
+
+#ifdef GCC
+ // windows.h includes winsock2.h
+ // if _WIN32_WINNT > 0x0400
+ // so someone cannot include winsock.h
+ // at the same time without patching
+ // windows.h
+ #include <windows.h>
+#ifdef __MINGW32__
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+#endif
+ #include <shlobj.h>
+ #ifndef NO_DEBUG_CRT
+ #include <crtdbg.h>
+ #endif
+#else
+ // winsock2.h includes windows.h
+ #pragma warning(push,1) /* disable warnings within system headers */
+ #pragma warning(disable:4917)
+ #include <winsock2.h>
+ #include <wsipx.h>
+ #include <shlobj.h>
+ #ifndef NO_DEBUG_CRT
+ #include <crtdbg.h>
+ #endif
+ #pragma warning(pop)
+#endif
+
+#define _MAX_CMD 4096 /* maximum length of commandline */
+/* #define _MAX_ENV 4096 maximum length of environment var (isn't used anywhere) */
+
+#ifdef GCC
+ # ifndef SA_FAMILY_DECL
+ # define SA_FAMILY_DECL short sa_family
+ # endif
+
+ typedef struct sockaddr_ipx {
+ SA_FAMILY_DECL;
+ char sa_netnum[4];
+ char sa_nodenum[6];
+ unsigned short sa_socket;
+ } SOCKADDR_IPX;
+
+ # define NSPROTO_IPX 1000
+ # define NSPROTO_SPX 1256
+ # define NSPROTO_SPXII 1257
+#endif // #ifdef GCC
+
+#ifdef _DLL_
+
+#ifdef __cplusplus
+ extern "C" DWORD g_dwPlatformId;
+#else
+ extern DWORD g_dwPlatformId;
+#endif // #ifdef __cplusplus
+
+ #define IS_NT (g_dwPlatformId == VER_PLATFORM_WIN32_NT)
+#else
+
+#ifdef __cplusplus
+ extern "C" DWORD GetPlatformId(void);
+#else
+ extern DWORD GetPlatformId(void);
+#endif // #ifdef __cplusplus
+
+ #define IS_NT (GetPlatformId() == VER_PLATFORM_WIN32_NT)
+#endif // #ifdef _DLL_
+
diff --git a/sal/osl/w32/tempfile.cxx b/sal/osl/w32/tempfile.cxx
new file mode 100644
index 000000000000..6a3d2549004a
--- /dev/null
+++ b/sal/osl/w32/tempfile.cxx
@@ -0,0 +1,274 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "osl/file.h"
+
+#include "file_error.h"
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include "osl/diagnose.h"
+
+#include <malloc.h>
+#include <tchar.h>
+
+//#####################################################
+#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+// Allocate n number of t's on the stack return a pointer to it in p
+#ifdef __MINGW32__
+#define STACK_ALLOC(p, t, n) (p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));
+#else
+#define STACK_ALLOC(p, t, n) __try {(p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));} \
+ __except(EXCEPTION_EXECUTE_HANDLER) {(p) = 0;}
+#endif
+
+extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle(HANDLE hFile, sal_uInt32 uFlags);
+
+//#####################################################
+// Temp file functions
+//#####################################################
+
+static oslFileError osl_setup_base_directory_impl_(
+ rtl_uString* pustrDirectoryURL,
+ rtl_uString** ppustr_base_dir)
+{
+ rtl_uString* dir_url = 0;
+ rtl_uString* dir = 0;
+ oslFileError error = osl_File_E_None;
+
+ if (pustrDirectoryURL)
+ rtl_uString_assign(&dir_url, pustrDirectoryURL);
+ else
+ error = osl_getTempDirURL(&dir_url);
+
+ if (osl_File_E_None == error)
+ {
+ error = _osl_getSystemPathFromFileURL(dir_url, &dir, sal_False);
+ rtl_uString_release(dir_url);
+ }
+
+ if (osl_File_E_None == error )
+ {
+ rtl_uString_assign(ppustr_base_dir, dir);
+ rtl_uString_release(dir);
+ }
+
+ return error;
+}
+
+//#####################################################
+static oslFileError osl_setup_createTempFile_impl_(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL,
+ rtl_uString** ppustr_base_dir,
+ sal_Bool* b_delete_on_close)
+{
+ oslFileError osl_error;
+
+ OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
+
+ if ((0 == pHandle) && (0 == ppustrTempFileURL))
+ {
+ osl_error = osl_File_E_INVAL;
+ }
+ else
+ {
+ osl_error = osl_setup_base_directory_impl_(
+ pustrDirectoryURL, ppustr_base_dir);
+
+ *b_delete_on_close = (sal_Bool)(0 == ppustrTempFileURL);
+ }
+
+ return osl_error;
+}
+
+//#####################################################
+static oslFileError osl_win32_GetTempFileName_impl_(
+ rtl_uString* base_directory, LPWSTR temp_file_name)
+{
+ oslFileError osl_error = osl_File_E_None;
+
+ if (0 == GetTempFileNameW(
+ reinterpret_cast<LPCWSTR>(rtl_uString_getStr(base_directory)),
+ L"",
+ 0,
+ temp_file_name))
+ {
+ osl_error = oslTranslateFileError(GetLastError());
+ }
+
+ return osl_error;
+}
+
+//#####################################################
+static sal_Bool osl_win32_CreateFile_impl_(
+ LPCWSTR file_name, sal_Bool b_delete_on_close, oslFileHandle* p_handle)
+{
+ DWORD flags = FILE_ATTRIBUTE_NORMAL;
+ HANDLE hFile;
+
+ OSL_ASSERT(p_handle);
+
+ if (b_delete_on_close)
+ flags |= FILE_FLAG_DELETE_ON_CLOSE;
+
+ hFile = CreateFileW(
+ file_name,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ TRUNCATE_EXISTING,
+ flags,
+ NULL);
+
+ // @@@ ERROR HANDLING @@@
+ if (IsValidHandle(hFile))
+ *p_handle = osl_createFileHandleFromOSHandle(hFile, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+
+ return (sal_Bool)IsValidHandle(hFile);
+}
+
+//#############################################
+static oslFileError osl_createTempFile_impl_(
+ rtl_uString* base_directory,
+ LPWSTR tmp_name,
+ sal_Bool b_delete_on_close,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL)
+{
+ oslFileError osl_error;
+
+ do
+ {
+ osl_error = osl_win32_GetTempFileName_impl_(base_directory, tmp_name);
+
+ /* if file could not be opened try again */
+
+ if ((osl_File_E_None != osl_error) || (0 == pHandle) ||
+ osl_win32_CreateFile_impl_(tmp_name, b_delete_on_close, pHandle))
+ break;
+
+ } while(1); // try until success
+
+ if ((osl_File_E_None == osl_error) && !b_delete_on_close)
+ {
+ rtl_uString* pustr = 0;
+ rtl_uString_newFromStr(&pustr, reinterpret_cast<const sal_Unicode*>(tmp_name));
+ osl_getFileURLFromSystemPath(pustr, ppustrTempFileURL);
+ rtl_uString_release(pustr);
+ }
+
+ return osl_error;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_createTempFile(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL)
+{
+ rtl_uString* base_directory = 0;
+ LPWSTR tmp_name;
+ sal_Bool b_delete_on_close;
+ oslFileError osl_error;
+
+ osl_error = osl_setup_createTempFile_impl_(
+ pustrDirectoryURL,
+ pHandle,
+ ppustrTempFileURL,
+ &base_directory,
+ &b_delete_on_close);
+
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ /* allocate enough space on the stack, the file name can not be longer than MAX_PATH */
+ STACK_ALLOC(tmp_name, WCHAR, (rtl_uString_getLength(base_directory) + MAX_PATH));
+
+ if (tmp_name)
+ {
+ osl_createTempFile_impl_(
+ base_directory,
+ tmp_name,
+ b_delete_on_close,
+ pHandle,
+ ppustrTempFileURL);
+ }
+ else // stack alloc failed
+ {
+ osl_error = osl_File_E_NOMEM;
+ }
+
+ if (base_directory)
+ rtl_uString_release(base_directory);
+
+ return osl_error;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_getTempDirURL(rtl_uString** pustrTempDir)
+{
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ LPWSTR lpBuffer = ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer);
+ DWORD nBufferLength = aBuffer.getBufSizeInSymbols() - 1;
+
+ DWORD nLength;
+ oslFileError error;
+
+ nLength = GetTempPathW( aBuffer.getBufSizeInSymbols(), lpBuffer );
+
+ if ( nLength > nBufferLength )
+ {
+ // the provided path has invalid length
+ error = osl_File_E_NOENT;
+ }
+ else if ( nLength )
+ {
+ rtl_uString *ustrTempPath = NULL;
+
+ if ( '\\' == lpBuffer[nLength-1] )
+ lpBuffer[nLength-1] = 0;
+
+ rtl_uString_newFromStr( &ustrTempPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
+
+ error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
+
+ rtl_uString_release( ustrTempPath );
+ }
+ else
+ error = oslTranslateFileError( GetLastError() );
+
+ return error;
+}
+
diff --git a/sal/osl/w32/thread.c b/sal/osl/w32/thread.c
new file mode 100644
index 000000000000..88ce87cdf175
--- /dev/null
+++ b/sal/osl/w32/thread.c
@@ -0,0 +1,593 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <rtl/alloc.h>
+#include <osl/time.h>
+#include <osl/interlck.h>
+#include <rtl/tencinfo.h>
+
+/*
+ Thread-data structure hidden behind oslThread:
+*/
+typedef struct _osl_TThreadImpl
+{
+ HANDLE m_hThread; /* OS-handle used for all thread-functions */
+ unsigned m_ThreadId; /* identifier for this thread */
+ sal_Int32 m_nTerminationRequested;
+ oslWorkerFunction m_WorkerFunction;
+ void* m_pData;
+
+} osl_TThreadImpl;
+
+#define THREADIMPL_FLAGS_TERMINATE 0x0001
+
+static unsigned __stdcall oslWorkerWrapperFunction(void* pData);
+static oslThread oslCreateThread(oslWorkerFunction pWorker, void* pThreadData, sal_uInt32 nFlags);
+
+/*****************************************************************************/
+/* oslWorkerWrapperFunction */
+/*****************************************************************************/
+static unsigned __stdcall oslWorkerWrapperFunction(void* pData)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)pData;
+
+ /* Initialize COM */
+
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+ /* call worker-function with data */
+
+ pThreadImpl->m_WorkerFunction(pThreadImpl->m_pData);
+
+ CoUninitialize();
+
+ return (0);
+}
+
+/*****************************************************************************/
+/* oslCreateThread */
+/*****************************************************************************/
+static oslThread oslCreateThread(oslWorkerFunction pWorker,
+ void* pThreadData,
+ sal_uInt32 nFlags)
+{
+ osl_TThreadImpl* pThreadImpl;
+
+ /* alloc mem. for our internal data structure */
+ pThreadImpl= malloc(sizeof(osl_TThreadImpl));
+
+ OSL_ASSERT(pThreadImpl);
+
+ if ( pThreadImpl == 0 )
+ {
+ return 0;
+ }
+
+ pThreadImpl->m_WorkerFunction= pWorker;
+ pThreadImpl->m_pData= pThreadData;
+ pThreadImpl->m_nTerminationRequested= 0;
+
+ pThreadImpl->m_hThread=
+ (HANDLE)_beginthreadex(NULL, /* no security */
+ 0, /* default stack-size */
+ oslWorkerWrapperFunction, /* worker-function */
+ pThreadImpl, /* provide worker-function with data */
+ nFlags, /* start thread immediately or suspended */
+ &pThreadImpl->m_ThreadId);
+
+ if(pThreadImpl->m_hThread == 0)
+ {
+ /* create failed */
+ free(pThreadImpl);
+ return 0;
+ }
+
+ return (oslThread)pThreadImpl;
+}
+
+/*****************************************************************************/
+/* osl_createThread */
+/*****************************************************************************/
+oslThread SAL_CALL osl_createThread(oslWorkerFunction pWorker,
+ void* pThreadData)
+{
+ return oslCreateThread(pWorker, pThreadData, 0);
+}
+
+/*****************************************************************************/
+/* osl_createSuspendedThread */
+/*****************************************************************************/
+oslThread SAL_CALL osl_createSuspendedThread(oslWorkerFunction pWorker,
+ void* pThreadData)
+{
+ return oslCreateThread(pWorker, pThreadData, CREATE_SUSPENDED);
+}
+
+/*****************************************************************************/
+/* osl_getThreadIdentifier */
+/*****************************************************************************/
+oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ if (pThreadImpl != NULL)
+ return ((oslThreadIdentifier)pThreadImpl->m_ThreadId);
+ else
+ return ((oslThreadIdentifier)GetCurrentThreadId());
+}
+
+/*****************************************************************************/
+/* osl_destroyThread */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ if (Thread == 0) /* valid ptr? */
+ {
+ /* thread already destroyed or not created */
+ return;
+ }
+
+ /* !!!! _exitthreadex does _not_ call CloseHandle !!! */
+ CloseHandle( pThreadImpl->m_hThread );
+
+ /* free memory */
+ free(Thread);
+}
+
+/*****************************************************************************/
+/* osl_resumeThread */
+/*****************************************************************************/
+void SAL_CALL osl_resumeThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+ ResumeThread(pThreadImpl->m_hThread);
+}
+
+/*****************************************************************************/
+/* osl_suspendThread */
+/*****************************************************************************/
+void SAL_CALL osl_suspendThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+ SuspendThread(pThreadImpl->m_hThread);
+}
+
+/*****************************************************************************/
+/* osl_setThreadPriority */
+/*****************************************************************************/
+void SAL_CALL osl_setThreadPriority(oslThread Thread,
+ oslThreadPriority Priority)
+{
+ int winPriority;
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+
+ /* map enum to WIN32 levels
+ it would be faster and more elegant to preset
+ the enums, but that would require an #ifdef in
+ the exported header, which is not desired.
+ */
+ switch(Priority) {
+
+ case osl_Thread_PriorityHighest:
+ winPriority= THREAD_PRIORITY_HIGHEST;
+ break;
+
+ case osl_Thread_PriorityAboveNormal:
+ winPriority= THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+
+ case osl_Thread_PriorityNormal:
+ winPriority= THREAD_PRIORITY_NORMAL;
+ break;
+
+ case osl_Thread_PriorityBelowNormal:
+ winPriority= THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+
+ case osl_Thread_PriorityLowest:
+ winPriority= THREAD_PRIORITY_LOWEST;
+ break;
+
+ case osl_Thread_PriorityUnknown:
+ OSL_ASSERT(FALSE); /* only fools try this...*/
+
+ /* let release-version behave friendly */
+ return;
+
+ default:
+ OSL_ASSERT(FALSE); /* enum expanded, but forgotten here...*/
+
+ /* let release-version behave friendly */
+ return;
+ }
+
+ SetThreadPriority(pThreadImpl->m_hThread, winPriority);
+}
+
+/*****************************************************************************/
+/* osl_getThreadPriority */
+/*****************************************************************************/
+oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
+{
+ int winPriority;
+ oslThreadPriority Priority;
+
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments ?*/
+ if(pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ return osl_Thread_PriorityUnknown;
+ }
+
+ winPriority=
+ GetThreadPriority(pThreadImpl->m_hThread);
+
+
+ if(winPriority == THREAD_PRIORITY_ERROR_RETURN)
+ {
+ return osl_Thread_PriorityUnknown;
+ }
+
+ /* map WIN32 priority to enum */
+ switch(winPriority)
+ {
+ case THREAD_PRIORITY_TIME_CRITICAL:
+ case THREAD_PRIORITY_HIGHEST:
+ Priority= osl_Thread_PriorityHighest;
+ break;
+
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ Priority= osl_Thread_PriorityAboveNormal;
+ break;
+
+ case THREAD_PRIORITY_NORMAL:
+ Priority= osl_Thread_PriorityNormal;
+ break;
+
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ Priority= osl_Thread_PriorityBelowNormal;
+ break;
+
+ case THREAD_PRIORITY_IDLE:
+ case THREAD_PRIORITY_LOWEST:
+ Priority= osl_Thread_PriorityLowest;
+ break;
+
+ default:
+ OSL_ASSERT(FALSE); /* WIN32 API changed, incorporate new prio-level! */
+
+ /* release-version behaves friendly */
+ Priority= osl_Thread_PriorityUnknown;
+ }
+
+ return Priority;
+}
+
+/*****************************************************************************/
+/* osl_isThreadRunning */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments ?*/
+ if(pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ return sal_False;
+ }
+
+ return (sal_Bool)(WaitForSingleObject(pThreadImpl->m_hThread, 0) != WAIT_OBJECT_0);
+}
+
+/*****************************************************************************/
+/* osl_joinWithThread */
+/*****************************************************************************/
+void SAL_CALL osl_joinWithThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments?*/
+ if(pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ /* assume thread is not running */
+ return;
+ }
+
+ WaitForSingleObject(pThreadImpl->m_hThread, INFINITE);
+}
+
+/*****************************************************************************/
+/* osl_waitThread */
+/*****************************************************************************/
+void SAL_CALL osl_waitThread(const TimeValue* pDelay)
+{
+ if (pDelay)
+ {
+ DWORD millisecs = pDelay->Seconds * 1000L + pDelay->Nanosec / 1000000L;
+
+ Sleep(millisecs);
+ }
+}
+
+/*****************************************************************************/
+/* osl_terminateThread */
+/*****************************************************************************/
+void SAL_CALL osl_terminateThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments?*/
+ if (pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ /* assume thread is not running */
+ return;
+ }
+
+ osl_incrementInterlockedCount(&(pThreadImpl->m_nTerminationRequested));
+}
+
+
+/*****************************************************************************/
+/* osl_scheduleThread */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ osl_yieldThread();
+
+ /* invalid arguments?*/
+ if (pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ /* assume thread is not running */
+ return sal_False;
+ }
+
+ return (sal_Bool)(0 == pThreadImpl->m_nTerminationRequested);
+}
+
+/*****************************************************************************/
+/* osl_yieldThread */
+/*****************************************************************************/
+void SAL_CALL osl_yieldThread(void)
+{
+ Sleep(0);
+}
+
+typedef struct _TLS
+{
+ DWORD dwIndex;
+ oslThreadKeyCallbackFunction pfnCallback;
+ struct _TLS *pNext, *pPrev;
+} TLS, *PTLS;
+
+static PTLS g_pThreadKeyList = NULL;
+CRITICAL_SECTION g_ThreadKeyListCS;
+
+static void AddKeyToList( PTLS pTls )
+{
+ if ( pTls )
+ {
+ EnterCriticalSection( &g_ThreadKeyListCS );
+
+ pTls->pNext = g_pThreadKeyList;
+ pTls->pPrev = 0;
+
+ if ( g_pThreadKeyList )
+ g_pThreadKeyList->pPrev = pTls;
+
+ g_pThreadKeyList = pTls;
+
+ LeaveCriticalSection( &g_ThreadKeyListCS );
+ }
+}
+
+static void RemoveKeyFromList( PTLS pTls )
+{
+ if ( pTls )
+ {
+ EnterCriticalSection( &g_ThreadKeyListCS );
+ if ( pTls->pPrev )
+ pTls->pPrev->pNext = pTls->pNext;
+ else
+ {
+ OSL_ASSERT( pTls == g_pThreadKeyList );
+ g_pThreadKeyList = pTls->pNext;
+ }
+
+ if ( pTls->pNext )
+ pTls->pNext->pPrev = pTls->pPrev;
+ LeaveCriticalSection( &g_ThreadKeyListCS );
+ }
+}
+
+void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void)
+{
+ PTLS pTls;
+
+
+ EnterCriticalSection( &g_ThreadKeyListCS );
+ pTls = g_pThreadKeyList;
+ while ( pTls )
+ {
+ if ( pTls->pfnCallback )
+ {
+ void *pValue = TlsGetValue( pTls->dwIndex );
+
+ if ( pValue )
+ pTls->pfnCallback( pValue );
+ }
+
+ pTls = pTls->pNext;
+ }
+ LeaveCriticalSection( &g_ThreadKeyListCS );
+}
+
+/*****************************************************************************/
+/* osl_createThreadKey */
+/*****************************************************************************/
+oslThreadKey SAL_CALL osl_createThreadKey(oslThreadKeyCallbackFunction pCallback)
+{
+ PTLS pTls = rtl_allocateMemory( sizeof(TLS) );
+
+ if ( pTls )
+ {
+ pTls->pfnCallback = pCallback;
+ if ( (DWORD)-1 == (pTls->dwIndex = TlsAlloc()) )
+ {
+ rtl_freeMemory( pTls );
+ pTls = 0;
+ }
+ else
+ AddKeyToList( pTls );
+ }
+
+ return ((oslThreadKey)pTls);
+}
+
+/*****************************************************************************/
+/* osl_destroyThreadKey */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+
+ RemoveKeyFromList( pTls );
+ TlsFree( pTls->dwIndex );
+ rtl_freeMemory( pTls );
+ }
+}
+
+/*****************************************************************************/
+/* osl_getThreadKeyData */
+/*****************************************************************************/
+void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+
+ return (TlsGetValue( pTls->dwIndex ));
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_setThreadKeyData */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+ void* pOldData = NULL;
+ BOOL fSuccess;
+
+ if ( pTls->pfnCallback )
+ pOldData = TlsGetValue( pTls->dwIndex );
+
+ fSuccess = TlsSetValue( pTls->dwIndex, pData );
+
+ if ( fSuccess && pTls->pfnCallback && pOldData )
+ pTls->pfnCallback( pOldData );
+
+ return (sal_Bool)(fSuccess != FALSE);
+ }
+
+ return (sal_False);
+}
+
+
+/*****************************************************************************/
+/* osl_getThreadTextEncoding */
+/*****************************************************************************/
+
+DWORD g_dwTLSTextEncodingIndex = (DWORD)-1;
+
+
+rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding(void)
+{
+ DWORD dwEncoding;
+ rtl_TextEncoding _encoding;
+ BOOL gotACP;
+
+ if ( (DWORD)-1 == g_dwTLSTextEncodingIndex )
+ g_dwTLSTextEncodingIndex = TlsAlloc();
+
+ dwEncoding = (DWORD)TlsGetValue( g_dwTLSTextEncodingIndex );
+ _encoding = LOWORD(dwEncoding);
+ gotACP = HIWORD(dwEncoding);
+
+
+ if ( !gotACP )
+ {
+ char *pszEncoding;
+
+ if ( NULL != (pszEncoding = getenv( "SOLAR_USER_RTL_TEXTENCODING" )) )
+ _encoding = (rtl_TextEncoding)atoi(pszEncoding);
+ else
+ _encoding = rtl_getTextEncodingFromWindowsCodePage( GetACP() );
+
+ TlsSetValue( g_dwTLSTextEncodingIndex, (LPVOID)MAKELONG( _encoding, TRUE ) );
+ }
+
+ return _encoding;
+}
+
+/*****************************************************************************/
+/* osl_getThreadTextEncoding */
+/*****************************************************************************/
+rtl_TextEncoding SAL_CALL osl_setThreadTextEncoding( rtl_TextEncoding Encoding )
+{
+ rtl_TextEncoding oldEncoding = osl_getThreadTextEncoding();
+
+ TlsSetValue( g_dwTLSTextEncodingIndex, (LPVOID)MAKELONG( Encoding, TRUE) );
+
+ return oldEncoding;
+}
+
+
+
diff --git a/sal/osl/w32/time.c b/sal/osl/w32/time.c
new file mode 100644
index 000000000000..a4d0b6fffbad
--- /dev/null
+++ b/sal/osl/w32/time.c
@@ -0,0 +1,216 @@
+/*************************************************************************
+ *
+ * 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 "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/time.h>
+#include <sys/timeb.h>
+
+extern sal_Bool TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime);
+
+extern BOOL FileTimeToTimeValue( const FILETIME *cpFTime, TimeValue *pTimeVal );
+
+//--------------------------------------------------
+// osl_getSystemTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getSystemTime(TimeValue* pTimeVal)
+{
+ SYSTEMTIME SystemTime;
+ FILETIME CurTime, OffTime;
+ __int64 Value;
+
+ OSL_ASSERT(pTimeVal != 0);
+
+ GetSystemTime(&SystemTime);
+ SystemTimeToFileTime(&SystemTime, &CurTime);
+
+ SystemTime.wYear = 1970;
+ SystemTime.wMonth = 1;
+ SystemTime.wDayOfWeek = 0;
+ SystemTime.wDay = 1;
+ SystemTime.wHour = 0;
+ SystemTime.wMinute = 0;
+ SystemTime.wSecond = 0;
+ SystemTime.wMilliseconds = 0;
+
+ SystemTimeToFileTime(&SystemTime, &OffTime);
+
+ Value = *((__int64 *)&CurTime) - *((__int64 *)&OffTime);
+
+ pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
+ pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
+
+ return (sal_True);
+}
+
+//--------------------------------------------------
+// osl_getDateTimeFromTimeValue
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getDateTimeFromTimeValue( TimeValue* pTimeVal, oslDateTime* pDateTime )
+{
+ FILETIME aFileTime;
+ SYSTEMTIME aSystemTime;
+
+ if ( TimeValueToFileTime(pTimeVal, &aFileTime) )
+ {
+ if ( FileTimeToSystemTime( &aFileTime, &aSystemTime ) )
+ {
+ pDateTime->NanoSeconds = pTimeVal->Nanosec;
+
+ pDateTime->Seconds = aSystemTime.wSecond;
+ pDateTime->Minutes = aSystemTime.wMinute;
+ pDateTime->Hours = aSystemTime.wHour;
+ pDateTime->Day = aSystemTime.wDay;
+ pDateTime->DayOfWeek = aSystemTime.wDayOfWeek;
+ pDateTime->Month = aSystemTime.wMonth;
+ pDateTime->Year = aSystemTime.wYear;
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//--------------------------------------------------
+// osl_getTimeValueFromDateTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getTimeValueFromDateTime( oslDateTime* pDateTime, TimeValue* pTimeVal )
+{
+ FILETIME aFileTime;
+ SYSTEMTIME aSystemTime;
+
+ aSystemTime.wMilliseconds = 0;
+ aSystemTime.wSecond = pDateTime->Seconds;
+ aSystemTime.wMinute = pDateTime->Minutes;
+ aSystemTime.wHour = pDateTime->Hours;
+ aSystemTime.wDay = pDateTime->Day;
+ aSystemTime.wDayOfWeek = pDateTime->DayOfWeek;
+ aSystemTime.wMonth = pDateTime->Month;
+ aSystemTime.wYear = pDateTime->Year;
+
+ if ( SystemTimeToFileTime( &aSystemTime, &aFileTime ) )
+ {
+ if (FileTimeToTimeValue( &aFileTime, pTimeVal ) )
+ {
+ pTimeVal->Nanosec = pDateTime->NanoSeconds;
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+//--------------------------------------------------
+// osl_getLocalTimeFromSystemTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getLocalTimeFromSystemTime( TimeValue* pSystemTimeVal, TimeValue* pLocalTimeVal )
+{
+ TIME_ZONE_INFORMATION aTimeZoneInformation;
+ DWORD Success;
+ sal_Int64 bias;
+
+ // get timezone information
+ if ( ( Success=GetTimeZoneInformation( &aTimeZoneInformation ) ) != TIME_ZONE_ID_INVALID)
+ {
+ bias=aTimeZoneInformation.Bias;
+
+ // add bias for daylight saving time
+ if ( Success== TIME_ZONE_ID_DAYLIGHT )
+ bias+=aTimeZoneInformation.DaylightBias;
+
+ if ( (sal_Int64) pSystemTimeVal->Seconds > ( bias * 60 ) )
+ {
+ pLocalTimeVal->Seconds = (sal_uInt32) (pSystemTimeVal->Seconds - ( bias * 60) );
+ pLocalTimeVal->Nanosec = pSystemTimeVal->Nanosec;
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//--------------------------------------------------
+// osl_getSystemTimeFromLocalTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime( TimeValue* pLocalTimeVal, TimeValue* pSystemTimeVal )
+{
+ TIME_ZONE_INFORMATION aTimeZoneInformation;
+ DWORD Success;
+ sal_Int64 bias;
+
+ // get timezone information
+ if ( ( Success=GetTimeZoneInformation( &aTimeZoneInformation ) ) != TIME_ZONE_ID_INVALID)
+ {
+ bias=aTimeZoneInformation.Bias;
+
+ // add bias for daylight saving time
+ if ( Success== TIME_ZONE_ID_DAYLIGHT )
+ bias+=aTimeZoneInformation.DaylightBias;
+
+ if ( (sal_Int64) pLocalTimeVal->Seconds + ( bias * 60 ) > 0 )
+ {
+ pSystemTimeVal->Seconds = (sal_uInt32) ( pLocalTimeVal->Seconds + ( bias * 60) );
+ pSystemTimeVal->Nanosec = pLocalTimeVal->Nanosec;
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+static struct _timeb startTime;
+static sal_Bool bGlobalTimer = sal_False;
+
+sal_uInt32 SAL_CALL osl_getGlobalTimer(void)
+{
+ struct _timeb currentTime;
+ sal_uInt32 nSeconds;
+
+ if ( bGlobalTimer == sal_False )
+ {
+ _ftime( &startTime );
+ bGlobalTimer=sal_True;
+ }
+
+ _ftime( &currentTime );
+
+ nSeconds = (sal_uInt32)( currentTime.time - startTime.time );
+
+ return ( nSeconds * 1000 ) + (long)( currentTime.millitm - startTime.millitm );
+}
+
diff --git a/sal/osl/w32/util.c b/sal/osl/w32/util.c
new file mode 100644
index 000000000000..f4d8cbf52d20
--- /dev/null
+++ b/sal/osl/w32/util.c
@@ -0,0 +1,37 @@
+/*************************************************************************
+ *
+ * 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 "osl/util.h"
+
+
+
+extern sal_Bool SAL_CALL osl_getEthernetAddress( sal_uInt8 *pAddr )
+{
+ pAddr = pAddr; /* avoid warnings */
+ return sal_False;
+}
+