xref: /trunk/main/fpicker/source/win32/filepicker/getfilenamewrapper.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
30 
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
34 
35 #include <stdio.h>
36 #include <osl/diagnose.h>
37 #include "getfilenamewrapper.hxx"
38 
39 #if defined _MSC_VER
40 #pragma warning(push, 1)
41 #endif
42 #include <objbase.h>
43 #include <process.h>
44 #if defined _MSC_VER
45 #pragma warning(pop)
46 #endif
47 
48 namespace /* private */
49 {
50 
51     //-----------------------------------------------
52     // This class prevents changing of the working
53     // directory.
54     //-----------------------------------------------
55     class CurDirGuard
56     {
57         sal_Bool m_bValid;
58         wchar_t* m_pBuffer;
59         DWORD m_nBufLen;
60 
61     public:
62         CurDirGuard()
63         : m_bValid( sal_False )
64         , m_pBuffer( NULL )
65         , m_nBufLen( 0 )
66         {
67             m_nBufLen = GetCurrentDirectoryW( 0, NULL );
68             if ( m_nBufLen )
69             {
70                 m_pBuffer = new wchar_t[m_nBufLen];
71                 m_bValid = ( GetCurrentDirectoryW( m_nBufLen, m_pBuffer ) == ( m_nBufLen - 1 ) );
72             }
73         }
74 
75         ~CurDirGuard()
76         {
77             bool bDirSet = false;
78 
79             if ( m_pBuffer )
80             {
81                 if ( m_bValid )
82                 {
83                     if ( m_nBufLen - 1 > MAX_PATH )
84                     {
85                         if ( (LONG32)GetVersion() < 0 )
86                         {
87                             // this is Win 98/ME branch, such a long path can not be set
88                             // use the system path as fallback later
89                         }
90                         else
91                         {
92                             DWORD nNewLen = m_nBufLen + 8;
93                             wchar_t* pNewBuffer = new wchar_t[nNewLen];
94                             if ( m_nBufLen > 3 && m_pBuffer[0] == (wchar_t)'\\' && m_pBuffer[1] == (wchar_t)'\\' )
95                             {
96                                 if ( m_pBuffer[2] == (wchar_t)'?' )
97                                     _snwprintf( pNewBuffer, nNewLen, L"%s", m_pBuffer );
98                                 else
99                                     _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\UNC\\%s", m_pBuffer+2 );
100                             }
101                             else
102                                 _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\%s", m_pBuffer );
103                             bDirSet = SetCurrentDirectoryW( pNewBuffer );
104 
105                             delete [] pNewBuffer;
106                         }
107                     }
108                     else
109                         bDirSet = SetCurrentDirectoryW( m_pBuffer );
110                 }
111 
112                 delete [] m_pBuffer;
113                 m_pBuffer = NULL;
114             }
115 
116             if ( !bDirSet )
117             {
118                 // the fallback solution
119                 wchar_t pPath[MAX_PATH+1];
120                 if ( GetWindowsDirectoryW( pPath, MAX_PATH+1 ) <= MAX_PATH )
121                 {
122                     SetCurrentDirectoryW( pPath );
123                 }
124                 else
125                 {
126                     // the system path is also too long?!!
127                 }
128             }
129         }
130     };
131 
132     //-----------------------------------------------
133     //
134     //-----------------------------------------------
135 
136     struct GetFileNameParam
137     {
138         GetFileNameParam(bool bOpen, LPOPENFILENAME lpofn) :
139             m_bOpen(bOpen),
140             m_lpofn(lpofn),
141             m_bRet(false),
142             m_ExtErr(0)
143         {}
144 
145         bool            m_bOpen;
146         LPOPENFILENAME  m_lpofn;
147         bool            m_bRet;
148         int             m_ExtErr;
149     };
150 
151     //-----------------------------------------------
152     //
153     //-----------------------------------------------
154 
155     unsigned __stdcall ThreadProc(void* pParam)
156     {
157         CurDirGuard aGuard;
158 
159         GetFileNameParam* lpgfnp =
160             reinterpret_cast<GetFileNameParam*>(pParam);
161 
162         HRESULT hr = OleInitialize( NULL );
163 
164         if (lpgfnp->m_bOpen)
165             lpgfnp->m_bRet = GetOpenFileName(lpgfnp->m_lpofn);
166         else
167             lpgfnp->m_bRet = GetSaveFileName(lpgfnp->m_lpofn);
168 
169         lpgfnp->m_ExtErr = CommDlgExtendedError();
170 
171         if ( SUCCEEDED( hr ) )
172             OleUninitialize();
173 
174         return 0;
175     }
176 
177     //-----------------------------------------------
178     // exceutes GetOpenFileName/GetSaveFileName in
179     // a separat thread
180     //-----------------------------------------------
181 
182     bool ThreadExecGetFileName(LPOPENFILENAME lpofn, bool bOpen, /*out*/ int& ExtErr)
183     {
184         GetFileNameParam gfnp(bOpen,lpofn);
185         unsigned         id;
186 
187         HANDLE hThread = reinterpret_cast<HANDLE>(
188             _beginthreadex(0, 0, ThreadProc, &gfnp, 0, &id));
189 
190         OSL_POSTCOND(hThread, "could not create STA thread");
191 
192         WaitForSingleObject(hThread, INFINITE);
193         CloseHandle(hThread);
194 
195         ExtErr = gfnp.m_ExtErr;
196 
197         return gfnp.m_bRet;
198     }
199 
200     //-----------------------------------------------
201     // This function returns true if the calling
202     // thread belongs to a Multithreaded Appartment
203     // (MTA)
204     //-----------------------------------------------
205 
206     bool IsMTA()
207     {
208         HRESULT hr = CoInitialize(NULL);
209 
210         if (RPC_E_CHANGED_MODE == hr)
211             return true;
212 
213         if(SUCCEEDED(hr))
214             CoUninitialize();
215 
216         return false;
217     }
218 
219 } // namespace private
220 
221 
222 //-----------------------------------------------
223 //
224 //-----------------------------------------------
225 
226 CGetFileNameWrapper::CGetFileNameWrapper() :
227     m_ExtendedDialogError(0)
228 {
229 }
230 
231 //-----------------------------------------------
232 //
233 //-----------------------------------------------
234 
235 bool CGetFileNameWrapper::getOpenFileName(LPOPENFILENAME lpofn)
236 {
237     OSL_PRECOND(lpofn,"invalid parameter");
238 
239     bool bRet = false;
240 
241     if (IsMTA())
242     {
243         bRet = ThreadExecGetFileName(
244             lpofn, true, m_ExtendedDialogError);
245     }
246     else
247     {
248         CurDirGuard aGuard;
249 
250         HRESULT hr = OleInitialize( NULL );
251 
252         bRet = GetOpenFileName(lpofn);
253         m_ExtendedDialogError = CommDlgExtendedError();
254 
255         if ( SUCCEEDED( hr ) )
256             OleUninitialize();
257     }
258 
259     return bRet;
260 }
261 
262 //-----------------------------------------------
263 //
264 //-----------------------------------------------
265 
266 bool CGetFileNameWrapper::getSaveFileName(LPOPENFILENAME lpofn)
267 {
268     OSL_PRECOND(lpofn,"invalid parameter");
269 
270     bool bRet = false;
271 
272     if (IsMTA())
273     {
274         bRet = ThreadExecGetFileName(
275             lpofn, false, m_ExtendedDialogError);
276     }
277     else
278     {
279         CurDirGuard aGuard;
280 
281         bRet = GetSaveFileName(lpofn);
282         m_ExtendedDialogError = CommDlgExtendedError();
283     }
284 
285     return bRet;
286 }
287 
288 //-----------------------------------------------
289 //
290 //-----------------------------------------------
291 
292 int CGetFileNameWrapper::commDlgExtendedError( )
293 {
294     return m_ExtendedDialogError;
295 }
296 
297