⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 appsearch.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
#include <stdarg.h>

#define COBJMACROS

#include "stdio.h"
#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"

WINE_DEFAULT_DEBUG_CHANNEL(msi);

typedef struct tagMSISIGNATURE
{
    LPCWSTR  Name;     /* 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));
    sig->Name = name;
    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 %d, MaxSize is %d;\n", sig->MinSize, sig->MaxSize);
        TRACE("Languages is %s\n", debugstr_w(sig->Languages));

end:
        if (row)
            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;
}

/* Frees any memory allocated in sig */
static void ACTION_FreeSignature(MSISIGNATURE *sig)
{
    msi_free(sig->File);
    msi_free(sig->Languages);
}

static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, LPWSTR *appValue,
 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, appValue %p, sig %p)\n", package, appValue, sig);
    *appValue = NULL;
    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:
        if (row)
            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 void ACTION_ConvertRegValue(DWORD regType, const BYTE *value, DWORD sz,
 LPWSTR *appValue)
{
    static const WCHAR dwordFmt[] = { '#','%','d','\0' };
    static const WCHAR expandSzFmt[] = { '#','%','%','%','s','\0' };
    static const WCHAR binFmt[] = { '#','x','%','x','\0' };
    DWORD i;

    switch (regType)
    {
        case REG_SZ:
            if (*(LPCWSTR)value == '#')
            {
                /* escape leading pound with another */
                *appValue = msi_alloc(sz + sizeof(WCHAR));
                (*appValue)[0] = '#';
                strcpyW(*appValue + 1, (LPCWSTR)value);
            }
            else
            {
                *appValue = msi_alloc(sz);
                strcpyW(*appValue, (LPCWSTR)value);
            }
            break;
        case REG_DWORD:
            /* 7 chars for digits, 1 for NULL, 1 for #, and 1 for sign
             * char if needed
             */
            *appValue = msi_alloc(10 * sizeof(WCHAR));
            sprintfW(*appValue, dwordFmt, *(const DWORD *)value);
            break;
        case REG_EXPAND_SZ:
            /* space for extra #% characters in front */
            *appValue = msi_alloc(sz + 2 * sizeof(WCHAR));
            sprintfW(*appValue, expandSzFmt, (LPCWSTR)value);
            break;
        case REG_BINARY:
            /* 3 == length of "#x<nibble>" */
            *appValue = msi_alloc((sz * 3 + 1) * sizeof(WCHAR));
            for (i = 0; i < sz; i++)
                sprintfW(*appValue + i * 3, binFmt, value[i]);
            break;
        default:
            WARN("unimplemented for values of type %d\n", regType);
            *appValue = NULL;
    }
}

static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig,
 LPCWSTR path, int depth, LPWSTR *appValue);

static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue,
 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};

    TRACE("(package %p, appValue %p, sig %p)\n", package, appValue, sig);
    *appValue = NULL;
    rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name);
    if (rc == ERROR_SUCCESS)
    {
        MSIRECORD *row = 0;
        LPWSTR keyPath = NULL, valueName = NULL;
        int root, type;
        HKEY rootKey, key = NULL;
        DWORD sz = 0, regType;
        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);

        switch (root)
        {
            case msidbRegistryRootClassesRoot:
                rootKey = HKEY_CLASSES_ROOT;
                break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -