mfplat/sample: Optimize copying to 2d buffer.
[wine.git] / dlls / setupapi / dialog.c
blob5c253db0a19720c6a5a376da5a4939e67533f21f
1 /*
2 * SetupAPI dialog functions
4 * Copyright 2009 Ricardo Filipe
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "wine/debug.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "commdlg.h"
30 #include "setupapi.h"
31 #include "winnls.h"
32 #include "setupapi_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
36 struct promptdisk_params {
37 PCWSTR DialogTitle;
38 PCWSTR DiskName;
39 PCWSTR PathToSource;
40 PCWSTR FileSought;
41 PCWSTR TagFile;
42 DWORD DiskPromptStyle;
43 PWSTR PathBuffer;
44 DWORD PathBufferSize;
45 PDWORD PathRequiredSize;
48 /* initiates the fields of the SetupPromptForDisk dialog according to the parameters
50 static void promptdisk_init(HWND hwnd, struct promptdisk_params *params)
52 SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)params);
54 if(params->DialogTitle)
55 SetWindowTextW(hwnd, params->DialogTitle);
56 if(params->PathToSource)
57 SetDlgItemTextW(hwnd, IDC_PATH, params->PathToSource);
59 if(!(params->DiskPromptStyle & IDF_OEMDISK))
61 WCHAR message[256+2*MAX_PATH];
62 WCHAR format[256];
63 WCHAR unknown[256];
64 DWORD_PTR args[2];
65 LoadStringW(SETUPAPI_hInstance, IDS_PROMPTDISK, format, ARRAY_SIZE(format));
67 args[0] = (DWORD_PTR)params->FileSought;
68 if(params->DiskName)
69 args[1] = (DWORD_PTR)params->DiskName;
70 else
72 LoadStringW(SETUPAPI_hInstance, IDS_UNKNOWN, unknown, ARRAY_SIZE(unknown));
73 args[1] = (DWORD_PTR)unknown;
75 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
76 format, 0, 0, message, ARRAY_SIZE(message), (va_list *)args);
77 SetDlgItemTextW(hwnd, IDC_FILENEEDED, message);
79 LoadStringW(SETUPAPI_hInstance, IDS_INFO, message, ARRAY_SIZE(message));
80 SetDlgItemTextW(hwnd, IDC_INFO, message);
81 LoadStringW(SETUPAPI_hInstance, IDS_COPYFROM, message, ARRAY_SIZE(message));
82 SetDlgItemTextW(hwnd, IDC_COPYFROM, message);
84 if(params->DiskPromptStyle & IDF_NOBROWSE)
85 ShowWindow(GetDlgItem(hwnd, IDC_RUNDLG_BROWSE), SW_HIDE);
88 /* When the user clicks in the Ok button in SetupPromptForDisk dialog
89 * if the parameters are good it copies the path from the dialog to the output buffer
90 * saves the required size for the buffer if PathRequiredSize is given
91 * returns NO_ERROR if there is no PathBuffer to copy too
92 * returns DPROMPT_BUFFERTOOSMALL if the path is too big to fit in PathBuffer
94 static void promptdisk_ok(HWND hwnd, struct promptdisk_params *params)
96 int requiredSize;
97 WCHAR aux[MAX_PATH];
98 GetWindowTextW(GetDlgItem(hwnd, IDC_PATH), aux, MAX_PATH);
99 requiredSize = lstrlenW(aux)+1;
101 if(params->PathRequiredSize)
103 *params->PathRequiredSize = requiredSize;
104 TRACE("returning PathRequiredSize=%ld\n",*params->PathRequiredSize);
106 if(!params->PathBuffer)
108 EndDialog(hwnd, NO_ERROR);
109 return;
111 if(requiredSize > params->PathBufferSize)
113 EndDialog(hwnd, DPROMPT_BUFFERTOOSMALL);
114 return;
116 lstrcpyW(params->PathBuffer, aux);
117 TRACE("returning PathBuffer=%s\n", debugstr_w(params->PathBuffer));
118 EndDialog(hwnd, DPROMPT_SUCCESS);
121 /* When the user clicks the browse button in SetupPromptForDisk dialog
122 * it copies the path of the selected file to the dialog path field
124 static void promptdisk_browse(HWND hwnd, struct promptdisk_params *params)
126 OPENFILENAMEW ofn;
127 ZeroMemory(&ofn, sizeof(ofn));
129 ofn.lStructSize = sizeof(ofn);
130 ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
131 ofn.hwndOwner = hwnd;
132 ofn.nMaxFile = MAX_PATH;
133 ofn.lpstrFile = malloc(MAX_PATH * sizeof(WCHAR));
134 lstrcpyW(ofn.lpstrFile, params->FileSought);
136 if(GetOpenFileNameW(&ofn))
138 WCHAR* last_slash = wcsrchr(ofn.lpstrFile, '\\');
139 if (last_slash) *last_slash = 0;
140 SetDlgItemTextW(hwnd, IDC_PATH, ofn.lpstrFile);
142 free(ofn.lpstrFile);
145 /* Handles the messages sent to the SetupPromptForDisk dialog
147 static INT_PTR CALLBACK promptdisk_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
149 switch(msg)
151 case WM_INITDIALOG:
152 promptdisk_init(hwnd, (struct promptdisk_params *)lParam);
153 return TRUE;
154 case WM_COMMAND:
155 switch(wParam)
157 case IDOK:
159 struct promptdisk_params *params =
160 (struct promptdisk_params *)GetWindowLongPtrW(hwnd, DWLP_USER);
161 promptdisk_ok(hwnd, params);
162 return TRUE;
164 case IDCANCEL:
165 EndDialog(hwnd, DPROMPT_CANCEL);
166 return TRUE;
167 case IDC_RUNDLG_BROWSE:
169 struct promptdisk_params *params =
170 (struct promptdisk_params *)GetWindowLongPtrW(hwnd, DWLP_USER);
171 promptdisk_browse(hwnd, params);
172 return TRUE;
176 return FALSE;
179 /***********************************************************************
180 * SetupPromptForDiskA (SETUPAPI.@)
182 UINT WINAPI SetupPromptForDiskA(HWND hwndParent, PCSTR DialogTitle, PCSTR DiskName,
183 PCSTR PathToSource, PCSTR FileSought, PCSTR TagFile, DWORD DiskPromptStyle,
184 PSTR PathBuffer, DWORD PathBufferSize, PDWORD PathRequiredSize)
186 WCHAR *DialogTitleW, *DiskNameW, *PathToSourceW;
187 WCHAR *FileSoughtW, *TagFileW, PathBufferW[MAX_PATH];
188 UINT ret, length;
190 TRACE("%p, %s, %s, %s, %s, %s, 0x%08lx, %p, %ld, %p\n", hwndParent, debugstr_a(DialogTitle),
191 debugstr_a(DiskName), debugstr_a(PathToSource), debugstr_a(FileSought),
192 debugstr_a(TagFile), DiskPromptStyle, PathBuffer, PathBufferSize,
193 PathRequiredSize);
195 DialogTitleW = strdupAtoW(DialogTitle);
196 DiskNameW = strdupAtoW(DiskName);
197 PathToSourceW = strdupAtoW(PathToSource);
198 FileSoughtW = strdupAtoW(FileSought);
199 TagFileW = strdupAtoW(TagFile);
201 ret = SetupPromptForDiskW(hwndParent, DialogTitleW, DiskNameW, PathToSourceW,
202 FileSoughtW, TagFileW, DiskPromptStyle, PathBufferW, MAX_PATH, PathRequiredSize);
204 free(DialogTitleW);
205 free(DiskNameW);
206 free(PathToSourceW);
207 free(FileSoughtW);
208 free(TagFileW);
210 if(ret == DPROMPT_SUCCESS)
212 length = WideCharToMultiByte(CP_ACP, 0, PathBufferW, -1, NULL, 0, NULL, NULL);
213 if(PathRequiredSize) *PathRequiredSize = length;
214 if(PathBuffer)
216 if(length > PathBufferSize)
217 return DPROMPT_BUFFERTOOSMALL;
218 WideCharToMultiByte(CP_ACP, 0, PathBufferW, -1, PathBuffer, length, NULL, NULL);
221 return ret;
224 /***********************************************************************
225 * SetupPromptForDiskW (SETUPAPI.@)
227 UINT WINAPI SetupPromptForDiskW(HWND hwndParent, PCWSTR DialogTitle, PCWSTR DiskName,
228 PCWSTR PathToSource, PCWSTR FileSought, PCWSTR TagFile, DWORD DiskPromptStyle,
229 PWSTR PathBuffer, DWORD PathBufferSize, PDWORD PathRequiredSize)
231 struct promptdisk_params params;
232 UINT ret;
234 TRACE("%p, %s, %s, %s, %s, %s, 0x%08lx, %p, %ld, %p\n", hwndParent, debugstr_w(DialogTitle),
235 debugstr_w(DiskName), debugstr_w(PathToSource), debugstr_w(FileSought),
236 debugstr_w(TagFile), DiskPromptStyle, PathBuffer, PathBufferSize,
237 PathRequiredSize);
239 if(!FileSought)
241 SetLastError(ERROR_INVALID_PARAMETER);
242 return DPROMPT_CANCEL;
245 if (PathToSource && (DiskPromptStyle & IDF_CHECKFIRST))
247 WCHAR filepath[MAX_PATH];
249 if (lstrlenW(PathToSource) + 1 + lstrlenW(FileSought) < ARRAY_SIZE(filepath))
251 swprintf(filepath, ARRAY_SIZE(filepath), L"%s\\%s", PathToSource, FileSought);
252 if (GetFileAttributesW(filepath) != INVALID_FILE_ATTRIBUTES)
254 if (PathRequiredSize)
255 *PathRequiredSize = lstrlenW(PathToSource) + 1;
257 if (!PathBuffer)
258 return DPROMPT_SUCCESS;
260 if (PathBufferSize >= lstrlenW(PathToSource) + 1)
262 lstrcpyW(PathBuffer, PathToSource);
263 return DPROMPT_SUCCESS;
265 else
266 return DPROMPT_BUFFERTOOSMALL;
271 params.DialogTitle = DialogTitle;
272 params.DiskName = DiskName;
273 params.PathToSource = PathToSource;
274 params.FileSought = FileSought;
275 params.TagFile = TagFile;
276 params.DiskPromptStyle = DiskPromptStyle;
277 params.PathBuffer = PathBuffer;
278 params.PathBufferSize = PathBufferSize;
279 params.PathRequiredSize = PathRequiredSize;
281 ret = DialogBoxParamW(SETUPAPI_hInstance, MAKEINTRESOURCEW(IDPROMPTFORDISK),
282 hwndParent, promptdisk_proc, (LPARAM)&params);
284 if(ret == DPROMPT_CANCEL)
285 SetLastError(ERROR_CANCELLED);
286 return ret;