| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_fpicker.hxx" |
| |
| //------------------------------------------------------------------------ |
| // includes |
| //------------------------------------------------------------------------ |
| |
| #include <stdio.h> |
| #include <osl/diagnose.h> |
| #include "getfilenamewrapper.hxx" |
| |
| #if defined _MSC_VER |
| #pragma warning(push, 1) |
| #endif |
| #include <objbase.h> |
| #include <process.h> |
| #if defined _MSC_VER |
| #pragma warning(pop) |
| #endif |
| |
| namespace /* private */ |
| { |
| |
| //----------------------------------------------- |
| // This class prevents changing of the working |
| // directory. |
| //----------------------------------------------- |
| class CurDirGuard |
| { |
| sal_Bool m_bValid; |
| wchar_t* m_pBuffer; |
| DWORD m_nBufLen; |
| |
| public: |
| CurDirGuard() |
| : m_bValid( sal_False ) |
| , m_pBuffer( NULL ) |
| , m_nBufLen( 0 ) |
| { |
| m_nBufLen = GetCurrentDirectoryW( 0, NULL ); |
| if ( m_nBufLen ) |
| { |
| m_pBuffer = new wchar_t[m_nBufLen]; |
| m_bValid = ( GetCurrentDirectoryW( m_nBufLen, m_pBuffer ) == ( m_nBufLen - 1 ) ); |
| } |
| } |
| |
| ~CurDirGuard() |
| { |
| bool bDirSet = false; |
| |
| if ( m_pBuffer ) |
| { |
| if ( m_bValid ) |
| { |
| if ( m_nBufLen - 1 > MAX_PATH ) |
| { |
| if ( (LONG32)GetVersion() < 0 ) |
| { |
| // this is Win 98/ME branch, such a long path can not be set |
| // use the system path as fallback later |
| } |
| else |
| { |
| DWORD nNewLen = m_nBufLen + 8; |
| wchar_t* pNewBuffer = new wchar_t[nNewLen]; |
| if ( m_nBufLen > 3 && m_pBuffer[0] == (wchar_t)'\\' && m_pBuffer[1] == (wchar_t)'\\' ) |
| { |
| if ( m_pBuffer[2] == (wchar_t)'?' ) |
| _snwprintf( pNewBuffer, nNewLen, L"%s", m_pBuffer ); |
| else |
| _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\UNC\\%s", m_pBuffer+2 ); |
| } |
| else |
| _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\%s", m_pBuffer ); |
| bDirSet = SetCurrentDirectoryW( pNewBuffer ); |
| |
| delete [] pNewBuffer; |
| } |
| } |
| else |
| bDirSet = SetCurrentDirectoryW( m_pBuffer ); |
| } |
| |
| delete [] m_pBuffer; |
| m_pBuffer = NULL; |
| } |
| |
| if ( !bDirSet ) |
| { |
| // the fallback solution |
| wchar_t pPath[MAX_PATH+1]; |
| if ( GetWindowsDirectoryW( pPath, MAX_PATH+1 ) <= MAX_PATH ) |
| { |
| SetCurrentDirectoryW( pPath ); |
| } |
| else |
| { |
| // the system path is also too long?!! |
| } |
| } |
| } |
| }; |
| |
| //----------------------------------------------- |
| // |
| //----------------------------------------------- |
| |
| struct GetFileNameParam |
| { |
| GetFileNameParam(bool bOpen, LPOPENFILENAME lpofn) : |
| m_bOpen(bOpen), |
| m_lpofn(lpofn), |
| m_bRet(false), |
| m_ExtErr(0) |
| {} |
| |
| bool m_bOpen; |
| LPOPENFILENAME m_lpofn; |
| bool m_bRet; |
| int m_ExtErr; |
| }; |
| |
| //----------------------------------------------- |
| // |
| //----------------------------------------------- |
| |
| unsigned __stdcall ThreadProc(void* pParam) |
| { |
| CurDirGuard aGuard; |
| |
| GetFileNameParam* lpgfnp = |
| reinterpret_cast<GetFileNameParam*>(pParam); |
| |
| HRESULT hr = OleInitialize( NULL ); |
| |
| if (lpgfnp->m_bOpen) |
| lpgfnp->m_bRet = GetOpenFileName(lpgfnp->m_lpofn); |
| else |
| lpgfnp->m_bRet = GetSaveFileName(lpgfnp->m_lpofn); |
| |
| lpgfnp->m_ExtErr = CommDlgExtendedError(); |
| |
| if ( SUCCEEDED( hr ) ) |
| OleUninitialize(); |
| |
| return 0; |
| } |
| |
| //----------------------------------------------- |
| // exceutes GetOpenFileName/GetSaveFileName in |
| // a separat thread |
| //----------------------------------------------- |
| |
| bool ThreadExecGetFileName(LPOPENFILENAME lpofn, bool bOpen, /*out*/ int& ExtErr) |
| { |
| GetFileNameParam gfnp(bOpen,lpofn); |
| unsigned id; |
| |
| HANDLE hThread = reinterpret_cast<HANDLE>( |
| _beginthreadex(0, 0, ThreadProc, &gfnp, 0, &id)); |
| |
| OSL_POSTCOND(hThread, "could not create STA thread"); |
| |
| WaitForSingleObject(hThread, INFINITE); |
| CloseHandle(hThread); |
| |
| ExtErr = gfnp.m_ExtErr; |
| |
| return gfnp.m_bRet; |
| } |
| |
| //----------------------------------------------- |
| // This function returns true if the calling |
| // thread belongs to a Multithreaded Appartment |
| // (MTA) |
| //----------------------------------------------- |
| |
| bool IsMTA() |
| { |
| HRESULT hr = CoInitialize(NULL); |
| |
| if (RPC_E_CHANGED_MODE == hr) |
| return true; |
| |
| if(SUCCEEDED(hr)) |
| CoUninitialize(); |
| |
| return false; |
| } |
| |
| } // namespace private |
| |
| |
| //----------------------------------------------- |
| // |
| //----------------------------------------------- |
| |
| CGetFileNameWrapper::CGetFileNameWrapper() : |
| m_ExtendedDialogError(0) |
| { |
| } |
| |
| //----------------------------------------------- |
| // |
| //----------------------------------------------- |
| |
| bool CGetFileNameWrapper::getOpenFileName(LPOPENFILENAME lpofn) |
| { |
| OSL_PRECOND(lpofn,"invalid parameter"); |
| |
| bool bRet = false; |
| |
| if (IsMTA()) |
| { |
| bRet = ThreadExecGetFileName( |
| lpofn, true, m_ExtendedDialogError); |
| } |
| else |
| { |
| CurDirGuard aGuard; |
| |
| HRESULT hr = OleInitialize( NULL ); |
| |
| bRet = GetOpenFileName(lpofn); |
| m_ExtendedDialogError = CommDlgExtendedError(); |
| |
| if ( SUCCEEDED( hr ) ) |
| OleUninitialize(); |
| } |
| |
| return bRet; |
| } |
| |
| //----------------------------------------------- |
| // |
| //----------------------------------------------- |
| |
| bool CGetFileNameWrapper::getSaveFileName(LPOPENFILENAME lpofn) |
| { |
| OSL_PRECOND(lpofn,"invalid parameter"); |
| |
| bool bRet = false; |
| |
| if (IsMTA()) |
| { |
| bRet = ThreadExecGetFileName( |
| lpofn, false, m_ExtendedDialogError); |
| } |
| else |
| { |
| CurDirGuard aGuard; |
| |
| bRet = GetSaveFileName(lpofn); |
| m_ExtendedDialogError = CommDlgExtendedError(); |
| } |
| |
| return bRet; |
| } |
| |
| //----------------------------------------------- |
| // |
| //----------------------------------------------- |
| |
| int CGetFileNameWrapper::commDlgExtendedError( ) |
| { |
| return m_ExtendedDialogError; |
| } |
| |