2009-02-18 09:44:15 +01:00
|
|
|
/*
|
|
|
|
* SetupAPI dialog functions
|
|
|
|
*
|
|
|
|
* Copyright 2009 Ricardo Filipe
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "wine/debug.h"
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "wingdi.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "winreg.h"
|
|
|
|
#include "commdlg.h"
|
|
|
|
#include "setupapi.h"
|
|
|
|
#include "winnls.h"
|
|
|
|
#include "setupapi_private.h"
|
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
|
|
|
|
|
|
|
struct promptdisk_params {
|
|
|
|
PCWSTR DialogTitle;
|
|
|
|
PCWSTR DiskName;
|
|
|
|
PCWSTR PathToSource;
|
|
|
|
PCWSTR FileSought;
|
|
|
|
PCWSTR TagFile;
|
|
|
|
DWORD DiskPromptStyle;
|
|
|
|
PWSTR PathBuffer;
|
|
|
|
DWORD PathBufferSize;
|
|
|
|
PDWORD PathRequiredSize;
|
|
|
|
};
|
|
|
|
|
2009-02-18 04:35:26 +01:00
|
|
|
/* initiates the fields of the SetupPromptForDisk dialog according to the parameters
|
|
|
|
*/
|
|
|
|
static void promptdisk_init(HWND hwnd, struct promptdisk_params *params)
|
|
|
|
{
|
|
|
|
SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)params);
|
|
|
|
|
|
|
|
if(params->DialogTitle)
|
|
|
|
SetWindowTextW(hwnd, params->DialogTitle);
|
|
|
|
if(params->PathToSource)
|
|
|
|
SetDlgItemTextW(hwnd, IDC_PATH, params->PathToSource);
|
|
|
|
|
|
|
|
if(!(params->DiskPromptStyle & IDF_OEMDISK))
|
|
|
|
{
|
2011-11-19 15:12:05 +01:00
|
|
|
WCHAR message[256+2*MAX_PATH];
|
|
|
|
WCHAR format[256];
|
|
|
|
WCHAR unknown[256];
|
|
|
|
DWORD_PTR args[2];
|
2018-09-15 00:10:28 +02:00
|
|
|
LoadStringW(SETUPAPI_hInstance, IDS_PROMPTDISK, format, ARRAY_SIZE(format));
|
2009-02-18 04:35:26 +01:00
|
|
|
|
2011-11-19 15:12:05 +01:00
|
|
|
args[0] = (DWORD_PTR)params->FileSought;
|
2009-02-18 04:35:26 +01:00
|
|
|
if(params->DiskName)
|
2011-11-19 15:12:05 +01:00
|
|
|
args[1] = (DWORD_PTR)params->DiskName;
|
2009-02-18 04:35:26 +01:00
|
|
|
else
|
|
|
|
{
|
2018-09-15 00:10:28 +02:00
|
|
|
LoadStringW(SETUPAPI_hInstance, IDS_UNKNOWN, unknown, ARRAY_SIZE(unknown));
|
2011-11-19 15:12:05 +01:00
|
|
|
args[1] = (DWORD_PTR)unknown;
|
2009-02-18 04:35:26 +01:00
|
|
|
}
|
2011-11-19 15:12:05 +01:00
|
|
|
FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
2018-09-15 00:10:28 +02:00
|
|
|
format, 0, 0, message, ARRAY_SIZE(message), (__ms_va_list*)args);
|
2009-02-18 04:35:26 +01:00
|
|
|
SetDlgItemTextW(hwnd, IDC_FILENEEDED, message);
|
|
|
|
|
2018-09-15 00:10:28 +02:00
|
|
|
LoadStringW(SETUPAPI_hInstance, IDS_INFO, message, ARRAY_SIZE(message));
|
2009-02-18 04:35:26 +01:00
|
|
|
SetDlgItemTextW(hwnd, IDC_INFO, message);
|
2018-09-15 00:10:28 +02:00
|
|
|
LoadStringW(SETUPAPI_hInstance, IDS_COPYFROM, message, ARRAY_SIZE(message));
|
2009-02-18 04:35:26 +01:00
|
|
|
SetDlgItemTextW(hwnd, IDC_COPYFROM, message);
|
|
|
|
}
|
|
|
|
if(params->DiskPromptStyle & IDF_NOBROWSE)
|
|
|
|
ShowWindow(GetDlgItem(hwnd, IDC_RUNDLG_BROWSE), SW_HIDE);
|
|
|
|
}
|
|
|
|
|
2009-02-18 04:46:01 +01:00
|
|
|
/* When the user clicks in the Ok button in SetupPromptForDisk dialog
|
|
|
|
* if the parameters are good it copies the path from the dialog to the output buffer
|
|
|
|
* saves the required size for the buffer if PathRequiredSize is given
|
|
|
|
* returns NO_ERROR if there is no PathBuffer to copy too
|
|
|
|
* returns DPROMPT_BUFFERTOOSMALL if the path is too big to fit in PathBuffer
|
|
|
|
*/
|
|
|
|
static void promptdisk_ok(HWND hwnd, struct promptdisk_params *params)
|
|
|
|
{
|
|
|
|
int requiredSize;
|
|
|
|
WCHAR aux[MAX_PATH];
|
|
|
|
GetWindowTextW(GetDlgItem(hwnd, IDC_PATH), aux, MAX_PATH);
|
2019-07-04 15:41:03 +02:00
|
|
|
requiredSize = lstrlenW(aux)+1;
|
2009-02-18 04:46:01 +01:00
|
|
|
|
|
|
|
if(params->PathRequiredSize)
|
|
|
|
{
|
|
|
|
*params->PathRequiredSize = requiredSize;
|
2022-02-17 07:13:03 +01:00
|
|
|
TRACE("returning PathRequiredSize=%ld\n",*params->PathRequiredSize);
|
2009-02-18 04:46:01 +01:00
|
|
|
}
|
2009-03-23 18:05:59 +01:00
|
|
|
if(!params->PathBuffer)
|
2009-02-18 04:46:01 +01:00
|
|
|
{
|
|
|
|
EndDialog(hwnd, NO_ERROR);
|
|
|
|
return;
|
|
|
|
}
|
2009-03-23 18:05:59 +01:00
|
|
|
if(requiredSize > params->PathBufferSize)
|
2009-02-18 04:46:01 +01:00
|
|
|
{
|
|
|
|
EndDialog(hwnd, DPROMPT_BUFFERTOOSMALL);
|
|
|
|
return;
|
|
|
|
}
|
2019-07-04 15:41:03 +02:00
|
|
|
lstrcpyW(params->PathBuffer, aux);
|
2009-02-18 04:46:01 +01:00
|
|
|
TRACE("returning PathBuffer=%s\n", debugstr_w(params->PathBuffer));
|
|
|
|
EndDialog(hwnd, DPROMPT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2009-02-18 04:40:15 +01:00
|
|
|
/* When the user clicks the browse button in SetupPromptForDisk dialog
|
|
|
|
* it copies the path of the selected file to the dialog path field
|
|
|
|
*/
|
|
|
|
static void promptdisk_browse(HWND hwnd, struct promptdisk_params *params)
|
|
|
|
{
|
|
|
|
OPENFILENAMEW ofn;
|
|
|
|
ZeroMemory(&ofn, sizeof(ofn));
|
|
|
|
|
|
|
|
ofn.lStructSize = sizeof(ofn);
|
|
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
|
|
|
|
ofn.hwndOwner = hwnd;
|
|
|
|
ofn.nMaxFile = MAX_PATH;
|
|
|
|
ofn.lpstrFile = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR));
|
2019-07-04 15:41:03 +02:00
|
|
|
lstrcpyW(ofn.lpstrFile, params->FileSought);
|
2009-02-18 04:40:15 +01:00
|
|
|
|
|
|
|
if(GetOpenFileNameW(&ofn))
|
|
|
|
{
|
2019-07-04 15:41:03 +02:00
|
|
|
WCHAR* last_slash = wcsrchr(ofn.lpstrFile, '\\');
|
2009-02-18 04:40:15 +01:00
|
|
|
if (last_slash) *last_slash = 0;
|
|
|
|
SetDlgItemTextW(hwnd, IDC_PATH, ofn.lpstrFile);
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
|
|
|
|
}
|
|
|
|
|
2009-02-18 09:44:15 +01:00
|
|
|
/* Handles the messages sent to the SetupPromptForDisk dialog
|
|
|
|
*/
|
|
|
|
static INT_PTR CALLBACK promptdisk_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch(msg)
|
|
|
|
{
|
2009-02-18 04:35:26 +01:00
|
|
|
case WM_INITDIALOG:
|
|
|
|
promptdisk_init(hwnd, (struct promptdisk_params *)lParam);
|
|
|
|
return TRUE;
|
2009-02-18 09:44:15 +01:00
|
|
|
case WM_COMMAND:
|
|
|
|
switch(wParam)
|
|
|
|
{
|
2009-02-18 04:46:01 +01:00
|
|
|
case IDOK:
|
|
|
|
{
|
|
|
|
struct promptdisk_params *params =
|
|
|
|
(struct promptdisk_params *)GetWindowLongPtrW(hwnd, DWLP_USER);
|
|
|
|
promptdisk_ok(hwnd, params);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-02-18 09:44:15 +01:00
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hwnd, DPROMPT_CANCEL);
|
|
|
|
return TRUE;
|
2009-02-18 04:40:15 +01:00
|
|
|
case IDC_RUNDLG_BROWSE:
|
|
|
|
{
|
|
|
|
struct promptdisk_params *params =
|
|
|
|
(struct promptdisk_params *)GetWindowLongPtrW(hwnd, DWLP_USER);
|
|
|
|
promptdisk_browse(hwnd, params);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-02-18 09:44:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-03-02 17:21:28 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* SetupPromptForDiskA (SETUPAPI.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI SetupPromptForDiskA(HWND hwndParent, PCSTR DialogTitle, PCSTR DiskName,
|
|
|
|
PCSTR PathToSource, PCSTR FileSought, PCSTR TagFile, DWORD DiskPromptStyle,
|
|
|
|
PSTR PathBuffer, DWORD PathBufferSize, PDWORD PathRequiredSize)
|
|
|
|
{
|
|
|
|
WCHAR *DialogTitleW, *DiskNameW, *PathToSourceW;
|
|
|
|
WCHAR *FileSoughtW, *TagFileW, PathBufferW[MAX_PATH];
|
|
|
|
UINT ret, length;
|
|
|
|
|
2022-02-17 07:13:03 +01:00
|
|
|
TRACE("%p, %s, %s, %s, %s, %s, 0x%08lx, %p, %ld, %p\n", hwndParent, debugstr_a(DialogTitle),
|
2009-03-02 17:21:28 +01:00
|
|
|
debugstr_a(DiskName), debugstr_a(PathToSource), debugstr_a(FileSought),
|
|
|
|
debugstr_a(TagFile), DiskPromptStyle, PathBuffer, PathBufferSize,
|
|
|
|
PathRequiredSize);
|
|
|
|
|
|
|
|
DialogTitleW = strdupAtoW(DialogTitle);
|
|
|
|
DiskNameW = strdupAtoW(DiskName);
|
|
|
|
PathToSourceW = strdupAtoW(PathToSource);
|
|
|
|
FileSoughtW = strdupAtoW(FileSought);
|
|
|
|
TagFileW = strdupAtoW(TagFile);
|
|
|
|
|
|
|
|
ret = SetupPromptForDiskW(hwndParent, DialogTitleW, DiskNameW, PathToSourceW,
|
|
|
|
FileSoughtW, TagFileW, DiskPromptStyle, PathBufferW, MAX_PATH, PathRequiredSize);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, DialogTitleW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, DiskNameW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, PathToSourceW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, FileSoughtW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, TagFileW);
|
|
|
|
|
|
|
|
if(ret == DPROMPT_SUCCESS)
|
|
|
|
{
|
|
|
|
length = WideCharToMultiByte(CP_ACP, 0, PathBufferW, -1, NULL, 0, NULL, NULL);
|
|
|
|
if(PathRequiredSize) *PathRequiredSize = length;
|
|
|
|
if(PathBuffer)
|
|
|
|
{
|
|
|
|
if(length > PathBufferSize)
|
|
|
|
return DPROMPT_BUFFERTOOSMALL;
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, PathBufferW, -1, PathBuffer, length, NULL, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-02-18 09:44:15 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* SetupPromptForDiskW (SETUPAPI.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI SetupPromptForDiskW(HWND hwndParent, PCWSTR DialogTitle, PCWSTR DiskName,
|
|
|
|
PCWSTR PathToSource, PCWSTR FileSought, PCWSTR TagFile, DWORD DiskPromptStyle,
|
|
|
|
PWSTR PathBuffer, DWORD PathBufferSize, PDWORD PathRequiredSize)
|
|
|
|
{
|
|
|
|
struct promptdisk_params params;
|
|
|
|
UINT ret;
|
|
|
|
|
2022-02-17 07:13:03 +01:00
|
|
|
TRACE("%p, %s, %s, %s, %s, %s, 0x%08lx, %p, %ld, %p\n", hwndParent, debugstr_w(DialogTitle),
|
2009-02-18 09:44:15 +01:00
|
|
|
debugstr_w(DiskName), debugstr_w(PathToSource), debugstr_w(FileSought),
|
|
|
|
debugstr_w(TagFile), DiskPromptStyle, PathBuffer, PathBufferSize,
|
|
|
|
PathRequiredSize);
|
|
|
|
|
|
|
|
if(!FileSought)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return DPROMPT_CANCEL;
|
|
|
|
}
|
2020-01-11 21:06:39 +01:00
|
|
|
|
|
|
|
if (PathToSource && (DiskPromptStyle & IDF_CHECKFIRST))
|
|
|
|
{
|
|
|
|
WCHAR filepath[MAX_PATH];
|
|
|
|
|
|
|
|
if (lstrlenW(PathToSource) + 1 + lstrlenW(FileSought) < ARRAY_SIZE(filepath))
|
|
|
|
{
|
|
|
|
swprintf(filepath, ARRAY_SIZE(filepath), L"%s\\%s", PathToSource, FileSought);
|
|
|
|
if (GetFileAttributesW(filepath) != INVALID_FILE_ATTRIBUTES)
|
|
|
|
{
|
|
|
|
if (PathRequiredSize)
|
|
|
|
*PathRequiredSize = lstrlenW(PathToSource) + 1;
|
|
|
|
|
|
|
|
if (!PathBuffer)
|
|
|
|
return DPROMPT_SUCCESS;
|
|
|
|
|
|
|
|
if (PathBufferSize >= lstrlenW(PathToSource) + 1)
|
|
|
|
{
|
|
|
|
lstrcpyW(PathBuffer, PathToSource);
|
|
|
|
return DPROMPT_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return DPROMPT_BUFFERTOOSMALL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-18 09:44:15 +01:00
|
|
|
params.DialogTitle = DialogTitle;
|
|
|
|
params.DiskName = DiskName;
|
|
|
|
params.PathToSource = PathToSource;
|
|
|
|
params.FileSought = FileSought;
|
|
|
|
params.TagFile = TagFile;
|
|
|
|
params.DiskPromptStyle = DiskPromptStyle;
|
|
|
|
params.PathBuffer = PathBuffer;
|
|
|
|
params.PathBufferSize = PathBufferSize;
|
|
|
|
params.PathRequiredSize = PathRequiredSize;
|
|
|
|
|
|
|
|
ret = DialogBoxParamW(SETUPAPI_hInstance, MAKEINTRESOURCEW(IDPROMPTFORDISK),
|
|
|
|
hwndParent, promptdisk_proc, (LPARAM)¶ms);
|
|
|
|
|
|
|
|
if(ret == DPROMPT_CANCEL)
|
|
|
|
SetLastError(ERROR_CANCELLED);
|
|
|
|
return ret;
|
|
|
|
}
|