Authors: Mike McCormack <mike@codeweavers.com>, Aric Stewart <aric@codeweavers.com>

Refcount all objects, and use pointers internally.
oldstable
Alexandre Julliard 2004-07-09 22:25:34 +00:00
parent 95dc472698
commit a7a6f5f31c
17 changed files with 1888 additions and 1326 deletions

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
#define YYLEX_PARAM info
#define YYPARSE_PARAM info
@ -43,7 +44,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
typedef struct tag_yyinput
{
MSIHANDLE hInstall;
MSIPACKAGE *package;
LPCWSTR str;
INT n;
MSICONDITION result;
@ -408,7 +409,7 @@ symbol_i:
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetComponentStateW(cond->hInstall, $2, &install, &action );
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = action;
HeapFree( GetProcessHeap(), 0, $2 );
}
@ -417,7 +418,7 @@ symbol_i:
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetComponentStateW(cond->hInstall, $2, &install, &action );
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = install;
HeapFree( GetProcessHeap(), 0, $2 );
}
@ -426,7 +427,7 @@ symbol_i:
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetFeatureStateW(cond->hInstall, $2, &install, &action );
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
$$ = action;
HeapFree( GetProcessHeap(), 0, $2 );
}
@ -435,7 +436,7 @@ symbol_i:
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetFeatureStateW(cond->hInstall, $2, &install, &action );
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
$$ = install;
HeapFree( GetProcessHeap(), 0, $2 );
}
@ -451,7 +452,7 @@ symbol_s:
/* Lookup the identifier */
sz=0x100;
if (MsiGetPropertyW(cond->hInstall,$1,$$,&sz) != ERROR_SUCCESS)
if (MSI_GetPropertyW(cond->package,$1,$$,&sz) != ERROR_SUCCESS)
{
$$[0]=0;
}
@ -687,12 +688,12 @@ static int COND_error(char *str)
return 0;
}
MSICONDITION WINAPI MsiEvaluateConditionW( MSIHANDLE hInstall, LPCWSTR szCondition )
MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
{
COND_input cond;
MSICONDITION r;
cond.hInstall = hInstall;
cond.package = package;
cond.str = szCondition;
cond.n = 0;
cond.result = -1;
@ -708,6 +709,19 @@ MSICONDITION WINAPI MsiEvaluateConditionW( MSIHANDLE hInstall, LPCWSTR szConditi
return r;
}
MSICONDITION WINAPI MsiEvaluateConditionW( MSIHANDLE hInstall, LPCWSTR szCondition )
{
MSIPACKAGE *package;
UINT ret;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if( !package)
return ERROR_INVALID_HANDLE;
ret = MSI_EvaluateConditionW( package, szCondition );
msiobj_release( &package->hdr );
return ret;
}
MSICONDITION WINAPI MsiEvaluateConditionA( MSIHANDLE hInstall, LPCSTR szCondition )
{
LPWSTR szwCond = NULL;

View File

@ -56,7 +56,7 @@ static UINT CREATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT
return ERROR_FUNCTION_FAILED;
}
static UINT CREATE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
create_col_info *col;
@ -214,6 +214,7 @@ static UINT CREATE_delete( struct tagMSIVIEW *view )
}
HeapFree( GetProcessHeap(), 0, cv->name );
HeapFree( GetProcessHeap(), 0, cv );
msiobj_release( &cv->db->hdr );
return ERROR_SUCCESS;
}
@ -246,6 +247,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
/* fill the structure */
cv->view.ops = &create_ops;
msiobj_addref( &db->hdr );
cv->db = db;
cv->name = table; /* FIXME: strdupW it? */
cv->col_info = col_info;

View File

@ -107,13 +107,13 @@ static UINT DISTINCT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UIN
return dv->table->ops->fetch_int( dv->table, row, col, val );
}
static UINT DISTINCT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
static UINT DISTINCT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
UINT r, i, j, r_count, c_count;
DISTINCTSET *rowset = NULL;
TRACE("%p %ld\n", dv, record);
TRACE("%p %p\n", dv, record);
if( !dv->table )
return ERROR_FUNCTION_FAILED;
@ -242,6 +242,7 @@ static UINT DISTINCT_delete( struct tagMSIVIEW *view )
if( dv->translation )
HeapFree( GetProcessHeap(), 0, dv->translation );
HeapFree( GetProcessHeap(), 0, dv );
msiobj_release( &dv->db->hdr );
return ERROR_SUCCESS;
}
@ -281,6 +282,7 @@ UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
/* fill the structure */
dv->view.ops = &distinct_ops;
msiobj_addref( &db->hdr );
dv->db = db;
dv->table = table;
dv->translation = NULL;

View File

@ -1,7 +1,7 @@
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 Mike McCormack for CodeWeavers
* Copyright 2002-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
@ -31,66 +31,109 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi);
MSIHANDLEINFO *msihandletable[MSIMAXHANDLES];
MSIHANDLE alloc_msihandle(UINT type, UINT size, msihandledestructor destroy, void **out)
static CRITICAL_SECTION MSI_handle_cs;
static CRITICAL_SECTION_DEBUG MSI_handle_cs_debug =
{
MSIHANDLEINFO *info;
0, 0, &MSI_handle_cs,
{ &MSI_handle_cs_debug.ProcessLocksList,
&MSI_handle_cs_debug.ProcessLocksList },
0, 0, { 0, (DWORD)(__FILE__ ": MSI_handle_cs") }
};
static CRITICAL_SECTION MSI_handle_cs = { &MSI_handle_cs_debug, -1, 0, 0, 0, 0 };
MSIOBJECTHDR *msihandletable[MSIMAXHANDLES];
MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj )
{
MSIHANDLE ret = 0;
UINT i;
*out = NULL;
EnterCriticalSection( &MSI_handle_cs );
/* find a slot */
for(i=0; i<MSIMAXHANDLES; i++)
if( !msihandletable[i] )
break;
if( (i>=MSIMAXHANDLES) || msihandletable[i] )
return 0;
goto out;
size += sizeof (MSIHANDLEINFO);
info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
if( !info )
return 0;
msiobj_addref( obj );
msihandletable[i] = obj;
ret = (MSIHANDLE) (i+1);
out:
TRACE("%p -> %ld\n", obj, ret );
info->magic = MSIHANDLE_MAGIC;
info->type = type;
info->refcount = 1;
info->destructor = destroy;
msihandletable[i] = info;
*out = (void*) &info[1];
return (MSIHANDLE) (i+1);
LeaveCriticalSection( &MSI_handle_cs );
return ret;
}
void *msihandle2msiinfo(MSIHANDLE handle, UINT type)
{
MSIOBJECTHDR *ret = NULL;
EnterCriticalSection( &MSI_handle_cs );
handle--;
if( handle<0 )
return NULL;
goto out;
if( handle>=MSIMAXHANDLES )
return NULL;
goto out;
if( !msihandletable[handle] )
return NULL;
goto out;
if( msihandletable[handle]->magic != MSIHANDLE_MAGIC )
return NULL;
goto out;
if( type && (msihandletable[handle]->type != type) )
return NULL;
goto out;
ret = msihandletable[handle];
msiobj_addref( ret );
out:
LeaveCriticalSection( &MSI_handle_cs );
return &msihandletable[handle][1];
return (void*) ret;
}
void msihandle_addref(MSIHANDLE handle)
MSIHANDLE msiobj_findhandle( MSIOBJECTHDR *hdr )
{
MSIHANDLEINFO *info = msihandle2msiinfo(handle, 0);
MSIHANDLE ret = 0;
UINT i;
TRACE("%lx\n",handle);
TRACE("%p\n", hdr);
EnterCriticalSection( &MSI_handle_cs );
for(i=0; (i<MSIMAXHANDLES) && !ret; i++)
if( msihandletable[i] == hdr )
ret = i+1;
LeaveCriticalSection( &MSI_handle_cs );
TRACE("%p -> %ld\n", hdr, ret);
msiobj_addref( hdr );
return ret;
}
void *alloc_msiobject(UINT type, UINT size, msihandledestructor destroy )
{
MSIOBJECTHDR *info;
info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
if( info )
{
info->magic = MSIHANDLE_MAGIC;
info->type = type;
info->refcount = 1;
info->destructor = destroy;
}
return info;
}
void msiobj_addref( MSIOBJECTHDR *info )
{
TRACE("%p\n", info);
if( !info )
return;
info--;
if( info->magic != MSIHANDLE_MAGIC )
{
ERR("Invalid handle!\n");
@ -100,36 +143,63 @@ void msihandle_addref(MSIHANDLE handle)
info->refcount++;
}
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
int msiobj_release( MSIOBJECTHDR *info )
{
MSIHANDLEINFO *info = msihandle2msiinfo(handle, 0);
int ret;
TRACE("%lx\n",handle);
TRACE("%p\n",info);
if( !info )
return ERROR_INVALID_HANDLE;
info--;
return -1;
if( info->magic != MSIHANDLE_MAGIC )
{
ERR("Invalid handle!\n");
return ERROR_INVALID_HANDLE;
return -1;
}
info->refcount--;
if (info->refcount > 0)
return ERROR_SUCCESS;
ret = info->refcount--;
if (info->refcount == 0)
{
if( info->destructor )
info->destructor( &info[1] );
info->destructor( info );
HeapFree( GetProcessHeap(), 0, info );
TRACE("object %p destroyed\n", info);
}
return ret;
}
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
{
MSIOBJECTHDR *info;
UINT ret = ERROR_INVALID_HANDLE;
TRACE("%lx\n",handle);
EnterCriticalSection( &MSI_handle_cs );
info = msihandle2msiinfo(handle, 0);
if( !info )
goto out;
if( info->magic != MSIHANDLE_MAGIC )
{
ERR("Invalid handle!\n");
goto out;
}
msiobj_release( info );
msihandletable[handle-1] = NULL;
ret = ERROR_SUCCESS;
TRACE("Destroyed\n");
TRACE("handle %lx Destroyed\n", handle);
out:
LeaveCriticalSection( &MSI_handle_cs );
if( info )
msiobj_release( info );
return 0;
return ret;
}
UINT WINAPI MsiCloseAllHandles(void)

View File

@ -56,13 +56,13 @@ static UINT INSERT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT
return ERROR_FUNCTION_FAILED;
}
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
UINT n, type, val, r, row, col_count = 0;
MSIVIEW *sv;
TRACE("%p %ld\n", iv, record );
TRACE("%p %p\n", iv, record );
sv = iv->sv;
if( !sv )
@ -77,7 +77,7 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
if( r )
goto err;
n = MsiRecordGetFieldCount( record );
n = MSI_RecordGetFieldCount( record );
if( n != col_count )
{
ERR("Number of fields do not match\n");
@ -103,7 +103,7 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
}
else
{
val = MsiRecordGetInteger( record, n );
val = MSI_RecordGetInteger( record, n );
val |= 0x8000;
}
r = sv->ops->set_int( sv, row, n, val );
@ -180,6 +180,7 @@ static UINT INSERT_delete( struct tagMSIVIEW *view )
sv->ops->delete( sv );
delete_value_list( iv->vals );
HeapFree( GetProcessHeap(), 0, iv );
msiobj_release( &iv->db->hdr );
return ERROR_SUCCESS;
}
@ -226,6 +227,7 @@ UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
/* fill the structure */
iv->view.ops = &insert_ops;
msiobj_addref( &db->hdr );
iv->db = db;
iv->vals = values;
iv->bIsTemp = temp;

View File

@ -1,7 +1,7 @@
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002,2003 Mike McCormack for CodeWeavers
* Copyright 2002,2003,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
@ -222,7 +222,7 @@ BOOL encode_base85_guid( GUID *guid, LPWSTR str )
}
VOID MSI_CloseDatabase( VOID *arg )
VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
{
MSIDATABASE *db = (MSIDATABASE *) arg;
@ -230,58 +230,18 @@ VOID MSI_CloseDatabase( VOID *arg )
IStorage_Release( db->storage );
}
UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
{
HRESULT r = ERROR_FUNCTION_FAILED;
LPWSTR szwDBPath = NULL, szwPersist = NULL;
UINT len;
TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
if( szDBPath )
{
len = MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, NULL, 0 );
szwDBPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
if( !szwDBPath )
goto end;
MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, szwDBPath, len );
}
if( HIWORD(szPersist) )
{
len = MultiByteToWideChar( CP_ACP, 0, szPersist, -1, NULL, 0 );
szwPersist = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
if( !szwPersist )
goto end;
MultiByteToWideChar( CP_ACP, 0, szPersist, -1, szwPersist, len );
}
else
szwPersist = (LPWSTR) szPersist;
r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
end:
if( szwPersist )
HeapFree( GetProcessHeap(), 0, szwPersist );
if( szwDBPath )
HeapFree( GetProcessHeap(), 0, szwDBPath );
return r;
}
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
{
IStorage *stg = NULL;
HRESULT r;
MSIHANDLE handle;
MSIDATABASE *db;
UINT ret;
MSIDATABASE *db = NULL;
UINT ret = ERROR_FUNCTION_FAILED;
LPWSTR szMode;
STATSTG stat;
TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
if( !phDB )
if( !pdb )
return ERROR_INVALID_PARAMETER;
szMode = (LPWSTR) szPersist;
@ -328,7 +288,6 @@ UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phD
if( FAILED( r ) )
{
FIXME("Failed to stat storage\n");
ret = ERROR_FUNCTION_FAILED;
goto end;
}
@ -336,17 +295,15 @@ UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phD
{
ERR("storage GUID is not a MSI database GUID %s\n",
debugstr_guid(&stat.clsid) );
ret = ERROR_FUNCTION_FAILED;
goto end;
}
handle = alloc_msihandle( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
MSI_CloseDatabase, (void**) &db );
if( !handle )
db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
MSI_CloseDatabase );
if( !db )
{
FIXME("Failed to allocate a handle\n");
ret = ERROR_FUNCTION_FAILED;
goto end;
}
@ -355,24 +312,80 @@ UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phD
db->storage = stg;
db->mode = szMode;
/* db->strings = NULL;
db->first_table = NULL;
db->last_table = NULL; */
ret = load_string_table( db );
if( ret != ERROR_SUCCESS )
goto end;
*phDB = handle;
msiobj_addref( &db->hdr );
IStorage_AddRef( stg );
*pdb = db;
end:
if( db )
msiobj_release( &db->hdr );
if( stg )
IStorage_Release( stg );
return ret;
}
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
{
MSIDATABASE *db;
UINT ret;
TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
if( ret == ERROR_SUCCESS )
{
*phDB = alloc_msihandle( &db->hdr );
msiobj_release( &db->hdr );
}
return ret;
}
UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
{
HRESULT r = ERROR_FUNCTION_FAILED;
LPWSTR szwDBPath = NULL, szwPersist = NULL;
UINT len;
TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
if( szDBPath )
{
len = MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, NULL, 0 );
szwDBPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
if( !szwDBPath )
goto end;
MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, szwDBPath, len );
}
if( HIWORD(szPersist) )
{
len = MultiByteToWideChar( CP_ACP, 0, szPersist, -1, NULL, 0 );
szwPersist = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
if( !szwPersist )
goto end;
MultiByteToWideChar( CP_ACP, 0, szPersist, -1, szwPersist, len );
}
else
szwPersist = (LPWSTR) szPersist;
r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
end:
if( szwPersist )
HeapFree( GetProcessHeap(), 0, szwPersist );
if( szwDBPath )
HeapFree( GetProcessHeap(), 0, szwDBPath );
return r;
}
UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
{
UINT len, ret;
@ -525,8 +538,9 @@ end:
UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
{
MSIHANDLE packagehandle;
MSIPACKAGE *package = NULL;
UINT rc = ERROR_SUCCESS;
MSIHANDLE handle;
FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
@ -534,13 +548,16 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
if (rc != ERROR_SUCCESS)
return rc;
rc = MsiOpenPackageW(szPackagePath,&packagehandle);
rc = MSI_OpenPackageW(szPackagePath,&package);
if (rc != ERROR_SUCCESS)
return rc;
ACTION_DoTopLevelINSTALL(packagehandle, szPackagePath, szCommandLine);
handle = alloc_msihandle( &package->hdr );
MsiCloseHandle(packagehandle);
rc = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine);
MsiCloseHandle(handle);
msiobj_release( &package->hdr );
return rc;
}

View File

@ -43,15 +43,58 @@ typedef struct tagMSITABLE MSITABLE;
struct string_table;
typedef struct string_table string_table;
struct tagMSIOBJECTHDR;
typedef struct tagMSIOBJECTHDR MSIOBJECTHDR;
typedef VOID (*msihandledestructor)( MSIOBJECTHDR * );
struct tagMSIOBJECTHDR
{
UINT magic;
UINT type;
UINT refcount;
msihandledestructor destructor;
struct tagMSIOBJECTHDR *next;
struct tagMSIOBJECTHDR *prev;
};
typedef struct tagMSIDATABASE
{
MSIOBJECTHDR hdr;
IStorage *storage;
string_table *strings;
LPWSTR mode;
MSITABLE *first_table, *last_table;
} MSIDATABASE;
struct tagMSIVIEW;
typedef struct tagMSIVIEW MSIVIEW;
typedef struct tagMSIQUERY
{
MSIOBJECTHDR hdr;
MSIVIEW *view;
UINT row;
MSIDATABASE *db;
} MSIQUERY;
/* maybe we can use a Variant instead of doing it ourselves? */
typedef struct tagMSIFIELD
{
UINT type;
union
{
INT iVal;
LPWSTR szwVal;
IStream *stream;
} u;
} MSIFIELD;
typedef struct tagMSIRECORD
{
MSIOBJECTHDR hdr;
UINT count; /* as passed to MsiCreateRecord */
MSIFIELD fields[1]; /* nb. array size is count+1 */
} MSIRECORD;
typedef struct tagMSIVIEWOPS
{
@ -90,7 +133,7 @@ typedef struct tagMSIVIEWOPS
/*
* execute - loads the underlying data into memory so it can be read
*/
UINT (*execute)( struct tagMSIVIEW *, MSIHANDLE );
UINT (*execute)( struct tagMSIVIEW *, MSIRECORD * );
/*
* close - clears the data read by execute from memory
@ -126,31 +169,22 @@ typedef struct tagMSIVIEWOPS
} MSIVIEWOPS;
typedef struct tagMSIVIEW
{
MSIVIEWOPS *ops;
} MSIVIEW;
typedef struct tagMSISUMMARYINFO
{
MSIOBJECTHDR hdr;
IPropertyStorage *propstg;
} MSISUMMARYINFO;
typedef VOID (*msihandledestructor)( VOID * );
typedef struct tagMSIHANDLEINFO
struct tagMSIVIEW
{
UINT magic;
UINT type;
UINT refcount;
msihandledestructor destructor;
struct tagMSIHANDLEINFO *next;
struct tagMSIHANDLEINFO *prev;
} MSIHANDLEINFO;
MSIOBJECTHDR hdr;
MSIVIEWOPS *ops;
};
typedef struct tagMSIPACKAGE
{
MSIHANDLE db;
MSIOBJECTHDR hdr;
MSIDATABASE *db;
struct tagMSIFEATURE *features;
UINT loaded_features;
struct tagMSIFOLDER *folders;
@ -186,10 +220,14 @@ DEFINE_GUID(CLSID_IMsiServerX3, 0x000C1094,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x0
DEFINE_GUID(CLSID_IMsiServerMessage, 0x000C101D,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
extern void *msihandle2msiinfo(MSIHANDLE handle, UINT type);
MSIHANDLE alloc_msihandle(UINT type, UINT extra, msihandledestructor destroy, void **out);
void msihandle_addref(MSIHANDLE handle);
/* handle functions */
extern void *msihandle2msiinfo(MSIHANDLE handle, UINT type);
extern MSIHANDLE alloc_msihandle( MSIOBJECTHDR * );
extern void *alloc_msiobject(UINT type, UINT size, msihandledestructor destroy );
extern void msiobj_addref(MSIOBJECTHDR *);
extern int msiobj_release(MSIOBJECTHDR *);
extern MSIHANDLE msiobj_findhandle( MSIOBJECTHDR *hdr );
/* add this table to the list of cached tables in the database */
extern void add_table(MSIDATABASE *db, MSITABLE *table);
@ -222,27 +260,53 @@ extern const WCHAR *msi_string_lookup_id( string_table *st, UINT id );
extern UINT msi_string_get_codepage( string_table *st );
UINT VIEW_find_column( MSIVIEW *view, LPWSTR name, UINT *n );
extern UINT VIEW_find_column( MSIVIEW *view, LPWSTR name, UINT *n );
extern BOOL TABLE_Exists( MSIDATABASE *db, LPWSTR name );
UINT read_raw_stream_data( MSIHANDLE hdb, LPCWSTR stname,
extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname,
USHORT **pdata, UINT *psz );
UINT ACTION_DoTopLevelINSTALL(MSIHANDLE hPackage, LPCWSTR szPackagePath,
LPCWSTR szCommandLine);
void ACTION_remove_tracked_tempfiles(MSIPACKAGE* hPackage);
extern UINT ACTION_DoTopLevelINSTALL( MSIPACKAGE *, LPCWSTR, LPCWSTR );
extern void ACTION_remove_tracked_tempfiles( MSIPACKAGE* );
/* record internals */
extern UINT WINAPI MSI_RecordSetIStream( MSIHANDLE handle,
unsigned int iField, IStream *stm );
extern const WCHAR *MSI_RecordGetString( MSIHANDLE handle, unsigned int iField );
extern UINT MSI_RecordSetIStream( MSIRECORD *, unsigned int, IStream *);
extern const WCHAR *MSI_RecordGetString( MSIRECORD *, unsigned int );
extern MSIRECORD *MSI_CreateRecord( unsigned int );
extern UINT MSI_RecordSetInteger( MSIRECORD *, unsigned int, int );
extern UINT MSI_RecordSetStringW( MSIRECORD *, unsigned int, LPCWSTR );
extern BOOL MSI_RecordIsNull( MSIRECORD *, unsigned int );
extern UINT MSI_RecordGetStringW( MSIRECORD * , unsigned int, LPWSTR, DWORD *);
extern int MSI_RecordGetInteger( MSIRECORD *, unsigned int );
extern UINT MSI_RecordReadStream( MSIRECORD *, unsigned int, char *, DWORD *);
extern unsigned int MSI_RecordGetFieldCount( MSIRECORD *rec );
/* stream internals */
extern UINT get_raw_stream( MSIHANDLE hdb, LPCWSTR stname, IStream **stm );
extern UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm );
extern void enum_stream_names( IStorage *stg );
/* database internals */
extern UINT MSI_OpenDatabaseW( LPCWSTR, LPCWSTR, MSIDATABASE ** );
extern UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY ** );
/* view internals */
extern UINT MSI_ViewExecute( MSIQUERY*, MSIRECORD * );
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 UINT MSI_SetPropertyW( MSIPACKAGE *, LPCWSTR, LPCWSTR );
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 *);
/* 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);

View File

@ -1,7 +1,7 @@
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 Mike McCormack for CodeWeavers
* Copyright 2002-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
@ -36,12 +36,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi);
#if 0
typedef struct tagMSIQUERY
{
MSIOBJECTHDR hdr;
MSIVIEW *view;
UINT row;
MSIDATABASE *db;
} MSIQUERY;
#endif
UINT WINAPI MsiDatabaseIsTablePersistentA(
MSIHANDLE hDatabase, LPSTR szTableName)
@ -57,12 +60,13 @@ UINT WINAPI MsiDatabaseIsTablePersistentW(
return ERROR_CALL_NOT_IMPLEMENTED;
}
void MSI_CloseView( VOID *arg )
void MSI_CloseView( MSIOBJECTHDR *arg )
{
MSIQUERY *query = arg;
MSIQUERY *query = (MSIQUERY*) arg;
if( query->view && query->view->ops->delete )
query->view->ops->delete( query->view );
msiobj_release( &query->db->hdr );
}
UINT VIEW_find_column( MSIVIEW *table, LPWSTR name, UINT *n )
@ -118,57 +122,71 @@ UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
return r;
}
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
LPCWSTR szQuery, MSIHANDLE *phView)
UINT MSI_DatabaseOpenViewW(MSIDATABASE *db,
LPCWSTR szQuery, MSIQUERY **pView)
{
MSIDATABASE *db;
MSIHANDLE handle;
MSIQUERY *query;
UINT r;
TRACE("%s %p\n", debugstr_w(szQuery), phView);
TRACE("%s %p\n", debugstr_w(szQuery), pView);
if( !szQuery)
return ERROR_INVALID_PARAMETER;
db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
if( !db )
return ERROR_INVALID_HANDLE;
/* pre allocate a handle to hold a pointer to the view */
handle = alloc_msihandle( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY),
MSI_CloseView, (void**) &query );
if( !handle )
query = alloc_msiobject( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY),
MSI_CloseView );
if( !query )
return ERROR_FUNCTION_FAILED;
msiobj_addref( &db->hdr );
query->row = 0;
query->db = db;
query->view = NULL;
r = MSI_ParseSQL( db, szQuery, &query->view );
if( r != ERROR_SUCCESS )
if( r == ERROR_SUCCESS )
{
MsiCloseHandle( handle );
return r;
msiobj_addref( &query->hdr );
*pView = query;
}
*phView = handle;
msiobj_release( &query->hdr );
return ERROR_SUCCESS;
}
UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
LPCWSTR szQuery, MSIHANDLE *phView)
{
MSIDATABASE *db;
MSIQUERY *query = NULL;
UINT ret;
TRACE("%s %p\n", debugstr_w(szQuery), phView);
db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
if( !db )
return ERROR_INVALID_HANDLE;
ret = MSI_DatabaseOpenViewW( db, szQuery, &query );
if( ret == ERROR_SUCCESS )
{
*phView = alloc_msihandle( &query->hdr );
msiobj_release( &query->hdr );
}
msiobj_release( &db->hdr );
return ret;
}
UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
{
MSIQUERY *query;
MSIVIEW *view;
MSIHANDLE handle;
MSIRECORD *rec;
UINT row_count = 0, col_count = 0, i, ival, ret, type;
TRACE("%ld %p\n", hView, record);
TRACE("%p %p\n", query, prec );
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
view = query->view;
if( !view )
return ERROR_FUNCTION_FAILED;
@ -182,8 +200,8 @@ UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
if( query->row >= row_count )
return ERROR_NO_MORE_ITEMS;
handle = MsiCreateRecord( col_count );
if( !handle )
rec = MSI_CreateRecord( col_count );
if( !rec )
return ERROR_FUNCTION_FAILED;
for( i=1; i<=col_count; i++ )
@ -215,25 +233,25 @@ UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
LPWSTR sval;
sval = MSI_makestring( query->db, ival );
MsiRecordSetStringW( handle, i, sval );
MSI_RecordSetStringW( rec, i, sval );
HeapFree( GetProcessHeap(), 0, sval );
}
else
{
if( (type & MSI_DATASIZEMASK) == 2 )
MsiRecordSetInteger( handle, i, ival - (1<<15) );
MSI_RecordSetInteger( rec, i, ival - (1<<15) );
else
MsiRecordSetInteger( handle, i, ival - (1<<31) );
MSI_RecordSetInteger( rec, i, ival - (1<<31) );
}
}
else
{
IStream *stm;
IStream *stm = NULL;
ret = view->ops->fetch_stream( view, query->row, i, &stm );
if( ( ret == ERROR_SUCCESS ) && stm )
{
MSI_RecordSetIStream( handle, i, stm );
MSI_RecordSetIStream( rec, i, stm );
IStream_Release( stm );
}
else
@ -242,21 +260,37 @@ UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
}
query->row ++;
*record = handle;
*prec = rec;
return ERROR_SUCCESS;
}
UINT WINAPI MsiViewClose(MSIHANDLE hView)
UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
{
MSIQUERY *query;
MSIVIEW *view;
MSIRECORD *rec = NULL;
UINT ret;
TRACE("%ld\n", hView );
TRACE("%ld %p\n", hView, record);
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
ret = MSI_ViewFetch( query, &rec );
if( ret == ERROR_SUCCESS )
{
*record = alloc_msihandle( &rec->hdr );
msiobj_release( &rec->hdr );
}
msiobj_release( &query->hdr );
return ret;
}
UINT MSI_ViewClose(MSIQUERY *query)
{
MSIVIEW *view;
TRACE("%p\n", query );
view = query->view;
if( !view )
@ -267,17 +301,28 @@ UINT WINAPI MsiViewClose(MSIHANDLE hView)
return view->ops->close( view );
}
UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
UINT WINAPI MsiViewClose(MSIHANDLE hView)
{
MSIQUERY *query;
MSIVIEW *view;
UINT ret;
TRACE("%ld %ld\n", hView, hRec);
TRACE("%ld\n", hView );
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
ret = MSI_ViewClose( query );
msiobj_release( &query->hdr );
return ret;
}
UINT MSI_ViewExecute(MSIQUERY *query, MSIRECORD *rec )
{
MSIVIEW *view;
TRACE("%p %p\n", query, rec);
view = query->view;
if( !view )
return ERROR_FUNCTION_FAILED;
@ -285,7 +330,39 @@ UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
return ERROR_FUNCTION_FAILED;
query->row = 0;
return view->ops->execute( view, hRec );
return view->ops->execute( view, rec );
}
UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
{
MSIQUERY *query;
MSIRECORD *rec = NULL;
UINT ret;
TRACE("%ld %ld\n", hView, hRec);
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
if( hRec )
{
rec = msihandle2msiinfo( hRec, MSIHANDLETYPE_RECORD );
if( !rec )
{
ret = ERROR_INVALID_HANDLE;
goto out;
}
}
ret = MSI_ViewExecute( query, rec );
out:
if( query )
msiobj_release( &query->hdr );
if( rec )
msiobj_release( &rec->hdr );
return ret;
}
UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)

View File

@ -142,12 +142,12 @@ static UINT ORDER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
return ov->table->ops->fetch_int( ov->table, row, col, val );
}
static UINT ORDER_execute( struct tagMSIVIEW *view, MSIHANDLE record )
static UINT ORDER_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
UINT r, num_rows = 0, i;
TRACE("%p %ld\n", ov, record);
TRACE("%p %p\n", ov, record);
if( !ov->table )
return ERROR_FUNCTION_FAILED;
@ -245,6 +245,7 @@ static UINT ORDER_delete( struct tagMSIVIEW *view )
ov->reorder = NULL;
HeapFree( GetProcessHeap(), 0, ov );
msiobj_release( &ov->db->hdr );
return ERROR_SUCCESS;
}
@ -285,6 +286,7 @@ UINT ORDER_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
/* fill the structure */
ov->view.ops = &order_ops;
msiobj_addref( &db->hdr );
ov->db = db;
ov->table = table;
ov->reorder = NULL;

View File

@ -48,13 +48,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
*/
#define LPCTSTR LPCWSTR
void MSI_FreePackage( VOID *arg);
void MSI_FreePackage( VOID *arg)
void MSI_FreePackage( MSIOBJECTHDR *arg)
{
MSIPACKAGE *package= arg;
MsiCloseHandle(package->db);
MSIPACKAGE *package= (MSIPACKAGE*) arg;
ACTION_remove_tracked_tempfiles(package);
@ -69,6 +65,7 @@ void MSI_FreePackage( VOID *arg)
if (package->files && package->loaded_files > 0)
HeapFree(GetProcessHeap(),0,package->files);
msiobj_release( &package->db->hdr );
}
UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
@ -95,45 +92,72 @@ UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
}
static const void clone_properties(MSIHANDLE db)
static const UINT clone_properties(MSIDATABASE *db)
{
MSIHANDLE view;
MSIQUERY * view = NULL;
UINT rc;
static const CHAR CreateSql[] = "CREATE TABLE `_Property` ( `_Property` "
"CHAR(56) NOT NULL, `Value` CHAR(98) NOT NULL PRIMARY KEY `_Property`)";
static const CHAR Query[] = "SELECT * from Property";
static const CHAR Insert[] =
"INSERT into `_Property` (`_Property`,`Value`) VALUES (?)";
static const WCHAR CreateSql[] = {
'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
'8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
static const WCHAR Query[] = {
'S','E','L','E','C','T',' ','*',' ',
'f','r','o','m',' ','P','r','o','p','e','r','t','y',0};
static const WCHAR Insert[] = {
'I','N','S','E','R','T',' ','i','n','t','o',' ',
'`','_','P','r','o','p','e','r','t','y','`',' ',
'(','`','_','P','r','o','p','e','r','t','y','`',',',
'`','V','a','l','u','e','`',')',' ',
'V','A','L','U','E','S',' ','(','?',')',0};
/* create the temporary properties table */
MsiDatabaseOpenViewA(db, CreateSql, &view);
MsiViewExecute(view,0);
MsiViewClose(view);
MsiCloseHandle(view);
rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MSI_ViewExecute(view,0);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
if (rc != ERROR_SUCCESS)
return rc;
/* clone the existing properties */
MsiDatabaseOpenViewA(db, Query, &view);
rc = MSI_DatabaseOpenViewW(db, Query, &view);
if (rc != ERROR_SUCCESS)
return rc;
MsiViewExecute(view, 0);
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
while (1)
{
MSIHANDLE row;
MSIHANDLE view2;
MSIRECORD * row;
MSIQUERY * view2;
rc = MsiViewFetch(view,&row);
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
break;
MsiDatabaseOpenViewA(db,Insert,&view2);
MsiViewExecute(view2,row);
MsiViewClose(view2);
MsiCloseHandle(view2);
rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
if (rc!= ERROR_SUCCESS)
continue;
rc = MSI_ViewExecute(view2,row);
MSI_ViewClose(view2);
msiobj_release(&view2->hdr);
MsiCloseHandle(row);
if (rc == ERROR_SUCCESS)
msiobj_release(&row->hdr);
}
MsiViewClose(view);
MsiCloseHandle(view);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
/*
@ -142,12 +166,12 @@ static const void clone_properties(MSIHANDLE db)
*
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
*/
static VOID set_installer_properties(MSIHANDLE hPackage)
static VOID set_installer_properties(MSIPACKAGE *package)
{
WCHAR pth[MAX_PATH];
OSVERSIONINFOA OSVersion;
DWORD verval;
CHAR verstr[10];
WCHAR verstr[10];
static const WCHAR cszbs[]={'\\',0};
static const WCHAR CFF[] =
@ -172,6 +196,62 @@ static VOID set_installer_properties(MSIHANDLE hPackage)
{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
static const WCHAR TF[]=
{'T','e','m','p','F','o','l','d','e','r',0};
static const WCHAR szAdminUser[] =
{'A','d','m','i','n','U','s','e','r',0};
static const WCHAR szPriv[] =
{'P','r','i','v','i','l','e','g','e','d',0};
static const WCHAR szOne[] =
{'1',0};
static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
static const WCHAR szFormat[] = {'%','l','i',0};
static const WCHAR szWinBuild[] =
{'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
static const WCHAR szSPL[] =
{'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
static const WCHAR szSix[] = {'6',0 };
/* these need to be dynamically descovered sometime */
static const WCHAR ProgramMenuFolder[] =
{'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
static const WCHAR PMFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',0};
static const WCHAR FavoritesFolder[] =
{'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
static const WCHAR FFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\',
'F','a','v','o','r','i','t','e','s','\\',0};
static const WCHAR FontsFolder[] =
{'F','o','n','t','s','F','o','l','d','e','r',0};
static const WCHAR FoFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\','F','o','n','t','s','\\',0};
static const WCHAR SendToFolder[] =
{'S','e','n','d','T','o','F','o','l','d','e','r',0};
static const WCHAR STFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\','S','e','n','d','T','o','\\',0};
static const WCHAR StartMenuFolder[] =
{'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
static const WCHAR SMFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
'M','e','n','u','\\',0};
static const WCHAR StartupFolder[] =
{'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
static const WCHAR SFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',
'S','t','a','r','t','u','p','\\',0};
static const WCHAR TemplateFolder[] =
{'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
static const WCHAR TFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\',
'S','h','e','l','l','N','e','w','\\',0};
static const WCHAR DesktopFolder[] =
{'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
static const WCHAR DFPath[] =
{'C',':','\\','W','i','n','d','o','w','s','\\',
'D','e','s','k','t','o','p','\\',0};
/*
* Other things i notice set
@ -204,143 +284,156 @@ Privilaged
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, CFF, pth);
MSI_SetPropertyW(package, CFF, pth);
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, PFF, pth);
MSI_SetPropertyW(package, PFF, pth);
SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, CADF, pth);
MSI_SetPropertyW(package, CADF, pth);
SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, ATF, pth);
MSI_SetPropertyW(package, ATF, pth);
SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, ADF, pth);
MSI_SetPropertyW(package, ADF, pth);
SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, SF, pth);
MSI_SetPropertyW(package, SF, pth);
SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, LADF, pth);
MSI_SetPropertyW(package, LADF, pth);
SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, MPF, pth);
MSI_SetPropertyW(package, MPF, pth);
SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, PF, pth);
MSI_SetPropertyW(package, PF, pth);
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
strcatW(pth,cszbs);
MsiSetPropertyW(hPackage, WF, pth);
MSI_SetPropertyW(package, WF, pth);
GetTempPathW(MAX_PATH,pth);
MsiSetPropertyW(hPackage, TF, pth);
MSI_SetPropertyW(package, TF, pth);
/* in a wine enviroment the user is always admin and privlaged */
MsiSetPropertyA(hPackage,"AdminUser","1");
MsiSetPropertyA(hPackage,"Privileged","1");
/* in a wine environment the user is always admin and privileged */
MSI_SetPropertyW(package,szAdminUser,szOne);
MSI_SetPropertyW(package,szPriv,szOne);
/* set the os things */
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(&OSVersion);
verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
sprintf(verstr,"%li",verval);
sprintfW(verstr,szFormat,verval);
switch (OSVersion.dwPlatformId)
{
case VER_PLATFORM_WIN32_WINDOWS:
MsiSetPropertyA(hPackage,"Version9X",verstr);
MSI_SetPropertyW(package,v9x,verstr);
break;
case VER_PLATFORM_WIN32_NT:
MsiSetPropertyA(hPackage,"VersionNT",verstr);
MSI_SetPropertyW(package,vNT,verstr);
break;
}
sprintf(verstr,"%li",OSVersion.dwBuildNumber);
MsiSetPropertyA(hPackage,"WindowsBuild",verstr);
sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
MSI_SetPropertyW(package,szWinBuild,verstr);
/* just fudge this */
MsiSetPropertyA(hPackage,"ServicePackLevel","6");
MSI_SetPropertyW(package,szSPL,szSix);
/* FIXME: these need to be set properly */
MsiSetPropertyA(hPackage,"ProgramMenuFolder",
"C:\\Windows\\Start Menu\\Programs\\");
MsiSetPropertyA(hPackage,"FavoritesFolder",
"C:\\Windows\\Favorites\\");
MsiSetPropertyA(hPackage,"FontsFolder",
"C:\\Windows\\Fonts\\");
MsiSetPropertyA(hPackage,"SendToFolder",
"C:\\Windows\\SendTo\\");
MsiSetPropertyA(hPackage,"StartMenuFolder",
"C:\\Windows\\Start Menu\\");
MsiSetPropertyA(hPackage,"StartupFolder",
"C:\\Windows\\Start Menu\\Programs\\Startup\\");
MsiSetPropertyA(hPackage,"TemplateFolder",
"C:\\Windows\\ShellNew\\");
MsiSetPropertyA(hPackage, "DesktopFolder",
"C:\\Windows\\Desktop\\");
MSI_SetPropertyW(package,ProgramMenuFolder,PMFPath);
MSI_SetPropertyW(package,FavoritesFolder,FFPath);
MSI_SetPropertyW(package,FontsFolder,FoFPath);
MSI_SetPropertyW(package,SendToFolder,STFPath);
MSI_SetPropertyW(package,StartMenuFolder,SMFPath);
MSI_SetPropertyW(package,StartupFolder,SFPath);
MSI_SetPropertyW(package,TemplateFolder,TFPath);
MSI_SetPropertyW(package,DesktopFolder,DFPath);
}
UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
{
UINT rc;
MSIHANDLE handle;
MSIHANDLE db;
MSIPACKAGE *package;
CHAR uilevel[10];
MSIDATABASE *db = NULL;
MSIPACKAGE *package = NULL;
WCHAR uilevel[10];
UINT ret = ERROR_FUNCTION_FAILED;
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};
static const WCHAR szpi[] = {'%','i',0};
static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
TRACE("%s %p\n",debugstr_w(szPackage), phPackage);
rc = MsiOpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
if (rc != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
handle = alloc_msihandle(MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
MSI_FreePackage, (void**)&package);
package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
MSI_FreePackage );
if (!handle)
if (package)
{
MsiCloseHandle(db);
return ERROR_FUNCTION_FAILED;
msiobj_addref( &db->hdr );
package->db = db;
package->features = NULL;
package->folders = NULL;
package->components = NULL;
package->files = NULL;
package->loaded_features = 0;
package->loaded_folders = 0;
package->loaded_components= 0;
package->loaded_files = 0;
/* OK, here is where we do a slew of things to the database to
* prep for all that is to come as a package */
clone_properties(db);
set_installer_properties(package);
MSI_SetPropertyW(package, OriginalDatabase, szPackage);
MSI_SetPropertyW(package, Database, szPackage);
sprintfW(uilevel,szpi,gUILevel);
MSI_SetPropertyW(package, szLevel, uilevel);
msiobj_addref( &package->hdr );
*pPackage = package;
ret = ERROR_SUCCESS;
}
package->db = db;
package->features = NULL;
package->folders = NULL;
package->components = NULL;
package->files = NULL;
package->loaded_features = 0;
package->loaded_folders = 0;
package->loaded_components= 0;
package->loaded_files = 0;
if( package )
msiobj_release( &package->hdr );
if( db )
msiobj_release( &db->hdr );
/* ok here is where we do a slew of things to the database to
* prep for all that is to come as a package */
return ret;
}
clone_properties(db);
set_installer_properties(handle);
MsiSetPropertyW(handle, OriginalDatabase, szPackage);
MsiSetPropertyW(handle, Database, szPackage);
sprintf(uilevel,"%i",gUILevel);
MsiSetPropertyA(handle, "UILevel", uilevel);
UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
{
MSIPACKAGE *package = NULL;
UINT ret;
*phPackage = handle;
return ERROR_SUCCESS;
ret = MSI_OpenPackageW( szPackage, &package);
if( ret == ERROR_SUCCESS )
{
*phPackage = alloc_msihandle( &package->hdr );
msiobj_release( &package->hdr );
}
return ret;
}
UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
@ -358,28 +451,32 @@ UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phP
MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
{
MSIPACKAGE *package;
MSIHANDLE handle = 0;
TRACE("(%ld)\n",hInstall);
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if( package)
{
handle = alloc_msihandle( &package->db->hdr );
msiobj_release( &package->hdr );
}
if( !package)
return ERROR_INVALID_HANDLE;
msihandle_addref(package->db);
return package->db;
return handle;
}
INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
MSIHANDLE hRecord)
INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
MSIRECORD *record)
{
DWORD log_type = 0;
LPSTR message;
LPWSTR message;
DWORD sz;
DWORD total_size = 0;
INT msg_field=1;
INT i;
INT rc;
char *msg;
int len;
TRACE("%x \n",eMessageType);
rc = 0;
@ -402,39 +499,50 @@ INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
log_type |= 0x800;
message = HeapAlloc(GetProcessHeap(),0,1);
message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
message[0]=0;
msg_field = MsiRecordGetFieldCount(hRecord);
msg_field = MSI_RecordGetFieldCount(record);
for (i = 1; i <= msg_field; i++)
{
LPSTR tmp;
CHAR number[3];
LPWSTR tmp;
WCHAR number[3];
const static WCHAR format[] = { '%','i',':',' ',0};
const static WCHAR space[] = { ' ',0};
sz = 0;
MsiRecordGetStringA(hRecord,i,NULL,&sz);
MSI_RecordGetStringW(record,i,NULL,&sz);
sz+=4;
total_size+=sz;
tmp = HeapAlloc(GetProcessHeap(),0,sz);
message = HeapReAlloc(GetProcessHeap(),0,message,total_size);
total_size+=sz*sizeof(WCHAR);
tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
MsiRecordGetStringA(hRecord,i,tmp,&sz);
MSI_RecordGetStringW(record,i,tmp,&sz);
if (msg_field > 1)
{
sprintf(number,"%i: ",i);
strcat(message,number);
sprintfW(number,format,i);
strcatW(message,number);
}
strcat(message,tmp);
strcatW(message,tmp);
if (msg_field > 1)
strcat(message," ");
strcatW(message,space);
HeapFree(GetProcessHeap(),0,tmp);
}
TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
debugstr_a(message));
debugstr_w(message));
/* convert it to ASCII */
len = WideCharToMultiByte( CP_ACP, 0, message, -1,
NULL, 0, NULL, NULL );
msg = HeapAlloc( GetProcessHeap(), 0, len );
WideCharToMultiByte( CP_ACP, 0, message, -1,
msg, len, NULL, NULL );
if (gUIHandler && (gUIFilter & log_type))
rc = gUIHandler(gUIContext,eMessageType,message);
{
rc = gUIHandler(gUIContext,eMessageType,msg);
}
if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
INSTALLMESSAGE_PROGRESS))
@ -446,16 +554,43 @@ INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
if (log_file != INVALID_HANDLE_VALUE)
{
SetFilePointer(log_file,0, NULL, FILE_END);
WriteFile(log_file,message,strlen(message),&write,NULL);
WriteFile(log_file,msg,strlen(msg),&write,NULL);
WriteFile(log_file,"\n",1,&write,NULL);
CloseHandle(log_file);
}
}
HeapFree( GetProcessHeap(), 0, msg );
HeapFree(GetProcessHeap(),0,message);
return ERROR_SUCCESS;
}
INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
MSIHANDLE hRecord)
{
UINT ret = ERROR_INVALID_HANDLE;
MSIPACKAGE *package = NULL;
MSIRECORD *record = NULL;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
if( !package )
goto out;
record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
if( !record )
goto out;
ret = MSI_ProcessMessage( package, eMessageType, record );
out:
if( package )
msiobj_release( &package->hdr );
if( record )
msiobj_release( &record->hdr );
return ret;
}
/* property code */
UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
{
@ -496,10 +631,10 @@ end:
return hr;
}
UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
{
MSIPACKAGE *package;
MSIHANDLE view,row;
MSIQUERY *view;
MSIRECORD *row;
UINT rc;
DWORD sz = 0;
static const WCHAR Insert[]=
@ -517,48 +652,54 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
TRACE("Setting property (%s %s)\n",debugstr_w(szName),
debugstr_w(szValue));
if (!hInstall)
return ERROR_INVALID_HANDLE;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if( !package)
return ERROR_INVALID_HANDLE;
rc = MsiGetPropertyW(hInstall,szName,0,&sz);
rc = MSI_GetPropertyW(package,szName,0,&sz);
if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
{
sprintfW(Query,Update,szName);
row = MsiCreateRecord(1);
MsiRecordSetStringW(row,1,szValue);
row = MSI_CreateRecord(1);
MSI_RecordSetStringW(row,1,szValue);
}
else
{
strcpyW(Query,Insert);
row = MsiCreateRecord(2);
MsiRecordSetStringW(row,1,szName);
MsiRecordSetStringW(row,2,szValue);
row = MSI_CreateRecord(2);
MSI_RecordSetStringW(row,1,szName);
MSI_RecordSetStringW(row,2,szValue);
}
rc = MsiDatabaseOpenViewW(package->db,Query,&view);
rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
if (rc!= ERROR_SUCCESS)
{
MsiCloseHandle(row);
msiobj_release(&row->hdr);
return rc;
}
rc = MsiViewExecute(view,row);
rc = MSI_ViewExecute(view,row);
MsiCloseHandle(row);
MsiViewClose(view);
MsiCloseHandle(view);
msiobj_release(&row->hdr);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
{
MSIPACKAGE *package;
UINT ret;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if( !package)
return ERROR_INVALID_HANDLE;
ret = MSI_SetPropertyW( package, szName, szValue);
msiobj_release( &package->hdr );
return ret;
}
UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
{
LPWSTR szwName = NULL, szwValueBuf = NULL;
@ -615,10 +756,11 @@ end:
return hr;
}
UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf)
{
MSIHANDLE view,row;
MSIQUERY *view;
MSIRECORD *row;
UINT rc;
WCHAR Query[1024]=
{'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
@ -626,23 +768,15 @@ UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
,'_','P','r','o','p','e','r','t','y','=','`',0};
static const WCHAR szEnd[]={'`',0};
MSIPACKAGE *package;
if (0 == hInstall) {
return ERROR_INVALID_HANDLE;
}
if (NULL == szName) {
return ERROR_INVALID_PARAMETER;
}
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if( !package)
return ERROR_INVALID_HANDLE;
strcatW(Query,szName);
strcatW(Query,szEnd);
rc = MsiDatabaseOpenViewW(package->db, Query, &view);
rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
if (rc == ERROR_SUCCESS)
{
DWORD sz;
@ -652,25 +786,25 @@ UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
if (*pchValueBuf > 0)
szValueBuf[0] = 0;
rc = MsiViewExecute(view, 0);
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return rc;
}
rc = MsiViewFetch(view,&row);
rc = MSI_ViewFetch(view,&row);
if (rc == ERROR_SUCCESS)
{
sz=0x100;
rc = MsiRecordGetStringW(row,1,value,&sz);
rc = MSI_RecordGetStringW(row,1,value,&sz);
strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
*pchValueBuf = sz+1;
MsiCloseHandle(row);
msiobj_release(&row->hdr);
}
MsiViewClose(view);
MsiCloseHandle(view);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
if (rc == ERROR_SUCCESS)
@ -684,3 +818,18 @@ UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
return rc;
}
UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf)
{
MSIPACKAGE *package;
UINT ret;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if( !package)
return ERROR_INVALID_HANDLE;
ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
msiobj_release( &package->hdr );
return ret;
}

View File

@ -1,7 +1,7 @@
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2002 Mike McCormack for CodeWeavers
* Copyright 2002-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
@ -41,24 +41,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
#define MSIFIELD_WSTR 3
#define MSIFIELD_STREAM 4
/* maybe we can use a Variant instead of doing it ourselves? */
typedef struct tagMSIFIELD
{
UINT type;
union
{
INT iVal;
LPWSTR szwVal;
IStream *stream;
} u;
} MSIFIELD;
typedef struct tagMSIRECORD
{
UINT count; /* as passed to MsiCreateRecord */
MSIFIELD fields[1]; /* nb. array size is count+1 */
} MSIRECORD;
void MSI_FreeField( MSIFIELD *field )
{
switch( field->type )
@ -77,7 +59,7 @@ void MSI_FreeField( MSIFIELD *field )
}
}
void MSI_CloseRecord( VOID *arg )
void MSI_CloseRecord( MSIOBJECTHDR *arg )
{
MSIRECORD *rec = (MSIRECORD *) arg;
UINT i;
@ -86,28 +68,42 @@ void MSI_CloseRecord( VOID *arg )
MSI_FreeField( &rec->fields[i] );
}
MSIHANDLE WINAPI MsiCreateRecord( unsigned int cParams )
MSIRECORD *MSI_CreateRecord( unsigned int cParams )
{
MSIHANDLE handle = 0;
UINT sz;
MSIRECORD *rec;
UINT len;
TRACE("%d\n", cParams);
sz = sizeof (MSIRECORD) + sizeof(MSIFIELD)*(cParams+1) ;
handle = alloc_msihandle( MSIHANDLETYPE_RECORD, sz,
MSI_CloseRecord, (void**) &rec );
if( !handle )
return 0;
len = sizeof (MSIRECORD) + sizeof (MSIFIELD)*cParams;
rec = alloc_msiobject( MSIHANDLETYPE_RECORD, len, MSI_CloseRecord );
if( rec )
rec->count = cParams;
return rec;
}
return handle;
MSIHANDLE WINAPI MsiCreateRecord( unsigned int cParams )
{
MSIRECORD *rec;
MSIHANDLE ret = 0;
TRACE("%d\n", cParams);
rec = MSI_CreateRecord( cParams );
if( rec )
ret = alloc_msihandle( &rec->hdr );
return ret;
}
unsigned int MSI_RecordGetFieldCount( MSIRECORD *rec )
{
return rec->count;
}
unsigned int WINAPI MsiRecordGetFieldCount( MSIHANDLE handle )
{
MSIRECORD *rec;
UINT ret;
TRACE("%ld\n", handle );
@ -118,7 +114,10 @@ unsigned int WINAPI MsiRecordGetFieldCount( MSIHANDLE handle )
return 0;
}
return rec->count;
ret = MSI_RecordGetFieldCount( rec );
msiobj_release( &rec->hdr );
return ret;
}
static BOOL string2intW( LPCWSTR str, int *out )
@ -144,16 +143,11 @@ static BOOL string2intW( LPCWSTR str, int *out )
return TRUE;
}
int WINAPI MsiRecordGetInteger( MSIHANDLE handle, unsigned int iField)
int MSI_RecordGetInteger( MSIRECORD *rec, unsigned int iField)
{
MSIRECORD *rec;
int ret = 0;
TRACE("%ld %d\n", handle, iField );
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return MSI_NULL_INTEGER;
TRACE("%p %d\n", rec, iField );
if( iField > rec->count )
return MSI_NULL_INTEGER;
@ -173,6 +167,23 @@ int WINAPI MsiRecordGetInteger( MSIHANDLE handle, unsigned int iField)
return MSI_NULL_INTEGER;
}
int WINAPI MsiRecordGetInteger( MSIHANDLE handle, unsigned int iField)
{
MSIRECORD *rec;
UINT ret;
TRACE("%ld %d\n", handle, iField );
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return MSI_NULL_INTEGER;
ret = MSI_RecordGetInteger( rec, iField );
msiobj_release( &rec->hdr );
return ret;
}
UINT WINAPI MsiRecordClearData( MSIHANDLE handle )
{
MSIRECORD *rec;
@ -194,15 +205,9 @@ UINT WINAPI MsiRecordClearData( MSIHANDLE handle )
return ERROR_SUCCESS;
}
UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, unsigned int iField, int iVal )
UINT MSI_RecordSetInteger( MSIRECORD *rec, unsigned int iField, int iVal )
{
MSIRECORD *rec;
TRACE("%ld %u %d\n", handle,iField, iVal);
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
TRACE("%p %u %d\n", rec, iField, iVal);
if( iField <= rec->count )
{
@ -214,35 +219,57 @@ UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, unsigned int iField, int iVal
return ERROR_SUCCESS;
}
BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, unsigned int iField )
UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, unsigned int iField, int iVal )
{
MSIRECORD *rec;
BOOL r = TRUE;
UINT ret;
TRACE("%ld %d\n", handle,iField );
TRACE("%ld %u %d\n", handle, iField, iVal);
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
ret = MSI_RecordSetInteger( rec, iField, iVal );
msiobj_release( &rec->hdr );
return ret;
}
BOOL MSI_RecordIsNull( MSIRECORD *rec, unsigned int iField )
{
BOOL r = TRUE;
TRACE("%p %d\n", rec, iField );
r = ( iField > rec->count ) ||
( rec->fields[iField].type == MSIFIELD_NULL );
return r;
}
UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, unsigned int iField,
LPSTR szValue, DWORD *pcchValue)
BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, unsigned int iField )
{
MSIRECORD *rec;
UINT len=0, ret;
CHAR buffer[16];
UINT ret;
TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
TRACE("%ld %d\n", handle, iField );
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
ret = MSI_RecordIsNull( rec, iField );
msiobj_release( &rec->hdr );
return ret;
}
UINT MSI_RecordGetStringA(MSIRECORD *rec, unsigned int iField,
LPSTR szValue, DWORD *pcchValue)
{
UINT len=0, ret;
CHAR buffer[16];
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
if( iField > rec->count )
return ERROR_INVALID_PARAMETER;
@ -277,14 +304,24 @@ UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, unsigned int iField,
return ret;
}
const WCHAR *MSI_RecordGetString( MSIHANDLE handle, unsigned int iField )
UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, unsigned int iField,
LPSTR szValue, DWORD *pcchValue)
{
MSIRECORD *rec;
UINT ret;
TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return NULL;
return ERROR_INVALID_HANDLE;
ret = MSI_RecordGetStringA( rec, iField, szValue, pcchValue);
msiobj_release( &rec->hdr );
return ret;
}
const WCHAR *MSI_RecordGetString( MSIRECORD *rec, unsigned int iField )
{
if( iField > rec->count )
return NULL;
@ -294,19 +331,14 @@ const WCHAR *MSI_RecordGetString( MSIHANDLE handle, unsigned int iField )
return rec->fields[iField].u.szwVal;
}
UINT WINAPI MsiRecordGetStringW(MSIHANDLE handle, unsigned int iField,
UINT MSI_RecordGetStringW(MSIRECORD *rec, unsigned int iField,
LPWSTR szValue, DWORD *pcchValue)
{
MSIRECORD *rec;
UINT len=0, ret;
WCHAR buffer[16];
static const WCHAR szFormat[] = { '%','d',0 };
TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
if( iField > rec->count )
return ERROR_INVALID_PARAMETER;
@ -338,23 +370,35 @@ UINT WINAPI MsiRecordGetStringW(MSIHANDLE handle, unsigned int iField,
return ret;
}
UINT WINAPI MsiRecordGetStringW(MSIHANDLE handle, unsigned int iField,
LPWSTR szValue, DWORD *pcchValue)
{
MSIRECORD *rec;
UINT ret;
TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
ret = MSI_RecordGetStringW( rec, iField, szValue, pcchValue );
msiobj_release( &rec->hdr );
return ret;
}
UINT WINAPI MsiRecordDataSize(MSIHANDLE hRecord, unsigned int iField)
{
FIXME("%ld %d\n", hRecord, iField);
return 0;
}
UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, unsigned int iField, LPCSTR szValue )
UINT MSI_RecordSetStringA( MSIRECORD *rec, unsigned int iField, LPCSTR szValue )
{
MSIRECORD *rec;
LPWSTR str;
UINT len;
TRACE("%ld %d %s\n", handle, iField, debugstr_a(szValue));
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
TRACE("%p %d %s\n", rec, iField, debugstr_a(szValue));
if( iField > rec->count )
return ERROR_INVALID_FIELD;
@ -369,21 +413,33 @@ UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, unsigned int iField, LPCSTR s
return 0;
}
UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, unsigned int iField, LPCWSTR szValue )
UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, unsigned int iField, LPCSTR szValue )
{
MSIRECORD *rec;
LPWSTR str;
UINT ret;
TRACE("%ld %d %s\n", handle, iField, debugstr_w(szValue));
TRACE("%ld %d %s\n", handle, iField, debugstr_a(szValue));
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
ret = MSI_RecordSetStringA( rec, iField, szValue );
msiobj_release( &rec->hdr );
return ret;
}
UINT MSI_RecordSetStringW( MSIRECORD *rec, unsigned int iField, LPCWSTR szValue )
{
LPWSTR str;
UINT len;
TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue));
if( iField > rec->count )
return ERROR_INVALID_FIELD;
str = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(szValue) + 1)*sizeof (WCHAR));
len = lstrlenW(szValue) + 1;
str = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR));
lstrcpyW( str, szValue );
MSI_FreeField( &rec->fields[iField] );
@ -393,6 +449,22 @@ UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, unsigned int iField, LPCWSTR
return 0;
}
UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, unsigned int iField, LPCWSTR szValue )
{
MSIRECORD *rec;
UINT ret;
TRACE("%ld %d %s\n", handle, iField, debugstr_w(szValue));
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
ret = MSI_RecordSetStringW( rec, iField, szValue );
msiobj_release( &rec->hdr );
return ret;
}
UINT WINAPI MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, LPSTR szResult, DWORD *sz)
{
FIXME("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz);
@ -417,18 +489,13 @@ UINT WINAPI MsiRecordSetStreamW(MSIHANDLE hRecord, unsigned int iField, LPCWSTR
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiRecordReadStream(MSIHANDLE handle, unsigned int iField, char *buf, DWORD *sz)
UINT MSI_RecordReadStream(MSIRECORD *rec, unsigned int iField, char *buf, DWORD *sz)
{
MSIRECORD *rec;
ULONG count;
HRESULT r;
IStream *stm;
TRACE("%ld %d %p %p\n", handle, iField, buf, sz);
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
TRACE("%p %d %p %p\n", rec, iField, buf, sz);
if( iField > rec->count )
return ERROR_INVALID_FIELD;
@ -471,15 +538,24 @@ UINT WINAPI MsiRecordReadStream(MSIHANDLE handle, unsigned int iField, char *buf
return ERROR_SUCCESS;
}
UINT WINAPI MSI_RecordSetIStream( MSIHANDLE handle, unsigned int iField, IStream *stm )
UINT WINAPI MsiRecordReadStream(MSIHANDLE handle, unsigned int iField, char *buf, DWORD *sz)
{
MSIRECORD *rec;
UINT ret;
TRACE("%ld %d %p\n", handle, iField, stm);
TRACE("%ld %d %p %p\n", handle, iField, buf, sz);
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec )
return ERROR_INVALID_HANDLE;
ret = MSI_RecordReadStream( rec, iField, buf, sz );
msiobj_release( &rec->hdr );
return ret;
}
UINT MSI_RecordSetIStream( MSIRECORD *rec, unsigned int iField, IStream *stm )
{
TRACE("%p %d %p\n", rec, iField, stm);
if( iField > rec->count )
return ERROR_INVALID_FIELD;

View File

@ -111,11 +111,11 @@ static UINT SELECT_insert_row( struct tagMSIVIEW *view, UINT *num )
return sv->table->ops->insert_row( sv->table, num );
}
static UINT SELECT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
static UINT SELECT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p %ld\n", sv, record);
TRACE("%p %p\n", sv, record);
if( !sv->table )
return ERROR_FUNCTION_FAILED;

View File

@ -38,7 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
static const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y',
'I','n','f','o','r','m','a','t','i','o','n',0 };
static void MSI_CloseSummaryInfo( VOID *arg )
static void MSI_CloseSummaryInfo( MSIOBJECTHDR *arg )
{
MSISUMMARYINFO *suminfo = (MSISUMMARYINFO *) arg;
IPropertyStorage_Release( suminfo->propstg );
@ -74,7 +74,7 @@ UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase,
LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo)
{
HRESULT r;
MSIHANDLE handle, hdb = hDatabase;
MSIHANDLE handle;
MSISUMMARYINFO *suminfo;
MSIDATABASE *db;
UINT ret = ERROR_SUCCESS;
@ -92,20 +92,24 @@ UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase,
{
UINT res;
res = MsiOpenDatabaseW(szDatabase, NULL, &hdb);
res = MSI_OpenDatabaseW(szDatabase, NULL, &db);
if( res != ERROR_SUCCESS )
return res;
}
db = msihandle2msiinfo(hdb, MSIHANDLETYPE_DATABASE);
if( !db )
return ERROR_INVALID_PARAMETER;
else
{
db = msihandle2msiinfo(hDatabase, MSIHANDLETYPE_DATABASE);
if( !db )
return ERROR_INVALID_PARAMETER;
}
r = IStorage_QueryInterface( db->storage,
&IID_IPropertySetStorage, (LPVOID)&psstg);
if( FAILED( r ) )
{
ERR("IStorage -> IPropertySetStorage failed\n");
if (db)
msiobj_release(&db->hdr);
return ERROR_FUNCTION_FAILED;
}
ERR("storage = %p propertysetstorage = %p\n", db->storage, psstg);
@ -119,10 +123,9 @@ UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase,
goto end;
}
handle = alloc_msihandle( MSIHANDLETYPE_SUMMARYINFO,
sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo,
(void**) &suminfo );
if( !handle )
suminfo = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO,
sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
if( !suminfo )
{
ret = ERROR_FUNCTION_FAILED;
goto end;
@ -130,15 +133,20 @@ UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase,
IPropertyStorage_AddRef(ps);
suminfo->propstg = ps;
handle = alloc_msihandle( &suminfo->hdr );
if( handle )
*phSummaryInfo = handle;
else
ret = ERROR_FUNCTION_FAILED;
msiobj_release( &suminfo->hdr );
end:
if( ps )
IPropertyStorage_Release(ps);
if( psstg )
IPropertySetStorage_Release(psstg);
if( !hDatabase )
MsiCloseHandle( hdb );
if (db)
msiobj_release(&db->hdr);
return ret;
}

View File

@ -288,18 +288,7 @@ UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm )
return ERROR_SUCCESS;
}
/* FIXME: we should be passing around pointers to db structures internally */
UINT get_raw_stream( MSIHANDLE hdb, LPCWSTR stname, IStream **stm )
{
MSIDATABASE *db = msihandle2msiinfo(hdb, MSIHANDLETYPE_DATABASE );
if ( !db )
return ERROR_INVALID_HANDLE;
return db_get_raw_stream( db, stname, stm );
}
UINT read_raw_stream_data( MSIHANDLE hdb, LPCWSTR stname,
UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
USHORT **pdata, UINT *psz )
{
HRESULT r;
@ -309,10 +298,9 @@ UINT read_raw_stream_data( MSIHANDLE hdb, LPCWSTR stname,
IStream *stm = NULL;
STATSTG stat;
r = get_raw_stream( hdb, stname, &stm );
r = db_get_raw_stream( db, stname, &stm );
if( r != ERROR_SUCCESS)
goto end;
ret = ERROR_FUNCTION_FAILED;
return ret;
r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
if( FAILED( r ) )
{
@ -1114,6 +1102,9 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT ival = 0, refcol = 0, r;
LPWSTR sval;
LPWSTR full_name;
DWORD len;
static const WCHAR szDot[] = { '.', 0 };
if( !view->ops->fetch_int )
return ERROR_INVALID_PARAMETER;
@ -1138,22 +1129,16 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
if( !sval )
return ERROR_INVALID_PARAMETER;
{
LPWSTR full_name;
DWORD len;
static const WCHAR szDot[] = { '.', 0 };
len = strlenW( tv->name ) + 2 + strlenW( sval );
full_name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
strcpyW( full_name, tv->name );
strcatW( full_name, szDot );
strcatW( full_name, sval );
len = strlenW( tv->name ) + 2 + strlenW( sval );
full_name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
strcpyW( full_name, tv->name );
strcatW( full_name, szDot );
strcatW( full_name, sval );
r = db_get_raw_stream( tv->db, full_name, stm );
if( r )
ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
HeapFree( GetProcessHeap(), 0, full_name );
}
r = db_get_raw_stream( tv->db, full_name, stm );
if( r )
ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
HeapFree( GetProcessHeap(), 0, full_name );
HeapFree( GetProcessHeap(), 0, sval );
return r;
@ -1228,12 +1213,12 @@ UINT TABLE_insert_row( struct tagMSIVIEW *view, UINT *num )
return ERROR_SUCCESS;
}
static UINT TABLE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
static UINT TABLE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT r;
TRACE("%p %ld\n", tv, record);
TRACE("%p %p\n", tv, record);
if( tv->table )
return ERROR_FUNCTION_FAILED;

View File

@ -55,13 +55,13 @@ static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT
return ERROR_FUNCTION_FAILED;
}
static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
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 %ld\n", uv, record );
TRACE("%p %p\n", uv, record );
if( !record )
return ERROR_FUNCTION_FAILED;
@ -94,7 +94,7 @@ static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
}
else
{
val = MsiRecordGetInteger( record, n );
val = MSI_RecordGetInteger( record, n );
val |= 0x8000;
}
r = wv->ops->set_int( wv, row, n, val );
@ -172,6 +172,7 @@ static UINT UPDATE_delete( struct tagMSIVIEW *view )
wv->ops->delete( wv );
delete_value_list( uv->vals );
HeapFree( GetProcessHeap(), 0, uv );
msiobj_release( &uv->db->hdr );
return ERROR_SUCCESS;
}
@ -228,6 +229,7 @@ UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
/* fill the structure */
uv->view.ops = &update_ops;
msiobj_addref( &db->hdr );
uv->db = db;
uv->vals = list->val_list;
uv->wv = sv;

View File

@ -131,7 +131,7 @@ static UINT INT_evaluate( UINT lval, UINT op, UINT rval )
}
static const WCHAR *STRING_evaluate( string_table *st,
MSIVIEW *table, UINT row, struct expr *expr, MSIHANDLE record )
MSIVIEW *table, UINT row, struct expr *expr, MSIRECORD *record )
{
UINT val = 0, r;
@ -157,7 +157,7 @@ static const WCHAR *STRING_evaluate( string_table *st,
}
static UINT STRCMP_Evaluate( string_table *st, MSIVIEW *table, UINT row,
struct expr *cond, UINT *val, MSIHANDLE record )
struct expr *cond, UINT *val, MSIRECORD *record )
{
int sr;
const WCHAR *l_str, *r_str;
@ -181,7 +181,7 @@ static UINT STRCMP_Evaluate( string_table *st, MSIVIEW *table, UINT row,
}
static UINT WHERE_evaluate( MSIDATABASE *db, MSIVIEW *table, UINT row,
struct expr *cond, UINT *val, MSIHANDLE record )
struct expr *cond, UINT *val, MSIRECORD *record )
{
UINT r, lval, rval;
@ -211,7 +211,7 @@ static UINT WHERE_evaluate( MSIDATABASE *db, MSIVIEW *table, UINT row,
return STRCMP_Evaluate( db->strings, table, row, cond, val, record );
case EXPR_WILDCARD:
*val = MsiRecordGetInteger( record, 1 );
*val = MSI_RecordGetInteger( record, 1 );
return ERROR_SUCCESS;
default:
@ -223,13 +223,13 @@ static UINT WHERE_evaluate( MSIDATABASE *db, MSIVIEW *table, UINT row,
}
static UINT WHERE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
static UINT WHERE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
UINT count = 0, r, val, i;
MSIVIEW *table = wv->table;
TRACE("%p %ld\n", wv, record);
TRACE("%p %p\n", wv, record);
if( !table )
return ERROR_FUNCTION_FAILED;
@ -337,6 +337,7 @@ static UINT WHERE_delete( struct tagMSIVIEW *view )
delete_expr( wv->cond );
HeapFree( GetProcessHeap(), 0, wv );
msiobj_release( &wv->db->hdr );
return ERROR_SUCCESS;
}
@ -458,6 +459,7 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table,
/* fill the structure */
wv->view.ops = &where_ops;
msiobj_addref( &db->hdr );
wv->db = db;
wv->table = table;
wv->row_count = 0;