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

📄 appsearch.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
        rc = ACTION_FileVersionMatches(sig, fullFilePath, matches);
    return rc;
}

/* Recursively searches the directory dir for files that match the signature
 * sig, up to (depth + 1) levels deep.  That is, if depth is 0, it searches dir
 * (and only dir).  If depth is 1, searches dir and its immediate
 * subdirectories.
 * Assumes sig->File is not NULL.
 * Returns ERROR_SUCCESS on success (which may include non-critical errors),
 * something else on failures which should halt the install.
 */
static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
 MSISIGNATURE *sig, LPCWSTR dir, int depth)
{
    static const WCHAR starDotStarW[] = { '*','.','*',0 };
    UINT rc = ERROR_SUCCESS;
    size_t dirLen = lstrlenW(dir), fileLen = lstrlenW(sig->File);
    WCHAR *buf;

    TRACE("Searching directory %s for file %s, depth %d\n", debugstr_w(dir),
     debugstr_w(sig->File), depth);

    if (depth < 0)
        return ERROR_INVALID_PARAMETER;

    *appValue = NULL;
    /* We need the buffer in both paths below, so go ahead and allocate it
     * here.  Add two because we might need to add a backslash if the dir name
     * isn't backslash-terminated.
     */
    buf = msi_alloc( (dirLen + max(fileLen, lstrlenW(starDotStarW)) + 2) * sizeof(WCHAR));
    if (buf)
    {
        /* a depth of 0 implies we should search dir, so go ahead and search */
        HANDLE hFind;
        WIN32_FIND_DATAW findData;

        memcpy(buf, dir, dirLen * sizeof(WCHAR));
        if (buf[dirLen - 1] != '\\')
            buf[dirLen++ - 1] = '\\';
        memcpy(buf + dirLen, sig->File, (fileLen + 1) * sizeof(WCHAR));
        hFind = FindFirstFileW(buf, &findData);
        if (hFind != INVALID_HANDLE_VALUE)
        {
            BOOL matches;

            /* assuming Signature can't contain wildcards for the file name,
             * so don't bother with FindNextFileW here.
             */
            if (!(rc = ACTION_FileMatchesSig(sig, &findData, buf, &matches))
             && matches)
            {
                TRACE("found file, returning %s\n", debugstr_w(buf));
                *appValue = buf;
            }
            FindClose(hFind);
        }
        if (rc == ERROR_SUCCESS && !*appValue && depth > 0)
        {
            HANDLE hFind;
            WIN32_FIND_DATAW findData;

            memcpy(buf, dir, dirLen * sizeof(WCHAR));
            if (buf[dirLen - 1] != '\\')
                buf[dirLen++ - 1] = '\\';
            lstrcpyW(buf + dirLen, starDotStarW);
            hFind = FindFirstFileW(buf, &findData);
            if (hFind != INVALID_HANDLE_VALUE)
            {
                if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                    rc = ACTION_RecurseSearchDirectory(package, appValue, sig,
                     findData.cFileName, depth - 1);
                while (rc == ERROR_SUCCESS && !*appValue &&
                 FindNextFileW(hFind, &findData) != 0)
                {
                    if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                        rc = ACTION_RecurseSearchDirectory(package, appValue,
                         sig, findData.cFileName, depth - 1);
                }
                FindClose(hFind);
            }
        }
        if (!*appValue)
            msi_free(buf);
    }
    else
        rc = ERROR_OUTOFMEMORY;

    return rc;
}

static UINT ACTION_CheckDirectory(MSIPACKAGE *package, LPCWSTR dir,
 LPWSTR *appValue)
{
    UINT rc = ERROR_SUCCESS;

    if (GetFileAttributesW(dir) & FILE_ATTRIBUTE_DIRECTORY)
    {
        TRACE("directory exists, returning %s\n", debugstr_w(dir));
        *appValue = strdupW(dir);
    }
    return rc;
}

static BOOL ACTION_IsFullPath(LPCWSTR path)
{
    WCHAR first = toupperW(path[0]);
    BOOL ret;

    if (first >= 'A' && first <= 'Z' && path[1] == ':')
        ret = TRUE;
    else if (path[0] == '\\' && path[1] == '\\')
        ret = TRUE;
    else
        ret = FALSE;
    return ret;
}

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

    TRACE("%p, %p, %s, %d, %p\n", package, sig, debugstr_w(path), depth,
     appValue);
    if (ACTION_IsFullPath(path))
    {
        if (sig->File)
            rc = ACTION_RecurseSearchDirectory(package, appValue, sig,
             path, depth);
        else
        {
            /* Recursively searching a directory makes no sense when the
             * directory to search is the thing you're trying to find.
             */
            rc = ACTION_CheckDirectory(package, path, appValue);
        }
    }
    else
    {
        WCHAR pathWithDrive[MAX_PATH] = { 'C',':','\\',0 };
        DWORD drives = GetLogicalDrives();
        int i;

        rc = ERROR_SUCCESS;
        *appValue = NULL;
        for (i = 0; rc == ERROR_SUCCESS && !*appValue && i < 26; i++)
            if (drives & (1 << drives))
            {
                pathWithDrive[0] = 'A' + i;
                if (GetDriveTypeW(pathWithDrive) == DRIVE_FIXED)
                {
                    lstrcpynW(pathWithDrive + 3, path,
                              sizeof(pathWithDrive) / sizeof(pathWithDrive[0]) - 3);
                    if (sig->File)
                        rc = ACTION_RecurseSearchDirectory(package, appValue,
                         sig, pathWithDrive, depth);
                    else
                        rc = ACTION_CheckDirectory(package, pathWithDrive,
                         appValue);
                }
            }
    }
    TRACE("returning %d\n", rc);
    return rc;
}

static UINT ACTION_AppSearchSigName(MSIPACKAGE *package, LPCWSTR sigName,
 MSISIGNATURE *sig, LPWSTR *appValue);

static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue,
 MSISIGNATURE *sig)
{
    MSIQUERY *view;
    UINT rc;
    static const WCHAR ExecSeqQuery[] =  {
   's','e','l','e','c','t',' ','*',' ',
   'f','r','o','m',' ',
   'D','r','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, sig %p)\n", package, sig);
    rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name);
    if (rc == ERROR_SUCCESS)
    {
        MSIRECORD *row = 0;
        WCHAR expanded[MAX_PATH];
        LPWSTR parentName = NULL, path = NULL, parent = NULL;
        int depth;

        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;
        }

        /* check whether parent is set */
        parentName = msi_dup_record_field(row,2);
        if (parentName)
        {
            MSISIGNATURE parentSig;

            rc = ACTION_AppSearchSigName(package, parentName, &parentSig,
             &parent);
            ACTION_FreeSignature(&parentSig);
            msi_free(parentName);
        }
        /* now look for path */
        path = msi_dup_record_field(row,3);
        if (MSI_RecordIsNull(row,4))
            depth = 0;
        else
            depth = MSI_RecordGetInteger(row,4);
        ACTION_ExpandAnyPath(package, path, expanded,
         sizeof(expanded) / sizeof(expanded[0]));
        msi_free(path);
        if (parent)
        {
            path = msi_alloc((strlenW(parent) + strlenW(expanded) + 1) * sizeof(WCHAR));
            if (!path)
                goto end;
            strcpyW(path, parent);
            strcatW(path, expanded);
        }
        else
            path = expanded;
        rc = ACTION_SearchDirectory(package, sig, path, depth, appValue);

end:
        if (path != expanded)
            msi_free(path);
        msi_free(parent);
        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 UINT ACTION_AppSearchSigName(MSIPACKAGE *package, LPCWSTR sigName,
 MSISIGNATURE *sig, LPWSTR *appValue)
{
    UINT rc;

    *appValue = NULL;
    rc = ACTION_AppSearchGetSignature(package, sig, sigName);
    if (rc == ERROR_SUCCESS)
    {
        rc = ACTION_AppSearchComponents(package, appValue, sig);
        if (rc == ERROR_SUCCESS && !*appValue)
        {
            rc = ACTION_AppSearchReg(package, appValue, sig);
            if (rc == ERROR_SUCCESS && !*appValue)
            {
                rc = ACTION_AppSearchIni(package, appValue, sig);
                if (rc == ERROR_SUCCESS && !*appValue)
                    rc = ACTION_AppSearchDr(package, appValue, sig);
            }
        }
    }
    return rc;
}

/* http://msdn.microsoft.com/library/en-us/msi/setup/appsearch_table.asp
 * is the best reference for the AppSearch table and how it's used.
 */
UINT ACTION_AppSearch(MSIPACKAGE *package)
{
    MSIQUERY *view;
    UINT rc;
    static const WCHAR ExecSeqQuery[] =  {
   's','e','l','e','c','t',' ','*',' ',
   'f','r','o','m',' ',
   'A','p','p','S','e','a','r','c','h',0};

    rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery);
    if (rc == ERROR_SUCCESS)
    {
        MSIRECORD *row = 0;
        LPWSTR propName, sigName;

        rc = MSI_ViewExecute(view, 0);
        if (rc != ERROR_SUCCESS)
            goto end;

        while (!rc)
        {
            MSISIGNATURE sig;
            LPWSTR value = NULL;

            rc = MSI_ViewFetch(view,&row);
            if (rc != ERROR_SUCCESS)
            {
                rc = ERROR_SUCCESS;
                break;
            }

            /* get property and signature */
            propName = msi_dup_record_field(row,1);
            sigName = msi_dup_record_field(row,2);

            TRACE("Searching for Property %s, Signature_ %s\n",
             debugstr_w(propName), debugstr_w(sigName));

            rc = ACTION_AppSearchSigName(package, sigName, &sig, &value);
            if (value)
            {
                MSI_SetPropertyW(package, propName, value);
                msi_free(value);
            }
            ACTION_FreeSignature(&sig);
            msi_free(propName);
            msi_free(sigName);
            msiobj_release(&row->hdr);
        }

end:
        MSI_ViewClose(view);
        msiobj_release(&view->hdr);
    }
    else
        rc = ERROR_SUCCESS;

    return rc;
}

⌨️ 快捷键说明

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