[PATCH 5/8] comdlg32: Implement SetDefaultFilename.
David Hedberg
david.hedberg at gmail.com
Tue May 24 14:09:50 CDT 2011
---
dlls/comdlg32/cdlg.h | 1 +
dlls/comdlg32/filedlg.c | 2 +-
dlls/comdlg32/itemdlg.c | 81 ++++++++++++-
dlls/comdlg32/tests/itemdlg.c | 275 ++++++++++++++++++++++++++++++++++++++++-
4 files changed, 352 insertions(+), 7 deletions(-)
diff --git a/dlls/comdlg32/cdlg.h b/dlls/comdlg32/cdlg.h
index e85ba9f..91491d3 100644
--- a/dlls/comdlg32/cdlg.h
+++ b/dlls/comdlg32/cdlg.h
@@ -178,6 +178,7 @@ void COMDLG32_GetCanonicalPath(PCIDLIST_ABSOLUTE pidlAbsCurrent, LPWSTR lpstrFil
int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction) DECLSPEC_HIDDEN;
int COMDLG32_SplitFileNames(LPWSTR lpstrEdit, UINT nStrLen, LPWSTR *lpstrFileList, UINT *sizeUsed) DECLSPEC_HIDDEN;
+void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText) DECLSPEC_HIDDEN;
/* ITEMIDLIST */
diff --git a/dlls/comdlg32/filedlg.c b/dlls/comdlg32/filedlg.c
index a36cd35..28d7c77 100644
--- a/dlls/comdlg32/filedlg.c
+++ b/dlls/comdlg32/filedlg.c
@@ -2259,7 +2259,7 @@ static void FILEDLG95_MRU_load_filename(LPWSTR stored_path)
TRACE("got MRU path: %s\n", wine_dbgstr_w(stored_path));
}
-static void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText)
+void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText)
{
WCHAR strMsgTitle[MAX_PATH];
WCHAR strMsgText [MAX_PATH];
diff --git a/dlls/comdlg32/itemdlg.c b/dlls/comdlg32/itemdlg.c
index a04b86a..80b0d86 100644
--- a/dlls/comdlg32/itemdlg.c
+++ b/dlls/comdlg32/itemdlg.c
@@ -87,6 +87,7 @@ typedef struct FileDialogImpl {
DWORD ebevents_cookie;
LPWSTR set_filename;
+ LPWSTR default_ext;
LPWSTR custom_title;
LPWSTR custom_okbutton;
LPWSTR custom_cancelbutton;
@@ -271,6 +272,21 @@ static void fill_filename_from_selection(FileDialogImpl *This)
return;
}
+static LPWSTR get_first_ext_from_spec(LPWSTR buf, LPCWSTR spec)
+{
+ WCHAR *endpos, *ext;
+
+ lstrcpyW(buf, spec);
+ if( (endpos = StrChrW(buf, ';')) )
+ *endpos = '\0';
+
+ ext = PathFindExtensionW(buf);
+ if(StrChrW(ext, '*'))
+ return NULL;
+
+ return ext;
+}
+
static HRESULT on_default_action(FileDialogImpl *This)
{
IShellFolder *psf_parent, *psf_desktop;
@@ -316,9 +332,62 @@ static HRESULT on_default_action(FileDialogImpl *This)
open_action = ONOPEN_BROWSE;
open_action = FILEDLG95_ValidatePathAction(canon_filename, &psf_parent, This->dlg_hwnd,
- This->options, (This->dlg_type == ITEMDLG_TYPE_SAVE),
+ This->options & ~FOS_FILEMUSTEXIST,
+ (This->dlg_type == ITEMDLG_TYPE_SAVE),
open_action);
+ /* Add the proper extension */
+ if(open_action == ONOPEN_OPEN)
+ {
+ static const WCHAR dotW[] = {'.',0};
+
+ if(This->dlg_type == ITEMDLG_TYPE_SAVE)
+ {
+ WCHAR extbuf[MAX_PATH], *newext = NULL;
+
+ if(This->filterspec_count)
+ {
+ newext = get_first_ext_from_spec(extbuf, This->filterspecs[This->filetypeindex].pszSpec);
+ }
+ else if(This->default_ext)
+ {
+ lstrcpyW(extbuf, dotW);
+ lstrcatW(extbuf, This->default_ext);
+ newext = extbuf;
+ }
+
+ if(newext)
+ {
+ WCHAR *ext = PathFindExtensionW(canon_filename);
+ if(lstrcmpW(ext, newext))
+ lstrcatW(canon_filename, newext);
+ }
+ }
+ else
+ {
+ if( !(This->options & FOS_NOVALIDATE) && (This->options & FOS_FILEMUSTEXIST) &&
+ !PathFileExistsW(canon_filename))
+ {
+ if(This->default_ext)
+ {
+ lstrcatW(canon_filename, dotW);
+ lstrcatW(canon_filename, This->default_ext);
+
+ if(!PathFileExistsW(canon_filename))
+ {
+ FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
+ open_action = ONOPEN_BROWSE;
+ }
+ }
+ else
+ {
+ FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
+ open_action = ONOPEN_BROWSE;
+ }
+ }
+ }
+ }
+
pidla[i] = COMDLG32_SHSimpleIDListFromPathAW(canon_filename);
if(psf_parent && !(open_action == ONOPEN_BROWSE))
@@ -959,6 +1028,7 @@ static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
if(This->psia_results) IShellItemArray_Release(This->psia_results);
LocalFree(This->set_filename);
+ LocalFree(This->default_ext);
LocalFree(This->custom_title);
LocalFree(This->custom_okbutton);
LocalFree(This->custom_cancelbutton);
@@ -1281,8 +1351,12 @@ static HRESULT WINAPI IFileDialog2_fnAddPlace(IFileDialog2 *iface, IShellItem *p
static HRESULT WINAPI IFileDialog2_fnSetDefaultExtension(IFileDialog2 *iface, LPCWSTR pszDefaultExtension)
{
FileDialogImpl *This = impl_from_IFileDialog2(iface);
- FIXME("stub - %p (%s)\n", This, debugstr_w(pszDefaultExtension));
- return E_NOTIMPL;
+ TRACE("%p (%s)\n", This, debugstr_w(pszDefaultExtension));
+
+ LocalFree(This->default_ext);
+ This->default_ext = StrDupW(pszDefaultExtension);
+
+ return S_OK;
}
static HRESULT WINAPI IFileDialog2_fnClose(IFileDialog2 *iface, HRESULT hr)
@@ -2316,6 +2390,7 @@ static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **p
fdimpl->peb = NULL;
fdimpl->set_filename = NULL;
+ fdimpl->default_ext = NULL;
fdimpl->custom_cancelbutton = fdimpl->custom_filenamelabel = NULL;
/* FIXME: The default folder setting should be restored for the
diff --git a/dlls/comdlg32/tests/itemdlg.c b/dlls/comdlg32/tests/itemdlg.c
index 7c52868..5d438ae 100644
--- a/dlls/comdlg32/tests/itemdlg.c
+++ b/dlls/comdlg32/tests/itemdlg.c
@@ -27,6 +27,7 @@
static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
static HRESULT (WINAPI *pSHGetIDListFromObject)(IUnknown*, PIDLIST_ABSOLUTE*);
+static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**);
static void init_function_pointers(void)
{
@@ -35,6 +36,7 @@ static void init_function_pointers(void)
#define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
MAKEFUNC(SHCreateShellItem);
MAKEFUNC(SHGetIDListFromObject);
+ MAKEFUNC(SHCreateItemFromParsingName);
#undef MAKEFUNC
}
@@ -48,6 +50,8 @@ typedef struct {
LONG OnFileOk, OnFolderChanging, OnFolderChange;
LONG OnSelectionChange, OnShareViolation, OnTypeChange;
LONG OnOverwrite;
+ LPCWSTR set_filename;
+ BOOL set_filename_tried;
} IFileDialogEventsImpl;
static inline IFileDialogEventsImpl *impl_from_IFileDialogEvents(IFileDialogEvents *iface)
@@ -99,6 +103,34 @@ static HRESULT WINAPI IFileDialogEvents_fnOnFolderChange(IFileDialogEvents *ifac
{
IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
This->OnFolderChange++;
+
+ if(This->set_filename)
+ {
+ IOleWindow *pow;
+ HWND dlg_hwnd;
+ HRESULT hr;
+ BOOL br;
+
+ hr = IFileDialog_QueryInterface(pfd, &IID_IOleWindow, (void**)&pow);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+
+ hr = IOleWindow_GetWindow(pow, &dlg_hwnd);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+ ok(dlg_hwnd != NULL, "Got NULL.\n");
+
+ IOleWindow_Release(pow);
+
+ hr = IFileDialog_SetFileName(pfd, This->set_filename);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+
+ if(!This->set_filename_tried)
+ {
+ br = PostMessageW(dlg_hwnd, WM_COMMAND, IDOK, 0);
+ ok(br, "Failed\n");
+ This->set_filename_tried = TRUE;
+ }
+ }
+
return S_OK;
}
@@ -523,8 +555,6 @@ static void test_basics(void)
ok(hr == S_OK, "got 0x%08x.\n", hr);
/* SetDefaultExtension */
- todo_wine
- {
hr = IFileOpenDialog_SetDefaultExtension(pfod, NULL);
ok(hr == S_OK, "got 0x%08x.\n", hr);
hr = IFileOpenDialog_SetDefaultExtension(pfod, txt);
@@ -538,7 +568,6 @@ static void test_basics(void)
ok(hr == S_OK, "got 0x%08x.\n", hr);
hr = IFileSaveDialog_SetDefaultExtension(pfsd, null);
ok(hr == S_OK, "got 0x%08x.\n", hr);
- }
/* SetDefaultFolder */
hr = IFileOpenDialog_SetDefaultFolder(pfod, NULL);
@@ -921,6 +950,245 @@ static void test_advise(void)
ok(!ref, "Got refcount %d, should have been released.\n", ref);
}
+static void touch_file(LPCWSTR filename)
+{
+ HANDLE file;
+ file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "Failed to create file.\n");
+ CloseHandle(file);
+}
+
+static void test_filename_savedlg_(LPCWSTR set_filename, LPCWSTR defext,
+ const COMDLG_FILTERSPEC *filterspec, UINT fs_count,
+ LPCWSTR exp_filename, const char *file, int line)
+{
+ IFileSaveDialog *pfsd;
+ IFileDialogEventsImpl *pfdeimpl;
+ IFileDialogEvents *pfde;
+ DWORD cookie;
+ LPWSTR filename;
+ IShellItem *psi;
+ LONG ref;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IFileSaveDialog, (void**)&pfsd);
+ ok_(file,line)(hr == S_OK, "Got 0x%08x\n", hr);
+
+ if(fs_count)
+ {
+ hr = IFileSaveDialog_SetFileTypes(pfsd, fs_count, filterspec);
+ ok_(file,line)(hr == S_OK, "SetFileTypes failed: Got 0x%08x\n", hr);
+ }
+
+ if(defext)
+ {
+ hr = IFileSaveDialog_SetDefaultExtension(pfsd, defext);
+ ok_(file,line)(hr == S_OK, "SetDefaultExtensions failed: Got 0x%08x\n", hr);
+ }
+
+ pfde = IFileDialogEvents_Constructor();
+ pfdeimpl = impl_from_IFileDialogEvents(pfde);
+ pfdeimpl->set_filename = set_filename;
+ hr = IFileSaveDialog_Advise(pfsd, pfde, &cookie);
+ ok_(file,line)(hr == S_OK, "Advise failed: Got 0x%08x\n", hr);
+
+ hr = IFileSaveDialog_Show(pfsd, NULL);
+ ok_(file,line)(hr == S_OK, "Show failed: Got 0x%08x\n", hr);
+
+ hr = IFileSaveDialog_GetFileName(pfsd, &filename);
+ ok_(file,line)(hr == S_OK, "GetFileName failed: Got 0x%08x\n", hr);
+ ok_(file,line)(!lstrcmpW(filename, set_filename), "Got %s\n", wine_dbgstr_w(filename));
+ CoTaskMemFree(filename);
+
+ hr = IFileSaveDialog_GetResult(pfsd, &psi);
+ ok_(file,line)(hr == S_OK, "GetResult failed: Got 0x%08x\n", hr);
+
+ hr = IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename);
+ ok_(file,line)(hr == S_OK, "GetDisplayName failed: Got 0x%08x\n", hr);
+ ok_(file,line)(!lstrcmpW(filename, exp_filename), "(GetDisplayName) Got %s\n", wine_dbgstr_w(filename));
+ CoTaskMemFree(filename);
+ IShellItem_Release(psi);
+
+ hr = IFileSaveDialog_Unadvise(pfsd, cookie);
+ ok_(file,line)(hr == S_OK, "Unadvise failed: Got 0x%08x\n", hr);
+
+ ref = IFileSaveDialog_Release(pfsd);
+ ok_(file,line)(!ref, "Got refcount %d, should have been released.\n", ref);
+
+ IFileDialogEvents_Release(pfde);
+}
+#define test_filename_savedlg(set_filename, defext, filterspec, fs_count, exp_filename) \
+ test_filename_savedlg_(set_filename, defext, filterspec, fs_count, exp_filename, __FILE__, __LINE__)
+
+static void test_filename_opendlg_(LPCWSTR set_filename, IShellItem *psi_current, LPCWSTR defext,
+ const COMDLG_FILTERSPEC *filterspec, UINT fs_count,
+ LPCWSTR exp_filename, const char *file, int line)
+{
+ IFileOpenDialog *pfod;
+ IFileDialogEventsImpl *pfdeimpl;
+ IFileDialogEvents *pfde;
+ DWORD cookie;
+ LPWSTR filename;
+ IShellItemArray *psia;
+ IShellItem *psi;
+ LONG ref;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IFileOpenDialog, (void**)&pfod);
+ ok_(file,line)(hr == S_OK, "CoCreateInstance failed: Got 0x%08x\n", hr);
+
+ if(defext)
+ {
+ hr = IFileOpenDialog_SetDefaultExtension(pfod, defext);
+ ok_(file,line)(hr == S_OK, "SetDefaultExtensions failed: Got 0x%08x\n", hr);
+ }
+
+ if(fs_count)
+ {
+ hr = IFileOpenDialog_SetFileTypes(pfod, 2, filterspec);
+ ok_(file,line)(hr == S_OK, "SetFileTypes failed: Got 0x%08x\n", hr);
+ }
+
+ hr = IFileOpenDialog_SetFolder(pfod, psi_current);
+ ok_(file,line)(hr == S_OK, "SetFolder failed: Got 0x%08x\n", hr);
+
+ pfde = IFileDialogEvents_Constructor();
+ pfdeimpl = impl_from_IFileDialogEvents(pfde);
+ pfdeimpl->set_filename = set_filename;
+ pfdeimpl->set_filename_tried = FALSE;
+ hr = IFileOpenDialog_Advise(pfod, pfde, &cookie);
+ ok_(file,line)(hr == S_OK, "Advise failed: Got 0x%08x\n", hr);
+
+ hr = IFileOpenDialog_Show(pfod, NULL);
+ ok_(file,line)(hr == S_OK || (!exp_filename && hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)),
+ "Show failed: Got 0x%08x\n", hr);
+ if(hr == S_OK)
+ {
+ hr = IFileOpenDialog_GetResult(pfod, &psi);
+ ok_(file,line)(hr == S_OK, "GetResult failed: Got 0x%08x\n", hr);
+
+ hr = IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename);
+ ok_(file,line)(hr == S_OK, "GetDisplayName(Result) failed: Got 0x%08x\n", hr);
+ ok_(file,line)(!lstrcmpW(filename, exp_filename), "(GetResult) Got %s\n", wine_dbgstr_w(filename));
+ CoTaskMemFree(filename);
+ IShellItem_Release(psi);
+
+ hr = IFileOpenDialog_GetResults(pfod, &psia);
+ ok_(file,line)(hr == S_OK, "GetResults failed: Got 0x%08x\n", hr);
+ hr = IShellItemArray_GetItemAt(psia, 0, &psi);
+ ok_(file,line)(hr == S_OK, "GetItemAt failed: Got 0x%08x\n", hr);
+
+ hr = IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename);
+ ok_(file,line)(hr == S_OK, "GetDisplayName(Results) failed: Got 0x%08x\n", hr);
+ ok_(file,line)(!lstrcmpW(filename, exp_filename), "(GetResults) Got %s\n", wine_dbgstr_w(filename));
+ CoTaskMemFree(filename);
+
+ IShellItem_Release(psi);
+ IShellItemArray_Release(psia);
+ }
+ else
+ {
+ hr = IFileOpenDialog_GetResult(pfod, &psi);
+ ok_(file,line)(hr == E_UNEXPECTED, "GetResult: Got 0x%08x\n", hr);
+
+ hr = IFileOpenDialog_GetResults(pfod, &psia);
+ ok_(file,line)(hr == E_FAIL, "GetResults: Got 0x%08x\n", hr);
+ }
+
+ hr = IFileOpenDialog_GetFileName(pfod, &filename);
+ ok_(file,line)(hr == S_OK, "GetFileName failed: Got 0x%08x\n", hr);
+ ok_(file,line)(!lstrcmpW(filename, set_filename), "(GetFileName) Got %s\n", wine_dbgstr_w(filename));
+ CoTaskMemFree(filename);
+
+
+ hr = IFileOpenDialog_Unadvise(pfod, cookie);
+ ok_(file,line)(hr == S_OK, "Unadvise failed: Got 0x%08x\n", hr);
+
+ ref = IFileOpenDialog_Release(pfod);
+ ok_(file,line)(!ref, "Got refcount %d, should have been released.\n", ref);
+
+ IFileDialogEvents_Release(pfde);
+}
+#define test_filename_opendlg(set_filename, psi, defext, filterspec, fs_count, exp_filename) \
+ test_filename_opendlg_(set_filename, psi, defext, filterspec, fs_count, exp_filename, __FILE__, __LINE__)
+
+static void test_filename(void)
+{
+ IShellItem *psi_current;
+ HRESULT hr;
+ WCHAR buf[MAX_PATH];
+
+ static const WCHAR filename_noextW[] = {'w','i','n','e','t','e','s','t',0};
+ static const WCHAR filename_dotextW[] = {'w','i','n','e','t','e','s','t','.',0};
+ static const WCHAR filename_dotanddefW[] = {'w','i','n','e','t','e','s','t','.','.','w','t','e',0};
+ static const WCHAR filename_defextW[] = {'w','i','n','e','t','e','s','t','.','w','t','e',0};
+ static const WCHAR filename_ext1W[] = {'w','i','n','e','t','e','s','t','.','w','t','1',0};
+ static const WCHAR filename_ext2W[] = {'w','i','n','e','t','e','s','t','.','w','t','2',0};
+ static const WCHAR filename_ext1anddefW[] =
+ {'w','i','n','e','t','e','s','t','.','w','t','1','.','w','t','e',0};
+ static const WCHAR defextW[] = {'w','t','e',0};
+ static const WCHAR desc1[] = {'d','e','s','c','r','i','p','t','i','o','n','1',0};
+ static const WCHAR desc2[] = {'d','e','s','c','r','i','p','t','i','o','n','2',0};
+ static const WCHAR descdef[] = {'d','e','f','a','u','l','t',' ','d','e','s','c',0};
+ static const WCHAR ext1[] = {'*','.','w','t','1',0};
+ static const WCHAR ext2[] = {'*','.','w','t','2',0};
+ static const WCHAR extdef[] = {'*','.','w','t','e',0};
+ static const WCHAR complexext[] = {'*','.','w','t','2',';','*','.','w','t','1',0};
+
+ static const COMDLG_FILTERSPEC filterspec[] = {
+ { desc1, ext1 }, { desc2, ext2 }, { descdef, extdef }
+ };
+ static const COMDLG_FILTERSPEC filterspec2[] = {
+ { desc1, complexext }
+ };
+
+ /* No extension */
+ test_filename_savedlg(filename_noextW, NULL, NULL, 0, filename_noextW);
+ /* Default extension */
+ test_filename_savedlg(filename_noextW, defextW, NULL, 0, filename_defextW);
+ /* Default extension on filename ending with a . */
+ test_filename_savedlg(filename_dotextW, defextW, NULL, 0, filename_dotanddefW);
+ /* Default extension on filename with default extension */
+ test_filename_savedlg(filename_defextW, defextW, NULL, 0, filename_defextW);
+ /* Default extension on filename with another extension */
+ test_filename_savedlg(filename_ext1W, defextW, NULL, 0, filename_ext1anddefW);
+ /* Default extension, filterspec without default extension */
+ test_filename_savedlg(filename_noextW, defextW, filterspec, 2, filename_ext1W);
+ /* Default extension, filterspec with default extension */
+ test_filename_savedlg(filename_noextW, defextW, filterspec, 3, filename_ext1W);
+ /* Default extension, filterspec with "complex" extension */
+ test_filename_savedlg(filename_noextW, defextW, filterspec2, 1, filename_ext2W);
+
+ GetCurrentDirectoryW(MAX_PATH, buf);
+ ok(!!pSHCreateItemFromParsingName, "SHCreateItemFromParsingName is missing.\n");
+ hr = pSHCreateItemFromParsingName(buf, NULL, &IID_IShellItem, (void**)&psi_current);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+
+ touch_file(filename_noextW);
+ touch_file(filename_defextW);
+ touch_file(filename_ext2W);
+
+ /* IFileOpenDialog, default extension */
+ test_filename_opendlg(filename_noextW, psi_current, defextW, NULL, 0, filename_noextW);
+ /* IFileOpenDialog, default extension and filterspec */
+ test_filename_opendlg(filename_noextW, psi_current, defextW, filterspec, 2, filename_noextW);
+
+ DeleteFileW(filename_noextW);
+ /* IFileOpenDialog, default extension, noextW deleted */
+ test_filename_opendlg(filename_noextW, psi_current, defextW, NULL, 0, filename_defextW);
+ if(0) /* Interactive */
+ {
+ /* IFileOpenDialog, filterspec, no default extension, noextW deleted */
+ test_filename_opendlg(filename_noextW, psi_current, NULL, filterspec, 2, NULL);
+ }
+
+ IShellItem_Release(psi_current);
+ DeleteFileW(filename_defextW);
+ DeleteFileW(filename_ext2W);
+}
+
START_TEST(itemdlg)
{
OleInitialize(NULL);
@@ -930,6 +1198,7 @@ START_TEST(itemdlg)
{
test_basics();
test_advise();
+ test_filename();
}
else
skip("Skipping all Item Dialog tests.\n");
--
1.7.5.rc3
More information about the wine-patches
mailing list