📄 appsearch.c
字号:
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 + -