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 //-----------------------------------------------------------------------------
29 // includes
30 //-----------------------------------------------------------------------------
31 
32 #include "VistaFilePickerImpl.hxx"
33 
34 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
35 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
36 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
37 #include <com/sun/star/beans/StringPair.hpp>
38 #include <comphelper/sequenceasvector.hxx>
39 #include <osl/file.hxx>
40 #include <osl/mutex.hxx>
41 #ifdef __MINGW32__
42 #include <limits.h>
43 #endif
44 #include "..\misc\WinImplHelper.hxx"
45 
46 #include <Shlguid.h>
47 
48  inline bool is_current_process_window(HWND hwnd)
49 {
50     DWORD pid;
51     GetWindowThreadProcessId(hwnd, &pid);
52     return (pid == GetCurrentProcessId());
53 }
54 
55 HWND choose_parent_window()
56 {
57     HWND hwnd_parent = GetForegroundWindow();
58     if (!is_current_process_window(hwnd_parent))
59        hwnd_parent = GetDesktopWindow();
60     return hwnd_parent;
61 }
62 
63 //-----------------------------------------------------------------------------
64 // namespace
65 //-----------------------------------------------------------------------------
66 
67 namespace fpicker{
68 namespace win32{
69 namespace vista{
70 
71 namespace css = ::com::sun::star;
72 
73 //-----------------------------------------------------------------------------
74 // types, const etcpp.
75 //-----------------------------------------------------------------------------
76 
77 
78 static const ::sal_Int16 INVALID_CONTROL_ID     = -1;
79 static const ::sal_Int16 INVALID_CONTROL_ACTION = -1;
80 
81 typedef ::comphelper::SequenceAsVector< ::rtl::OUString > TStringList;
82 
83 // Guids used for IFileDialog::SetClientGuid
84 static const GUID CLIENTID_FILEDIALOG_SIMPLE		= {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83};
85 static const GUID CLIENTID_FILEDIALOG_OPTIONS		= {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36};
86 static const GUID CLIENTID_FILESAVE					= {0x3B2E2261, 0x402D, 0x4049, 0xB0, 0xC0, 0x91, 0x13, 0xF8, 0x6E, 0x84, 0x7C};
87 static const GUID CLIENTID_FILESAVE_PASSWORD		= {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6};
88 static const GUID CLIENTID_FILESAVE_SELECTION		= {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE};
89 static const GUID CLIENTID_FILESAVE_TEMPLATE		= {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE};
90 static const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE	= {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C};
91 static const GUID CLIENTID_FILEOPEN_PLAY			= {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5};
92 static const GUID CLIENTID_FILEOPEN_LINK			= {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A};
93 
94 //-----------------------------------------------------------------------------
95 ::rtl::OUString lcl_getURLFromShellItem (IShellItem* pItem)
96 {
97     LPOLESTR pStr = NULL;
98 	::rtl::OUString sURL;
99 
100 	SIGDN   eConversion = SIGDN_FILESYSPATH;
101     HRESULT hr          = pItem->GetDisplayName ( eConversion, &pStr );
102 
103     if ( FAILED(hr) )
104 	{
105 		eConversion = SIGDN_URL;
106 		hr          = pItem->GetDisplayName ( eConversion, &pStr );
107 
108 		if ( FAILED(hr) )
109 			return ::rtl::OUString();
110 
111 		sURL = ::rtl::OUString(reinterpret_cast<sal_Unicode*>(pStr));
112 	}
113 	else
114 	{
115 		::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode*>(pStr), sURL );
116 	}
117 
118     CoTaskMemFree (pStr);
119     return sURL;
120 }
121 
122 //-----------------------------------------------------------------------------------------
123 ::std::vector< COMDLG_FILTERSPEC > lcl_buildFilterList(CFilterContainer& rContainer)
124 {
125     const sal_Int32                          c      = rContainer.numFilter();
126           sal_Int32                          i      = 0;
127           ::std::vector< COMDLG_FILTERSPEC > lList  ;
128           CFilterContainer::FILTER_ENTRY_T   aFilter;
129 
130     rContainer.beginEnumFilter( );
131 	while( rContainer.getNextFilter(aFilter) )
132     {
133         COMDLG_FILTERSPEC aSpec;
134 
135 		aSpec.pszName = reinterpret_cast<LPCTSTR>(aFilter.first.getStr()) ;
136 		aSpec.pszSpec = reinterpret_cast<LPCTSTR>(aFilter.second.getStr());
137 
138         lList.push_back(aSpec);
139     }
140 
141     return lList;
142 }
143 
144 //-----------------------------------------------------------------------------------------
145 VistaFilePickerImpl::VistaFilePickerImpl()
146     : m_iDialogOpen  ()
147     , m_iDialogSave  ()
148     , m_hLastResult  ()
149     , m_lFilters     ()
150     , m_lLastFiles   ()
151     , m_iEventHandler(new VistaFilePickerEventHandler(this))
152     , m_bInExecute   (sal_False)
153     , m_bWasExecuted (sal_False)
154 	, m_sDirectory   ()
155 	, m_sFilename    ()
156 {
157 	m_hParentWindow = choose_parent_window();
158 }
159 
160 //-------------------------------------------------------------------------------
161 VistaFilePickerImpl::~VistaFilePickerImpl()
162 {
163 }
164 
165 //-------------------------------------------------------------------------------
166 void VistaFilePickerImpl::before()
167 {
168     // SYNCHRONIZED->
169     ::osl::ResettableMutexGuard aLock(m_aMutex);
170 
171     // TRICKY .-)
172     // osl::Thread class initializes COm already in MTA mode because it's needed
173     // by VCL and UNO so. There is no way to change that from outside ...
174     // but we need a STA environment ...
175     // So we make it by try-and-error ...
176     // If first CoInitialize will fail .. we unitialize COM initialize it new .-)
177 
178     m_hLastResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
179     if ( FAILED(m_hLastResult) )
180     {
181         CoUninitialize();
182         m_hLastResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
183     }
184 }
185 
186 //-------------------------------------------------------------------------------
187 void VistaFilePickerImpl::doRequest(const RequestRef& rRequest)
188 {
189     try
190     {
191         switch(rRequest->getRequest())
192         {
193             case E_ADD_PICKER_LISTENER :
194                     impl_sta_addFilePickerListener(rRequest);
195                     break;
196 
197             case E_REMOVE_PICKER_LISTENER :
198                     impl_sta_removeFilePickerListener(rRequest);
199                     break;
200 
201             case E_APPEND_FILTER :
202                     impl_sta_appendFilter(rRequest);
203                     break;
204 
205 			case E_APPEND_FILTERGROUP :
206 					impl_sta_appendFilterGroup(rRequest);
207 					break;
208 
209 			case E_SET_CURRENT_FILTER :
210                     impl_sta_setCurrentFilter(rRequest);
211                     break;
212 
213             case E_GET_CURRENT_FILTER :
214                     impl_sta_getCurrentFilter(rRequest);
215                     break;
216 
217             case E_CREATE_OPEN_DIALOG :
218                     impl_sta_CreateOpenDialog(rRequest);
219                     break;
220 
221             case E_CREATE_SAVE_DIALOG :
222                     impl_sta_CreateSaveDialog(rRequest);
223                     break;
224 
225             case E_SET_MULTISELECTION_MODE :
226                     impl_sta_SetMultiSelectionMode(rRequest);
227                     break;
228 
229             case E_SET_TITLE :
230                     impl_sta_SetTitle(rRequest);
231                     break;
232 
233 			case E_SET_FILENAME:
234 				impl_sta_SetFileName(rRequest);
235 				break;
236 
237             case E_SET_DIRECTORY :
238                     impl_sta_SetDirectory(rRequest);
239                     break;
240 
241 			case E_GET_DIRECTORY :
242 					impl_sta_GetDirectory(rRequest);
243 					break;
244 
245 			case E_SET_DEFAULT_NAME :
246 					impl_sta_SetDefaultName(rRequest);
247 					break;
248 
249             case E_GET_SELECTED_FILES :
250                     impl_sta_getSelectedFiles(rRequest);
251                     break;
252 
253             case E_SHOW_DIALOG_MODAL :
254                     impl_sta_ShowDialogModal(rRequest);
255                     break;
256 
257             case E_SET_CONTROL_VALUE :
258                     impl_sta_SetControlValue(rRequest);
259                     break;
260 
261             case E_GET_CONTROL_VALUE :
262                     impl_sta_GetControlValue(rRequest);
263                     break;
264 
265             case E_SET_CONTROL_LABEL :
266                     impl_sta_SetControlLabel(rRequest);
267                     break;
268 
269             case E_GET_CONTROL_LABEL :
270                     impl_sta_GetControlLabel(rRequest);
271                     break;
272 
273             case E_ENABLE_CONTROL :
274                     impl_sta_EnableControl(rRequest);
275                     break;
276 
277             // no default: let the compiler detect changes on enum ERequest !
278         }
279     }
280     catch(...)
281     {}
282 }
283 
284 //-------------------------------------------------------------------------------
285 void VistaFilePickerImpl::after()
286 {
287     CoUninitialize();
288 }
289 
290 //-------------------------------------------------------------------------------
291 void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef& rRequest)
292 {
293     // SYNCHRONIZED outside !
294     const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
295     if ( ! xListener.is())
296         return;
297 
298     // SYNCHRONIZED->
299     ::osl::ResettableMutexGuard aLock(m_aMutex);
300     TFileDialogEvents iHandler = m_iEventHandler;
301     aLock.clear();
302     // <- SYNCHRONIZED
303 
304     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
305     if (pHandlerImpl)
306         pHandlerImpl->addFilePickerListener(xListener);
307 }
308 
309 //-------------------------------------------------------------------------------
310 void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef& rRequest)
311 {
312     // SYNCHRONIZED outside !
313     const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
314     if ( ! xListener.is())
315         return;
316 
317     // SYNCHRONIZED->
318     ::osl::ResettableMutexGuard aLock(m_aMutex);
319     TFileDialogEvents iHandler = m_iEventHandler;
320     aLock.clear();
321     // <- SYNCHRONIZED
322 
323     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
324     if (pHandlerImpl)
325         pHandlerImpl->removeFilePickerListener(xListener);
326 }
327 
328 //-------------------------------------------------------------------------------
329 void VistaFilePickerImpl::impl_sta_appendFilter(const RequestRef& rRequest)
330 {
331     const ::rtl::OUString sTitle  = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, ::rtl::OUString());
332     const ::rtl::OUString sFilter = rRequest->getArgumentOrDefault(PROP_FILTER_VALUE, ::rtl::OUString());
333 
334     // SYNCHRONIZED->
335     ::osl::ResettableMutexGuard aLock(m_aMutex);
336 
337     m_lFilters.addFilter(sTitle, sFilter);
338 }
339 
340 //-------------------------------------------------------------------------------
341 void VistaFilePickerImpl::impl_sta_appendFilterGroup(const RequestRef& rRequest)
342 {
343 	const css::uno::Sequence< css::beans::StringPair > aFilterGroup  =
344 		rRequest->getArgumentOrDefault(PROP_FILTER_GROUP, css::uno::Sequence< css::beans::StringPair >());
345 
346     // SYNCHRONIZED->
347 	::rtl::OUString aEmpty;
348     ::osl::ResettableMutexGuard aLock(m_aMutex);
349 
350     if ( m_lFilters.numFilter() > 0 && aFilterGroup.getLength() > 0 )
351 		m_lFilters.addFilter( STRING_SEPARATOR, aEmpty, sal_True );
352 
353 	::sal_Int32 c = aFilterGroup.getLength();
354     ::sal_Int32 i = 0;
355     for (i=0; i<c; ++i)
356     {
357         const css::beans::StringPair& rFilter = aFilterGroup[i];
358         m_lFilters.addFilter(rFilter.First, rFilter.Second);
359     }
360 }
361 
362 //-------------------------------------------------------------------------------
363 void VistaFilePickerImpl::impl_sta_setCurrentFilter(const RequestRef& rRequest)
364 {
365     const ::rtl::OUString sTitle  = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, ::rtl::OUString());
366 
367     // SYNCHRONIZED->
368     ::osl::ResettableMutexGuard aLock(m_aMutex);
369 
370     m_lFilters.setCurrentFilter(sTitle);
371 }
372 
373 //-------------------------------------------------------------------------------
374 void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef& rRequest)
375 {
376     TFileDialog iDialog = impl_getBaseDialogInterface();
377     UINT        nIndex  = UINT_MAX;
378     HRESULT     hResult = iDialog->GetFileTypeIndex(&nIndex);
379     if (
380         ( FAILED(hResult)    ) ||
381         ( nIndex == UINT_MAX )      // COM dialog sometimes return S_OK for empty filter lists .-(
382        )
383         return;
384 
385     // SYNCHRONIZED->
386     ::osl::ResettableMutexGuard aLock(m_aMutex);
387 
388     ::rtl::OUString sTitle;
389     ::sal_Int32     nRealIndex = (nIndex-1); // COM dialog base on 1 ... filter container on 0 .-)
390     if (
391         (nRealIndex >= 0                         ) &&
392         (m_lFilters.getFilter(nRealIndex, sTitle))
393        )
394         rRequest->setArgument(PROP_FILTER_TITLE, sTitle);
395 	else if ( nRealIndex == -1 ) // Dialog not visible yet
396 	{
397 		sTitle = m_lFilters.getCurrentFilter();
398         rRequest->setArgument(PROP_FILTER_TITLE, sTitle);
399 	}
400 
401     aLock.clear();
402     // <- SYNCHRONIZED
403 }
404 
405 //-------------------------------------------------------------------------------
406 void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef& rRequest)
407 {
408     // SYNCHRONIZED->
409     ::osl::ResettableMutexGuard aLock(m_aMutex);
410 
411     m_hLastResult = m_iDialogOpen.create();
412     if (FAILED(m_hLastResult))
413         return;
414 
415     TFileDialog iDialog;
416 #ifdef __MINGW32__
417     m_iDialogOpen->QueryInterface(IID_IFileDialog, (void **)(&iDialog));
418 #else
419     m_iDialogOpen.query(&iDialog);
420 #endif
421 
422     TFileDialogEvents iHandler = m_iEventHandler;
423 
424     aLock.clear();
425     // <- SYNCHRONIZED
426 
427 	DWORD nFlags = 0;
428     iDialog->GetOptions ( &nFlags );
429 
430     nFlags &= ~FOS_FORCESHOWHIDDEN;
431     nFlags |=  FOS_PATHMUSTEXIST;
432     nFlags |=  FOS_FILEMUSTEXIST;
433     nFlags |=  FOS_OVERWRITEPROMPT;
434     nFlags |=  FOS_DONTADDTORECENT;
435 
436     iDialog->SetOptions ( nFlags );
437 
438     ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, (::sal_Int32)0);
439 	::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, (::sal_Int32)0);
440     impl_sta_enableFeatures(nFeatures, nTemplate);
441 
442     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
443     if (pHandlerImpl)
444         pHandlerImpl->startListening(iDialog);
445 }
446 
447 //-------------------------------------------------------------------------------
448 void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef& rRequest)
449 {
450     // SYNCHRONIZED->
451     ::osl::ResettableMutexGuard aLock(m_aMutex);
452 
453     m_hLastResult = m_iDialogSave.create();
454     if (FAILED(m_hLastResult))
455         return;
456 
457     TFileDialogEvents  iHandler = m_iEventHandler;
458     TFileDialog        iDialog;
459 #ifdef __MINGW32__
460     m_iDialogSave->QueryInterface(IID_IFileDialog, (void **)(&iDialog));
461 #else
462     m_iDialogSave.query(&iDialog);
463 #endif
464 
465     aLock.clear();
466     // <- SYNCHRONIZED
467 
468 	DWORD nFlags = 0;
469     iDialog->GetOptions ( &nFlags );
470 
471     nFlags &= ~FOS_FORCESHOWHIDDEN;
472     nFlags |=  FOS_PATHMUSTEXIST;
473     nFlags |=  FOS_FILEMUSTEXIST;
474     nFlags |=  FOS_OVERWRITEPROMPT;
475     nFlags |=  FOS_DONTADDTORECENT;
476 
477     iDialog->SetOptions ( nFlags );
478 
479     ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, (::sal_Int32)0);
480 	::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, (::sal_Int32)0);
481     impl_sta_enableFeatures(nFeatures, nTemplate);
482 
483     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
484     if (pHandlerImpl)
485         pHandlerImpl->startListening(iDialog);
486 }
487 
488 //-------------------------------------------------------------------------------
489 static const ::sal_Int32 GROUP_VERSION         =   1;
490 static const ::sal_Int32 GROUP_TEMPLATE        =   2;
491 static const ::sal_Int32 GROUP_IMAGETEMPLATE   =   3;
492 static const ::sal_Int32 GROUP_CHECKBOXES      =   4;
493 
494 //-------------------------------------------------------------------------------
495 static void setLabelToControl(CResourceProvider& rResourceProvider, TFileDialogCustomize iCustom, sal_uInt16 nControlId)
496 {
497     ::rtl::OUString aLabel = rResourceProvider.getResString(nControlId);
498     aLabel = SOfficeToWindowsLabel(aLabel);
499     iCustom->SetControlLabel(nControlId, reinterpret_cast<LPCWSTR>(aLabel.getStr()) );
500 }
501 
502 //-------------------------------------------------------------------------------
503 void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate)
504 {
505 	GUID aGUID = {};
506 	switch (nTemplate)
507 	{
508         case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE :
509         case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE :
510 			aGUID = CLIENTID_FILEDIALOG_SIMPLE;
511 			break;
512 
513 		case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION :
514         case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS :
515 			aGUID = CLIENTID_FILEDIALOG_OPTIONS;
516 			break;
517 
518 		case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION :
519 			aGUID = CLIENTID_FILESAVE;
520 			break;
521 
522 		case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD :
523 			aGUID = CLIENTID_FILESAVE_PASSWORD;
524 			break;
525 
526         case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION :
527 			aGUID = CLIENTID_FILESAVE_SELECTION;
528 			break;
529 
530         case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE :
531 			aGUID = CLIENTID_FILESAVE_TEMPLATE;
532 			break;
533 
534         case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE :
535 			aGUID = CLIENTID_FILEOPEN_LINK_TEMPLATE;
536 			break;
537 
538         case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY :
539 			aGUID = CLIENTID_FILEOPEN_PLAY;
540 			break;
541 
542         case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW :
543 			aGUID = CLIENTID_FILEOPEN_LINK;
544 			break;
545     }
546 	TFileDialog iDialog = impl_getBaseDialogInterface();
547 	iDialog->SetClientGuid ( aGUID );
548 
549     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
550 
551     if ((nFeatures & FEATURE_VERSION) == FEATURE_VERSION)
552     {
553         iCustom->StartVisualGroup (GROUP_VERSION, L"Version");
554         iCustom->AddComboBox      (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION);
555         iCustom->EndVisualGroup   ();
556         iCustom->MakeProminent    (GROUP_VERSION);
557     }
558 
559     if ((nFeatures & FEATURE_TEMPLATE) == FEATURE_TEMPLATE)
560     {
561         iCustom->StartVisualGroup (GROUP_TEMPLATE, L"Template");
562         iCustom->AddComboBox      (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE);
563         iCustom->EndVisualGroup   ();
564         iCustom->MakeProminent    (GROUP_TEMPLATE);
565     }
566 
567     if ((nFeatures & FEATURE_IMAGETEMPLATE) == FEATURE_IMAGETEMPLATE)
568     {
569         iCustom->StartVisualGroup (GROUP_IMAGETEMPLATE, L"Style");
570         iCustom->AddComboBox      (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE);
571         iCustom->EndVisualGroup   ();
572         iCustom->MakeProminent    (GROUP_IMAGETEMPLATE);
573     }
574 
575 	iCustom->StartVisualGroup (GROUP_CHECKBOXES, L"");
576 
577     sal_uInt16 nControlId(0);
578     if ((nFeatures & FEATURE_AUTOEXTENSION) == FEATURE_AUTOEXTENSION)
579     {
580         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION;
581         iCustom->AddCheckButton (nControlId, L"Auto Extension", true);
582         setLabelToControl(m_ResProvider, iCustom, nControlId);
583     }
584 
585     if ((nFeatures & FEATURE_PASSWORD) == FEATURE_PASSWORD)
586     {
587         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD;
588         iCustom->AddCheckButton (nControlId, L"Password", false);
589         setLabelToControl(m_ResProvider, iCustom, nControlId);
590     }
591 
592     if ((nFeatures & FEATURE_READONLY) == FEATURE_READONLY)
593     {
594         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY;
595         iCustom->AddCheckButton (nControlId, L"Readonly", false);
596         setLabelToControl(m_ResProvider, iCustom, nControlId);
597     }
598 
599     if ((nFeatures & FEATURE_FILTEROPTIONS) == FEATURE_FILTEROPTIONS)
600     {
601         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS;
602         iCustom->AddCheckButton (nControlId, L"Filter Options", false);
603         setLabelToControl(m_ResProvider, iCustom, nControlId);
604     }
605 
606     if ((nFeatures & FEATURE_LINK) == FEATURE_LINK)
607     {
608         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK;
609         iCustom->AddCheckButton (nControlId, L"Link", false);
610         setLabelToControl(m_ResProvider, iCustom, nControlId);
611     }
612 
613     if ((nFeatures & FEATURE_SELECTION) == FEATURE_SELECTION)
614     {
615         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION;
616         iCustom->AddCheckButton (nControlId, L"Selection", false);
617         setLabelToControl(m_ResProvider, iCustom, nControlId);
618     }
619 
620     /* can be ignored ... new COM dialog supports preview native now  !
621     if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW)
622         iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false);
623     */
624 
625 	iCustom->EndVisualGroup();
626 
627     if ((nFeatures & FEATURE_PLAY) == FEATURE_PLAY)
628         iCustom->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY, L"Play");
629 
630 }
631 
632 //-------------------------------------------------------------------------------
633 void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef& rRequest)
634 {
635     const ::sal_Bool bMultiSelection = rRequest->getArgumentOrDefault(PROP_MULTISELECTION_MODE, (::sal_Bool)sal_True);
636 
637     // SYNCHRONIZED->
638     ::osl::ResettableMutexGuard aLock(m_aMutex);
639     TFileDialog iDialog = impl_getBaseDialogInterface();
640     aLock.clear();
641     // <- SYNCHRONIZED
642 
643 	DWORD nFlags = 0;
644     m_hLastResult = iDialog->GetOptions ( &nFlags );
645 
646     if (bMultiSelection)
647         nFlags |=  FOS_ALLOWMULTISELECT;
648     else
649         nFlags &= ~FOS_ALLOWMULTISELECT;
650 
651     iDialog->SetOptions ( nFlags );
652 }
653 
654 //-------------------------------------------------------------------------------
655 void VistaFilePickerImpl::impl_sta_SetTitle(const RequestRef& rRequest)
656 {
657     ::rtl::OUString sTitle = rRequest->getArgumentOrDefault(PROP_TITLE, ::rtl::OUString());
658 
659     // SYNCHRONIZED->
660     ::osl::ResettableMutexGuard aLock(m_aMutex);
661     TFileDialog iDialog = impl_getBaseDialogInterface();
662     aLock.clear();
663     // <- SYNCHRONIZED
664 
665     iDialog->SetTitle(reinterpret_cast<LPCTSTR>(sTitle.getStr()));
666 }
667 
668 //-------------------------------------------------------------------------------
669 void VistaFilePickerImpl::impl_sta_SetFileName(const RequestRef& rRequest)
670 {
671     ::rtl::OUString sFileName = rRequest->getArgumentOrDefault(PROP_FILENAME, ::rtl::OUString());
672 
673     // SYNCHRONIZED->
674     ::osl::ResettableMutexGuard aLock(m_aMutex);
675     TFileDialog iDialog = impl_getBaseDialogInterface();
676     aLock.clear();
677     // <- SYNCHRONIZED
678 
679     iDialog->SetFileName(reinterpret_cast<LPCTSTR>(sFileName.getStr()));
680 }
681 
682 //-------------------------------------------------------------------------------
683 void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef& rRequest)
684 {
685     ::rtl::OUString sDirectory = rRequest->getArgumentOrDefault(PROP_DIRECTORY, ::rtl::OUString());
686     bool            bForce     = rRequest->getArgumentOrDefault(PROP_FORCE, false);
687 
688 	if( !m_bInExecute)
689 	{
690 		// Vista stores last used folders for file dialogs
691 		// so we don't want the application to change the folder
692 		// in most cases.
693 		// Store the requested folder in the mean time and decide later
694 		// what to do
695 		m_sDirectory = sDirectory;
696 	}
697 
698     // SYNCHRONIZED->
699     ::osl::ResettableMutexGuard aLock(m_aMutex);
700     TFileDialog iDialog = impl_getBaseDialogInterface();
701     aLock.clear();
702     // <- SYNCHRONIZED
703 
704     ComPtr< IShellItem > pFolder;
705 #ifdef __MINGW32__
706     HRESULT hResult = SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR>(sDirectory.getStr()), NULL, IID_IShellItem, reinterpret_cast<void**>(&pFolder) );
707 #else
708     HRESULT hResult = SHCreateItemFromParsingName ( sDirectory, NULL, IID_PPV_ARGS(&pFolder) );
709 #endif
710     if ( FAILED(hResult) )
711         return;
712 
713     if ( m_bInExecute || bForce )
714         iDialog->SetFolder(pFolder);
715     else
716     {
717         // Use set default folder as Microsoft recommends in the IFileDialog documentation.
718         iDialog->SetDefaultFolder(pFolder);
719     }
720 }
721 
722 void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef& rRequest)
723 {
724     TFileDialog iDialog = impl_getBaseDialogInterface();
725     ComPtr< IShellItem > pFolder;
726 	HRESULT hResult = iDialog->GetFolder( &pFolder );
727 	if ( FAILED(hResult) )
728         return;
729 	::rtl::OUString sFolder = lcl_getURLFromShellItem ( pFolder );
730 	if( sFolder.getLength())
731 		rRequest->setArgument( PROP_DIRECTORY, sFolder );
732 }
733 
734 //-------------------------------------------------------------------------------
735 void VistaFilePickerImpl::impl_sta_SetDefaultName(const RequestRef& rRequest)
736 {
737 	::rtl::OUString sFilename = rRequest->getArgumentOrDefault(PROP_FILENAME, ::rtl::OUString());
738 	TFileDialog iDialog = impl_getBaseDialogInterface();
739 
740     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
741     if ( ! iCustom.is())
742         return;
743 
744     // if we have the autoextension check box set, remove (or change ???) the extension of the filename
745     // so that the autoextension mechanism can do its job
746     BOOL bValue = FALSE;
747     HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
748     if ( bValue )
749     {
750         sal_Int32 nSepPos = sFilename.lastIndexOf( '.' );
751         if ( -1 != nSepPos )
752             sFilename = sFilename.copy(0, nSepPos);
753     }
754 
755 	iDialog->SetFileName ( reinterpret_cast<LPCTSTR>(sFilename.getStr()));
756 	m_sFilename = sFilename;
757 }
758 
759 //-------------------------------------------------------------------------------
760 void VistaFilePickerImpl::impl_sta_setFiltersOnDialog()
761 {
762     // SYNCHRONIZED->
763     ::osl::ResettableMutexGuard aLock(m_aMutex);
764 
765     ::std::vector< COMDLG_FILTERSPEC > lFilters       = lcl_buildFilterList(m_lFilters);
766     ::rtl::OUString                    sCurrentFilter = m_lFilters.getCurrentFilter();
767     sal_Int32                          nCurrentFilter = m_lFilters.getFilterPos(sCurrentFilter);
768     TFileDialog                        iDialog        = impl_getBaseDialogInterface();
769 	TFileDialogCustomize               iCustomize     = impl_getCustomizeInterface();
770 
771     aLock.clear();
772     // <- SYNCHRONIZED
773 
774 	COMDLG_FILTERSPEC	*pFilt = &lFilters[0];
775     iDialog->SetFileTypes(lFilters.size(), pFilt/*&lFilters[0]*/);
776     iDialog->SetFileTypeIndex(nCurrentFilter + 1);
777 
778 	BOOL bValue = FALSE;
779 	HRESULT hResult = iCustomize->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
780 
781 	if ( bValue )
782 	{
783 		LPCWSTR lpFilterExt = lFilters[0].pszSpec;
784 
785 		lpFilterExt = wcsrchr( lpFilterExt, '.' );
786 		if ( lpFilterExt )
787 			lpFilterExt++;
788 		iDialog->SetDefaultExtension( lpFilterExt );
789 	}
790 
791 }
792 
793 //-------------------------------------------------------------------------------
794 void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef& rRequest)
795 {
796     // SYNCHRONIZED->
797     ::osl::ResettableMutexGuard aLock(m_aMutex);
798 
799     TFileOpenDialog iOpen      = m_iDialogOpen;
800     TFileSaveDialog iSave      = m_iDialogSave;
801     ::sal_Bool      bInExecute = m_bInExecute;
802 
803     aLock.clear();
804     // <- SYNCHRONIZED
805 
806     // ask dialog for results
807     // Note        : we must differ between single/multi selection !
808     // Note further: we must react different if dialog is in execute or not .-(
809     ComPtr< IShellItem >      iItem;
810     ComPtr< IShellItemArray > iItems;
811     HRESULT                   hResult = E_FAIL;
812 
813     if (iOpen.is())
814     {
815         if (bInExecute)
816             hResult = iOpen->GetSelectedItems(&iItems);
817         else
818         {
819             hResult = iOpen->GetResults(&iItems);
820             if (FAILED(hResult))
821                 hResult = iOpen->GetResult(&iItem);
822         }
823     }
824     else
825     if (iSave.is())
826     {
827         if (bInExecute)
828             hResult = iSave->GetCurrentSelection(&iItem);
829         else
830             hResult = iSave->GetResult(&iItem);
831     }
832 
833     if (FAILED(hResult))
834         return;
835 
836     // convert and pack results
837     TStringList lFiles;
838     if (iItem.is())
839     {
840         const ::rtl::OUString sURL = lcl_getURLFromShellItem(iItem);
841         if (sURL.getLength() > 0)
842             lFiles.push_back(sURL);
843     }
844 
845     if (iItems.is())
846     {
847         DWORD nCount;
848         hResult = iItems->GetCount(&nCount);
849         if ( SUCCEEDED(hResult) )
850         {
851             for (DWORD i=0; i<nCount; ++i)
852             {
853                 hResult = iItems->GetItemAt(i, &iItem);
854                 if ( SUCCEEDED(hResult) )
855                 {
856                     const ::rtl::OUString sURL = lcl_getURLFromShellItem(iItem);
857                     if (sURL.getLength() > 0)
858                         lFiles.push_back(sURL);
859                 }
860             }
861         }
862     }
863 
864     rRequest->setArgument(PROP_SELECTED_FILES, lFiles.getAsConstList());
865 }
866 
867 //-------------------------------------------------------------------------------
868 void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest)
869 {
870     impl_sta_setFiltersOnDialog();
871 
872     // SYNCHRONIZED->
873     ::osl::ResettableMutexGuard aLock(m_aMutex);
874 
875     TFileDialog iDialog = impl_getBaseDialogInterface();
876     TFileOpenDialog iOpen = m_iDialogOpen;
877     TFileSaveDialog iSave = m_iDialogSave;
878 
879 	// it's important to know if we are showing the dialog.
880     // Some dialog interface methods cant be called then or some
881     // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles())
882     m_bInExecute = sal_True;
883 
884     m_bWasExecuted = sal_True;
885 
886     aLock.clear();
887     // <- SYNCHRONIZED
888 
889 	// we set the directory only if we have a save dialog and a filename
890 	// for the other cases, the file dialog remembers its last location
891 	// according to its client guid.
892 	if( m_sDirectory.getLength())
893 	{
894 		ComPtr< IShellItem > pFolder;
895 		#ifdef __MINGW32__
896 			HRESULT hResult = SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR>(m_sDirectory.getStr()), NULL, IID_IShellItem, reinterpret_cast<void**>(&pFolder) );
897 		#else
898 			HRESULT hResult = SHCreateItemFromParsingName ( m_sDirectory, NULL, IID_PPV_ARGS(&pFolder) );
899 		#endif
900 		if ( SUCCEEDED(hResult) )
901         {
902 		    if (m_sFilename.getLength())
903             {
904                 ::rtl::OUString aFileURL(m_sDirectory);
905                 sal_Int32 nIndex = aFileURL.lastIndexOf('/');
906                 if (nIndex != aFileURL.getLength()-1)
907                     aFileURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/"));
908                 aFileURL += m_sFilename;
909 
910                 TFileDialogCustomize iCustom = impl_getCustomizeInterface();
911 
912                 BOOL bValue = FALSE;
913                 HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
914                 if ( bValue )
915                 {
916                     ::rtl::OUString aExt;
917                     UINT nFileType;
918                     hResult = iDialog->GetFileTypeIndex(&nFileType);
919 		            if ( SUCCEEDED(hResult) )
920                     {
921                         ::sal_Int32 nRealIndex = (nFileType-1); // COM dialog base on 1 ... filter container on 0 .-)
922                         ::std::vector< COMDLG_FILTERSPEC > lFilters = lcl_buildFilterList(m_lFilters);
923 		                LPCWSTR lpFilterExt = lFilters[nRealIndex].pszSpec;
924 
925 		                lpFilterExt = wcsrchr( lpFilterExt, '.' );
926 		                if ( lpFilterExt )
927                             aFileURL += reinterpret_cast<const sal_Unicode*>(lpFilterExt);
928                     }
929                 }
930 
931                 // Check existence of file. Set folder only for this special case
932                 ::rtl::OUString aSystemPath;
933                 osl_getSystemPathFromFileURL( aFileURL.pData, &aSystemPath.pData );
934 
935 			    WIN32_FIND_DATA	aFindFileData;
936                 HANDLE	hFind = FindFirstFile( reinterpret_cast<LPCWSTR>(aSystemPath.getStr()), &aFindFileData );
937                 if (hFind != INVALID_HANDLE_VALUE)
938                     iDialog->SetFolder(pFolder);
939                 else
940                     hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
941 
942                 FindClose( hFind );
943             }
944 			else
945 				hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
946 		}
947 	}
948 
949 
950     HRESULT hResult = E_FAIL;
951     try
952     {
953         // show dialog and wait for user decision
954         if (iOpen.is())
955             hResult = iOpen->Show( m_hParentWindow ); // parent window needed
956         else
957         if (iSave.is())
958             hResult = iSave->Show( m_hParentWindow ); // parent window needed
959     }
960     catch(...)
961     {}
962 
963     // SYNCHRONIZED->
964     aLock.reset();
965     m_bInExecute = sal_False;
966     aLock.clear();
967     // <- SYNCHRONIZED
968 
969     if ( FAILED(hResult) )
970         return;
971 
972     impl_sta_getSelectedFiles(rRequest);
973     rRequest->setArgument(PROP_DIALOG_SHOW_RESULT, sal_True);
974 }
975 
976 //-------------------------------------------------------------------------------
977 TFileDialog VistaFilePickerImpl::impl_getBaseDialogInterface()
978 {
979     TFileDialog iDialog;
980 
981     // SYNCHRONIZED->
982     ::osl::ResettableMutexGuard aLock(m_aMutex);
983 
984     if (m_iDialogOpen.is())
985 #ifdef __MINGW32__
986         m_iDialogOpen->QueryInterface(IID_IFileDialog, (void**)(&iDialog));
987 #else
988         m_iDialogOpen.query(&iDialog);
989 #endif
990     if (m_iDialogSave.is())
991 #ifdef __MINGW32__
992         m_iDialogSave->QueryInterface(IID_IFileDialog, (void**)(&iDialog));
993 #else
994         m_iDialogSave.query(&iDialog);
995 #endif
996 
997     return iDialog;
998 }
999 
1000 //-------------------------------------------------------------------------------
1001 TFileDialogCustomize VistaFilePickerImpl::impl_getCustomizeInterface()
1002 {
1003     TFileDialogCustomize iCustom;
1004 
1005     // SYNCHRONIZED->
1006     ::osl::ResettableMutexGuard aLock(m_aMutex);
1007 
1008     if (m_iDialogOpen.is())
1009 #ifdef __MINGW32__
1010         m_iDialogOpen->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom));
1011 #else
1012         m_iDialogOpen.query(&iCustom);
1013 #endif
1014     else
1015     if (m_iDialogSave.is())
1016 #ifdef __MINGW32__
1017         m_iDialogSave->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom));
1018 #else
1019         m_iDialogSave.query(&iCustom);
1020 #endif
1021 
1022     return iCustom;
1023 }
1024 
1025 //-------------------------------------------------------------------------------
1026 void lcl_removeControlItemsWorkaround(const TFileDialogCustomize& iCustom   ,
1027                                             ::sal_Int16           nControlId)
1028 {
1029     ::sal_Int32 i       = 0;
1030     HRESULT   hResult;
1031 
1032     hResult = iCustom->SetSelectedControlItem(nControlId, 1000);
1033 	hResult = S_OK;
1034     while ( SUCCEEDED(hResult) )
1035         hResult = iCustom->RemoveControlItem(nControlId, i++);
1036 }
1037 
1038 //-------------------------------------------------------------------------------
1039 void VistaFilePickerImpl::impl_sta_SetControlValue(const RequestRef& rRequest)
1040 {
1041     ::sal_Int16   nId     = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID    );
1042     ::sal_Int16   nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
1043     css::uno::Any aValue  = rRequest->getArgumentOrDefault(PROP_CONTROL_VALUE , css::uno::Any()       );
1044 
1045     // dont check for right values here ...
1046     // most parameters are optional !
1047 
1048     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1049     if ( ! iCustom.is())
1050         return;
1051 
1052     switch (nId)
1053     {
1054         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
1055         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1056         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1057         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1058         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1059         //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1060         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1061             {
1062                 ::sal_Bool bValue   = sal_False;
1063                            aValue >>= bValue;
1064                 iCustom->SetCheckButtonState(nId, bValue);
1065             }
1066             break;
1067 
1068         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION :
1069         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
1070         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
1071             {
1072                 HRESULT hResult;
1073                 switch (nAction)
1074                 {
1075                     case css::ui::dialogs::ControlActions::DELETE_ITEMS :
1076                         {
1077                             hResult = iCustom->RemoveAllControlItems(nId);
1078                             if ( FAILED(hResult) )
1079                                 lcl_removeControlItemsWorkaround(iCustom, nId);
1080                         }
1081                         break;
1082 
1083                     case css::ui::dialogs::ControlActions::ADD_ITEMS :
1084                         {
1085                             css::uno::Sequence< ::rtl::OUString > lItems;
1086                                                        aValue >>= lItems;
1087                             for (::sal_Int32 i=0; i<lItems.getLength(); ++i)
1088                             {
1089                                 const ::rtl::OUString& sItem = lItems[i];
1090                                 hResult = iCustom->AddControlItem(nId, i, reinterpret_cast<LPCTSTR>(sItem.getStr()));
1091                             }
1092                         }
1093                         break;
1094 
1095                     case css::ui::dialogs::ControlActions::SET_SELECT_ITEM :
1096                         {
1097                             ::sal_Int32 nItem    = 0;
1098                                         aValue >>= nItem;
1099                             hResult = iCustom->SetSelectedControlItem(nId, nItem);
1100                         }
1101                         break;
1102                 }
1103             }
1104             break;
1105 
1106         case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
1107             {
1108             }
1109             break;
1110         }
1111 }
1112 
1113 //-------------------------------------------------------------------------------
1114 void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef& rRequest)
1115 {
1116     ::sal_Int16 nId     = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID    );
1117     ::sal_Int16 nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
1118 
1119     // dont check for right values here ...
1120     // most parameters are optional !
1121 
1122     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1123     if ( ! iCustom.is())
1124         return;
1125 
1126     css::uno::Any aValue;
1127     if( m_bWasExecuted )
1128     switch (nId)
1129     {
1130         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1131         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1132         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1133         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1134         //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1135         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1136             {
1137                 BOOL    bValue  = FALSE;
1138                 HRESULT hResult = iCustom->GetCheckButtonState(nId, &bValue);
1139                 if ( SUCCEEDED(hResult) )
1140                     aValue = css::uno::makeAny((sal_Bool)bValue);
1141             }
1142             break;
1143     }
1144 
1145     if (aValue.hasValue())
1146         rRequest->setArgument(PROP_CONTROL_VALUE, aValue);
1147 }
1148 
1149 //-------------------------------------------------------------------------------
1150 void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef& rRequest)
1151 {
1152 	::sal_Int16     nId    = rRequest->getArgumentOrDefault(PROP_CONTROL_ID   , INVALID_CONTROL_ID  );
1153 	::rtl::OUString sLabel = rRequest->getArgumentOrDefault(PROP_CONTROL_LABEL, ::rtl::OUString() );
1154 
1155     // dont check for right values here ...
1156     // most parameters are optional !
1157 
1158     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1159     if ( ! iCustom.is())
1160         return;
1161 	iCustom->SetControlLabel ( nId, reinterpret_cast<LPCTSTR>(sLabel.getStr()));
1162 }
1163 
1164 //-------------------------------------------------------------------------------
1165 void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef& /*rRequest*/)
1166 {
1167 }
1168 
1169 //-------------------------------------------------------------------------------
1170 void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef& rRequest)
1171 {
1172     ::sal_Int16 nId      = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID  );
1173     ::sal_Bool  bEnabled = rRequest->getArgumentOrDefault(PROP_CONTROL_ENABLE, (::sal_Bool)sal_True);
1174 
1175     // dont check for right values here ...
1176     // most parameters are optional !
1177 
1178     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1179     if ( ! iCustom.is())
1180         return;
1181 
1182     CDCONTROLSTATEF eState = CDCS_VISIBLE;
1183     if (bEnabled)
1184         eState |= CDCS_ENABLED;
1185     else
1186         eState |= CDCS_INACTIVE;
1187 
1188     iCustom->SetControlState(nId, eState);
1189 }
1190 //-------------------------------------------------------------------------------
1191 void VistaFilePickerImpl::impl_SetDefaultExtension( const rtl::OUString& currentFilter )
1192 {
1193    TFileDialog iDialog = impl_getBaseDialogInterface();
1194    if (currentFilter.getLength())
1195    {
1196 		rtl::OUString FilterExt;
1197 		m_lFilters.getFilter(currentFilter, FilterExt);
1198 
1199 		sal_Int32 posOfPoint = FilterExt.indexOf(L'.');
1200 		const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1;
1201 
1202 		sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1;
1203 		if (posOfSemiColon < 0)
1204 			posOfSemiColon = FilterExt.getLength() - 1;
1205 
1206 		FilterExt = rtl::OUString(pFirstExtStart, posOfSemiColon - posOfPoint);
1207 		iDialog->SetDefaultExtension ( reinterpret_cast<LPCTSTR>(FilterExt.getStr()) );
1208    }
1209 }
1210 
1211 static void impl_refreshFileDialog( TFileDialog iDialog )
1212 {
1213 	if ( SUCCEEDED(iDialog->SetFileName(L"")) &&
1214 	     SUCCEEDED(iDialog->SetFileName(L"*.*")) )
1215 	{
1216 		IOleWindow* iOleWindow;
1217 #ifdef __MINGW32__
1218 		if (SUCCEEDED(iDialog->QueryInterface(IID_IOleWindow, reinterpret_cast<void**>(&iOleWindow))))
1219 #else
1220 		if (SUCCEEDED(iDialog->QueryInterface(IID_PPV_ARGS(&iOleWindow))))
1221 #endif
1222 		{
1223 			HWND hwnd;
1224 			if (SUCCEEDED(iOleWindow->GetWindow(&hwnd)))
1225 			{
1226 				PostMessage(hwnd, WM_COMMAND, IDOK, 0);
1227 			}
1228 			iOleWindow->Release();
1229 		}
1230 	}
1231 }
1232 
1233 //-------------------------------------------------------------------------------
1234 void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked)
1235 {
1236     // SYNCHRONIZED->
1237     ::osl::ResettableMutexGuard aLock(m_aMutex);
1238 
1239 	const ::rtl::OUString sFilter = m_lFilters.getCurrentFilter ();
1240 		  ::rtl::OUString sExt    ;
1241 	if ( !m_lFilters.getFilter (sFilter, sExt))
1242 		return;
1243 
1244     TFileDialog iDialog = impl_getBaseDialogInterface();
1245 
1246     aLock.clear();
1247     // <- SYNCHRONIZED
1248 
1249 	LPCWSTR pExt = 0;
1250 	if ( bChecked )
1251 	{
1252 		pExt = reinterpret_cast<LPCTSTR>(sExt.getStr());
1253 		pExt = wcsrchr( pExt, '.' );
1254 		if ( pExt )
1255 			pExt++;
1256 	}
1257 	iDialog->SetDefaultExtension( pExt );
1258 }
1259 
1260 bool VistaFilePickerImpl::onFileTypeChanged( UINT /*nTypeIndex*/ )
1261 {
1262 	return true;
1263 }
1264 
1265 } // namespace vista
1266 } // namespace win32
1267 } // namespace fpicker
1268