Implement MsiPreviewDialog.
This commit is contained in:
parent
9b634b97ae
commit
479213c455
|
@ -10,6 +10,7 @@ C_SRCS = \
|
|||
action.c \
|
||||
create.c \
|
||||
custom.c \
|
||||
dialog.c \
|
||||
distinct.c \
|
||||
format.c \
|
||||
handle.c \
|
||||
|
|
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
* Implementation of the Microsoft Installer (msi.dll)
|
||||
*
|
||||
* Copyright 2005 Mike McCormack for CodeWeavers
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "winnls.h"
|
||||
#include "wingdi.h"
|
||||
#include "msi.h"
|
||||
#include "msipriv.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
|
||||
const WCHAR szMsiDialogClass[] = {
|
||||
'M','s','i','D','i','a','l','o','g','C','l','o','s','e','C','l','a','s','s',0
|
||||
};
|
||||
|
||||
struct tag_dialog_info
|
||||
{
|
||||
MSIPACKAGE *package;
|
||||
msi_dialog_event_handler event_handler;
|
||||
INT scale;
|
||||
HWND hwnd;
|
||||
WCHAR name[1];
|
||||
};
|
||||
|
||||
typedef UINT (*msi_dialog_control_func)( dialog_info *dialog, MSIRECORD *rec );
|
||||
struct control_handler
|
||||
{
|
||||
LPCWSTR control_type;
|
||||
msi_dialog_control_func func;
|
||||
};
|
||||
|
||||
static UINT msi_dialog_text_control( dialog_info *dialog, MSIRECORD *rec )
|
||||
{
|
||||
DWORD x, y, width, height;
|
||||
LPCWSTR text;
|
||||
const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
|
||||
HWND hwnd;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
x = MSI_RecordGetInteger( rec, 4 );
|
||||
y = MSI_RecordGetInteger( rec, 5 );
|
||||
width = MSI_RecordGetInteger( rec, 6 );
|
||||
height = MSI_RecordGetInteger( rec, 7 );
|
||||
text = MSI_RecordGetString( rec, 10 );
|
||||
|
||||
x = (dialog->scale * x) / 10;
|
||||
y = (dialog->scale * y) / 10;
|
||||
width = (dialog->scale * width) / 10;
|
||||
height = (dialog->scale * height) / 10;
|
||||
|
||||
hwnd = CreateWindowW( szStatic, text, WS_CHILD | WS_VISIBLE |WS_GROUP,
|
||||
x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
|
||||
if (!hwnd)
|
||||
ERR("Failed to create hwnd\n");
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_button_control( dialog_info *dialog, MSIRECORD *rec )
|
||||
{
|
||||
const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
|
||||
DWORD x, y, width, height;
|
||||
LPCWSTR text;
|
||||
HWND hwnd;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
x = MSI_RecordGetInteger( rec, 4 );
|
||||
y = MSI_RecordGetInteger( rec, 5 );
|
||||
width = MSI_RecordGetInteger( rec, 6 );
|
||||
height = MSI_RecordGetInteger( rec, 7 );
|
||||
text = MSI_RecordGetString( rec, 10 );
|
||||
|
||||
x = (dialog->scale * x) / 10;
|
||||
y = (dialog->scale * y) / 10;
|
||||
width = (dialog->scale * width) / 10;
|
||||
height = (dialog->scale * height) / 10;
|
||||
|
||||
hwnd = CreateWindowW( szButton, text, WS_CHILD | WS_VISIBLE |WS_GROUP,
|
||||
x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_line_control( dialog_info *dialog, MSIRECORD *rec )
|
||||
{
|
||||
DWORD x, y, width, height;
|
||||
LPCWSTR text;
|
||||
const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
|
||||
HWND hwnd;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
x = MSI_RecordGetInteger( rec, 4 );
|
||||
y = MSI_RecordGetInteger( rec, 5 );
|
||||
width = MSI_RecordGetInteger( rec, 6 );
|
||||
height = MSI_RecordGetInteger( rec, 7 );
|
||||
text = MSI_RecordGetString( rec, 10 );
|
||||
|
||||
x = (dialog->scale * x) / 10;
|
||||
y = (dialog->scale * y) / 10;
|
||||
width = (dialog->scale * width) / 10;
|
||||
height = (dialog->scale * height) / 10;
|
||||
|
||||
hwnd = CreateWindowW( szStatic, text, WS_CHILD | WS_VISIBLE |WS_GROUP |
|
||||
SS_ETCHEDHORZ |SS_SUNKEN,
|
||||
x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
|
||||
if (!hwnd)
|
||||
ERR("Failed to create hwnd\n");
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static UINT msi_load_picture( MSIDATABASE *db, LPCWSTR name, HBITMAP *hbm )
|
||||
{
|
||||
IPicture *pic = NULL;
|
||||
IPersistFile *pf = NULL;
|
||||
IStream *stm = NULL;
|
||||
HRESULT r;
|
||||
|
||||
r = CoCreateObject( &CLSID_Picture, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IPicture, (LPVOID*)&pic );
|
||||
if (FAILED(r))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = IPicture_QueryInterface( pic, &IID_IPersistFile, (LPVOID*) &pf );
|
||||
if (SUCCEEDED(r) )
|
||||
{
|
||||
r = IPersistFile_Load( pf, stm );
|
||||
IPersistFile_Release( pf );
|
||||
}
|
||||
|
||||
if (SUCCEEDED(r) )
|
||||
IPicture_get_Handle( pic, hbm );
|
||||
IPicture_Release( pic );
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
static UINT msi_dialog_bitmap_control( dialog_info *dialog, MSIRECORD *rec )
|
||||
{
|
||||
DWORD x, y, width, height;
|
||||
LPCWSTR text;
|
||||
const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
|
||||
HWND hwnd;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
x = MSI_RecordGetInteger( rec, 4 );
|
||||
y = MSI_RecordGetInteger( rec, 5 );
|
||||
width = MSI_RecordGetInteger( rec, 6 );
|
||||
height = MSI_RecordGetInteger( rec, 7 );
|
||||
text = MSI_RecordGetString( rec, 10 );
|
||||
|
||||
x = (dialog->scale * x) / 10;
|
||||
y = (dialog->scale * y) / 10;
|
||||
width = (dialog->scale * width) / 10;
|
||||
height = (dialog->scale * height) / 10;
|
||||
|
||||
hwnd = CreateWindowW( szStatic, text, WS_CHILD | WS_VISIBLE |WS_GROUP | WS_DISABLED |
|
||||
SS_BITMAP | SS_LEFT | SS_CENTERIMAGE,
|
||||
x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
|
||||
if (!hwnd)
|
||||
ERR("Failed to create hwnd\n");
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static const WCHAR szText[] = { 'T','e','x','t',0 };
|
||||
static const WCHAR szButton[] = { 'P','u','s','h','B','u','t','t','o','n',0 };
|
||||
static const WCHAR szLine[] = { 'L','i','n','e',0 };
|
||||
static const WCHAR szBitmap[] = { 'B','i','t','m','a','p',0 };
|
||||
|
||||
struct control_handler msi_dialog_handler[] =
|
||||
{
|
||||
{ szText, msi_dialog_text_control },
|
||||
{ szButton, msi_dialog_button_control },
|
||||
{ szLine, msi_dialog_line_control },
|
||||
{ szBitmap, msi_dialog_bitmap_control },
|
||||
};
|
||||
|
||||
#define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0])
|
||||
|
||||
typedef UINT (*record_func)( MSIRECORD *rec, LPVOID param );
|
||||
|
||||
static UINT msi_iterate_records( MSIQUERY *view, record_func func, LPVOID param )
|
||||
{
|
||||
MSIRECORD *rec = NULL;
|
||||
UINT r;
|
||||
|
||||
r = MSI_ViewExecute( view, NULL );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
||||
/* iterate a query */
|
||||
while( 1 )
|
||||
{
|
||||
r = MSI_ViewFetch( view, &rec );
|
||||
if( r != ERROR_SUCCESS )
|
||||
break;
|
||||
r = func( rec, param );
|
||||
msiobj_release( &rec->hdr );
|
||||
if( r != ERROR_SUCCESS )
|
||||
break;
|
||||
}
|
||||
|
||||
MSI_ViewClose( view );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_create_controls( MSIRECORD *rec, LPVOID param )
|
||||
{
|
||||
dialog_info *dialog = param;
|
||||
LPCWSTR control_type;
|
||||
UINT i;
|
||||
|
||||
/* find and call the function that can create this type of control */
|
||||
control_type = MSI_RecordGetString( rec, 3 );
|
||||
for( i=0; i<NUM_CONTROL_TYPES; i++ )
|
||||
if (!strcmpiW( msi_dialog_handler[i].control_type, control_type ))
|
||||
break;
|
||||
if( i != NUM_CONTROL_TYPES )
|
||||
msi_dialog_handler[i].func( dialog, rec );
|
||||
else
|
||||
ERR("no handler for element type %s\n", debugstr_w(control_type));
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_fill_controls( dialog_info *dialog, LPCWSTR name )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
'S','E','L','E','C','T',' ','*',' ',
|
||||
'F','R','O','M',' ','C','o','n','t','r','o','l',' ',
|
||||
'W','H','E','R','E',' ',
|
||||
'`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',0};
|
||||
UINT r;
|
||||
MSIQUERY *view = NULL;
|
||||
MSIPACKAGE *package = dialog->package;
|
||||
|
||||
TRACE("%p %s\n", dialog, debugstr_w(name) );
|
||||
|
||||
/* query the Control table for all the elements of the control */
|
||||
r = MSI_OpenQuery( package->db, &view, query, name );
|
||||
if( r != ERROR_SUCCESS )
|
||||
{
|
||||
ERR("query failed for dialog %s\n", debugstr_w(name));
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
r = msi_iterate_records( view, msi_dialog_create_controls, dialog );
|
||||
msiobj_release( &view->hdr );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* figure out the height of 10 point MS Sans Serif */
|
||||
static INT msi_dialog_get_sans_serif_height( HWND hwnd )
|
||||
{
|
||||
static const WCHAR szSansSerif[] = {
|
||||
'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0 };
|
||||
LOGFONTW lf;
|
||||
TEXTMETRICW tm;
|
||||
BOOL r;
|
||||
LONG height = 0;
|
||||
HFONT hFont, hOldFont;
|
||||
HDC hdc;
|
||||
|
||||
hdc = GetDC( hwnd );
|
||||
if (hdc)
|
||||
{
|
||||
memset( &lf, 0, sizeof lf );
|
||||
lf.lfHeight = -MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
||||
strcpyW( lf.lfFaceName, szSansSerif );
|
||||
hFont = CreateFontIndirectW(&lf);
|
||||
if (hFont)
|
||||
{
|
||||
hOldFont = SelectObject( hdc, hFont );
|
||||
r = GetTextMetricsW( hdc, &tm );
|
||||
if (r)
|
||||
height = tm.tmHeight;
|
||||
SelectObject( hdc, hOldFont );
|
||||
DeleteObject( hFont );
|
||||
}
|
||||
ReleaseDC( hwnd, hdc );
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
'S','E','L','E','C','T',' ','*',' ',
|
||||
'F','R','O','M',' ','D','i','a','l','o','g',' ',
|
||||
'W','H','E','R','E',' ',
|
||||
'`','D','i','a','l','o','g','`',' ','=',' ','\'','%','s','\'',0};
|
||||
dialog_info *dialog = (dialog_info*) cs->lpCreateParams;
|
||||
MSIPACKAGE *package = dialog->package;
|
||||
MSIQUERY *view = NULL;
|
||||
MSIRECORD *rec = NULL;
|
||||
DWORD width, height;
|
||||
LPCWSTR title;
|
||||
UINT r;
|
||||
|
||||
TRACE("%p %p\n", dialog, package);
|
||||
|
||||
dialog->hwnd = hwnd;
|
||||
SetWindowLongPtrW( hwnd, GWLP_USERDATA, (LONG_PTR) dialog );
|
||||
|
||||
/* fetch the associated record from the Dialog table */
|
||||
r = MSI_OpenQuery( package->db, &view, query, dialog->name );
|
||||
if( r != ERROR_SUCCESS )
|
||||
{
|
||||
ERR("query failed for dialog %s\n", debugstr_w(dialog->name));
|
||||
return 1;
|
||||
}
|
||||
MSI_ViewExecute( view, NULL );
|
||||
MSI_ViewFetch( view, &rec );
|
||||
MSI_ViewClose( view );
|
||||
msiobj_release( &view->hdr );
|
||||
|
||||
if( !rec )
|
||||
{
|
||||
ERR("No record found for dialog %s\n", debugstr_w(dialog->name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
dialog->scale = msi_dialog_get_sans_serif_height(dialog->hwnd);
|
||||
|
||||
width = MSI_RecordGetInteger( rec, 4 );
|
||||
height = MSI_RecordGetInteger( rec, 5 );
|
||||
title = MSI_RecordGetString( rec, 7 );
|
||||
|
||||
width = (dialog->scale * width) / 10;
|
||||
height = (dialog->scale * height) / 10;
|
||||
|
||||
SetWindowTextW( hwnd, title );
|
||||
SetWindowPos( hwnd, 0, 0, 0, width, height,
|
||||
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW );
|
||||
|
||||
msiobj_release( &rec->hdr );
|
||||
|
||||
msi_dialog_fill_controls( dialog, dialog->name );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT msi_dialog_handle_click( dialog_info *dialog,
|
||||
DWORD id, HWND handle )
|
||||
{
|
||||
TRACE("BN_CLICKED %08lx %p\n", id, handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
dialog_info *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
return msi_dialog_oncreate( hwnd, (LPCREATESTRUCTW)lParam );
|
||||
|
||||
case WM_COMMAND:
|
||||
if( HIWORD(wParam) == BN_CLICKED )
|
||||
return msi_dialog_handle_click( dialog, LOWORD(wParam), (HWND)lParam );
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
dialog->hwnd = NULL;
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
/* functions that interface to other modules within MSI */
|
||||
|
||||
dialog_info *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
|
||||
msi_dialog_event_handler event_handler )
|
||||
{
|
||||
dialog_info *dialog;
|
||||
HWND hwnd;
|
||||
|
||||
TRACE("%p %s\n", package, debugstr_w(szDialogName));
|
||||
|
||||
/* allocate the structure for the dialog to use */
|
||||
dialog = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof *dialog + sizeof(WCHAR)*strlenW(szDialogName) );
|
||||
if( !dialog )
|
||||
return NULL;
|
||||
strcpyW( dialog->name, szDialogName );
|
||||
dialog->package = package;
|
||||
dialog->event_handler = event_handler;
|
||||
msiobj_addref( &package->hdr );
|
||||
|
||||
/* create and show the dialog window */
|
||||
hwnd = CreateWindowW( szMsiDialogClass, szDialogName, WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
NULL, NULL, NULL, dialog );
|
||||
if( !hwnd )
|
||||
{
|
||||
msi_dialog_destroy( dialog );
|
||||
return NULL;
|
||||
}
|
||||
ShowWindow( hwnd, SW_SHOW );
|
||||
UpdateWindow( hwnd );
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
void msi_dialog_destroy( dialog_info *dialog )
|
||||
{
|
||||
if( dialog->hwnd )
|
||||
DestroyWindow( dialog->hwnd );
|
||||
msiobj_release( &dialog->package->hdr );
|
||||
dialog->package = NULL;
|
||||
HeapFree( GetProcessHeap(), 0, dialog );
|
||||
}
|
||||
|
||||
void msi_dialog_register_class( void )
|
||||
{
|
||||
WNDCLASSW cls;
|
||||
|
||||
ZeroMemory( &cls, sizeof cls );
|
||||
cls.lpfnWndProc = MSIDialog_WndProc;
|
||||
cls.hInstance = NULL;
|
||||
cls.hIcon = LoadIconW(0, (LPWSTR)IDI_APPLICATION);
|
||||
cls.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
|
||||
cls.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
||||
cls.lpszMenuName = NULL;
|
||||
cls.lpszClassName = szMsiDialogClass;
|
||||
|
||||
RegisterClassW( &cls );
|
||||
}
|
||||
|
||||
void msi_dialog_unregister_class( void )
|
||||
{
|
||||
UnregisterClassW( szMsiDialogClass, NULL );
|
||||
}
|
|
@ -1467,8 +1467,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
msi_dialog_register_class();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
msi_dialog_unregister_class();
|
||||
/* FIXME: Cleanup */
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Implementation of the Microsoft Installer (msi.dll)
|
||||
*
|
||||
* Copyright 2002 Mike McCormack for CodeWeavers
|
||||
* Copyright 2002-2005 Mike McCormack for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -211,10 +211,14 @@ typedef struct tagMSIPACKAGE
|
|||
UINT CurrentInstallState;
|
||||
} MSIPACKAGE;
|
||||
|
||||
struct tag_dialog_info;
|
||||
typedef struct tag_dialog_info dialog_info;
|
||||
|
||||
typedef struct tagMSIPREVIEW
|
||||
{
|
||||
MSIOBJECTHDR hdr;
|
||||
MSIDATABASE *db;
|
||||
MSIPACKAGE *package;
|
||||
dialog_info *dialog;
|
||||
} MSIPREVIEW;
|
||||
|
||||
#define MSIHANDLETYPE_ANY 0
|
||||
|
@ -232,7 +236,7 @@ typedef struct tagMSIPREVIEW
|
|||
#define GUID_SIZE 39
|
||||
|
||||
#define MSIHANDLE_MAGIC 0x4d434923
|
||||
#define MSIMAXHANDLES 0x80
|
||||
#define MSIMAXHANDLES 0xf0
|
||||
|
||||
#define MSISUMINFO_OFFSET 0x30LL
|
||||
|
||||
|
@ -325,33 +329,41 @@ extern UINT MSI_ViewFetch( MSIQUERY*, MSIRECORD ** );
|
|||
extern UINT MSI_ViewClose( MSIQUERY* );
|
||||
|
||||
/* package internals */
|
||||
extern UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE ** );
|
||||
extern UINT MSI_SetTargetPathW( MSIPACKAGE *, LPCWSTR, LPCWSTR);
|
||||
extern MSIPACKAGE *MSI_CreatePackage( MSIDATABASE * );
|
||||
extern UINT MSI_OpenPackageW( LPCWSTR szPackage, MSIPACKAGE ** );
|
||||
extern UINT MSI_SetTargetPathW( MSIPACKAGE *, LPCWSTR, LPCWSTR );
|
||||
extern UINT MSI_SetPropertyW( MSIPACKAGE *, LPCWSTR, LPCWSTR );
|
||||
extern INT MSI_ProcessMessage( MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD* );
|
||||
extern UINT MSI_GetPropertyW( MSIPACKAGE *, LPCWSTR, LPWSTR, DWORD*);
|
||||
extern INT MSI_ProcessMessage( MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD * );
|
||||
extern UINT MSI_GetPropertyW( MSIPACKAGE *, LPCWSTR, LPWSTR, DWORD * );
|
||||
extern MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *, LPCWSTR );
|
||||
extern UINT MSI_SetPropertyW( MSIPACKAGE *, LPCWSTR, LPCWSTR );
|
||||
extern UINT MSI_GetComponentStateW(MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE *);
|
||||
extern UINT MSI_GetFeatureStateW(MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE *);
|
||||
extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE * );
|
||||
extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE * );
|
||||
|
||||
/* for deformating */
|
||||
extern UINT MSI_FormatRecordW(MSIPACKAGE* package, MSIRECORD* record,
|
||||
LPWSTR buffer, DWORD *size);
|
||||
|
||||
/* registry data encoding/decoding functions */
|
||||
BOOL unsquash_guid(LPCWSTR in, LPWSTR out);
|
||||
BOOL squash_guid(LPCWSTR in, LPWSTR out);
|
||||
BOOL encode_base85_guid(GUID *,LPWSTR);
|
||||
BOOL decode_base85_guid(LPCWSTR,GUID*);
|
||||
UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
UINT MSIREG_OpenFeatures(HKEY* key);
|
||||
UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
UINT MSIREG_OpenComponents(HKEY* key);
|
||||
UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
|
||||
UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
extern BOOL unsquash_guid(LPCWSTR in, LPWSTR out);
|
||||
extern BOOL squash_guid(LPCWSTR in, LPWSTR out);
|
||||
extern BOOL encode_base85_guid(GUID *,LPWSTR);
|
||||
extern BOOL decode_base85_guid(LPCWSTR,GUID*);
|
||||
extern UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
extern UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
extern UINT MSIREG_OpenFeatures(HKEY* key);
|
||||
extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
extern UINT MSIREG_OpenComponents(HKEY* key);
|
||||
extern UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
|
||||
extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
extern UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
|
||||
/* msi dialog interface */
|
||||
typedef VOID (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, HWND );
|
||||
extern dialog_info *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog_event_handler );
|
||||
extern void msi_dialog_destroy( dialog_info* );
|
||||
extern void msi_dialog_register_class( void );
|
||||
extern void msi_dialog_unregister_class( void );
|
||||
|
||||
/* UI globals */
|
||||
extern INSTALLUILEVEL gUILevel;
|
||||
|
|
|
@ -352,15 +352,14 @@ Privileged
|
|||
ReleaseDC(0, dc);
|
||||
}
|
||||
|
||||
UINT MSI_CreatePackage(MSIDATABASE *db, MSIPACKAGE **pPackage)
|
||||
MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
|
||||
{
|
||||
static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
|
||||
static const WCHAR szpi[] = {'%','i',0};
|
||||
MSIPACKAGE *package = NULL;
|
||||
WCHAR uilevel[10];
|
||||
UINT ret = ERROR_FUNCTION_FAILED;
|
||||
|
||||
TRACE("%p %p\n", db, pPackage);
|
||||
TRACE("%p\n", db);
|
||||
|
||||
package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
|
||||
MSI_FreePackage );
|
||||
|
@ -387,22 +386,15 @@ UINT MSI_CreatePackage(MSIDATABASE *db, MSIPACKAGE **pPackage)
|
|||
set_installer_properties(package);
|
||||
sprintfW(uilevel,szpi,gUILevel);
|
||||
MSI_SetPropertyW(package, szLevel, uilevel);
|
||||
|
||||
msiobj_addref( &package->hdr );
|
||||
*pPackage = package;
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
if( package )
|
||||
msiobj_release( &package->hdr );
|
||||
|
||||
return ret;
|
||||
return package;
|
||||
}
|
||||
|
||||
UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
||||
{
|
||||
MSIDATABASE *db = NULL;
|
||||
UINT ret = ERROR_FUNCTION_FAILED;
|
||||
MSIPACKAGE *package;
|
||||
MSIHANDLE handle;
|
||||
|
||||
TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
|
||||
|
@ -416,32 +408,34 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
|||
}
|
||||
else
|
||||
{
|
||||
ret = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
|
||||
if( ret != ERROR_SUCCESS )
|
||||
return ret;
|
||||
UINT r = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
}
|
||||
|
||||
ret = MSI_CreatePackage( db, pPackage );
|
||||
package = MSI_CreatePackage( db );
|
||||
msiobj_release( &db->hdr );
|
||||
if( !package )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
/*
|
||||
* FIXME: I don't think this is right. Maybe we should be storing the
|
||||
* name of the database in the MSIDATABASE structure and fetching this
|
||||
* info from there, or maybe this is only relevant to cached databases.
|
||||
*/
|
||||
if( ret == ERROR_SUCCESS && szPackage[0] != '#' )
|
||||
if( szPackage[0] != '#' )
|
||||
{
|
||||
static const WCHAR OriginalDatabase[] =
|
||||
{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
|
||||
static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
|
||||
|
||||
MSI_SetPropertyW(*pPackage, OriginalDatabase, szPackage);
|
||||
MSI_SetPropertyW(*pPackage, Database, szPackage);
|
||||
MSI_SetPropertyW( package, OriginalDatabase, szPackage );
|
||||
MSI_SetPropertyW( package, Database, szPackage );
|
||||
}
|
||||
|
||||
if( db )
|
||||
msiobj_release( &db->hdr );
|
||||
*pPackage = package;
|
||||
|
||||
return ret;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
|
||||
|
|
|
@ -22,32 +22,39 @@
|
|||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winreg.h"
|
||||
#include "winnls.h"
|
||||
#include "shlwapi.h"
|
||||
#include "wine/debug.h"
|
||||
#include "msi.h"
|
||||
#include "msipriv.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
static void MSI_ClosePreview( MSIOBJECTHDR *arg )
|
||||
{
|
||||
MSIPREVIEW *preview = (MSIPREVIEW *) arg;
|
||||
|
||||
msiobj_release( &preview->db->hdr );
|
||||
msiobj_release( &preview->package->hdr );
|
||||
}
|
||||
|
||||
MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE *db )
|
||||
{
|
||||
MSIPREVIEW *preview;
|
||||
MSIPREVIEW *preview = NULL;
|
||||
MSIPACKAGE *package;
|
||||
|
||||
preview = alloc_msiobject( MSIHANDLETYPE_PREVIEW, sizeof (MSIPREVIEW),
|
||||
MSI_ClosePreview );
|
||||
if( preview )
|
||||
package = MSI_CreatePackage( db );
|
||||
if( package )
|
||||
{
|
||||
preview->db = db;
|
||||
msiobj_addref( &db->hdr );
|
||||
preview = alloc_msiobject( MSIHANDLETYPE_PREVIEW, sizeof (MSIPREVIEW),
|
||||
MSI_ClosePreview );
|
||||
if( preview )
|
||||
{
|
||||
preview->package = package;
|
||||
preview->dialog = 0;
|
||||
msiobj_addref( &package->hdr );
|
||||
}
|
||||
msiobj_release( &package->hdr );
|
||||
}
|
||||
return preview;
|
||||
}
|
||||
|
@ -70,15 +77,54 @@ UINT WINAPI MsiEnableUIPreview( MSIHANDLE hdb, MSIHANDLE* phPreview )
|
|||
msiobj_release( &preview->hdr );
|
||||
r = ERROR_SUCCESS;
|
||||
}
|
||||
msiobj_release( &db->hdr );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static VOID preview_event_handler( MSIPACKAGE *package, LPCWSTR event,
|
||||
LPCWSTR argument, HWND dialog )
|
||||
{
|
||||
MESSAGE("Preview dialog event '%s' (arg='%s')\n",
|
||||
debugstr_w( event ), debugstr_w( argument ));
|
||||
}
|
||||
|
||||
UINT MSI_PreviewDialogW( MSIPREVIEW *preview, LPCWSTR szDialogName )
|
||||
{
|
||||
dialog_info *dialog = NULL;
|
||||
UINT r = ERROR_SUCCESS;
|
||||
|
||||
if( preview->dialog )
|
||||
msi_dialog_destroy( preview->dialog );
|
||||
|
||||
/* an empty name means we should just destroy the current preview dialog */
|
||||
if( szDialogName )
|
||||
{
|
||||
dialog = msi_dialog_create( preview->package, szDialogName,
|
||||
preview_event_handler );
|
||||
if( !dialog )
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
preview->dialog = dialog;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiPreviewDialogW( MSIHANDLE hPreview, LPCWSTR szDialogName )
|
||||
{
|
||||
FIXME("%ld %s\n", hPreview, debugstr_w(szDialogName));
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
MSIPREVIEW *preview;
|
||||
UINT r;
|
||||
|
||||
TRACE("%ld %s\n", hPreview, debugstr_w(szDialogName));
|
||||
|
||||
preview = msihandle2msiinfo( hPreview, MSIHANDLETYPE_PREVIEW );
|
||||
if( !preview )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
r = MSI_PreviewDialogW( preview, szDialogName );
|
||||
|
||||
msiobj_release( &preview->hdr );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiPreviewDialogA( MSIHANDLE hPreview, LPCSTR szDialogName )
|
||||
|
|
Loading…
Reference in New Issue