appsearch.c
来自「一个类似windows」· C语言 代码 · 共 977 行 · 第 1/3 页
C
977 行
/*
* Implementation of the AppSearch action of the Microsoft Installer (msi.dll)
*
* Copyright 2005 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "msi.h"
#include "msiquery.h"
#include "msidefs.h"
#include "winver.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "msipriv.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
typedef struct tagMSISIGNATURE
{
LPWSTR Name; /* NOT owned by this structure */
LPWSTR Property; /* NOT owned by this structure */
LPWSTR File;
DWORD MinVersionMS;
DWORD MinVersionLS;
DWORD MaxVersionMS;
DWORD MaxVersionLS;
DWORD MinSize;
DWORD MaxSize;
FILETIME MinTime;
FILETIME MaxTime;
LPWSTR Languages;
}MSISIGNATURE;
static void ACTION_VerStrToInteger(LPCWSTR verStr, PDWORD ms, PDWORD ls)
{
const WCHAR *ptr;
int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
x1 = atoiW(verStr);
ptr = strchrW(verStr, '.');
if (ptr)
{
x2 = atoiW(ptr + 1);
ptr = strchrW(ptr + 1, '.');
}
if (ptr)
{
x3 = atoiW(ptr + 1);
ptr = strchrW(ptr + 1, '.');
}
if (ptr)
x4 = atoiW(ptr + 1);
/* FIXME: byte-order dependent? */
*ms = x1 << 16 | x2;
*ls = x3 << 16 | x4;
}
/* Fills in sig with the the values from the Signature table, where name is the
* signature to find. Upon return, sig->File will be NULL if the record is not
* found, and not NULL if it is found.
* Warning: clears all fields in sig!
* Returns ERROR_SUCCESS upon success (where not finding the record counts as
* success), something else on error.
*/
static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
LPCWSTR name)
{
MSIQUERY *view;
UINT rc;
static const WCHAR ExecSeqQuery[] = {
's','e','l','e','c','t',' ','*',' ',
'f','r','o','m',' ',
'S','i','g','n','a','t','u','r','e',' ',
'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e',' ','=',' ',
'\'','%','s','\'',0};
TRACE("(package %p, sig %p)\n", package, sig);
memset(sig, 0, sizeof(*sig));
rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, name);
if (rc == ERROR_SUCCESS)
{
MSIRECORD *row = 0;
DWORD time;
WCHAR *minVersion, *maxVersion;
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
TRACE("MSI_ViewExecute returned %d\n", rc);
goto end;
}
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
TRACE("MSI_ViewFetch returned %d\n", rc);
rc = ERROR_SUCCESS;
goto end;
}
/* get properties */
sig->File = msi_dup_record_field(row,2);
minVersion = msi_dup_record_field(row,3);
if (minVersion)
{
ACTION_VerStrToInteger(minVersion, &sig->MinVersionMS,
&sig->MinVersionLS);
msi_free( minVersion);
}
maxVersion = msi_dup_record_field(row,4);
if (maxVersion)
{
ACTION_VerStrToInteger(maxVersion, &sig->MaxVersionMS,
&sig->MaxVersionLS);
msi_free( maxVersion);
}
sig->MinSize = MSI_RecordGetInteger(row,5);
if (sig->MinSize == MSI_NULL_INTEGER)
sig->MinSize = 0;
sig->MaxSize = MSI_RecordGetInteger(row,6);
if (sig->MaxSize == MSI_NULL_INTEGER)
sig->MaxSize = 0;
sig->Languages = msi_dup_record_field(row,9);
time = MSI_RecordGetInteger(row,7);
if (time != MSI_NULL_INTEGER)
DosDateTimeToFileTime(HIWORD(time), LOWORD(time), &sig->MinTime);
time = MSI_RecordGetInteger(row,8);
if (time != MSI_NULL_INTEGER)
DosDateTimeToFileTime(HIWORD(time), LOWORD(time), &sig->MaxTime);
TRACE("Found file name %s for Signature_ %s;\n",
debugstr_w(sig->File), debugstr_w(name));
TRACE("MinVersion is %d.%d.%d.%d\n", HIWORD(sig->MinVersionMS),
LOWORD(sig->MinVersionMS), HIWORD(sig->MinVersionLS),
LOWORD(sig->MinVersionLS));
TRACE("MaxVersion is %d.%d.%d.%d\n", HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS), HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS));
TRACE("MinSize is %ld, MaxSize is %ld;\n", sig->MinSize, sig->MaxSize);
TRACE("Languages is %s\n", debugstr_w(sig->Languages));
end:
msiobj_release(&row->hdr);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
else
{
TRACE("MSI_OpenQuery returned %d\n", rc);
rc = ERROR_SUCCESS;
}
TRACE("returning %d\n", rc);
return rc;
}
static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, BOOL *appFound,
MSISIGNATURE *sig)
{
MSIQUERY *view;
UINT rc;
static const WCHAR ExecSeqQuery[] = {
's','e','l','e','c','t',' ','*',' ',
'f','r','o','m',' ',
'C','o','m','p','L','o','c','a','t','o','r',' ',
'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e','_',' ','=',' ',
'\'','%','s','\'',0};
TRACE("(package %p, appFound %p, sig %p)\n", package, appFound, sig);
*appFound = FALSE;
rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name);
if (rc == ERROR_SUCCESS)
{
MSIRECORD *row = 0;
WCHAR guid[50];
DWORD sz;
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
TRACE("MSI_ViewExecute returned %d\n", rc);
goto end;
}
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
TRACE("MSI_ViewFetch returned %d\n", rc);
rc = ERROR_SUCCESS;
goto end;
}
/* get GUID */
guid[0] = 0;
sz=sizeof(guid)/sizeof(guid[0]);
rc = MSI_RecordGetStringW(row,2,guid,&sz);
if (rc != ERROR_SUCCESS)
{
ERR("Error is %x\n",rc);
goto end;
}
FIXME("AppSearch unimplemented for CompLocator table (GUID %s)\n",
debugstr_w(guid));
end:
msiobj_release(&row->hdr);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
else
{
TRACE("MSI_OpenQuery returned %d\n", rc);
rc = ERROR_SUCCESS;
}
TRACE("returning %d\n", rc);
return rc;
}
static UINT ACTION_AppSearchReg(MSIPACKAGE *package, BOOL *appFound,
MSISIGNATURE *sig)
{
MSIQUERY *view;
UINT rc;
static const WCHAR ExecSeqQuery[] = {
's','e','l','e','c','t',' ','*',' ',
'f','r','o','m',' ',
'R','e','g','L','o','c','a','t','o','r',' ',
'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e','_',' ','=',' ',
'\'','%','s','\'',0};
static const WCHAR dwordFmt[] = { '#','%','d','\0' };
static const WCHAR expandSzFmt[] = { '#','%','%','%','s','\0' };
static const WCHAR binFmt[] = { '#','x','%','x','\0' };
TRACE("(package %p, appFound %p, sig %p)\n", package, appFound, sig);
*appFound = FALSE;
rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name);
if (rc == ERROR_SUCCESS)
{
MSIRECORD *row = 0;
LPWSTR keyPath = NULL, valueName = NULL, propertyValue = NULL;
int root, type;
HKEY rootKey, key = NULL;
DWORD sz = 0, regType, i;
LPBYTE value = NULL;
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
TRACE("MSI_ViewExecute returned %d\n", rc);
goto end;
}
rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
TRACE("MSI_ViewFetch returned %d\n", rc);
rc = ERROR_SUCCESS;
goto end;
}
root = MSI_RecordGetInteger(row,2);
keyPath = msi_dup_record_field(row,3);
/* FIXME: keyPath needs to be expanded for properties */
valueName = msi_dup_record_field(row,4);
/* FIXME: valueName probably does too */
type = MSI_RecordGetInteger(row,5);
if ((type & 0x0f) != msidbLocatorTypeRawValue)
{
FIXME("AppSearch unimplemented for type %d (key path %s, value %s)\n",
type, debugstr_w(keyPath), debugstr_w(valueName));
goto end;
}
switch (root)
{
case msidbRegistryRootClassesRoot:
rootKey = HKEY_CLASSES_ROOT;
break;
case msidbRegistryRootCurrentUser:
rootKey = HKEY_CURRENT_USER;
break;
case msidbRegistryRootLocalMachine:
rootKey = HKEY_LOCAL_MACHINE;
break;
case msidbRegistryRootUsers:
rootKey = HKEY_USERS;
break;
default:
WARN("Unknown root key %d\n", root);
goto end;
}
rc = RegCreateKeyW(rootKey, keyPath, &key);
if (rc)
{
TRACE("RegCreateKeyW returned %d\n", rc);
rc = ERROR_SUCCESS;
goto end;
}
rc = RegQueryValueExW(key, valueName, NULL, NULL, NULL, &sz);
if (rc)
{
TRACE("RegQueryValueExW returned %d\n", rc);
rc = ERROR_SUCCESS;
goto end;
}
/* FIXME: sanity-check sz before allocating (is there an upper-limit
* on the value of a property?)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?