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