Start implementing MsiOpenPackage.
This commit is contained in:
parent
de8674ec6f
commit
eb0e0df908
|
@ -15,6 +15,7 @@ C_SRCS = \
|
|||
msi.c \
|
||||
msiquery.c \
|
||||
order.c \
|
||||
package.c \
|
||||
record.c \
|
||||
regsvr.c \
|
||||
select.c \
|
||||
|
|
|
@ -47,23 +47,6 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/stand
|
|||
|
||||
#define CUSTOM_ACTION_TYPE_MASK 0x3F
|
||||
|
||||
/*
|
||||
* These are hacks to get around the inability to write
|
||||
* to the database and the inability to select on string values
|
||||
* once those values are done then it will be possible to do
|
||||
* all this inside the database.
|
||||
*/
|
||||
|
||||
#define MAX_PROP 1024
|
||||
|
||||
typedef struct {
|
||||
WCHAR *prop_name;
|
||||
WCHAR *prop_value;
|
||||
} internal_property;
|
||||
|
||||
static internal_property PropTableHack[MAX_PROP];
|
||||
static INT PropCount = -1;
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
/*
|
||||
|
@ -83,13 +66,6 @@ static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
|
|||
static UINT HANDLE_CustomType2(MSIHANDLE hPackage, const LPWSTR source,
|
||||
const LPWSTR target, const INT type);
|
||||
|
||||
|
||||
static UINT set_property(MSIHANDLE hPackage, const WCHAR* prop,
|
||||
const WCHAR* value);
|
||||
UINT get_property(MSIHANDLE hPackage, const WCHAR* prop, WCHAR* value,
|
||||
DWORD* size);
|
||||
static VOID blitz_propertytable();
|
||||
static VOID set_installer_properties(MSIHANDLE hPackage);
|
||||
static DWORD deformat_string(MSIHANDLE hPackage, WCHAR* ptr,WCHAR** data);
|
||||
|
||||
/*
|
||||
|
@ -98,6 +74,7 @@ static DWORD deformat_string(MSIHANDLE hPackage, WCHAR* ptr,WCHAR** data);
|
|||
static const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
|
||||
static const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
|
||||
static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
|
||||
static const WCHAR c_collen[] = {'C',':','\\',0};
|
||||
|
||||
static const WCHAR cszlsb[]={'[',0};
|
||||
static const WCHAR cszrsb[]={']',0};
|
||||
|
@ -120,226 +97,6 @@ inline static char *strdupWtoA( const WCHAR *str )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static VOID blitz_propertytable()
|
||||
{
|
||||
if (PropCount == -1)
|
||||
{
|
||||
PropCount = 0;
|
||||
memset(&PropTableHack,0,sizeof(PropTableHack));
|
||||
}
|
||||
else if (PropCount > 0)
|
||||
{
|
||||
int i;
|
||||
TRACE("Clearing %i properties\n",PropCount);
|
||||
for (i = 0; i < PropCount; i++)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, PropTableHack[i].prop_name);
|
||||
HeapFree(GetProcessHeap(), 0, PropTableHack[i].prop_value);
|
||||
}
|
||||
memset(&PropTableHack,0,sizeof(PropTableHack));
|
||||
PropCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
UINT get_property(MSIHANDLE hPackage, const WCHAR* prop, WCHAR* value,
|
||||
DWORD* size)
|
||||
{
|
||||
UINT rc = 1;
|
||||
int index = 0;
|
||||
WCHAR* pName = PropTableHack[0].prop_name;
|
||||
|
||||
TRACE("Looking for property %s\n",debugstr_w(prop));
|
||||
|
||||
/* prop table hacks take presidence */
|
||||
|
||||
while (pName && strcmpW(pName,prop) && index < PropCount)
|
||||
{
|
||||
index ++;
|
||||
pName = PropTableHack[index].prop_name;
|
||||
}
|
||||
|
||||
if (pName && index < PropCount)
|
||||
{
|
||||
if (*size > strlenW(PropTableHack[index].prop_value))
|
||||
{
|
||||
*size = strlenW(PropTableHack[index].prop_value)+1;
|
||||
TRACE(" index %i\n", index);
|
||||
strcpyW(value , PropTableHack[index].prop_value);
|
||||
TRACE(" found value %s\n",debugstr_w(value));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*size = strlenW(PropTableHack[index].prop_value);
|
||||
return ERROR_MORE_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
rc = MsiGetPropertyW(hPackage,prop,value,size);
|
||||
|
||||
if (rc == ERROR_SUCCESS)
|
||||
TRACE(" found value %s\n",debugstr_w(value));
|
||||
else
|
||||
TRACE(" value not found\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static UINT set_property(MSIHANDLE hPackage, const WCHAR* prop,
|
||||
const WCHAR* value)
|
||||
{
|
||||
/* prop table hacks take precedence */
|
||||
UINT rc;
|
||||
int index = 0;
|
||||
WCHAR* pName;
|
||||
|
||||
if (PropCount == -1)
|
||||
blitz_propertytable();
|
||||
|
||||
pName = PropTableHack[0].prop_name;
|
||||
|
||||
TRACE("Setting property %s to %s\n",debugstr_w(prop),debugstr_w(value));
|
||||
|
||||
while (pName && strcmpW(pName,prop) && index < MAX_PROP)
|
||||
{
|
||||
index ++;
|
||||
pName = PropTableHack[index].prop_name;
|
||||
}
|
||||
|
||||
if (pName && index < MAX_PROP)
|
||||
{
|
||||
TRACE("property index %i\n",index);
|
||||
strcpyW(PropTableHack[index].prop_value,value);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index >= MAX_PROP)
|
||||
{
|
||||
ERR("EXCEEDING MAX PROP!!!!\n");
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
PropTableHack[index].prop_name = HeapAlloc(GetProcessHeap(),0,1024);
|
||||
PropTableHack[index].prop_value= HeapAlloc(GetProcessHeap(),0,1024);
|
||||
strcpyW(PropTableHack[index].prop_name,prop);
|
||||
strcpyW(PropTableHack[index].prop_value,value);
|
||||
PropCount++;
|
||||
TRACE("new property index %i (%i)\n",index,PropCount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* currently unreachable */
|
||||
rc = MsiSetPropertyW(hPackage,prop,value);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are a whole slew of these we need to set
|
||||
*
|
||||
*
|
||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
|
||||
*/
|
||||
|
||||
static VOID set_installer_properties(MSIHANDLE hPackage)
|
||||
{
|
||||
WCHAR pth[MAX_PATH];
|
||||
|
||||
static const WCHAR c_col[] =
|
||||
{'C',':','\\',0};
|
||||
static const WCHAR CFF[] =
|
||||
{'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR PFF[] =
|
||||
{'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR CADF[] =
|
||||
{'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR ATF[] =
|
||||
{'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR ADF[] =
|
||||
{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR SF[] =
|
||||
{'S','y','s','t','e','m','F','o','l','d','e','r',0};
|
||||
static const WCHAR LADF[] =
|
||||
{'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR MPF[] =
|
||||
{'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR PF[] =
|
||||
{'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
|
||||
static const WCHAR WF[] =
|
||||
{'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};
|
||||
|
||||
/* Not yet set ... but needed by iTunes
|
||||
*
|
||||
static const WCHAR DF[] =
|
||||
{'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
|
||||
static const WCHAR FF[] =
|
||||
{'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR FoF[] =
|
||||
{'F','o','n','t','s','F','o','l','d','e','r',0};
|
||||
PrimaryVolumePath
|
||||
ProgramFiles64Folder
|
||||
ProgramMenuFolder
|
||||
SendToFolder
|
||||
StartMenuFolder
|
||||
StartupFolder
|
||||
System16Folder
|
||||
System64Folder
|
||||
TemplateFolder
|
||||
*/
|
||||
|
||||
/* asked for by iTunes ... but are they installer set?
|
||||
*
|
||||
* GlobalAssemblyCache
|
||||
*/
|
||||
|
||||
set_property(hPackage, cszRootDrive, c_col);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, CFF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, PFF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, CADF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, ATF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, ADF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, SF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, LADF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, MPF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, PF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
set_property(hPackage, WF, pth);
|
||||
|
||||
GetTempPathW(MAX_PATH,pth);
|
||||
set_property(hPackage, TF, pth);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************
|
||||
* TOP level entry points
|
||||
*****************************************************/
|
||||
|
@ -351,23 +108,17 @@ UINT ACTION_DoTopLevelINSTALL(MSIHANDLE hPackage, LPCWSTR szPackagePath,
|
|||
UINT rc;
|
||||
static const CHAR *ExecSeqQuery =
|
||||
"select * from InstallExecuteSequence where Sequence > 0 order by Sequence";
|
||||
MSIHANDLE db;
|
||||
|
||||
FIXME("****We do not do any of the UI level stuff yet***\n");
|
||||
|
||||
/* reset our properties */
|
||||
blitz_propertytable();
|
||||
|
||||
if (szPackagePath)
|
||||
{
|
||||
static const WCHAR OriginalDatabase[] =
|
||||
{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
|
||||
LPWSTR p;
|
||||
WCHAR check[MAX_PATH];
|
||||
WCHAR pth[MAX_PATH];
|
||||
DWORD size;
|
||||
|
||||
set_property(hPackage, OriginalDatabase, szPackagePath);
|
||||
|
||||
strcpyW(pth,szPackagePath);
|
||||
p = strrchrW(pth,'\\');
|
||||
if (p)
|
||||
|
@ -377,11 +128,13 @@ UINT ACTION_DoTopLevelINSTALL(MSIHANDLE hPackage, LPCWSTR szPackagePath,
|
|||
}
|
||||
|
||||
size = MAX_PATH;
|
||||
if (get_property(hPackage,cszSourceDir,check,&size) != ERROR_SUCCESS )
|
||||
set_property(hPackage, cszSourceDir, pth);
|
||||
if (MsiGetPropertyW(hPackage,cszSourceDir,check,&size) != ERROR_SUCCESS )
|
||||
MsiSetPropertyW(hPackage, cszSourceDir, pth);
|
||||
}
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
|
@ -456,7 +209,6 @@ UINT ACTION_DoTopLevelINSTALL(MSIHANDLE hPackage, LPCWSTR szPackagePath,
|
|||
}
|
||||
|
||||
end:
|
||||
blitz_propertytable();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -588,10 +340,15 @@ static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action)
|
|||
WCHAR source[0x100];
|
||||
WCHAR target[0x200];
|
||||
WCHAR *deformated=NULL;
|
||||
MSIHANDLE db;
|
||||
|
||||
strcatW(ExecSeqQuery,action);
|
||||
strcatW(ExecSeqQuery,end);
|
||||
rc = MsiDatabaseOpenViewW(hPackage, ExecSeqQuery, &view);
|
||||
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewW(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -633,7 +390,7 @@ static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action)
|
|||
case 35: /* Directory set with formatted text. */
|
||||
case 51: /* Property set with formatted text. */
|
||||
deformat_string(hPackage,target,&deformated);
|
||||
set_property(hPackage,source,deformated);
|
||||
MsiSetPropertyW(hPackage,source,deformated);
|
||||
HeapFree(GetProcessHeap(),0,deformated);
|
||||
break;
|
||||
default:
|
||||
|
@ -654,7 +411,7 @@ static UINT store_binary_to_temp(MSIHANDLE hPackage, const LPWSTR source,
|
|||
static const WCHAR TF[]= {'T','e','m','p','F','o','l','d','e','r',0};
|
||||
DWORD sz=MAX_PATH;
|
||||
|
||||
if (get_property(hPackage, TF,tmp_file, &sz) != ERROR_SUCCESS)
|
||||
if (MsiGetPropertyW(hPackage, TF,tmp_file, &sz) != ERROR_SUCCESS)
|
||||
GetTempPathW(MAX_PATH,tmp_file);
|
||||
|
||||
strcatW(tmp_file,source);
|
||||
|
@ -676,6 +433,7 @@ static UINT store_binary_to_temp(MSIHANDLE hPackage, const LPWSTR source,
|
|||
static const WCHAR end[]={'`',0};
|
||||
HANDLE the_file;
|
||||
CHAR buffer[1024];
|
||||
MSIHANDLE db;
|
||||
|
||||
the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
@ -685,7 +443,11 @@ static UINT store_binary_to_temp(MSIHANDLE hPackage, const LPWSTR source,
|
|||
|
||||
strcatW(Query,source);
|
||||
strcatW(Query,end);
|
||||
rc = MsiDatabaseOpenViewW(hPackage, Query, &view);
|
||||
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewW(db, Query, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -782,7 +544,6 @@ static UINT HANDLE_CustomType2(MSIHANDLE hPackage, const LPWSTR source,
|
|||
PROCESS_INFORMATION info;
|
||||
BOOL rc;
|
||||
WCHAR *deformated;
|
||||
static const WCHAR c_collen[] = {'C',':','\\',0};
|
||||
static const WCHAR spc[] = {' ',0};
|
||||
|
||||
memset(&si,0,sizeof(STARTUPINFOW));
|
||||
|
@ -875,8 +636,12 @@ static UINT ACTION_CreateFolders(MSIHANDLE hPackage)
|
|||
static const CHAR *ExecSeqQuery = "select * from CreateFolder";
|
||||
UINT rc;
|
||||
MSIHANDLE view;
|
||||
MSIHANDLE db;
|
||||
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -913,7 +678,7 @@ static UINT ACTION_CreateFolders(MSIHANDLE hPackage)
|
|||
}
|
||||
|
||||
sz = MAX_PATH;
|
||||
rc = get_property(hPackage, dir,full_path,&sz);
|
||||
rc = MsiGetPropertyW(hPackage, dir,full_path,&sz);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
|
@ -961,9 +726,10 @@ static UINT resolve_directory(MSIHANDLE hPackage, const WCHAR* dir,
|
|||
MSIHANDLE row = 0;
|
||||
WCHAR full_path[MAX_PATH];
|
||||
WCHAR name_source[0x100];
|
||||
MSIHANDLE db;
|
||||
|
||||
sz = MAX_PATH;
|
||||
if (get_property(hPackage,dir,path,&sz)==ERROR_SUCCESS)
|
||||
if (MsiGetPropertyW(hPackage,dir,path,&sz)==ERROR_SUCCESS)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
TRACE("Working to resolve %s\n",debugstr_w(dir));
|
||||
|
@ -974,18 +740,14 @@ static UINT resolve_directory(MSIHANDLE hPackage, const WCHAR* dir,
|
|||
if (!source)
|
||||
{
|
||||
sz = 0x100;
|
||||
if(!get_property(hPackage,cszRootDrive,buffer,&sz))
|
||||
if(!MsiGetPropertyW(hPackage,cszRootDrive,buffer,&sz))
|
||||
{
|
||||
set_property(hPackage,cszTargetDir,buffer);
|
||||
MsiSetPropertyW(hPackage,cszTargetDir,buffer);
|
||||
strcpyW(path,buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("No RootDrive property defined disaster!\n");
|
||||
MsiCloseHandle(row);
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
strcpyW(path,c_collen);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -996,7 +758,11 @@ static UINT resolve_directory(MSIHANDLE hPackage, const WCHAR* dir,
|
|||
|
||||
strcatW(Query,dir);
|
||||
strcatW(Query,end);
|
||||
rc = MsiDatabaseOpenViewW(hPackage, Query, &view);
|
||||
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewW(db, Query, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -1068,7 +834,7 @@ static UINT resolve_directory(MSIHANDLE hPackage, const WCHAR* dir,
|
|||
strcatW(full_path,targetdir);
|
||||
strcatW(full_path,cszbs);
|
||||
}
|
||||
set_property(hPackage,dir,full_path);
|
||||
MsiSetPropertyW(hPackage,dir,full_path);
|
||||
if (!source)
|
||||
strcpyW(path,full_path);
|
||||
|
||||
|
@ -1087,7 +853,7 @@ static UINT resolve_directory(MSIHANDLE hPackage, const WCHAR* dir,
|
|||
|
||||
strcpyW(name_source,dir);
|
||||
strcatW(name_source,cszsrc);
|
||||
set_property(hPackage,name_source,full_path);
|
||||
MsiSetPropertyW(hPackage,name_source,full_path);
|
||||
if (source)
|
||||
strcpyW(path,full_path);
|
||||
}
|
||||
|
@ -1122,15 +888,14 @@ static UINT ACTION_CostFinalize(MSIHANDLE hPackage)
|
|||
static const CHAR *ExecSeqQuery = "select * from Directory";
|
||||
UINT rc;
|
||||
MSIHANDLE view;
|
||||
|
||||
/* According to MSDN these properties are set when CostFinalize is run
|
||||
* or MsiSetInstallLevel is called */
|
||||
TRACE("Setting installer properties\n");
|
||||
set_installer_properties(hPackage);
|
||||
MSIHANDLE db;
|
||||
|
||||
TRACE("Building Directory properties\n");
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -1184,14 +949,17 @@ static UINT writeout_cabinet_stream(MSIHANDLE hPackage, WCHAR* stream_name,
|
|||
UINT size;
|
||||
DWORD write;
|
||||
HANDLE the_file;
|
||||
MSIHANDLE db;
|
||||
|
||||
rc = read_raw_stream_data(hPackage,stream_name,&data,&size);
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = read_raw_stream_data(db,stream_name,&data,&size);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
write = 0x100;
|
||||
if (get_property(hPackage, cszSourceDir, source, &write))
|
||||
if (MsiGetPropertyW(hPackage, cszSourceDir, source, &write))
|
||||
{
|
||||
ERR("No Source dir defined \n");
|
||||
rc = ERROR_FUNCTION_FAILED;
|
||||
|
@ -1271,6 +1039,7 @@ static UINT ready_media_for_file(MSIHANDLE hPackage, UINT sequence,
|
|||
DWORD sz=0x100;
|
||||
INT seq;
|
||||
static INT last_sequence = 0;
|
||||
MSIHANDLE db;
|
||||
|
||||
if (sequence <= last_sequence)
|
||||
{
|
||||
|
@ -1280,7 +1049,10 @@ static UINT ready_media_for_file(MSIHANDLE hPackage, UINT sequence,
|
|||
|
||||
sprintf(Query,ExecSeqQuery,sequence);
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, Query, &view);
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, Query, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -1316,7 +1088,7 @@ static UINT ready_media_for_file(MSIHANDLE hPackage, UINT sequence,
|
|||
else
|
||||
{
|
||||
sz = 0x100;
|
||||
if (get_property(hPackage, cszSourceDir, source, &sz))
|
||||
if (MsiGetPropertyW(hPackage, cszSourceDir, source, &sz))
|
||||
{
|
||||
ERR("No Source dir defined \n");
|
||||
rc = ERROR_FUNCTION_FAILED;
|
||||
|
@ -1358,11 +1130,14 @@ static UINT get_directory_for_component(MSIHANDLE hPackage,
|
|||
static const WCHAR end[]={'`',0};
|
||||
WCHAR dir[0x100];
|
||||
DWORD sz=0x100;
|
||||
MSIHANDLE db;
|
||||
|
||||
strcatW(ExecSeqQuery,component);
|
||||
strcatW(ExecSeqQuery,end);
|
||||
|
||||
rc = MsiDatabaseOpenViewW(hPackage, ExecSeqQuery, &view);
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewW(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
@ -1387,7 +1162,7 @@ static UINT get_directory_for_component(MSIHANDLE hPackage,
|
|||
sz=0x100;
|
||||
MsiRecordGetStringW(row,3,dir,&sz);
|
||||
sz=MAX_PATH;
|
||||
rc = get_property(hPackage, dir, install_path, &sz);
|
||||
rc = MsiGetPropertyW(hPackage, dir, install_path, &sz);
|
||||
|
||||
MsiCloseHandle(row);
|
||||
MsiViewClose(view);
|
||||
|
@ -1402,6 +1177,7 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
|
|||
MSIHANDLE row = 0;
|
||||
static const CHAR *ExecSeqQuery =
|
||||
"select * from File order by Sequence";
|
||||
MSIHANDLE db;
|
||||
|
||||
/* REALLY what we want to do is go through all the enabled
|
||||
* features and check all the components of that feature and
|
||||
|
@ -1410,8 +1186,10 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
|
|||
* but for sheer gratification I am going to just brute force
|
||||
* install all the files
|
||||
*/
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -1497,7 +1275,7 @@ static UINT ACTION_InstallFiles(MSIHANDLE hPackage)
|
|||
}
|
||||
|
||||
/* for future use lets keep track of this file and where it went */
|
||||
set_property(hPackage,sourcename,install_path);
|
||||
MsiSetPropertyW(hPackage,sourcename,install_path);
|
||||
|
||||
MsiCloseHandle(row);
|
||||
}
|
||||
|
@ -1513,14 +1291,17 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
|
|||
MSIHANDLE view;
|
||||
MSIHANDLE row = 0;
|
||||
static const CHAR *ExecSeqQuery = "select * from DuplicateFile";
|
||||
MSIHANDLE db;
|
||||
|
||||
|
||||
/*
|
||||
* Yes we should only do this for componenets that are installed
|
||||
* but again I need to do that went I track components.
|
||||
*/
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -1558,7 +1339,7 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
|
|||
}
|
||||
|
||||
sz = 0x100;
|
||||
rc = get_property(hPackage,file_key,file_source,&sz);
|
||||
rc = MsiGetPropertyW(hPackage,file_key,file_source,&sz);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("Original file unknown %s\n",debugstr_w(file_key));
|
||||
|
@ -1586,7 +1367,7 @@ static UINT ACTION_DuplicateFiles(MSIHANDLE hPackage)
|
|||
sz=0x100;
|
||||
MsiRecordGetStringW(row,5,destkey,&sz);
|
||||
sz = 0x100;
|
||||
rc = get_property(hPackage, destkey, dest_path, &sz);
|
||||
rc = MsiGetPropertyW(hPackage, destkey, dest_path, &sz);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("Unable to get destination folder\n");
|
||||
|
@ -1700,12 +1481,15 @@ static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage)
|
|||
MSIHANDLE view;
|
||||
MSIHANDLE row = 0;
|
||||
static const CHAR *ExecSeqQuery = "select * from Registry";
|
||||
MSIHANDLE db;
|
||||
|
||||
/* Again here we want to key off of the components being installed...
|
||||
* oh well
|
||||
*/
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
@ -1851,7 +1635,7 @@ static DWORD deformat_string(MSIHANDLE hPackage, WCHAR* ptr,WCHAR** data)
|
|||
mark++;
|
||||
TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark));
|
||||
sz = 0x100;
|
||||
if (get_property(hPackage, key, value,&sz) == ERROR_SUCCESS)
|
||||
if (MsiGetPropertyW(hPackage, key, value,&sz) == ERROR_SUCCESS)
|
||||
{
|
||||
LPWSTR newdata;
|
||||
chunk = (strlenW(value)+1) * sizeof(WCHAR);
|
||||
|
@ -1953,7 +1737,7 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
|
|||
szPathBuf, DWORD* pcchPathBuf)
|
||||
{
|
||||
TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
|
||||
return get_property(hInstall,szFolder,szPathBuf,pcchPathBuf);
|
||||
return MsiGetPropertyW(hInstall,szFolder,szPathBuf,pcchPathBuf);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2007,11 +1791,11 @@ UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
|
|||
(strlenW(szFolder)+8)*sizeof(WCHAR));
|
||||
strcpyW(newfolder,szFolder);
|
||||
strcatW(newfolder,cszsrc);
|
||||
rc = get_property(hInstall,newfolder,szPathBuf,pcchPathBuf);
|
||||
rc = MsiGetPropertyW(hInstall,newfolder,szPathBuf,pcchPathBuf);
|
||||
HeapFree(GetProcessHeap(),0,newfolder);
|
||||
}
|
||||
else
|
||||
rc = get_property(hInstall,szFolder,szPathBuf,pcchPathBuf);
|
||||
rc = MsiGetPropertyW(hInstall,szFolder,szPathBuf,pcchPathBuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2028,8 +1812,12 @@ static UINT ACTION_Template(MSIHANDLE hPackage)
|
|||
MSIHANDLE view;
|
||||
MSIHANDLE row = 0;
|
||||
static const CHAR *ExecSeqQuery;
|
||||
MSIHANDLE db;
|
||||
|
||||
db = MsiGetActiveDatabase(hPackage);
|
||||
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
|
||||
MsiCloseHandle(db);
|
||||
|
||||
rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
|
|
@ -449,11 +449,9 @@ symbol_s:
|
|||
$$ = HeapAlloc( GetProcessHeap(), 0, 0x100*sizeof (WCHAR) );
|
||||
|
||||
/* Lookup the identifier */
|
||||
/* This will not really work until we have write access to the table*/
|
||||
/* HACK ALERT HACK ALERT... */
|
||||
|
||||
sz=0x100;
|
||||
if (get_property(cond->hInstall,$1,$$,&sz) != ERROR_SUCCESS)
|
||||
if (MsiGetPropertyW(cond->hInstall,$1,$$,&sz) != ERROR_SUCCESS)
|
||||
{
|
||||
$$[0]=0;
|
||||
}
|
||||
|
|
179
dlls/msi/msi.c
179
dlls/msi/msi.c
|
@ -375,32 +375,6 @@ end:
|
|||
return r;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
|
||||
{
|
||||
FIXME("%s %p\n",debugstr_a(szPackage), phPackage);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
|
||||
{
|
||||
UINT rc;
|
||||
FIXME("%s %p\n",debugstr_w(szPackage), phPackage);
|
||||
rc = MsiOpenDatabaseW(szPackage,MSIDBOPEN_READONLY,phPackage);
|
||||
return rc;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
|
||||
{
|
||||
FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
|
||||
{
|
||||
FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage)
|
||||
{
|
||||
FIXME("%s %s %s 0x%08x\n",debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
|
||||
|
@ -466,7 +440,7 @@ end:
|
|||
|
||||
UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
|
||||
{
|
||||
MSIHANDLE dbhandle;
|
||||
MSIHANDLE packagehandle;
|
||||
UINT rc = ERROR_SUCCESS;
|
||||
|
||||
FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
|
||||
|
@ -475,13 +449,13 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
|
|||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
rc = MsiOpenDatabaseW(szPackagePath,MSIDBOPEN_READONLY,&dbhandle);
|
||||
rc = MsiOpenPackageW(szPackagePath,&packagehandle);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
ACTION_DoTopLevelINSTALL(dbhandle, szPackagePath, szCommandLine);
|
||||
ACTION_DoTopLevelINSTALL(packagehandle, szPackagePath, szCommandLine);
|
||||
|
||||
MsiCloseHandle(dbhandle);
|
||||
MsiCloseHandle(packagehandle);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1224,151 +1198,6 @@ BOOL WINAPI MSI_DllCanUnloadNow(void)
|
|||
return S_FALSE;
|
||||
}
|
||||
|
||||
/* property code */
|
||||
UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
|
||||
{
|
||||
FIXME("STUB until write access is done: (%s %s)\n", szName,
|
||||
szValue);
|
||||
|
||||
if (!hInstall)
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
|
||||
{
|
||||
FIXME("STUB until write access is done: (%s %s)\n",debugstr_w(szName),
|
||||
debugstr_w(szValue));
|
||||
|
||||
if (!hInstall)
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
|
||||
{
|
||||
LPWSTR szwName = NULL, szwValueBuf = NULL;
|
||||
UINT hr = ERROR_INSTALL_FAILURE;
|
||||
|
||||
if (0 == hInstall) {
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (NULL == szName) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
FIXME("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
|
||||
|
||||
if (NULL != szValueBuf && NULL == pchValueBuf) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if( szName )
|
||||
{
|
||||
UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
|
||||
szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
if( !szwName )
|
||||
goto end;
|
||||
MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
|
||||
} else {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if( szValueBuf )
|
||||
{
|
||||
szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
|
||||
if( !szwValueBuf )
|
||||
goto end;
|
||||
}
|
||||
|
||||
hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
|
||||
|
||||
if( ERROR_SUCCESS == hr )
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
|
||||
}
|
||||
|
||||
end:
|
||||
if( szwName )
|
||||
HeapFree( GetProcessHeap(), 0, szwName );
|
||||
if( szwValueBuf )
|
||||
HeapFree( GetProcessHeap(), 0, szwValueBuf );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
|
||||
LPWSTR szValueBuf, DWORD* pchValueBuf)
|
||||
{
|
||||
MSIHANDLE view,row;
|
||||
UINT rc;
|
||||
WCHAR Query[1024]=
|
||||
{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' '
|
||||
,'P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' ','`'
|
||||
,'P','r','o','p','e','r','t','y','`','=','`',0};
|
||||
|
||||
static const WCHAR szEnd[]={'`',0};
|
||||
|
||||
if (0 == hInstall) {
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (NULL == szName) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
strcatW(Query,szName);
|
||||
strcatW(Query,szEnd);
|
||||
|
||||
rc = MsiDatabaseOpenViewW(hInstall, Query, &view);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD sz;
|
||||
WCHAR value[0x100];
|
||||
|
||||
rc = MsiViewExecute(view, 0);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = MsiViewFetch(view,&row);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
sz=0x100;
|
||||
rc = MsiRecordGetStringW(row,2,value,&sz);
|
||||
strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
|
||||
*pchValueBuf = sz+1;
|
||||
MsiCloseHandle(row);
|
||||
}
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
}
|
||||
|
||||
if (rc == ERROR_SUCCESS)
|
||||
TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
|
||||
debugstr_w(szName));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
|
||||
MSIHANDLE hRecord)
|
||||
{
|
||||
FIXME("STUB: \n");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
|
||||
{
|
||||
FIXME("Is this correct?\n");
|
||||
msihandle_addref(hInstall);
|
||||
return hInstall;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
|
||||
DWORD iProductIndex, LPSTR lpProductBuf)
|
||||
{
|
||||
|
|
|
@ -145,6 +145,7 @@ typedef struct tagMSIHANDLEINFO
|
|||
#define MSIHANDLETYPE_SUMMARYINFO 2
|
||||
#define MSIHANDLETYPE_VIEW 3
|
||||
#define MSIHANDLETYPE_RECORD 4
|
||||
#define MSIHANDLETYPE_PACKAGE 5
|
||||
|
||||
#define MSI_MAJORVERSION 1
|
||||
#define MSI_MINORVERSION 10
|
||||
|
|
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* Implementation of the Microsoft Installer (msi.dll)
|
||||
*
|
||||
* Copyright 2004 Aric Stewart 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
|
||||
*/
|
||||
|
||||
#define NONAMELESSUNION
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winreg.h"
|
||||
#include "winnls.h"
|
||||
#include "shlwapi.h"
|
||||
#include "wine/debug.h"
|
||||
#include "msi.h"
|
||||
#include "msiquery.h"
|
||||
#include "msipriv.h"
|
||||
#include "objidl.h"
|
||||
#include "wincrypt.h"
|
||||
#include "winuser.h"
|
||||
#include "shlobj.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "objbase.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
/*
|
||||
* The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
|
||||
* which is a problem because LPCTSTR isn't defined when compiling wine.
|
||||
* To work around this problem, we need to define LPCTSTR as LPCWSTR here,
|
||||
* and make sure to only use it in W functions.
|
||||
*/
|
||||
#define LPCTSTR LPCWSTR
|
||||
|
||||
void MSI_FreePackage( VOID *arg);
|
||||
|
||||
typedef struct tagMSIPACKAGE
|
||||
{
|
||||
MSIHANDLE db;
|
||||
} MSIPACKAGE;
|
||||
|
||||
void MSI_FreePackage( VOID *arg)
|
||||
{
|
||||
MSIPACKAGE *package= arg;
|
||||
|
||||
MsiCloseHandle(package->db);
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
|
||||
{
|
||||
LPWSTR szwPack = NULL;
|
||||
UINT len, ret;
|
||||
|
||||
TRACE("%s %p\n",debugstr_a(szPackage), phPackage);
|
||||
|
||||
if( szPackage )
|
||||
{
|
||||
len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
|
||||
szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
|
||||
if( szwPack )
|
||||
MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len );
|
||||
}
|
||||
|
||||
ret = MsiOpenPackageW( szwPack, phPackage );
|
||||
|
||||
if( szwPack )
|
||||
HeapFree( GetProcessHeap(), 0, szwPack );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const void clone_properties(MSIHANDLE db)
|
||||
{
|
||||
MSIHANDLE view;
|
||||
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 (?)";
|
||||
|
||||
/* create the temporary properties table */
|
||||
MsiDatabaseOpenViewA(db, CreateSql, &view);
|
||||
MsiViewExecute(view,0);
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
|
||||
/* clone the existing properties */
|
||||
MsiDatabaseOpenViewA(db, Query, &view);
|
||||
|
||||
MsiViewExecute(view, 0);
|
||||
while (1)
|
||||
{
|
||||
MSIHANDLE row;
|
||||
MSIHANDLE view2;
|
||||
|
||||
rc = MsiViewFetch(view,&row);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
MsiDatabaseOpenViewA(db,Insert,&view2);
|
||||
MsiViewExecute(view2,row);
|
||||
MsiViewClose(view2);
|
||||
MsiCloseHandle(view2);
|
||||
|
||||
MsiCloseHandle(row);
|
||||
}
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* There are a whole slew of these we need to set
|
||||
*
|
||||
*
|
||||
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
|
||||
*/
|
||||
static VOID set_installer_properties(MSIHANDLE hPackage)
|
||||
{
|
||||
WCHAR pth[MAX_PATH];
|
||||
|
||||
static const WCHAR cszbs[]={'\\',0};
|
||||
static const WCHAR CFF[] =
|
||||
{'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR PFF[] =
|
||||
{'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR CADF[] =
|
||||
{'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR ATF[] =
|
||||
{'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR ADF[] =
|
||||
{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR SF[] =
|
||||
{'S','y','s','t','e','m','F','o','l','d','e','r',0};
|
||||
static const WCHAR LADF[] =
|
||||
{'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
|
||||
static const WCHAR MPF[] =
|
||||
{'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
|
||||
static const WCHAR PF[] =
|
||||
{'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
|
||||
static const WCHAR WF[] =
|
||||
{'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};
|
||||
|
||||
/* Not yet set ... but needed by iTunes
|
||||
*
|
||||
DesktopFolder
|
||||
FavoritesFolder
|
||||
FontsFolder
|
||||
PrimaryVolumePath
|
||||
ProgramFiles64Folder
|
||||
ProgramMenuFolder
|
||||
SendToFolder
|
||||
StartMenuFolder
|
||||
StartupFolder
|
||||
System16Folder
|
||||
System64Folder
|
||||
TemplateFolder
|
||||
*/
|
||||
|
||||
/* asked for by iTunes ... but are they installer set?
|
||||
*
|
||||
* GlobalAssemblyCache
|
||||
*/
|
||||
|
||||
/*
|
||||
* Other things i notice set
|
||||
*
|
||||
ScreenY
|
||||
ScreenX
|
||||
SystemLanguageID
|
||||
ComputerName
|
||||
UserLanguageID
|
||||
LogonUser
|
||||
VirtualMemory
|
||||
PhysicalMemory
|
||||
Intel
|
||||
ShellAdvSupport
|
||||
ServicePackLevel
|
||||
WindowsBuild
|
||||
Version9x
|
||||
Version95
|
||||
VersionNT
|
||||
AdminUser
|
||||
DefaultUIFont
|
||||
VersionMsi
|
||||
VersionDatabase
|
||||
PackagecodeChanging
|
||||
ProductState
|
||||
CaptionHeight
|
||||
BorderTop
|
||||
BorderSide
|
||||
TextHeight
|
||||
ColorBits
|
||||
RedirectedDllSupport
|
||||
Time
|
||||
Date
|
||||
Privilaged
|
||||
DATABASE
|
||||
OriginalDatabase
|
||||
UILevel
|
||||
*/
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, CFF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, PFF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, CADF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, ATF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, ADF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, SF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, LADF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, MPF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, PF, pth);
|
||||
|
||||
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
|
||||
strcatW(pth,cszbs);
|
||||
MsiSetPropertyW(hPackage, WF, pth);
|
||||
|
||||
GetTempPathW(MAX_PATH,pth);
|
||||
MsiSetPropertyW(hPackage, TF, pth);
|
||||
}
|
||||
|
||||
|
||||
UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
|
||||
{
|
||||
UINT rc;
|
||||
MSIHANDLE handle;
|
||||
MSIHANDLE db;
|
||||
MSIPACKAGE *package;
|
||||
|
||||
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};
|
||||
|
||||
TRACE("%s %p\n",debugstr_w(szPackage), phPackage);
|
||||
|
||||
rc = MsiOpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
|
||||
|
||||
if (rc != ERROR_SUCCESS)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
handle = alloc_msihandle(MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
|
||||
MSI_FreePackage, (void**)&package);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
MsiCloseHandle(db);
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
package->db = db;
|
||||
|
||||
/* 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(handle);
|
||||
MsiSetPropertyW(handle, OriginalDatabase, szPackage);
|
||||
MsiSetPropertyW(handle, Database, szPackage);
|
||||
|
||||
*phPackage = handle;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
|
||||
{
|
||||
FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
|
||||
{
|
||||
FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
|
||||
{
|
||||
MSIPACKAGE *package;
|
||||
|
||||
TRACE("(%i)\n",(INT)hInstall);
|
||||
|
||||
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
|
||||
|
||||
if( !package)
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
msihandle_addref(package->db);
|
||||
return package->db;
|
||||
}
|
||||
|
||||
INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
|
||||
MSIHANDLE hRecord)
|
||||
{
|
||||
FIXME("STUB: \n");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/* property code */
|
||||
UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
|
||||
{
|
||||
LPWSTR szwName = NULL, szwValue = NULL;
|
||||
UINT hr = ERROR_INSTALL_FAILURE;
|
||||
UINT len;
|
||||
|
||||
if (0 == hInstall) {
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (NULL == szName) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if (NULL == szValue) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
|
||||
szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
if( !szwName )
|
||||
goto end;
|
||||
MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
|
||||
|
||||
len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
|
||||
szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
if( !szwValue)
|
||||
goto end;
|
||||
MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
|
||||
|
||||
hr = MsiSetPropertyW( hInstall, szwName, szwValue);
|
||||
|
||||
end:
|
||||
if( szwName )
|
||||
HeapFree( GetProcessHeap(), 0, szwName );
|
||||
if( szwValue )
|
||||
HeapFree( GetProcessHeap(), 0, szwValue );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
|
||||
{
|
||||
MSIPACKAGE *package;
|
||||
MSIHANDLE view,row;
|
||||
UINT rc;
|
||||
DWORD sz = 0;
|
||||
static const CHAR Insert[]=
|
||||
"INSERT into `_Property` (`_Property`,`Value`) VALUES (?)";
|
||||
|
||||
TRACE("Setting property (%s %s)\n",debugstr_w(szName),
|
||||
debugstr_w(szValue));
|
||||
|
||||
if (!hInstall)
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
if (MsiGetPropertyW(hInstall,szName,0,&sz)==ERROR_MORE_DATA)
|
||||
{
|
||||
FIXME("Cannot set exising properties! FIXME MIKE!\n");
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
|
||||
if( !package)
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
rc = MsiDatabaseOpenViewA(package->db,Insert,&view);
|
||||
if (rc!= ERROR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
row = MsiCreateRecord(2);
|
||||
MsiRecordSetStringW(row,1,szName);
|
||||
MsiRecordSetStringW(row,2,szValue);
|
||||
|
||||
rc = MsiViewExecute(view,row);
|
||||
|
||||
MsiCloseHandle(row);
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
|
||||
{
|
||||
LPWSTR szwName = NULL, szwValueBuf = NULL;
|
||||
UINT hr = ERROR_INSTALL_FAILURE;
|
||||
|
||||
if (0 == hInstall) {
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (NULL == szName) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
|
||||
|
||||
if (NULL != szValueBuf && NULL == pchValueBuf) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if( szName )
|
||||
{
|
||||
UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
|
||||
szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
if( !szwName )
|
||||
goto end;
|
||||
MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
|
||||
} else {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
if( szValueBuf )
|
||||
{
|
||||
szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
|
||||
if( !szwValueBuf )
|
||||
goto end;
|
||||
}
|
||||
|
||||
hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
|
||||
|
||||
if( *pchValueBuf > 0 )
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
|
||||
}
|
||||
|
||||
end:
|
||||
if( szwName )
|
||||
HeapFree( GetProcessHeap(), 0, szwName );
|
||||
if( szwValueBuf )
|
||||
HeapFree( GetProcessHeap(), 0, szwValueBuf );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
|
||||
LPWSTR szValueBuf, DWORD* pchValueBuf)
|
||||
{
|
||||
MSIHANDLE view,row;
|
||||
UINT rc;
|
||||
WCHAR Query[1024]=
|
||||
{'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
|
||||
,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
|
||||
,'_','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);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD sz;
|
||||
WCHAR value[0x100];
|
||||
|
||||
rc = MsiViewExecute(view, 0);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = MsiViewFetch(view,&row);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
sz=0x100;
|
||||
rc = MsiRecordGetStringW(row,1,value,&sz);
|
||||
strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
|
||||
*pchValueBuf = sz+1;
|
||||
MsiCloseHandle(row);
|
||||
}
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
}
|
||||
|
||||
if (rc == ERROR_SUCCESS)
|
||||
TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
|
||||
debugstr_w(szName));
|
||||
else
|
||||
{
|
||||
*pchValueBuf = 0;
|
||||
TRACE("property not found\n");
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
Loading…
Reference in New Issue