zloop1982 / bwapi

Automatically exported from code.google.com/p/bwapi
0 stars 0 forks source link

BWAPI version 4 only: Can't inject on versions of Windows before Vista / before Windows Server 2003 #460

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
Done, using an alternative implementation but to the same effect in r4173.

Original comment by AHeinerm on 4 Sep 2012 at 10:06