DWORD WINAPI InitThread(LPVOID lparam) { HookSetCursor(); //OffsetMngr.AddOffset("DXRenderer", "48 8B 0D ? ? ? ? 48 85 C9 74 0E E8 ? ? ? ? 48 8B A8 ? ? ? ? EB 19",0x141FDF650); DxRenderer* pDxRenderer = DxRenderer::GetInstance(); while (!IsValidPtr(pDxRenderer)) { DxRenderer* pDxRenderer = DxRenderer::GetInstance(); } Screen* pScreen = pDxRenderer->m_pScreen; while (!IsValidPtr(pScreen)) { Screen* pScreen = pDxRenderer->m_pScreen; } IDXGISwapChain* pSwap = pScreen->m_pSwapChain; while (!IsValidPtr(pSwap)) { pSwap = pScreen->m_pSwapChain; } PresentHook = new CVMTHookManager64((DWORD64**)pSwap); oPresent = (tPresent)PresentHook->dwGetMethodAddress(8); PresentHook->dwHookMethod((DWORD64)hkPresent, 8); Helpers::OffsetManager mngr; mngr.AddOffset("DXRenderer", "48 8B 0D ? ? ? ? 48 8B 01 FF 50 08 85 C0 75 2D 48 8B 05 ? ? ? ? 48 85 C0 75 1A", 3); mngr.AddOffset("GameContext", "48 8B 0D ? ? ? ? E8 ? ? ? ? 48 8B D8 48 89 44 24 ? 4C 8D B6 ? ? ? ? 49 8B 3E 48 8B AE ? ? ? ?", 3); mngr.AddOffset("GameRenderer", "48 8B 0D ? ? ? ? 48 85 C9 74 06 48 8B 01 FF 50 50", 3); mngr.AddOffset("Dedicated Server Settings", "48 8B 05 ? ? ? ? 48 85 C0 75 1A 48 8D 15 ? ? ? ? 48 8B 0D ? ? ? ? E8 ? ? ? ? 48 89 05 ? ? ? ? 48 8B 58 20 48 85 DB 74 06 48 8B 5B 28 EB 28", 3); mngr.AddOffset("DebugRenderer", "48 8B 0D ? ? ? ? 48 85 C9 75 03 33 C0 C3 E9 ? ? ? ?", 0); mngr.AddOffset("DrawText", "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 49 8B F9 41 8B F0 8B EA 48 83 CB FF 48 FF C3", 0); mngr.AddOffset("DrawLine", "48 89 5C 24 ? 44 89 4C 24 ? 57 48 83 EC 20 48 8B DA BA ? ? ? ? 49 8B F8 44 8D 42 FF E8 ? ? ? ? 8B 0B 89 08 8B 4B 04 48 8B 5C 24 ?", 0); mngr.AddOffset("DrawLineRect", "48 89 5C 24 ? 48 89 74 24 ? 44 89 4C 24 ? 57 48 83 EC 50 0F 29 74 24 ? F3 0F 10 32 0F 29 7C 24 ? F3 0F 10 7A ? 48 8B DA 49 8B F8 BA ? ? ? ? 48 8B F1 44 0F 29 44 24 ? F3 45 0F 10 00 44 8D 42 FF E8 ? ? ? ?", 0); mngr.FindSignatures(); mngr.PrintSignatures(); while (1) { if (GetAsyncKeyState(VK_F8) & 0x8000) EjectDLL(); if (GetAsyncKeyState(VK_F7) & 0x8000) { ShowMenu = !ShowMenu; Sleep(200); } Sleep(100); } return 1; }
BOOL CCmdDlg::Cmd_DB() { ULONG_PTR addr; if (GetParamCount() >= 2) { ULONG_PTR addr = xtol(GetParam(1)); if (!IsValidPtr(addr)) { PrintLine(_T("invalid address: %p"), addr ); return TRUE; } } else addr = m_dumpAddr; BYTE buf[1024]; size_t len = 0x10; if (GetParamCount() > 2) { len = atol(GetParam(2)); if (len == 0) len = 1; if (len > sizeof(buf)) len = sizeof(buf); } size_t readlen = g_dbgEng->ReadMemory((PVOID )addr, buf, len); len = readlen; size_t n = 0; while (n < len) { Print("%p\t", addr + n); for (int i = 0; i < 0x10; i ++) { if (n + i < len) Print("%02X ", buf[n + i]); else Print(" "); } Print("|"); for (int i = 0; i < 0x10 && n + i < len; i ++) { BYTE c = buf[n + i]; #define IsVisableChar(C) ( (C) < 0x20 ) Print("%c", IsVisableChar(c) ? '.' : c); } Print(CRLF); n += 0x10; } m_dumpAddr = addr + len; return TRUE; }
/****************************************************************************** ** Read and pass the config file. ** This expects the fields to be in a specific order. */ BOOL ReadConfigFile(PSTR pszCfgFile) { FILE *fCfgFile; /* The config file. */ ASSERT(IsValidPtr(pszCfgFile)); /* Open config file. */ fCfgFile = fopen(pszCfgFile, "r"); if (!fCfgFile) ReportFileError("Cannot open file", pszCfgFile); /* Read the outgoing mail path. */ ReadCfgData(fCfgFile, pszPathTag, szDstDir); /* Read the organisation. ReadCfgData(fCfgFile, pszOrgTag, szOrg); /* Read the domain. ReadCfgData(fCfgFile, pszDomainTag, szDomain);*/ /* Close config file. */ fclose(fCfgFile); return TRUE; }
BOOL CCmdDlg::Cmd_RTTI() { if (GetParamCount() != 2) { PrintLine(_T("invalid command")); return TRUE; } ULONG_PTR addr = xtol(GetParam(1)); if (!IsValidPtr(addr)) { PrintLine(_T("invalid address: %p"), addr ); return TRUE; } ULONG_PTR vtablePtr = 0; g_dbgEng->ReadMemory((PVOID )addr, (PBYTE )&vtablePtr, sizeof(vtablePtr)); ULONG_PTR rttiPtr = vtablePtr - sizeof(ULONG_PTR); ULONG_PTR rtti; g_dbgEng->ReadMemory((PVOID )rttiPtr, (PBYTE )&rtti, sizeof(rtti)); ULONG_PTR typeDescPtrPtr = rtti + offsetof(RTTICompleteObjectLocator, pTypeDescriptor); ULONG_PTR typeDescPtr; g_dbgEng->ReadMemory((PVOID )typeDescPtrPtr, (PBYTE )&typeDescPtr, sizeof(typeDescPtr)); TypeDescriptor typeDesc; memset(&typeDesc, 0 , sizeof(typeDesc)); g_dbgEng->ReadMemory((PVOID )typeDescPtr, (PBYTE )&typeDesc, sizeof(typeDesc)); PrintLine("class name: %s", typeDesc.name); ULONG_PTR vtable[32]; memset(vtable, 0 , sizeof(vtable)); g_dbgEng->ReadMemory((PVOID )vtablePtr, (PBYTE )vtable, sizeof(vtable)); PrintLine("vtable: %p", vtablePtr); for (int i = 0; i < 32; i ++) { if (!IsValidPtr(vtable[i])) break; PrintLine("\t%d\t%p", i, vtable[i]); } return TRUE; }
BOOL CCmdDlg::Cmd_E() { if (GetParamCount() != 2) { PrintLine(_T("invalid command")); return TRUE; } ULONG_PTR addr = xtol(GetParam(1)); if (!IsValidPtr(addr)) { PrintLine(_T("invalid address: %p"), addr ); return TRUE; } CBinModifyDlg dlg; if (dlg.DoModal() != IDOK) return TRUE; DWORD n; WCHAR* wstr; size_t len; bool result = false; USES_CONVERSION; switch(dlg.m_type) { case 0: // BYTE case 1: // WORD case 2: // DWORD if (dlg.m_hex) _stscanf((LPCTSTR )dlg.m_strWhat, "%x", &n); else _stscanf((LPCTSTR )dlg.m_strWhat, "%d", &n); result = ModifyMem(addr, (BYTE* )&n, dlg.m_type == 0 ? 1 : dlg.m_type * 2); break; case 3: // ASCII result = ModifyMem(addr, (BYTE* )(LPCSTR )dlg.m_strWhat, dlg.m_strWhat.GetLength()); break; case 4: // UNICODE wstr = T2W((LPCSTR )dlg.m_strWhat); len = wcslen(wstr) * 2; result = ModifyMem(addr, (BYTE* )wstr, len); break; } if (!result) MessageBox(_T("modification failed."), NULL); return TRUE; }
int PLH::VTableSwap::GetVFuncCount(BYTE** pVtable) { int FuncCount = 0; for (; ; FuncCount++) { if (!IsValidPtr(pVtable[FuncCount])) break; } return FuncCount; }
BOOL CCmdDlg::Cmd_U() { ULONG_PTR addr; if (GetParamCount() >= 2) { addr = xtol(GetParam(1)); if (!IsValidPtr(addr)) { PrintLine(_T("invalid address: %p"), addr ); return TRUE; } } else addr = m_disasmAddr; BYTE buf[1024]; size_t len = 0x10; if (GetParamCount() > 2) { len = atol(GetParam(2)); if (len == 0) len = 1; if (len > sizeof(buf)) len = sizeof(buf); } size_t readlen = g_dbgEng->ReadMemory((PVOID )addr, buf, len); len = readlen; t_disasm da; memset(&da, 0, sizeof(da)); // ulong l = Disasm(code, len, (ulong )addr, &da, DISASM_SIZE); ULONG pos = 0; ulong l; m_disasmAddr = addr; while (pos <= len) { l = Disasm((char* )&buf[pos], len - pos, (ulong )addr + pos, &da, DISASM_CODE); if (l == 0) break; m_disasmAddr += l; PrintLine(" %p | %3i %-24s %-24s\n", addr + pos, l, da.dump, da.result); pos += l; } return TRUE; }
/****************************************************************************** ** Read a field from the file. It automatically closes the file on error, and ** reports it. */ void ReadCfgData(FILE *fCfgFile, PSTR pszField, PSTR pszOutput) { BOOL bFound = FALSE; char szBuffer[MAX_READBUF_LEN]; /* Read strings until found or EOF. */ while(!bFound) { /* Read a line. */ if (!fgets(szBuffer, MAX_READBUF_LEN, fCfgFile)) { char szMsg[128]; /* Read error or EOF. */ fclose(fCfgFile); /* Make error string and report. */ sprintf(szMsg, "Could not find config entry:- %s", pszField); ReportError(szMsg); } /* Check for comment or null line. */ if ( (szBuffer[0] == ';') || (szBuffer[0] == '\r') || (szBuffer[0] == '\n') ) continue; /* Check field name. */ if (_strnicmp(szBuffer, pszField, strlen(pszField)) == 0) { PSTR pszData; int iStrLen; /* Get start of data. */ pszData = strchr(szBuffer, '='); ASSERT(IsValidPtr(pszData)); /* Remove CR-LF if included. */ iStrLen = strlen(szBuffer); if (szBuffer[iStrLen-1] == '\n') szBuffer[iStrLen-1] = '\0'; /* Skip "=" and extract data. */ pszData++; strcpy(pszOutput, pszData); /* break. */ bFound = TRUE; continue; } } }
/******************************************************************************* ** Set the hint. ** If the hint is the same as before it will ignore it. **/ VOID FAR SetHint(LPSTR lpszHint) { AssertEx(IsValidPtr(lpszHint), "SetHint(lpszHint)"); /* Check for change. */ if (lstrcmp(lpszHint, (LPSTR) szDilHint) == 0) return; /* Copy in new string and re-draw. */ lstrcpy((LPSTR) szDilHint, lpszHint); /* Redraw. */ InvalidateRect(hDilWnd, NULL, TRUE); UpdateWindow(hDilWnd); }
BOOL CCmdDlg::Cmd_DD() { ULONG_PTR addr; if (GetParamCount() >= 2) { ULONG_PTR addr = xtol(GetParam(1)); if (!IsValidPtr(addr)) { PrintLine(_T("invalid address: %p"), addr ); return TRUE; } } else addr = m_dumpAddr; BYTE buf[1024]; size_t len = 0x10 / sizeof(DWORD); if (GetParamCount() > 2) { len = atol(GetParam(2)); if (len == 0) len = 1; if (len > sizeof(buf) / sizeof(DWORD)) len = sizeof(buf) / sizeof(DWORD); } size_t readlen = g_dbgEng->ReadMemory((PVOID )addr, buf, len * sizeof(DWORD)); len = readlen / sizeof(DWORD); size_t n = 0; while (n < len) { Print("%p\t", addr + n * sizeof(DWORD)); for (int i = 0; i < 0x10 && n < len; i ++, n ++) { Print("%08X ", *(DWORD* )&buf[n * sizeof(DWORD)]); } Print(CRLF); } m_dumpAddr = addr + len * sizeof(DWORD); return TRUE; }
/******************************************************************************* ** Initialise the progress meter. **/ VOID FAR InitProgress(LPSTR lpszProcess, int iMax) { AssertEx(IsValidPtr(lpszProcess), "InitProgress(lpszProcess)"); AssertEx(iMax, "InitProgress(iMax)"); /* Set DIL mode. */ iDilMode = DIL_PROGRESS; /* Setup values. */ iDilMax = iMax; iDilLast = 0; /* Copy in process string. */ lstrcpy((LPSTR) szDilHint, lpszProcess); /* Redraw. */ InvalidateRect(hDilWnd, NULL, TRUE); UpdateWindow(hDilWnd); }
void DisplayException (void) { #ifdef DEBUG WCHAR wszTemp[1024]; // Temp output save area EXCEPTION_CODES exceptCode; // Exception code UINT uMem, // Loop counter uCnt, // ... SILevel; // The current SI level APLU3264 nearAddress, // Offset from closest address nearIndex, // Index into StartAddresses nearAddress0, // Offset from closest address nearIndex0, // Index into StartAddresses nearAddress1, // Offset from closest address nearIndex1; // Index into StartAddresses LPPERTABDATA lpMemPTD; // Ptr to PerTabData global memory LPWCHAR exceptText; // Ptr to exception text LPUCHAR exceptAddr; // Exception address APLU3264 regEBP, // Stack trace ptr regEIP; // Instruction ptr LPSIS_HEADER lpSISCur; // Ptr to current SIS header LPMEMVIRTSTR lpLstMVS; // Ptr to last MEMVIRTSTR (NULL = none) // Sort the StartAddresses in ascending order by address qsort (StartAddresses, START_ADDRESSES_LENGTH, sizeof (StartAddresses[0]), &CompareStartAddresses); // Get ptr to PerTabData global memory lpMemPTD = TlsGetValue (dwTlsPerTabData); // Assert (IsValidPtr (lpMemPTD, sizeof (lpMemPTD))); // If lpMemPTD isn't valid, just exit if (!IsValidPtr (lpMemPTD, sizeof (lpMemPTD))) return; // Get the saved exception code & address, & text exceptCode = gExceptionCode; exceptAddr = (LPUCHAR) gExceptionRecord.ExceptionAddress; exceptText = glpExceptionText; #ifdef _WIN64 regEBP = gContextRecord.Rbp; #elif defined (_WIN32) regEBP = gContextRecord.Ebp; #else #error Need code for this architecture. #endif lpSISCur = lpMemPTD->lpSISCur; lpLstMVS = lpMemPTD->lpLstMVS; // If the exception is EXCEPTION_BREAKPOINT (from DbgStop), // we need to display the return address as that's from // where we were called. Displaying DbgStop address is // of no help if (exceptCode EQ EXCEPTION_BREAKPOINT) exceptAddr = *(LPUCHAR *) &gExceptAddr; // Find the address closest to and at or below the given address // If the address is not found, it could be that we're // running under a debugger and the debugger has changed the // starting address of the routine to a near JMP instruction, // so try again with that assumption FindRoutineAddress (exceptAddr, &nearAddress0, &nearIndex0, FALSE); FindRoutineAddress (exceptAddr, &nearAddress1, &nearIndex1, TRUE); if (nearAddress0 < nearAddress1) { nearAddress = nearAddress0; nearIndex = nearIndex0; } else { nearAddress = nearAddress1; nearIndex = nearIndex1; } // End IF/ELSE ShowWindow (hWndCC, SW_SHOWNORMAL); UpdateWindow (hWndCC); #define NewMsg(a) SendMessageW (hWndCC_LB, LB_ADDSTRING, 0, (LPARAM) (a)); UpdateWindow (hWndCC_LB) NewMsg (L"COPY THIS TEXT TO AN EMAIL MESSAGE" ); NewMsg (L"----------------------------------------------------" ); NewMsg (L"Use Right-click: Select All, and" ); NewMsg (L" Right-click: Copy" ); NewMsg (L" to copy the entire text to the clipboard." ); NewMsg (L"----------------------------------------------------" ); NewMsg (L"Post the text on the Forum <http://forum.nars2000.org>"); NewMsg (L" in the Bug Reports section along with a detailed" ); NewMsg (L" statement of what you were doing just prior to the" ); NewMsg (L" crash." ); NewMsg (L"Also, if at all possible, it would be great if you" ); NewMsg (L" could send along a copy of the last saved workspace"); NewMsg (L" (the one with an extension of .save.bak.ws.nars)." ); NewMsg (L"----------------- Copy Below Here ------------------" ); // Display the version # of the executable MySprintfW (wszTemp, sizeof (wszTemp), WS_APPNAME L" -- Version %s (%s)" WS_APPEND_DEBUG, wszFileVer, #ifdef _WIN64 L"Win64" #elif defined (_WIN32) L"Win32" #else #error Need code for this architecture. #endif ); NewMsg (wszTemp); // Display the exception code and string MySprintfW (wszTemp, sizeof (wszTemp), L"Exception code = %08X (%s)", exceptCode, MyGetExceptionStr (exceptCode)); NewMsg (L""); NewMsg (wszTemp); MySprintfW (wszTemp, sizeof (wszTemp), L" at %p (%S + %p)", exceptAddr, StartAddresses[nearIndex].StartAddressName, nearAddress); NewMsg (wszTemp); MySprintfW (wszTemp, sizeof (wszTemp), L" from %s", exceptText); NewMsg (wszTemp); // Display the registers NewMsg (L""); NewMsg (L"== REGISTERS =="); MySprintfW (wszTemp, sizeof (wszTemp), #ifdef _WIN64 L"RAX = %p RBX = %p RCX = %p RDX = %p RIP = %p", gContextRecord.Rax, gContextRecord.Rbx, gContextRecord.Rcx, gContextRecord.Rdx, gContextRecord.Rip #elif defined (_WIN32) L"EAX = %p EBX = %p ECX = %p EDX = %p EIP = %p", gContextRecord.Eax, gContextRecord.Ebx, gContextRecord.Ecx, gContextRecord.Edx, gContextRecord.Eip #else #error Need code for this architecture. #endif ); NewMsg (wszTemp); MySprintfW (wszTemp, sizeof (wszTemp), #ifdef _WIN64 L"RSI = %p RDI = %p RBP = %p RSP = %p EFL = %08X", gContextRecord.Rsi, gContextRecord.Rdi, gContextRecord.Rbp, gContextRecord.Rsp, #elif defined (_WIN32) L"ESI = %p EDI = %p EBP = %p ESP = %p EFL = %08X", gContextRecord.Esi, gContextRecord.Edi, gContextRecord.Ebp, gContextRecord.Esp, #else #error Need code for this architecture. #endif gContextRecord.EFlags); NewMsg (wszTemp); MySprintfW (wszTemp, sizeof (wszTemp), #ifdef _WIN64 L"CS = %04X DS = %04X ES = %04X FS = %04X GS = %04X SS = %04X CR2 = %p", #elif defined (_WIN32) L"CS = %04X DS = %04X ES = %04X FS = %04X GS = %04X SS = %04X CR2 = %p", #else #error Need code for this architecture. #endif gContextRecord.SegCs, gContextRecord.SegDs, gContextRecord.SegEs, gContextRecord.SegFs, gContextRecord.SegGs, gContextRecord.SegSs, gExceptionRecord.ExceptionInformation[1]); NewMsg (wszTemp); // Display the instruction stream NewMsg (L""); NewMsg (L"== INSTRUCTIONS =="); // Get the instruction pointer #ifdef _WIN64 regEIP = gContextRecord.Rip; #elif defined (_WIN32) regEIP = gContextRecord.Eip; #else #error Need code for this architecture. #endif // Start instruction display three rows before the actual fault instruction regEIP -= 3 * 16; if (IsGoodReadPtr (*(LPUCHAR *) ®EIP, 48)) { for (uCnt = 0; uCnt < 7; uCnt++, regEIP += 16) { MySprintfW (wszTemp, sizeof (wszTemp), L"%p: ", regEIP); for (uMem = 0; uMem < 16; uMem++) MySprintfW (&wszTemp[lstrlenW (wszTemp)], sizeof (wszTemp) - (lstrlenW (wszTemp) * sizeof (wszTemp[0])), L" %02X", *(LPBYTE) (regEIP + uMem)); NewMsg (wszTemp); } // End FOR } // End IF // Display the backtrace NewMsg (L""); NewMsg (L"== BACKTRACE =="); // Do a stack walk DoStackWalk (&gContextRecord); // Display the virtual memory ranges NewMsg (L""); NewMsg (L"== MEMVIRTSTR =="); #ifdef _WIN64 NewMsg (L" IniAddr IncrSize MaxSize GuardPage"); #elif defined (_WIN32) NewMsg (L" IniAddr IncrSize MaxSize GuardPage"); #else #error Need code for this architecture. #endif // Check for global VirtualAlloc memory that needs to be expanded for (uMem = 0; uMem < uMemVirtCnt; uMem++) { MySprintfW (wszTemp, sizeof (wszTemp), L"%p %08X %08X %p %S", memVirtStr[uMem].IniAddr, memVirtStr[uMem].IncrSize, memVirtStr[uMem].MaxSize, memVirtStr[uMem].IniAddr + memVirtStr[uMem].MaxSize, memVirtStr[uMem].lpText ); NewMsg (wszTemp); } // End FOR // Display the local virtual memory ranges NewMsg (L""); NewMsg (L"== LCLMEMVIRTSTR =="); #ifdef _WIN64 NewMsg (L" IniAddr IncrSize MaxSize GuardPage"); #elif defined (_WIN32) NewMsg (L" IniAddr IncrSize MaxSize GuardPage"); #else #error Need code for this architecture. #endif while (lpLstMVS) { MySprintfW (wszTemp, sizeof (wszTemp), L"%p %08X %08X %p %S", lpLstMVS->IniAddr, lpLstMVS->IncrSize, lpLstMVS->MaxSize, lpLstMVS->IniAddr + lpLstMVS->MaxSize, lpLstMVS->lpText ); NewMsg (wszTemp); // Get the previous ptr in the chain lpLstMVS = lpLstMVS->lpPrvMVS; } // End WHILE // Display the SI stack NewMsg (L""); NewMsg (L"== SI STACK =="); // Loop backwards through the SI levels for (SILevel = 0; lpSISCur; lpSISCur = lpSISCur->lpSISPrv, SILevel++) { LPAPLCHAR lpMemName; // Ptr to function name global memory // Split cases based upon the caller's function type switch (lpSISCur->DfnType) { case DFNTYPE_IMM: #ifdef DEBUG NewMsg (WS_UTF16_IOTA); #endif break; case DFNTYPE_OP1: case DFNTYPE_OP2: case DFNTYPE_FCN: // Lock the memory to get a ptr to it lpMemName = MyGlobalLockWsz (lpSISCur->hGlbFcnName); // Format the Name, Line #, and Suspension marker MySprintfW (wszTemp, sizeof (wszTemp), L"%s[%d] %c", lpMemName, lpSISCur->CurLineNum, L" *"[lpSISCur->bSuspended]); // We no longer need this ptr MyGlobalUnlock (lpSISCur->hGlbFcnName); lpMemName = NULL; // Display the function name & line # NewMsg (wszTemp); break; case DFNTYPE_EXEC: NewMsg (WS_UTF16_UPTACKJOT); break; case DFNTYPE_QUAD: NewMsg (WS_UTF16_QUAD); break; case DFNTYPE_UNK: default: NewMsg (L"***UNKNOWN***"); break; } // End SWITCH } // End FOR // Tell the Crash Control window to display a MessageBox SendMessageW (hWndCC, MYWM_DISPMB, 0, 0); #undef NewMsg exit (exceptCode); #endif } // End DisplayException
static PVOID ParseFonFile( PVOID pvView, ULONG cjView) { PIMAGE_DOS_HEADER pDosHeader = pvView; PIMAGE_OS2_HEADER pOs2Header; PNE_RESTABLE pResTable; PNE_TYPEINFO pTInfo; PFONTINFO16 pFontInfo; PCHAR pStart, pEnd; PBMFD_FILE pfile = NULL; WORD wShift; ULONG i, cjOffset, cjLength; ULONG type_id, count; /* Initial margins for valid pointers */ pStart = pvView; pEnd = pStart + cjView; /* Check for image dos header */ if (GETVAL(pDosHeader->e_magic) != IMAGE_DOS_MAGIC) { return NULL; } /* Get pointer to OS2 header and veryfy it is valid */ pOs2Header = (PVOID)((PCHAR)pDosHeader + GETVAL(pDosHeader->e_lfanew)); pStart += sizeof(IMAGE_DOS_HEADER); if (!IsValidPtr(pOs2Header, sizeof(IMAGE_OS2_HEADER), pStart, pEnd, 4)) { DbgPrint("e_lfanew is invalid: 0x%lx\n", pDosHeader->e_lfanew); return NULL; } /* Get pointer to resource table and verify it is valid */ pResTable = (PVOID)((PCHAR)pOs2Header + GETVAL(pOs2Header->ne_rsrctab)); pStart = (PCHAR)pOs2Header; if (!IsValidPtr(pResTable, sizeof(NE_RESTABLE), pStart, pEnd, 1)) { DbgPrint("pTInfo is invalid: 0x%p\n", pResTable); return NULL; } wShift = GETVAL(pResTable->size_shift); pTInfo = pResTable->typeinfo; type_id = GETVAL(pTInfo->type_id); /* Loop the resource table to find a font resource */ while (type_id) { /* Get number of nameinfo entries */ count = GETVAL(pTInfo->count); /* Look for a font resource */ if (type_id == NE_RSCTYPE_FONT && count > 0) { DbgPrint("Found NE_RSCTYPE_FONT\n"); /* Allocate an info structure for this font and all faces */ cjLength = sizeof(BMFD_FILE) + (count-1) * sizeof(BMFD_FACE); pfile = EngAllocMem(0, cjLength, TAG_FONTINFO); if (!pfile) { DbgPrint("Not enough memory: %ld\n", cjLength); return NULL; } pfile->cNumFaces = count; /* Fill all face info structures */ for (i = 0; i < count; i++) { cjOffset = GETVAL(pTInfo->nameinfo[i].offset) << wShift; cjLength = GETVAL(pTInfo->nameinfo[i].length) << wShift; pFontInfo = (PVOID)((PCHAR)pDosHeader + cjOffset); if (!IsValidPtr(pFontInfo, cjLength, pStart, pEnd, 1)) { DbgPrint("pFontInfo is invalid: 0x%p\n", pFontInfo); EngFreeMem(pfile); return NULL; } /* Validate FONTINFO and fill face info */ if (!FillFaceInfo(&pfile->aface[i], pFontInfo)) { DbgPrint("pFontInfo is invalid: 0x%p\n", pFontInfo); EngFreeMem(pfile); return NULL; } } /* Break out of the loop */ break; } /* Following pointers must be bigger than this */ pStart = (PCHAR)pTInfo; /* Goto next entry in resource table */ pTInfo = (PVOID)&pTInfo->nameinfo[count]; /* Verify that the new pTInfo pointer is valid */ if (!IsValidPtr(pTInfo, sizeof(NE_TYPEINFO), pStart, pEnd, 1)) { DbgPrint("pTInfo is invalid: 0x%p\n", pTInfo); return NULL; } type_id = GETVAL(pTInfo->type_id); } return pfile; }