Files
reactos/reactos/lib/msi/update.c
Gé van Geldorp c4a2530191 Sync to Wine-20050211
Mike McCormack <mike@codeweavers.com>
- add support for Edit boxes in MSI dialogs
- run the message loop when waiting for threads or processes
- fix the dialog font
- allow waiting on a handle while running the message loop
- implement checkboxes in dialogs
- use TextStyle enumeration instead of numbers
- fix MSI_IterateRecords to return the correct count
- Add more dialog controls, do something when they're clicked on.
- Implement MsiPreviewDialog.
- Implement and document MsiLoadString.
- Added stub implementations for MsiPreviewDialog and
  MsiPreviewBillboard.
- Fix MsiModifyView and MsiViewGetColumnInfo to use MSIRECORD* not MSIHANDLE.
- Implement, test and document MsiDecomposeDescriptor.
- Handle a number as a parameter for custom action 19.
- Move OpenQuery into msiquery.c and make it non-static.
- Fix and test inserting records.
- Fix refcounting, use Interlocked functions.
- MsiEvaluateCondition returns an error when passed NULL as a
  condition.
- Lock record in MsiViewExecute, move stubs to end.
- Fix MsiRecordSetString for NULL strings and update test case.
- Fix a bug caused by freeing memory too soon in the table code.
- Update headers, add MsiGetUserInfoA stub implementation.
- Fix a memory leak in MsiConfigureProductExW.
- Indentation and style cleanup.
- implement MsiOpenPackageEx, and forward MsiOpenPackage there
- make a MSI_CreatePackage function and use it in MSI_OpenPackage
- move MsiOpenPackageA down with the rest of the API functions
Juan Lang <juan_lang@yahoo.com>
- Partially implement AppSearch action.
- If a full path isn't specified, search across all fixed drives.
- Simplify AppSearch error checking.
- Identifiers evaluate to true if they are non-empty, regardless of
  value.
Aric Stewart <aric@codeweavers.com>
- action.c is getting too big, so split out all the handling of
  CustomActions into custom.c. Cleaned up a lot of the handling of
  custom actions including scripting actions and processing return
  codes.
- Mike McCormack pointed out that MsiFormatRecord is basically the
  same as internal function deformat_string. So broke deformat_string
  out and updated it to function as MsiFormatRecord and implemented
  MsiFormatRecord.
- A number of random fixes to action.c including properly calculating
  the length for the LocalPackage name, not forcing a reboot when
  really we should just return ERROR_INSTALL_SUSPEND and handling
  REG_MULTI_SZ now that we can deformat the properly.
- Move the guid squishing functions out of msi.c and make a new
  registry.c file. Also clean up all the various registry keys we need
  to open and create to this module and modify the functions for msi.c
  to call these functions.
- Added a few more stub implementations.
- Implement custom action type 19, Halt install and display error
  message.
- Continued work to simplify the ProcessAction call, also split it into
  a ProcessAction and ProcessUIAction for future dialog box work.
  Also fix a bug in deformat_string where i was not freeing the created
  record.
- Make a temp file for each dll saved for custom actions. This prevents
  name collisions from causing custom actions to fail.
- Do not track the temp files for custom actions based on the name from
  the table because then we get conflicts and files not tracked or
  cleaned up.
- Add the RegisterUser action.
- Implement RegisterExtensionInfo and RegisterMIMEInfo.
- Add logic to be able to resolve the SourceDir based on
  CurrentPath. Also add logic to get the source locations of a file if
  it is not in a cabinet.
- Finish up the framework by stubbing out all the remaining Standard
  actions.
- A fix to deformat_string so it only returns a null return if you
  provided a null buffer.
- Eliminate the giant if.. else if block from ACTION_ProcessAction in
  favor of a table of handlers.
- Return code of the install should not depend on the return code of the
  final action.
- Update component installed states as they are installed so that
  conditions based on component states are at least a little more
  correct.
- Add icon and argument when regestering clsids.
- Add a stub for ResolveSource because we do that work just not in
  ResolveSource like we should.
- When quering a Component state return the correct state.
- Enable the updating of Feature and thus the resulting component
  states.
- Run the end of install actions for suspend and user exit states as
  well.
- Start putting in place a currently running state for future ui use.
- Use the new registry functions in registry.c.
- Do not force a reboot, just return ERROR_INSTALL_SUSPEND and write
  some keys to the registry.
- Quite a few fixes:
- Allow for the queing of custom actions to trigger on the
  InstallExecute or InstallExecuteAgain actions.
- allow for the queing of custom actions to trigger on
  InstallFinalize.
- Properly set the CustomActionData property for said queued actions.
- Implement RegisterProduct.
- Beginning implementation of ForceReboot.
- Don't kill install if an item to be duplicated does not exist.
- Write out SourceList and LastUsedSource for resuming installs.
- Use regsvr32 to register self reg dlls.
- Implementations for SelfRegModules and PublishFeatures.
- Set default ACTION property for Install.
- Deformat more than JUST properties properly. Allows for Files and
  Component paths in deformat.
- Properly deformat a LaunchCondition failure dialog box.
- Resolve and save registry Keypaths.
- Write the Features published keys more correctly. Still some
  problems.
- First implementation of the WriteIniValues action.
- Custom actions can have null in their target parameters, handle that
  without crashing. Also enable deformating of lines greater than 256
  characters.
- Added some more suminfo stubs.
- An implementation of MsiSummaryInfoGetPropertyW based off of
  MsiSummaryInfoGetPropertyA.
- Added stubs for MsiGetShortcutTargetA/W.
- Do a very basic first implementation of MsiConfigureProductExW for
  msiexec /@  when run as a reboot.
- Also add a number of new stubs for the office xp and 2k3 install and
  startup process.
- Fix a copy and paste error, check for a null value and discard
  unneeded errors.
- Do not limit properties to 256 characters when evaluating them.
- Setting a record to an empty string is the same as making it null.
- First pass implement ion of MsiQueryProductState[A/W] as well as a few
  fixes for MsiGetComponentPath.
- Actually start on an implemention for MsiGetComponentPathW that should
  handle all keypaths that are files.
- A reworking of format.c to remove the recursion, clean things up and
  stabilize behavior to match windows.
- Cleanup processing a bit more.
- Allow for nested keys to work properly.
- MsiGetProperty does not return any error on missing properties.
- The new Insert fixes now properly require ?,? instead of just ? for
  the Insert call. This fix modifies the MSI_SetProperty query to be
  correct.
Michael Stefaniuc <mstefani@redhat.de>
- Do not check for non NULL pointer before HeapFree'ing it. It's
  redundant.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Ulrich Czekalla <ulrich@codeweavers.com>
- Handle 0 length buffers in MSI_FormatRecordW.
- Remove unused buffer in deformat_string.
Mike Hearn <mh@codeweavers.com>
- Correctly ensure properties set from resolved directory paths are
  backslash terminated.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Marcus Meissner <meissner@suse.de>
- Initialize rc in create_component_directory().
Alexandre Julliard <julliard@winehq.org>
- Avoid unnecessary run-time initializations.

svn path=/trunk/; revision=13518
2005-02-12 22:59:04 +00:00

241 lines
5.8 KiB
C

/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2004 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 receuved 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 "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
#include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
/* below is the query interface to a table */
typedef struct tagMSIUPDATEVIEW
{
MSIVIEW view;
MSIDATABASE *db;
MSIVIEW *wv;
value_list *vals;
} MSIUPDATEVIEW;
static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
TRACE("%p %d %d %p\n", uv, row, col, val );
return ERROR_FUNCTION_FAILED;
}
static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
UINT n, type, val, r, row, col_count = 0, row_count = 0;
MSIVIEW *wv;
TRACE("%p %p\n", uv, record );
if( !record )
return ERROR_FUNCTION_FAILED;
wv = uv->wv;
if( !wv )
return ERROR_FUNCTION_FAILED;
r = wv->ops->execute( wv, 0 );
TRACE("tv execute returned %x\n", r);
if( r )
return r;
r = wv->ops->get_dimensions( wv, &row_count, &col_count );
if( r )
goto err;
for( row = 0; row < row_count; row++ )
{
for( n = 1; n <= col_count; n++ )
{
r = wv->ops->get_column_info( wv, n, NULL, &type );
if( r )
break;
if( type & MSITYPE_STRING )
{
const WCHAR *str = MSI_RecordGetString( record, n );
val = msi_addstringW( uv->db->strings, 0, str, -1, 1 );
}
else
{
val = MSI_RecordGetInteger( record, n );
val |= 0x8000;
}
r = wv->ops->set_int( wv, row, n, val );
if( r )
break;
}
}
err:
return ERROR_SUCCESS;
}
static UINT UPDATE_close( struct tagMSIVIEW *view )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
MSIVIEW *wv;
TRACE("%p\n", uv);
wv = uv->wv;
if( !wv )
return ERROR_FUNCTION_FAILED;
return wv->ops->close( wv );
}
static UINT UPDATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
MSIVIEW *wv;
TRACE("%p %p %p\n", uv, rows, cols );
wv = uv->wv;
if( !wv )
return ERROR_FUNCTION_FAILED;
return wv->ops->get_dimensions( wv, rows, cols );
}
static UINT UPDATE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
MSIVIEW *wv;
TRACE("%p %d %p %p\n", uv, n, name, type );
wv = uv->wv;
if( !wv )
return ERROR_FUNCTION_FAILED;
return wv->ops->get_column_info( wv, n, name, type );
}
static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
TRACE("%p %d %p\n", uv, eModifyMode, rec );
return ERROR_FUNCTION_FAILED;
}
static UINT UPDATE_delete( struct tagMSIVIEW *view )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
MSIVIEW *wv;
TRACE("%p\n", uv );
wv = uv->wv;
if( wv )
wv->ops->delete( wv );
delete_value_list( uv->vals );
msiobj_release( &uv->db->hdr );
HeapFree( GetProcessHeap(), 0, uv );
return ERROR_SUCCESS;
}
static MSIVIEWOPS update_ops =
{
UPDATE_fetch_int,
NULL,
NULL,
NULL,
UPDATE_execute,
UPDATE_close,
UPDATE_get_dimensions,
UPDATE_get_column_info,
UPDATE_modify,
UPDATE_delete
};
UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
column_assignment *list, struct expr *expr )
{
MSIUPDATEVIEW *uv = NULL;
UINT r;
MSIVIEW *tv = NULL, *sv = NULL, *wv = NULL;
TRACE("%p\n", uv );
r = TABLE_CreateView( db, table, &tv );
if( r != ERROR_SUCCESS )
return r;
/* add conditions first */
r = WHERE_CreateView( db, &wv, tv, expr );
if( r != ERROR_SUCCESS )
{
if( sv )
sv->ops->delete( tv );
return r;
}
/* then select the columns we want */
r = SELECT_CreateView( db, &sv, wv, list->col_list );
if( r != ERROR_SUCCESS )
{
if( tv )
tv->ops->delete( sv );
return r;
}
uv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *uv );
if( !uv )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
uv->view.ops = &update_ops;
msiobj_addref( &db->hdr );
uv->db = db;
uv->vals = list->val_list;
uv->wv = sv;
*view = (MSIVIEW*) uv;
return ERROR_SUCCESS;
}