But I found that the OpenProcess(PROCESS_ALL_ACCESS...) doesn't work
in DLL under WinXP. It always returns ACCESS_DENIED. I don't know why
because this situation is not documented. I also tried the DLL under
Vista, it works. Furthermore, the DLL also works in Debug mode under
WinXP.
I also tried to move OpenProcess(PROCESS_ALL_ACCESS...) to my
execution...It works!!! It is very weird......
Does WinXP not allow DLL to run OpenProcess(PROCESS_ALL_ACCESS...)?
Can anyone tell my why?
In all past cases where we see this, failures of APIs are due to one of two causes
(a) they really are called with different parameters in the exe and dll
(b) they are called from DllMain, which has a lot of limitations, read
the documentation
Since you showed no code nor gave any information by which we can deduce whether either of
the above cases applies, it is hard to guess what you did wrong.
joe
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
bool __stdcall _FindApp(wstring sClass, wstring sImage,
PROCESS_INFORMATION *pi)
{
DECLARE_DBG_SCOPE(_FindApp, true)
TCHAR buf[MAXSTR]=NULLSTR;
HWND hWnd=NULL;
hWnd=FindWindow((TCHAR *)sClass.c_str(), NULL);
pi->dwThreadId=GetWindowThreadProcessId(hWnd, &pi->dwProcessId);
pi->hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi->dwProcessId);
ASSERT(pi->hProcess); //in debug mode or under vista, this line
passes. but in xp, pi->hProcess==NULL and
GetLastError()==ACCESS_DENIED
GetModuleBaseName(pi->hProcess, NULL, buf, MAXSTR);
if(!hWnd || wstring(buf)!=sImage)
{
CloseHandle(pi->hProcess);
return false;
}
pi->hThread=OpenThread(THREAD_ALL_ACCESS, FALSE, pi->dwThreadId);
return true;
}
MSDN doc for GetModuleBaseName() says the hProcess needs to have
PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights only, so you
might want to call OpenProcess() with just these flags and not
PROCESS_ALL_ACCESS.
-- David
Now you have done several things here which are suspicious; for example, you have cast
s_Class.c_str as a (TCHAR*), but it should ALREADY be a TCHAR*; if it isn't, then this
would explain potential problems. You did not check the hWnd to see if it was NULL, but
went blindly ahead and used it as if the FindWindow call (which is looking for a class,
which is potentially a very dangerous thing to do because you have no guarantee that the
application you are looking for is the only instance of that class, or even the only
instance of that application) had worked. So there is no real way to tell if the
OpenProcess call failed because the hWnd was NULL, or the GetWindowThreadProcessId call
failed, so it is meaningless to call OpenProcess until you have checked both of those; any
return from OpenProcess is meaningless if you have not ascertained that its parameters are
correct!
Now you did say that pi->hProcess is NULL, but you failed to report the INPUT parameters
to the entire OpenProcess sequence, including pi->dwProcessId and for that matter hWnd.
Only much later do you heck the hWnd, and it appears to be a precondition for closing the
handle, which is nonsensical; the only precondition for closing the handle would be if the
handle was opened, and you have no evidence of that. You are creating a wstring of buf
and asking if it is the same as sImage, but you have not reported what values you found
for either of those, and it is not clear why these tests are here at all; the correct
codewould be.
There is no particular reason to make the linkage __stdcall, so I'm not sure why you are
using it.
bool __stdcall FindApp(wstring sClass, wstring sImage, PROCESS_INFORMATION & pi)
{
hWnd = ::FindWindow(sClass.cstr(), NULL);
if(hWnd == NULL)
return false;
pi.dwThreadId = ::GetWindowThreadProcessId(hWnd, &pi.dwProcessId);
if(pi.dwThreadId == 0)
return FALSE;
pi.hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
if(pi.hProcess == NULL)
return FALSE;
/*
until you have recoded to test EVERY step, you have no reason to assume that OpenProcess
can possibly work!
*/
if(::GetModuleBaseName(pi.hProcess, NULL, buff, MAX_PATH) == 0)
{ /* failed to get name */
::CloseHandle(pi.hProcess);
return false;
} /* failed to get name */
if(wstring(buf) != sImage)
{ /* different image */
::CloseHandle(pi.hProcess);
return false;
} /* different image */
Note that there is only one case to test here, but also note that if there are multiple
instances of a window with the same class name, and this one doesn't work, the other one
MIGHT have worked, so this code is a bit dangerous.
pi.hThread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, pi.dwThreadId);
if(pi.hThread == NULL)
{ /* thread open failed */
::CloseHandle(pi.hProcess);
return false;
} /* thread open failed */
return true;
}
The use of std::string is a bit odd in an MFC app, since it offers no real advantages over
CString and makes using it in MFC more than a little inconvenient.
But I don't see anything here that reports where the REAL error is, only where some
potential cascade of multiple errors finally gets detected.
joe