Hey all,

Punkbuster have changed their screenshot routine a few months back (I think), they are no longer using GetForegroundWindow() so the older methods don't work. To fix this, I hook the api function GetWindowThreadProcessId by modifing the IAT of the PBCL module and redirecting the function to our own. Then, we return null to get a blank. Tested on COD2/COD4, worked fine. Code below:

Code:
#include <windows.h>
#include <stdio.h>

// credits to osGB writers / temp2 for highlighting the func 
DWORD xx IATHook(charxx DllWhichImports, charxx DllImportsFrom, charxx OldFunctionName)
{
    DWORD dwIndex;
    DWORD dwOffset;
    HMODULE hDllWhichImports;
    PIMAGE_DATA_DIRECTORY pDataDirectory;
    PIMAGE_DOS_HEADER pDosHeader;
    PDWORD pdwIAT;
    PDWORD pdwINT;
    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
    PIMAGE_IMPORT_BY_NAME pImportName;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader;
    PIMAGE_NT_HEADERS pPeHeader;
    PSTR strCurrent;
    hDllWhichImports = GetModuleHandleA(DllWhichImports);

    if(!hDllWhichImports) return NULL;
          
    pDosHeader = PIMAGE_DOS_HEADER(hDllWhichImports);
    dwOffset = pDosHeader->e_lfanew;
    pPeHeader = PIMAGE_NT_HEADERS(long(hDllWhichImports) + dwOffset);
    pOptionalHeader = &pPeHeader->OptionalHeader;
    pDataDirectory = pOptionalHeader->DataDirectory;
    dwOffset = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    pImportDescriptor = PIMAGE_IMPORT_DESCRIPTOR(long(hDllWhichImports) + dwOffset);
    for(dwIndex = 0; true; dwIndex++)
    {
        dwOffset = pImportDescriptor[dwIndex].Name;
        if (!dwOffset) return NULL;
        strCurrent = PSTR(long(hDllWhichImports) + dwOffset);
        if(stricmp(strCurrent, DllImportsFrom) == 0) break;
    } 
    dwOffset = pImportDescriptor[dwIndex].FirstThunk;
    pdwIAT = PDWORD(long(hDllWhichImports) + dwOffset);
    dwOffset = pImportDescriptor[dwIndex].OriginalFirstThunk;
    pdwINT = PDWORD(long(hDllWhichImports) + dwOffset);
    for(dwIndex = 0; true; dwIndex++)
    {
        dwOffset = pdwINT[dwIndex];
        if (!dwOffset) return NULL;
        pImportName = PIMAGE_IMPORT_BY_NAME(long(hDllWhichImports) + dwOffset);
        strCurrent = PSTR(pImportName->Name);
        if(stricmp(strCurrent, OldFunctionName) == 0)
        {
            return &pdwIAT[dwIndex];
        }
    }
    return NULL;
}  

/xx Our cloned func, we direct the calls to this and return null for blankies xx/ 
DWORD MyGetWindowThreadProcessId(HWND hWnd,LPDWORD lpdwProcessId)
{
  return NULL; 
}

/xx DLL Main, Hook is performed here... xx/ 
BOOL APIENTRY DllMain(HMODULE hDll, DWORD dwReason, PVOID lpReserved) 
{
    if(dwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hDll);

        DWORD dwBackup;
        DWORD dwOffset;
        DWORD xxdwAddress = IATHook("pbcl.dll", "user32.dll", "GetWindowThreadProcessId");

        if (dwAddress)
        {
            VirtualProtect(dwAddress, sizeof(DWORD), PAGE_READWRITE, &dwBackup);
            xxdwAddress = PtrToUlong((DWORD)&MyGetWindowThreadProcessId);
            VirtualProtect(dwAddress, sizeof(DWORD), dwBackup, &dwOffset);
            dwAddress = NULL;
        }


    }
    return 0x1; 
}