xref: /reactos/dll/win32/setupapi/dialog.c (revision bebdfda8)
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)&params);
277 
278     if(ret == DPROMPT_CANCEL)
279         SetLastError(ERROR_CANCELLED);
280     return ret;
281 }
282