What steps will reproduce the problem?
1. On Windows XP SP3, compile & run BWAPI4. This issue only occurs in BWAPI
version 4 - earlier versions of BWAPI are not affected. Versions of Windows
that have the GetThreadId function are not affected, i.e. Vista and above is
not affected; Windows Server 2003 and above is not affected. Ref.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683233%28v=vs.85%29.as
px
2. When I inject, Chaoslauncher pops up an error message saying something like
"The procedure entry point GetThreadId could not be located in the dynamic link
library KERNEL32.dll" and exits after a couple more error pop-ups (rather than
starting Starcraft).
What is the expected output? What do you see instead?
No error pup-ups, and Starcraft starts.
What version of the product are you using? On what operating system?
BWAPI4 (I checked out from svn a few days ago), i.e. .../svn/branches/bwapi4/,
on Windows XP SP3.
Please provide any additional information below.
I patched my local working copy in Detours.cpp by avoiding calling
GetThreadId(), as follows. Injection and Starcraft was then able to work as
normal.
Before:
HANDLE WINAPI _CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T
dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD
dwCreationFlags, LPDWORD lpThreadId)
{
HANDLE rval = NULL;
if ( _CreateThreadOld )
rval = _CreateThreadOld(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
else
rval = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
if ( rval != NULL )
RegisterThreadName("Starcraft Broodwar", GetThreadId(rval) );
return rval;
}
After:
HANDLE WINAPI _CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T
dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD
dwCreationFlags, LPDWORD lpThreadId)
{
// Use a temporary var to store the thread ID rather than calling GetThreadId() later, because
// GetThreadId() doesn't exist on Windows OS'es before Vista (client OS) / Windows Server 2003 (server OS).
DWORD dwThreadIdTmp = 0;
LPDWORD lpThreadIdTmp = lpThreadId ? lpThreadId : &dwThreadIdTmp;
HANDLE rval = NULL;
if ( _CreateThreadOld )
rval = _CreateThreadOld(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId ? lpThreadId : lpThreadIdTmp);
else
rval = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId ? lpThreadId : lpThreadIdTmp);
if ( rval != NULL )
RegisterThreadName("Starcraft Broodwar", *lpThreadIdTmp);
return rval;
}
As you can see, if the caller doesn't provide a place to store the thread ID
(i.e. the lpThreadId input argument) then I use a local variable as the
location to store the thread ID. The CreateThread()/_CreateThreadOld() call
stores the thread ID, then I simply read it instead of calling GetThreadId().
Original issue reported on code.google.com by chris.c...@gmail.com on 4 Sep 2012 at 8:13
Original issue reported on code.google.com by
chris.c...@gmail.com
on 4 Sep 2012 at 8:13