Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can I not OpenProcess(PROCESS_ALL_ACCESS...) in DLL under WinXP?

296 views
Skip to first unread message

ccb...@gmail.com

unread,
Dec 24, 2007, 12:22:04 PM12/24/07
to
I wrote a DLL to help my application. The DLL seeks and opens some
processes (not childs) that I interested.

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?

Joseph M. Newcomer

unread,
Dec 24, 2007, 3:31:42 PM12/24/07
to
The fact that it is done from a DLL is completely irrelevant. There is nothing special
about DLLs as such that would change the behavior of this API, except for DllMain, which
has many limitations on what you can and cannot call. If it doesn't work in the DLL
(other than in DllMain), you have something else wrong. Note that generally
PROCESS_ALL_ACCESS might be overkill; you should not ask for more rights than you need.

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

ccb...@gmail.com

unread,
Dec 24, 2007, 8:53:14 PM12/24/07
to
No, I didn' call OpenProcess in DllMain... I am sure that the same
thing was done in dll and exe.
The following is my code:

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

David Ching

unread,
Dec 24, 2007, 9:24:07 PM12/24/07
to

<ccb...@gmail.com> wrote in message
news:b423c48e-29c3-47ef...@b40g2000prf.googlegroups.com...

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


Joseph M. Newcomer

unread,
Dec 24, 2007, 11:16:57 PM12/24/07
to
If the PROCESS_INFORMATION cannot be NULL, you might be better served by using
PROCESS_INFORMATION &pi, which is more aesthetic.

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

0 new messages