1 /*
2 * SetupAPI dialog functions
3 *
4 * Copyright 2009 Ricardo Filipe
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "setupapi_private.h"
22
23 struct promptdisk_params {
24 PCWSTR DialogTitle;
25 PCWSTR DiskName;
26 PCWSTR PathToSource;
27 PCWSTR FileSought;
28 PCWSTR TagFile;
29 DWORD DiskPromptStyle;
30 PWSTR PathBuffer;
31 DWORD PathBufferSize;
32 PDWORD PathRequiredSize;
33 };
34
35 /* initiates the fields of the SetupPromptForDisk dialog according to the parameters
36 */
promptdisk_init(HWND hwnd,struct promptdisk_params * params)37 static void promptdisk_init(HWND hwnd, struct promptdisk_params *params)
38 {
39 SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)params);
40
41 if(params->DialogTitle)
42 SetWindowTextW(hwnd, params->DialogTitle);
43 if(params->PathToSource)
44 SetDlgItemTextW(hwnd, IDC_PATH, params->PathToSource);
45
46 if(!(params->DiskPromptStyle & IDF_OEMDISK))
47 {
48 WCHAR message[256+2*MAX_PATH];
49 WCHAR format[256];
50 WCHAR unknown[256];
51 DWORD_PTR args[2];
52 LoadStringW(hInstance, IDS_PROMPTDISK, format,
53 sizeof(format)/sizeof(format[0]));
54
55 args[0] = (DWORD_PTR)params->FileSought;
56 if(params->DiskName)
57 args[1] = (DWORD_PTR)params->DiskName;
58 else
59 {
60 LoadStringW(hInstance, IDS_UNKNOWN, unknown,
61 sizeof(unknown)/sizeof(unknown[0]));
62 args[1] = (DWORD_PTR)unknown;
63 }
64 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
65 format, 0, 0, message, sizeof(message)/sizeof(*message),
66 (__ms_va_list*)args);
67 SetDlgItemTextW(hwnd, IDC_FILENEEDED, message);
68
69 LoadStringW(hInstance, IDS_INFO, message,
70 sizeof(message)/sizeof(message[0]));
71 SetDlgItemTextW(hwnd, IDC_INFO, message);
72 LoadStringW(hInstance, IDS_COPYFROM, message,
73 sizeof(message)/sizeof(message[0]));
74 SetDlgItemTextW(hwnd, IDC_COPYFROM, message);
75 }
76 if(params->DiskPromptStyle & IDF_NOBROWSE)
77 ShowWindow(GetDlgItem(hwnd, IDC_RUNDLG_BROWSE), SW_HIDE);
78 }
79
80 /* When the user clicks in the Ok button in SetupPromptForDisk dialog
81 * if the parameters are good it copies the path from the dialog to the output buffer
82 * saves the required size for the buffer if PathRequiredSize is given
83 * returns NO_ERROR if there is no PathBuffer to copy too
84 * returns DPROMPT_BUFFERTOOSMALL if the path is too big to fit in PathBuffer
85 */
promptdisk_ok(HWND hwnd,struct promptdisk_params * params)86 static void promptdisk_ok(HWND hwnd, struct promptdisk_params *params)
87 {
88 int requiredSize;
89 WCHAR aux[MAX_PATH];
90 GetWindowTextW(GetDlgItem(hwnd, IDC_PATH), aux, MAX_PATH);
91 requiredSize = strlenW(aux)+1;
92
93 if(params->PathRequiredSize)
94 {
95 *params->PathRequiredSize = requiredSize;
96 TRACE("returning PathRequiredSize=%d\n",*params->PathRequiredSize);
97 }
98 if(!params->PathBuffer)
99 {
100 EndDialog(hwnd, NO_ERROR);
101 return;
102 }
103 if(requiredSize > params->PathBufferSize)
104 {
105 EndDialog(hwnd, DPROMPT_BUFFERTOOSMALL);
106 return;
107 }
108 strcpyW(params->PathBuffer, aux);
109 TRACE("returning PathBuffer=%s\n", debugstr_w(params->PathBuffer));
110 EndDialog(hwnd, DPROMPT_SUCCESS);
111 }
112
113 /* When the user clicks the browse button in SetupPromptForDisk dialog
114 * it copies the path of the selected file to the dialog path field
115 */
promptdisk_browse(HWND hwnd,struct promptdisk_params * params)116 static void promptdisk_browse(HWND hwnd, struct promptdisk_params *params)
117 {
118 OPENFILENAMEW ofn;
119 ZeroMemory(&ofn, sizeof(ofn));
120
121 ofn.lStructSize = sizeof(ofn);
122 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
123 ofn.hwndOwner = hwnd;
124 ofn.nMaxFile = MAX_PATH;
125 ofn.lpstrFile = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR));
126 strcpyW(ofn.lpstrFile, params->FileSought);
127
128 if(GetOpenFileNameW(&ofn))
129 {
130 WCHAR* last_slash = strrchrW(ofn.lpstrFile, '\\');
131 if (last_slash) *last_slash = 0;
132 SetDlgItemTextW(hwnd, IDC_PATH, ofn.lpstrFile);
133 }
134 HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
135 }
136
137 /* Handles the messages sent to the SetupPromptForDisk dialog
138 */
promptdisk_proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)139 static INT_PTR CALLBACK promptdisk_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
140 {
141 switch(msg)
142 {
143 case WM_INITDIALOG:
144 promptdisk_init(hwnd, (struct promptdisk_params *)lParam);
145 return TRUE;
146 case WM_COMMAND:
147 switch(wParam)
148 {
149 case IDOK:
150 {
151 struct promptdisk_params *params =
152 (struct promptdisk_params *)GetWindowLongPtrW(hwnd, DWLP_USER);
153 promptdisk_ok(hwnd, params);
154 return TRUE;
155 }
156 case IDCANCEL:
157 EndDialog(hwnd, DPROMPT_CANCEL);
158 return TRUE;
159 case IDC_RUNDLG_BROWSE:
160 {
161 struct promptdisk_params *params =
162 (struct promptdisk_params *)GetWindowLongPtrW(hwnd, DWLP_USER);
163 promptdisk_browse(hwnd, params);
164 return TRUE;
165 }
166 }
167 }
168 return FALSE;
169 }
170
171 /***********************************************************************
172 * SetupPromptForDiskA (SETUPAPI.@)
173 */
SetupPromptForDiskA(HWND hwndParent,PCSTR DialogTitle,PCSTR DiskName,PCSTR PathToSource,PCSTR FileSought,PCSTR TagFile,DWORD DiskPromptStyle,PSTR PathBuffer,DWORD PathBufferSize,PDWORD PathRequiredSize)174 UINT WINAPI SetupPromptForDiskA(HWND hwndParent, PCSTR DialogTitle, PCSTR DiskName,
175 PCSTR PathToSource, PCSTR FileSought, PCSTR TagFile, DWORD DiskPromptStyle,
176 PSTR PathBuffer, DWORD PathBufferSize, PDWORD PathRequiredSize)
177 {
178 WCHAR *DialogTitleW, *DiskNameW, *PathToSourceW;
179 WCHAR *FileSoughtW, *TagFileW, PathBufferW[MAX_PATH];
180 UINT ret, length;
181
182 TRACE("%p, %s, %s, %s, %s, %s, 0x%08x, %p, %d, %p\n", hwndParent, debugstr_a(DialogTitle),
183 debugstr_a(DiskName), debugstr_a(PathToSource), debugstr_a(FileSought),
184 debugstr_a(TagFile), DiskPromptStyle, PathBuffer, PathBufferSize,
185 PathRequiredSize);
186
187 DialogTitleW = strdupAtoW(DialogTitle);
188 DiskNameW = strdupAtoW(DiskName);
189 PathToSourceW = strdupAtoW(PathToSource);
190 FileSoughtW = strdupAtoW(FileSought);
191 TagFileW = strdupAtoW(TagFile);
192
193 ret = SetupPromptForDiskW(hwndParent, DialogTitleW, DiskNameW, PathToSourceW,
194 FileSoughtW, TagFileW, DiskPromptStyle, PathBufferW, MAX_PATH, PathRequiredSize);
195
196 HeapFree(GetProcessHeap(), 0, DialogTitleW);
197 HeapFree(GetProcessHeap(), 0, DiskNameW);
198 HeapFree(GetProcessHeap(), 0, PathToSourceW);
199 HeapFree(GetProcessHeap(), 0, FileSoughtW);
200 HeapFree(GetProcessHeap(), 0, TagFileW);
201
202 if(ret == DPROMPT_SUCCESS)
203 {
204 length = WideCharToMultiByte(CP_ACP, 0, PathBufferW, -1, NULL, 0, NULL, NULL);
205 if(PathRequiredSize) *PathRequiredSize = length;
206 if(PathBuffer)
207 {
208 if(length > PathBufferSize)
209 return DPROMPT_BUFFERTOOSMALL;
210 WideCharToMultiByte(CP_ACP, 0, PathBufferW, -1, PathBuffer, length, NULL, NULL);
211 }
212 }
213 return ret;
214 }
215
216 /***********************************************************************
217 * SetupPromptForDiskW (SETUPAPI.@)
218 */
SetupPromptForDiskW(HWND hwndParent,PCWSTR DialogTitle,PCWSTR DiskName,PCWSTR PathToSource,PCWSTR FileSought,PCWSTR TagFile,DWORD DiskPromptStyle,PWSTR PathBuffer,DWORD PathBufferSize,PDWORD PathRequiredSize)219 UINT WINAPI SetupPromptForDiskW(HWND hwndParent, PCWSTR DialogTitle, PCWSTR DiskName,
220 PCWSTR PathToSource, PCWSTR FileSought, PCWSTR TagFile, DWORD DiskPromptStyle,
221 PWSTR PathBuffer, DWORD PathBufferSize, PDWORD PathRequiredSize)
222 {
223 struct promptdisk_params params;
224 UINT ret;
225
226 TRACE("%p, %s, %s, %s, %s, %s, 0x%08x, %p, %d, %p\n", hwndParent, debugstr_w(DialogTitle),
227 debugstr_w(DiskName), debugstr_w(PathToSource), debugstr_w(FileSought),
228 debugstr_w(TagFile), DiskPromptStyle, PathBuffer, PathBufferSize,
229 PathRequiredSize);
230
231 if(!FileSought)
232 {
233 SetLastError(ERROR_INVALID_PARAMETER);
234 return DPROMPT_CANCEL;
235 }
236
237 if (PathToSource && (DiskPromptStyle & IDF_CHECKFIRST))
238 {
239 static const WCHAR format[] = {'%', 's', '\\', '%', 's', '\0'};
240 WCHAR filepath[MAX_PATH];
241
242 if (strlenW(PathToSource) + 1 + strlenW(FileSought) < sizeof(filepath))
243 {
244 snprintfW(filepath, MAX_PATH, format, PathToSource, FileSought);
245
246 if (GetFileAttributesW(filepath) != INVALID_FILE_ATTRIBUTES)
247 {
248 if (PathRequiredSize)
249 *PathRequiredSize = strlenW(PathToSource) + 1;
250
251 if (!PathBuffer)
252 return DPROMPT_SUCCESS;
253
254 if (PathBufferSize >= strlenW(PathToSource) + 1)
255 {
256 strcpyW(PathBuffer, PathToSource);
257 return DPROMPT_SUCCESS;
258 }
259 else
260 return DPROMPT_BUFFERTOOSMALL;
261 }
262 }
263 }
264
265 params.DialogTitle = DialogTitle;
266 params.DiskName = DiskName;
267 params.PathToSource = PathToSource;
268 params.FileSought = FileSought;
269 params.TagFile = TagFile;
270 params.DiskPromptStyle = DiskPromptStyle;
271 params.PathBuffer = PathBuffer;
272 params.PathBufferSize = PathBufferSize;
273 params.PathRequiredSize = PathRequiredSize;
274
275 ret = DialogBoxParamW(hInstance, MAKEINTRESOURCEW(IDPROMPTFORDISK),
276 hwndParent, promptdisk_proc, (LPARAM)¶ms);
277
278 if(ret == DPROMPT_CANCEL)
279 SetLastError(ERROR_CANCELLED);
280 return ret;
281 }
282