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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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