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