Windows2003-3790/windows/appcompat/shims/layer/win2kpropagatelayer_wowtask.cpp
2020-09-30 16:53:55 +02:00

1007 lines
26 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
WoWTask.cpp
Abstract:
Functions that retrieve process-history related information from
16-bit environment. This includes the retrieval of the correct
__PROCESS_HISTORY that was passed in from the parent (32-bit)process
and tracing the process history through WOW
Notes:
History:
10/26/00 VadimB Created
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(Win2kPropagateLayer)
#include "ShimHookMacro.h"
#include "Win2kPropagateLayer.h"
typedef struct tagFINDWOWTASKDATA {
BOOL bFound;
DWORD dwProcessId;
DWORD dwThreadId;
WORD hMod16;
WORD hTask16;
} FINDWOWTASKDATA, *PFINDWOWTASKDATA;
//
// Dynamically Linked apis
//
// from WOW32.dll
//
typedef LPVOID (WINAPI *PFNWOWGetVDMPointer)(DWORD vp,
DWORD dwBytes,
BOOL fProtectedMode);
//
// from vdmdbg.dll - defined in the header file
//
//
typedef INT (WINAPI *PFNVDMEnumTaskWOW)(DWORD dwProcessId,
TASKENUMPROC fp,
LPARAM lparam);
//
// Api importing -- modules
//
WCHAR g_wszWOW32ModName[] = L"wow32.dll";
WCHAR g_wszVdmDbgModName[] = L"VdmDbg.dll";
//
// Api importing - module handles and function pointers
//
HMODULE g_hWow32;
HMODULE g_hVdmDbg;
BOOL g_bInitialized; // set to true when imports are initialized
PFNWOWGetVDMPointer g_pfnWOWGetVDMPointer;
PFNVDMEnumTaskWOW g_pfnVDMEnumTaskWOW;
extern BOOL* g_pSeparateWow;
//
// function in this module to import apis
//
BOOL ImportWowApis(VOID);
//
// Marcro to access 16-bit memory
//
#define SEGPTR(seg,off) ((g_pfnWOWGetVDMPointer)((((ULONG)seg) << 16) | (off), 0, TRUE))
//
// task enum proc, called back from vdmdbg
//
BOOL WINAPI MyTaskEnumProc(
DWORD dwThreadId,
WORD hMod16,
WORD hTask16,
LPARAM lParam
)
{
PFINDWOWTASKDATA pFindData = (PFINDWOWTASKDATA)lParam;
if (dwThreadId == pFindData->dwThreadId) {
pFindData->hMod16 = hMod16;
pFindData->hTask16 = hTask16;
pFindData->bFound = TRUE;
return TRUE;
}
return FALSE;
}
BOOL FindWowTask(
DWORD dwProcessId,
DWORD dwThreadId,
PFINDWOWTASKDATA pFindData
)
{
RtlZeroMemory(pFindData, sizeof(*pFindData));
pFindData->dwProcessId = dwProcessId;
pFindData->dwThreadId = dwThreadId;
g_pfnVDMEnumTaskWOW(dwProcessId, (TASKENUMPROC)MyTaskEnumProc, (LPARAM)pFindData);
return pFindData->bFound;
}
//
// get the pointer to task database block from hTask
//
PTDB
GetTDB(
WORD wTDB
)
{
PTDB pTDB;
pTDB = (PTDB)SEGPTR(wTDB, 0);
if (NULL == pTDB || TDB_SIGNATURE != pTDB->TDB_sig) {
LOGN(
eDbgLevelError,
"[GetTDB] TDB is invalid for task 0x%x",
(DWORD)wTDB);
return NULL;
}
return pTDB;
}
//
// GetModName
// wTDB - TDB entry
// szModName - pointer to the buffer that receives module name
// buffer should be at least 9 characters long
//
// returns FALSE if the entry is invalid
BOOL
GetModName(
WORD wTDB,
PCH szModName
)
{
PTDB pTDB;
PCH pch;
pTDB = GetTDB(wTDB);
if (NULL == pTDB) {
return FALSE;
}
RtlCopyMemory(szModName, pTDB->TDB_ModName, 8 * sizeof(CHAR)); // we have modname now
szModName[8] = '\0';
pch = &szModName[8];
while (--pch >= szModName && *pch == ' ') {
*pch = 0;
}
if( pch < szModName ) {
return FALSE;
}
return TRUE;
}
//
// ShimGetTaskFileName
// IN wTask - 16-bit task handle
// Returns:
// Fully qualified exe that is running in this task's context
//
PSZ
ShimGetTaskFileName(
WORD wTask
)
{
PSZ pszFileName = NULL;
PTDB pTDB;
pTDB = GetTDB(wTask);
if (NULL == pTDB) {
// this is really bad -- the module is invalid, debug output is generated by GetTDB
return pszFileName;
}
if (NULL == pTDB->TDB_pModule) {
LOGN(
eDbgLevelError,
"[ShimGetTaskFileName] module pointer is NULL for 0x%x",
(DWORD)wTask);
return pszFileName;
}
pszFileName = (PSZ)SEGPTR(pTDB->TDB_pModule, (*(WORD *)SEGPTR(pTDB->TDB_pModule, 10)) + 8);
return pszFileName;
}
PSZ
ShimGetTaskEnvptr(
WORD hTask16
)
{
PTDB pTDB = GetTDB(hTask16);
PSZ pszEnv = NULL;
PDOSPDB pPSP;
if (NULL == pTDB) {
LOGN( eDbgLevelError,
"[ShimGetTaskEnvptr] Bad TDB entry 0x%x", hTask16);
return NULL;
}
//
// Prepare environment data - this buffer is used when we're starting a new task from the
// root of the chain (as opposed to spawning from an existing 16-bit task)
//
pPSP = (PDOSPDB)SEGPTR(pTDB->TDB_PDB, 0); // psp
if (pPSP != NULL) {
pszEnv = (PCH)SEGPTR(pPSP->PDB_environ, 0);
}
return pszEnv;
}
// IsWowExec
// IN wTDB - entry into the task database
// Returns:
// TRUE if this particular entry points to WOWEXEC
//
// Note:
// WOWEXEC is a special stub module that always runs on NTVDM
// new tasks are spawned by wowexec (in the most typical case)
// it is therefore the "root" module and it's environment's contents
// should not be counted, since we don't know what was ntvdm's parent process
//
BOOL
IsWOWExec(
WORD wTDB
)
{
PTDB pTDB;
CHAR szModName[9];
pTDB = GetTDB(wTDB);
if (NULL == pTDB) {
LOGN(
eDbgLevelError,
"[IsWOWExec] Bad TDB entry 0x%x",
(DWORD)wTDB);
return FALSE;
}
if (!GetModName(wTDB, szModName)) { // can we get modname ?
LOGN(
eDbgLevelError,
"[IsWOWExec] GetModName failed.");
return FALSE;
}
return (0 == _strcmpi(szModName, "wowexec")); // is the module named WOWEXEC ?
}
//
// ImportWowApis
// Function imports necessary apis from wow32.dll and vdmdbg.dll
//
//
BOOL
ImportWowApis(
VOID
)
{
g_hWow32 = LoadLibraryW(g_wszWOW32ModName);
if (g_hWow32 == NULL) {
LOGN(
eDbgLevelError,
"[ImportWowApis] Failed to load wow32.dll Error 0x%x",
GetLastError());
goto Fail;
}
g_pfnWOWGetVDMPointer = (PFNWOWGetVDMPointer)GetProcAddress(g_hWow32, "WOWGetVDMPointer");
if (g_pfnWOWGetVDMPointer == NULL) {
LOGN(
eDbgLevelError,
"[ImportWowApis] Failed to get address of WOWGetVDMPointer Error 0x%x",
GetLastError());
goto Fail;
}
g_hVdmDbg = LoadLibraryW(g_wszVdmDbgModName);
if (g_hVdmDbg == NULL) {
LOGN(
eDbgLevelError,
"[ImportWowApis] Failed to load vdmdbg.dll Error 0x%x",
GetLastError());
goto Fail;
}
g_pfnVDMEnumTaskWOW = (PFNVDMEnumTaskWOW)GetProcAddress(g_hVdmDbg, "VDMEnumTaskWOW");
if (g_pfnVDMEnumTaskWOW == NULL) {
LOGN(
eDbgLevelError,
"[ImportWowApis] Failed to get address of VDMEnumTaskWOW Error 0x%x",
GetLastError());
goto Fail;
}
g_bInitialized = TRUE;
return TRUE;
Fail:
if (g_hWow32) {
FreeLibrary(g_hWow32);
g_hWow32 = NULL;
}
if (g_hVdmDbg) {
FreeLibrary(g_hVdmDbg);
g_hVdmDbg = NULL;
}
g_pfnWOWGetVDMPointer = NULL;
g_pfnVDMEnumTaskWOW = NULL;
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////////////////////
//
//
// WOWTaskList
//
// We maintain a shadow list of running wow tasks complete with respective process history and
// inherited process history
//
//
typedef struct tagWOWTASKLISTITEM* PWOWTASKLISTITEM;
typedef struct tagWOWTASKLISTITEM {
WORD hTask16; // 16-bit tdb entry
DWORD dwThreadId; // thread id of the task
WOWENVDATA EnvData; // environment data (process history, compat layer, etc)
PWOWTASKLISTITEM pTaskNext;
} WOWTASKLISTITEM;
PWOWTASKLISTITEM g_pWowTaskList;
/*++
FindWowTaskInfo
IN hTask16 16-bit task's handle
IN dwThreadId OPTIONAL 32-bit thread id of the task, might be 0
Returns: pointer to the task information structure
--*/
PWOWTASKLISTITEM
FindWowTaskInfo(
WORD hTask16,
DWORD dwThreadId
)
{
PWOWTASKLISTITEM pTask = g_pWowTaskList;
while (NULL != pTask) {
if (hTask16 == pTask->hTask16) {
if (dwThreadId == 0 || dwThreadId == pTask->dwThreadId) {
break;
}
}
pTask = pTask->pTaskNext;
}
return pTask;
}
/*++
UpdateWowTaskList
IN hTask16 16-bit task's handle
Returns: True if the task was added successfully
Note: wowexec is not among the "legitimate" tasks
--*/
BOOL
UpdateWowTaskList(
WORD hTask16
)
{
PTDB pTDB;
WORD wTaskParent;
PWOWTASKLISTITEM pTaskParent = NULL;
LPSTR lpszFileName;
PSZ pszEnv;
WOWENVDATA EnvData;
PWOWENVDATA pData = NULL;
DWORD dwLength;
PWOWTASKLISTITEM pTaskNew;
PCH pBuffer;
PDOSPDB pPSP;
BOOL bSuccess;
//
// see that we are initialized, import apis
//
if (!g_bInitialized) { // first call, link apis
bSuccess = ImportWowApis();
if (!bSuccess) {
LOGN(
eDbgLevelError,
"[UpdateWowTaskList] Failed to import apis.");
return FALSE;
}
}
//
// If this task is WOWEXEC -- just return, it's not an error condition, but we don't need
// wowexec in our list
//
if (IsWOWExec(hTask16)) { // this is ok, we don't want wowexec
return FALSE;
}
//
// next, see what the parent item is, to do so -- access it through TDB
//
pTDB = GetTDB(hTask16);
if (NULL == pTDB) {
LOGN(
eDbgLevelError,
"[UpdateWowTaskList] Bad TDB entry 0x%x",
hTask16);
return FALSE;
}
//
// Prepare environment data - this buffer is used when we're starting a new task from the
// root of the chain (as opposed to spawning from an existing 16-bit task)
//
RtlZeroMemory(&EnvData, sizeof(EnvData));
pData = &EnvData;
wTaskParent = pTDB->TDB_Parent;
if (IsWOWExec(wTaskParent) || GetTDB(wTaskParent) == NULL) {
//
// Root task, extract process history, compat layer, etc
//
pszEnv = NULL;
pPSP = (PDOSPDB)SEGPTR(pTDB->TDB_PDB, 0); // psp
if (pPSP != NULL) {
pszEnv = (PCH)SEGPTR(pPSP->PDB_environ, 0);
}
//
// we have a pointer to the current environment here, pData is initialized
//
if (pszEnv != NULL) {
pData->pszProcessHistory = ShimFindEnvironmentVar(g_szProcessHistoryVar,
pszEnv,
&pData->pszProcessHistoryVal);
pData->pszCompatLayer = ShimFindEnvironmentVar(g_szCompatLayerVar,
pszEnv,
&pData->pszCompatLayerVal);
pData->pszShimFileLog = ShimFindEnvironmentVar(g_szShimFileLogVar,
pszEnv,
&pData->pszShimFileLogVal);
}
} else {
//
// Not a root task, find parent process
//
pTaskParent = FindWowTaskInfo(wTaskParent, 0); // we can't determine which thread owns the task
if (pTaskParent == NULL) {
//
// something is very wrong
// we can't inherit
//
LOGN(
eDbgLevelError,
"[UpdateWowTaskList] Task 0x%x is not root but parent not listed 0x%x",
(DWORD)hTask16,
(DWORD)wTaskParent);
//
// we still allow building up process history. The initial variables will be empty
//
} else {
//
// inherit everything from the parent and add it's module name (later)
//
pData = &pTaskParent->EnvData;
}
}
//
// Get the filename involved
//
//
lpszFileName = ShimGetTaskFileName(hTask16);
//
// now calculate how much space is required to hold all of the data
//
dwLength = sizeof(WOWTASKLISTITEM) +
(NULL == pData->pszProcessHistory ? 0 : (strlen(pData->pszProcessHistory) + 1) * sizeof(CHAR)) +
(NULL == pData->pszCompatLayer ? 0 : (strlen(pData->pszCompatLayer) + 1) * sizeof(CHAR)) +
(NULL == pData->pszShimFileLog ? 0 : (strlen(pData->pszShimFileLog) + 1) * sizeof(CHAR)) +
(NULL == pData->pszCurrentProcessHistory ? 0 : (strlen(pData->pszCurrentProcessHistory) + 2) * sizeof(CHAR)) +
(NULL == lpszFileName ? 0 : (strlen(lpszFileName) + 1) * sizeof(CHAR));
pTaskNew = (PWOWTASKLISTITEM)ShimMalloc(dwLength);
if (pTaskNew == NULL) {
LOGN(
eDbgLevelError,
"[UpdateWowTaskList] failed to allocate 0x%x bytes",
dwLength);
return FALSE;
}
RtlZeroMemory(pTaskNew, dwLength);
//
// now this entry has to be setup
// process history is first
//
pBuffer = (PCH)(pTaskNew + 1);
// Keep track of how much of the buffer is left.
size_t cchRemaining = dwLength - sizeof(WOWTASKLISTITEM);
pTaskNew->hTask16 = hTask16;
pTaskNew->dwThreadId = GetCurrentThreadId();
if (pData->pszProcessHistory != NULL) {
//
// Copy process history. The processHistoryVal is a pointer into the buffer
// pointed to by pszProcessHistory: __PROCESS_HISTORY=c:\foo;c:\docs~1\install
// then pszProcessHistoryVal will point here ---------^
//
// we are copying the data and moving the pointer using the calculated offset
pTaskNew->EnvData.pszProcessHistory = pBuffer;
StringCchCopyExA(pTaskNew->EnvData.pszProcessHistory, cchRemaining, pData->pszProcessHistory, NULL, &cchRemaining, 0);
pTaskNew->EnvData.pszProcessHistoryVal = pTaskNew->EnvData.pszProcessHistory +
(INT)(pData->pszProcessHistoryVal - pData->pszProcessHistory);
//
// There is enough space in the buffer to accomodate all the strings, so
// move pointer past current string to point at the "empty" space
//
pBuffer += strlen(pData->pszProcessHistory) + 1;
}
if (pData->pszCompatLayer != NULL) {
pTaskNew->EnvData.pszCompatLayer = pBuffer;
StringCchCopyExA(pTaskNew->EnvData.pszCompatLayer, cchRemaining, pData->pszCompatLayer, NULL, &cchRemaining, 0);
pTaskNew->EnvData.pszCompatLayerVal = pTaskNew->EnvData.pszCompatLayer +
(INT)(pData->pszCompatLayerVal - pData->pszCompatLayer);
pBuffer += strlen(pData->pszCompatLayer) + 1;
}
if (pData->pszShimFileLog != NULL) {
pTaskNew->EnvData.pszShimFileLog = pBuffer;
StringCchCopyExA(pTaskNew->EnvData.pszShimFileLog, cchRemaining, pData->pszShimFileLog, NULL, &cchRemaining, 0);
pTaskNew->EnvData.pszShimFileLogVal = pTaskNew->EnvData.pszShimFileLog +
(INT)(pData->pszShimFileLogVal - pData->pszShimFileLog);
pBuffer += strlen(pData->pszShimFileLog) + 1;
}
if (pData->pszCurrentProcessHistory != NULL || lpszFileName != NULL) {
//
// Now process history
//
pTaskNew->EnvData.pszCurrentProcessHistory = pBuffer;
if (pData->pszCurrentProcessHistory != NULL) {
StringCchCopyExA(pTaskNew->EnvData.pszCurrentProcessHistory, cchRemaining, pData->pszCurrentProcessHistory, NULL, &cchRemaining, 0);
if (lpszFileName != NULL ) {
StringCchCatExA(pTaskNew->EnvData.pszCurrentProcessHistory, cchRemaining, ";", NULL, &cchRemaining, 0);
}
}
if (lpszFileName != NULL) {
StringCchCatA(pTaskNew->EnvData.pszCurrentProcessHistory, cchRemaining, lpszFileName);
}
}
LOGN(
eDbgLevelInfo,
"[UpdateWowTaskList] Running : \"%s\"",
lpszFileName);
LOGN(
eDbgLevelInfo,
"[UpdateWowTaskList] ProcessHistory : \"%s\"",
pTaskNew->EnvData.pszCurrentProcessHistory);
LOGN(
eDbgLevelInfo,
"[UpdateWowTaskList] BaseProcessHistory: \"%s\"",
pTaskNew->EnvData.pszProcessHistory);
LOGN(
eDbgLevelInfo,
"[UpdateWowTaskList] CompatLayer : \"%s\"",
pTaskNew->EnvData.pszCompatLayer);
//
// We are done, link the entry into the list
//
pTaskNew->pTaskNext = g_pWowTaskList;
g_pWowTaskList = pTaskNew;
return TRUE;
}
/*++
CleanupWowTaskList
IN hTask16 16-bit task handle that is to be removed from the list of running tasks
Returns : TRUE if the function succeeds
--*/
BOOL
CleanupWowTaskList(
WORD hTask16
)
{
PWOWTASKLISTITEM pTask = g_pWowTaskList;
PWOWTASKLISTITEM pTaskPrev = NULL;
while (pTask != NULL) {
if (pTask->hTask16 == hTask16) {
// this is the item
break;
}
pTaskPrev = pTask;
pTask = pTask->pTaskNext;
}
if (pTask == NULL) {
LOGN(
eDbgLevelError,
"[CleanupWowTaskList] Failed to locate task information for 0x%x",
(DWORD)hTask16);
return FALSE;
}
if (pTaskPrev == NULL) {
g_pWowTaskList = pTask->pTaskNext;
} else {
pTaskPrev->pTaskNext = pTask->pTaskNext;
}
ShimFree(pTask);
return TRUE;
}
/*++
ShimRetrieveVariablesEx
IN pData Structure that receives pointers to all the relevant environment information
for the calling thread. The threads are scheduled non-preemptively by user and
threadid is used to identify the calling 16-bit task
All the real work on information retrieval is done in UpdateWowTaskList
Returns: TRUE if success
--*/
BOOL
ShimRetrieveVariablesEx(
PWOWENVDATA pData
)
{
DWORD dwProcessId = GetCurrentProcessId();
DWORD dwThreadId = GetCurrentThreadId();
PWOWTASKLISTITEM pTask;
FINDWOWTASKDATA FindData;
WORD hTask;
BOOL bSuccess;
RtlZeroMemory(pData, sizeof(*pData));
if (!g_bInitialized) { // first call, link apis
bSuccess = ImportWowApis();
if (!bSuccess) {
LOGN(
eDbgLevelError,
"[ShimRetrieveVariablesEx] Failed to import apis.");
return FALSE;
}
}
if (!FindWowTask(dwProcessId, dwThreadId, &FindData)) {
LOGN(
eDbgLevelError,
"[ShimRetrieveVariablesEx] Task not found ProcessId 0x%x ThreadId 0x%x",
dwProcessId,
dwThreadId);
return FALSE;
}
hTask = FindData.hTask16;
pTask = FindWowTaskInfo(hTask, dwThreadId);
if (pTask == NULL) {
LOGN(
eDbgLevelError,
"[ShimRetrieveVariablesEx] Failed to locate wow task.");
return FALSE;
}
//
// Found this one. Copy the info.
//
RtlMoveMemory(pData, &pTask->EnvData, sizeof(*pData));
return TRUE;
}
/*++
ShimThisProcess
Function invokes Shim Engine for dynamic shimming of the current process
Which happens to be ntvdm, naturally. This ntvdm is a separate ntvdm
(which is insured through various checks in CheckAndShimNTVDM)
--*/
BOOL
ShimThisProcess(
HMODULE hModShimEngine,
HSDB hSDB,
SDBQUERYRESULT* pQueryResult
)
{
typedef BOOL (WINAPI *PFNDynamicShim)(LPCWSTR , HSDB , SDBQUERYRESULT*, LPCSTR, LPDWORD);
PFNDynamicShim pfnDynamicShim = NULL;
WCHAR wszFileName[MAX_PATH];
DWORD dwLength;
DWORD dwDynamicToken = 0;
pfnDynamicShim = (PFNDynamicShim) GetProcAddress(hModShimEngine, "SE_DynamicShim");
if (NULL == pfnDynamicShim) {
LOGN( eDbgLevelError,
"[ShimThisProcess] failed to obtain dynamic shim proc address\n");
return FALSE;
}
dwLength = GetModuleFileNameW(GetModuleHandle(NULL), wszFileName, CHARCOUNT(wszFileName));
if (!dwLength || dwLength == CHARCOUNT(wszFileName)) {
LOGN( eDbgLevelError,
"[ShimThisProcess] failed to obtain module file name\n");
return FALSE;
}
return pfnDynamicShim(wszFileName, hSDB, pQueryResult, NULL, &dwDynamicToken);
}
/*++
CheckAndShimNTVDM
Procedure checks ntvdm application for having to be shimmed. If an application is located in
appcompat database, this ntvdm would have to be running as a separate ntvdm (explorer is shimmed as
well, as a result it will have checked the binary first and set the separate vdm flag in CreateProcess)
Further, this call comes through InitTask (intercepted between ntvdm and user32) -- as a parameter it
takes hTask16 - which we're able to use to retrieve application's environment and other important
information.
--*/
BOOL
CheckAndShimNTVDM(
WORD hTask16
)
{
HMODULE hModShimEngine;
CString csTaskFileName;
PSZ pszEnv = NULL;
PTDB pTDB = NULL;
PVOID pEnvNew = NULL;
BOOL bSuccess = FALSE;
BOOL bMatch;
BOOL bNewEnv = FALSE;
HSDB hSDB;
NTSTATUS Status;
SDBQUERYRESULT QueryResult;
DWORD dwFlags;
hModShimEngine = GetModuleHandle(TEXT("shim.dll"));
if (hModShimEngine == NULL) {
// impossible -- shim.dll is not injected!!!
return FALSE;
}
if (g_pSeparateWow != NULL && *g_pSeparateWow == FALSE) {
//
// not a separate wow
//
LOGN( eDbgLevelError,
"[CheckAndShimNTVDM] running in shared wow, no shimming\n");
return FALSE;
}
if (!g_bInitialized) { // first call, link apis
bSuccess = ImportWowApis();
if (!bSuccess) {
LOGN( eDbgLevelError,
"[CheckAndShimNTVDM] Failed to import apis.\n");
return FALSE;
}
}
if (IsWOWExec(hTask16)) {
LOGN( eDbgLevelError,
"[CheckAndShimNTVDM] not touching wowexec\n");
return FALSE;
}
csTaskFileName = ShimGetTaskFileName(hTask16);
if (csTaskFileName.IsEmpty()) {
LOGN( eDbgLevelError,
"[CheckAndShimNTVDM] failed to get the filename for task 0x%lx\n", hTask16);
return FALSE;
}
//
// init database
//
hSDB = SdbInitDatabase(0, NULL);
if (hSDB == NULL) {
LOGN( eDbgLevelError,
"[CheckAndShimNTVDM] failed to init shim database\n");
return FALSE;
}
//
// process history please --
// if we end up here, we are a separate ntvdm
// running with a process history in the env, was retrieved in init
//
pTDB = GetTDB(hTask16);
if (NULL == pTDB) {
LOGN( eDbgLevelError, "[UpdateWowTaskList] Bad TDB entry 0x%x", hTask16);
return FALSE;
}
//
// Prepare environment data - this buffer is used when we're starting a new task from the
// root of the chain (as opposed to spawning from an existing 16-bit task)
//
pszEnv = ShimGetTaskEnvptr(hTask16);
if (NULL != pszEnv) {
Status = ShimCloneEnvironment(&pEnvNew, (LPVOID)pszEnv, FALSE);
if (!NT_SUCCESS(Status)) {
LOGN( eDbgLevelError,
"[CheckAndShimNTVDM] cannot clone environment 0x%lx\n", Status);
pEnvNew = NULL;
bNewEnv = TRUE;
}
//
// if this call has come the way of VDM - we need to carry over our environment stuff
// which is stored separately in this shim
//
// should the call to ShimCloneEnvironment fail, we will have pEnvNew == NULL
// and bNewEnv = TRUE, as a result, we shall try again to clone the environment
dwFlags = CREATE_UNICODE_ENVIRONMENT;
pEnvNew = ShimCreateWowEnvironment_U(pEnvNew, &dwFlags, bNewEnv);
}
//
// run detection please
//
bMatch = SdbGetMatchingExe(hSDB,
(LPCWSTR)csTaskFileName,
NULL, // we can give out module name as well -- but WHY?
(LPCWSTR)pEnvNew,
0,
&QueryResult);
if (bMatch) {
bSuccess = ShimThisProcess(hModShimEngine, hSDB, &QueryResult);
}
if (pEnvNew != NULL) {
ShimFreeEnvironment(pEnvNew);
}
return bSuccess;
}
IMPLEMENT_SHIM_END