/* (C) 2003-2007 Willem Jan Hengeveld * Web: http://www.xs4all.nl/~itsme/ * http://wiki.xda-developers.com/ * * $Id: itsutils.cpp 1933 2008-08-05 10:02:47Z itsme $ */ #include #include #include "MemoryUsage.h" // !!! I am mixing up handles and processid's quite often. // on WinCE this is not a problem, but this needs to be // fixed before porting to another platform. // todo: // * merge docread and sdread and p300read // * add options to specify // - ioctl read blocksize ( how large blocks are read at once. ) // - sectorsize ( for converting offset -> sector nr ) // - ITReadDisk blocksize ( how large blocks are transfered over rapi at once ) // - file blocksize ( how large blocks are read/written at once ) // * getmodulelist: always returns empty - fix this // #include "ItsUtils.h" #include "dllversion.h" #include "cever_deps.h" #include "kernelmisc.h" #include "WINDEV.H" #include "diskio.h" #include "cenk.h" #include "GsmDevice.h" #include "debug.h" #include "stringutils.h" #include "ptrutils.h" #if 0 #define NKvDbgPrintf (*(void (*)(const wchar_t*msg, const void *lpParms))0xF000FFA4) inline void klogmsg(const wchar_t *msg, ...) { va_list ap; va_start(ap, msg); NKvDbgPrintf(msg, ap); va_end(ap); } #else #define klogmsg while(0) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #define AT_NONEXISTANT 1 #define AT_ISDIRECTORY 2 #define AT_ISFILE 3 int getWin32Attributes(const TCHAR *szName) { WIN32_FIND_DATA wfd; HANDLE hFind = FindFirstFile( szName, &wfd); if (INVALID_HANDLE_VALUE == hFind) return AT_NONEXISTANT; FindClose( hFind); if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return AT_ISDIRECTORY; return AT_ISFILE; } #ifdef LOCKED_DLL_CFG void *g_cfg; HANDLE g_instance; HMODULE g_hlib; #endif void *get_persistent_data(const WCHAR *name, DWORD size, bool bCreate) { #ifndef LOCKED_DLL_CFG void *ptr=NULL; HWND hWnd= FindWindow(L"static", name); if (hWnd==NULL) { klogmsg(L"cfg window static/'%ls' not found\n", name); if (!bCreate) { klogmsg(L"get_persistent_data: not creating\n"); return NULL; } hWnd= CreateWindow(L"static", name, WS_DISABLED, -1, -1, 0, 0, 0, 0, 0, 0); ptr= LocalAlloc(LPTR, size); SetWindowLong(hWnd, GWL_USERDATA, (LONG)ptr); klogmsg(L"get_persistent_data: created wnd=%08lx ptr=%08lx\n", hWnd, ptr); } else { ptr= (void*)GetWindowLong(hWnd, GWL_USERDATA); klogmsg(L"get_persistent_data: existing wnd=%08lx ptr=%08lx\n", hWnd, ptr); } return ptr; #else if (g_cfg==NULL) { TCHAR modname[MAX_PATH]; GetModuleFileName((HMODULE)g_instance, modname, MAX_PATH); g_hlib= LoadLibrary(modname); g_cfg= LocalAlloc(LPTR, size); } return g_cfg; #endif } void load_config() { klogmsg(L"load_config\n"); GetVersionParams *cfg= (GetVersionParams *)get_persistent_data(L"itsutils_config_ptr", MAX_PATH+sizeof(DWORD), false); if (cfg==NULL) { klogmsg(L"no config found: logging disabled\n"); } else switch(cfg->logtype) { case LOG_NONE : klogmsg(L"logtype=LOG_NONE\n"); DebugSetLogfile(NULL); #ifdef _DEBUG_SOCKET DebugSetSocket(NULL); #endif DebugRegisterWindow(NULL); DebugNoMessagebox(); DebugNoOutputDebugString(); DebugNoStdOut(); break; case LOG_DEBUGSTRING: klogmsg(L"logtype=LOG_DEBUGSTRING\n"); DebugOutputDebugString(); break; case LOG_FILE : klogmsg(L"logtype=LOG_FILE '%hs'\n", cfg->szLogfile); DebugSetLogfile(cfg->szLogfile); break; #ifdef _DEBUG_SOCKET case LOG_NETWORK : klogmsg(L"logtype=LOG_NETWORK '%hs'\n", cfg->szLogfile); DebugSetSocket(cfg->szLogfile); break; #endif default: klogmsg(L"logtype=unknown %d\n", cfg->logtype); DebugSetLogfile("itsutils.log"); } //DebugOutputDebugString(); } void save_config(GetVersionParams*cfg) { klogmsg(L"save_config %d\n", cfg->logtype); GetVersionParams *memcfg= (GetVersionParams *)get_persistent_data(L"itsutils_config_ptr", MAX_PATH+sizeof(DWORD), true); memcpy(memcfg, cfg, MAX_PATH+sizeof(DWORD)); } BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { //DebugOutputDebugString(); //test300(); //test420(); //test500(); #ifdef LOCKED_DLL_CFG g_instance= hModule; #endif switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: load_config(); //debug("DLL_PROCESS_ATTACH\n"); break; #ifdef LOCKED_DLL_CFG case DLL_THREAD_ATTACH: load_config(); //debug("DLL_THREAD_ATTACH\n"); break; #endif //case DLL_THREAD_DETACH: debug("DLL_THREAD_DETACH\n"); break; //case DLL_PROCESS_DETACH: debug("DLL_PROCESS_DETACH\n"); break; } //debug("DllMain: pid=%08lx:tid=%08lx mod=%08lx\n", GetCurrentProcessId(), GetCurrentThreadId(), hModule); return TRUE; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetVersion( DWORD cbInput, GetVersionParams*pbInput, DWORD *pcbOutput, void **ppbOutput, IRAPIStream *pStream) { *pcbOutput=0; *ppbOutput=NULL; klogmsg(L"ITGetVersion\n"); if (cbInput>=sizeof(DWORD) && pbInput) { klogmsg(L"changing logtype to %d\n", pbInput->logtype); save_config(pbInput); load_config(); } else { klogmsg(L"not changing logtype: pb=%08lx cb=%08lx\n", pbInput, cbInput); #ifdef LOCKED_DLL_CFG klogmsg(L"cfg= %08lx\n", g_cfg); #endif } debugt("its version=%d\n", ITSDLL_VERSION); return ITSDLL_VERSION; } HANDLE GetProcessHandle(WCHAR *wszProcessName); // returns 0 when process not found, 1 when process not killed, 2 when process killed. ITSUTILS_API HRESULT STDAPICALLTYPE ITTerminateProcess( DWORD cbInput, TerminateProcessParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *ppbOutput=NULL; *pcbOutput=0; KernelMode _km; HANDLE hProc; if (pbInput->dwProcessHandle) hProc= OpenProcess(0, 0, pbInput->dwProcessHandle); else hProc= GetProcessHandle(pbInput->wszProcessName); if (hProc==NULL || hProc==INVALID_HANDLE_VALUE) { return ERROR_NOT_FOUND; } DWORD res= 0; if (!TerminateProcess(hProc, 0)) res= GetLastError(); else if (pbInput->bWait) WaitForSingleObject(hProc, INFINITE); CloseHandle(hProc); return res; } // returns 0 when process not found, 1 when process not killed, 2 when process killed. ITSUTILS_API HRESULT STDAPICALLTYPE ITTerminateThread( DWORD cbInput, TerminateThreadParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *ppbOutput=NULL; *pcbOutput=0; HANDLE hThread= (HANDLE)pbInput->dwThreadHandle; if (hThread==NULL || hThread==INVALID_HANDLE_VALUE) { return ERROR_NOT_FOUND; } DWORD res= 0; if (!TerminateThread(hThread, 0)) res= GetLastError(); CloseHandle(hThread); return res; } // returns 0 when process not found, 1 when process not killed, 2 when process killed. ITSUTILS_API HRESULT STDAPICALLTYPE ITWaitForProcess( DWORD cbInput, WaitForProcessParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *ppbOutput=NULL; *pcbOutput=0; KernelMode _km; HANDLE hProc = OpenProcess(0, 0, pbInput->dwProcessHandle); if (hProc==NULL || hProc==INVALID_HANDLE_VALUE) { return ERROR_NOT_FOUND; } DWORD res= 0; if (WAIT_OBJECT_0!=WaitForSingleObject(hProc, INFINITE)) res= GetLastError(); CloseHandle(hProc); return res; } #define MEM_PAGE_SIZE 4096 bool ReadMemory(DWORD dwStart, BYTE *buf, DWORD dwLength, DWORD *pdwCopied, DWORD nDataAccess) { DWORD nCopied= 0; DWORD addr= dwStart; bool bIgnoreErrors= (nDataAccess&8)!=0; //debug("readmem(a=%08lx, o=%08lx l=%08lx)\n", nDataAccess, dwStart, dwLength); if ((nDataAccess&7)==0) { while (nCopied < dwLength) { DWORD nChunkSize= min(MEM_PAGE_SIZE-(addr&(MEM_PAGE_SIZE-1)), dwLength-nCopied); //debug("chunk(%08lx, %08lx) = %08lx\n", addr, nChunkSize, dwLength-nCopied); if (IsBadReadPtr((void*)addr, nChunkSize)) { if (bIgnoreErrors) memset(&buf[nCopied], 0, nChunkSize); else return false; } else memcpy(&buf[nCopied], (void*)addr, nChunkSize); nCopied += nChunkSize; addr += nChunkSize; } //debug("readmem(%08lx,%08lx) done: nc=%08lx ad=%08lx\n", dwStart, dwLength, nCopied, addr); } else if (IsBadReadPtr((void*)addr, dwLength)) { // no direct access. debug("readmem: no direct access\n"); } else if ((nDataAccess&7)==1) { while (nCopied < dwLength) { *(BYTE*)(buf+nCopied)= *(BYTE*)addr; nCopied++; addr++; } } else if (addr&1) { // non-word aligned address not allowed debug("readmem: non-dword aligned address not allowed\n"); } else if ((nDataAccess&7)==2) { while (nCopied+1 < dwLength) { *(WORD*)(buf+nCopied)= *(WORD*)addr; nCopied+=2; addr+=2; } } else if (addr&3) { // non-dword aligned address not allowed debug("readmem: non-dword aligned address not allowed\n"); } else if ((nDataAccess&7)==4) { while (nCopied+3 < dwLength) { *(DWORD*)(buf+nCopied)= *(DWORD*)addr; nCopied+=4; addr+=4; } } *pdwCopied= nCopied; return true; } bool SafeReadProcMem(HANDLE hProc, DWORD dwStart, BYTE *buf, DWORD dwLength, DWORD *pdwCopied, bool bIgnoreErrors) { DWORD nCopied= 0; DWORD addr= dwStart; while (nCopied < dwLength) { DWORD nChunkSize= min(MEM_PAGE_SIZE-(addr&(MEM_PAGE_SIZE-1)), dwLength-nCopied); DWORD nRead; if (!ReadProcessMemory(hProc, (void*)addr, &buf[nCopied], nChunkSize, &nRead)) { if (bIgnoreErrors) memset(&buf[nCopied], 0, nChunkSize); else return false; } nCopied += nChunkSize; addr += nChunkSize; } *pdwCopied= nCopied; return true; } bool WriteMemory(DWORD dwStart, const BYTE *buf, DWORD dwLength, DWORD *pdwCopied, DWORD nDataAccess) { DWORD nCopied= 0; DWORD addr= dwStart; bool bIgnoreErrors= (nDataAccess&8)!=0; if ((nDataAccess&7)==0) { while (nCopied < dwLength) { DWORD nChunkSize= min(MEM_PAGE_SIZE-(addr&(MEM_PAGE_SIZE-1)), dwLength-nCopied); if (IsBadWritePtr((void*)addr, nChunkSize)) { if (!bIgnoreErrors) return false; } else { memcpy((void*)addr, &buf[nCopied], nChunkSize); } nCopied += nChunkSize; addr += nChunkSize; } } else if (IsBadWritePtr((void*)addr, dwLength)) { // no direct access. } else if ((nDataAccess&7)==1) { while (nCopied < dwLength) { *(BYTE*)addr= *(BYTE*)(buf+nCopied); nCopied++; addr++; } } else if (addr&1) { // non-word aligned address not allowed } else if ((nDataAccess&7)==2) { while (nCopied+1 < dwLength) { *(WORD*)addr= *(WORD*)(buf+nCopied); nCopied+=2; addr+=2; } } else if (addr&3) { // non-dword aligned address not allowed } else if ((nDataAccess&7)==4) { while (nCopied+3 < dwLength) { *(DWORD*)addr= *(DWORD*)(buf+nCopied); nCopied+=4; addr+=4; } } *pdwCopied= nCopied; return true; } bool ReadPhysicalMemory(DWORD dwStart, BYTE *buf, DWORD dwLength, DWORD *pdwCopied, int nDataAccess) { DWORD nCopied= 0; DWORD dwRoundedStart= dwStart&KInfoTable[KINX_PFN_MASK]; DWORD dwStartOffset= dwStart-dwRoundedStart; DWORD dwRoundedLength= dwLength+dwStartOffset; BYTE *pVirt= (BYTE*)VirtualAlloc(NULL, dwRoundedLength, MEM_RESERVE, PAGE_NOACCESS); if (pVirt==NULL) { *pdwCopied= nCopied; error("VirtualAlloc(l=%08lx)\n", dwRoundedLength); return false; } if (!VirtualCopy(pVirt, (void*)(dwRoundedStart>>8), dwRoundedLength, PAGE_PHYSICAL|PAGE_READONLY|PAGE_NOCACHE)) { error("VirtualCopy(s=%08lx l=%08lx)\n", dwRoundedStart, dwRoundedLength); VirtualFree(pVirt, dwRoundedLength, MEM_DECOMMIT); VirtualFree(pVirt, dwRoundedLength, MEM_RELEASE); *pdwCopied= nCopied; return false; } DWORD addr= (DWORD)pVirt+dwStartOffset; bool bRes= ReadMemory(addr, buf, dwLength, pdwCopied, nDataAccess); VirtualFree(pVirt, dwRoundedLength, MEM_DECOMMIT); VirtualFree(pVirt, dwRoundedLength, MEM_RELEASE); return bRes; } bool WritePhysicalMemory(DWORD dwStart, const BYTE *buf, DWORD dwLength, DWORD *pdwCopied, DWORD nDataAccess) { DWORD nCopied= 0; DWORD dwRoundedStart= dwStart&KInfoTable[KINX_PFN_MASK]; DWORD dwStartOffset= dwStart-dwRoundedStart; DWORD dwRoundedLength= dwLength+dwStartOffset; BYTE *pVirt= (BYTE*)VirtualAlloc(NULL, dwRoundedLength, MEM_RESERVE, PAGE_NOACCESS); if (pVirt==NULL) { *pdwCopied= nCopied; return false; } if (!VirtualCopy(pVirt, (void*)(dwRoundedStart>>8), dwRoundedLength, PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE)) { VirtualFree(pVirt, dwRoundedLength, MEM_DECOMMIT); VirtualFree(pVirt, dwRoundedLength, MEM_RELEASE); *pdwCopied= nCopied; return false; } DWORD addr= (DWORD)pVirt+dwStartOffset; bool bRes= WriteMemory(addr, buf, dwLength, pdwCopied, nDataAccess); VirtualFree(pVirt, dwRoundedLength, MEM_DECOMMIT); VirtualFree(pVirt, dwRoundedLength, MEM_RELEASE); return bRes; } ITSUTILS_API HRESULT STDAPICALLTYPE ITReadProcessMemory( DWORD cbInput, ReadProcessMemoryParams *pbInput, DWORD *pcbOutput, ReadProcessMemoryResult **ppbOutput, IRAPIStream *pStream) { ReadProcessMemoryResult *pOut=NULL; *pcbOutput= PTR_DIFF(pOut, pOut->buffer+pbInput->nSize); pOut= *ppbOutput= (ReadProcessMemoryResult*)LocalAlloc(LPTR, *pcbOutput); KernelMode _km; //debug("itrm(h=%08lx)\n", pbInput->hProcess); DWORD res= 0; if (pbInput->hProcess==INVALID_HANDLE_VALUE) // -p ReadPhysicalMemory(pbInput->dwOffset, &pOut->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesRead, pbInput->nDataAccess); else if (pbInput->hProcess==NULL) // -m ReadMemory(pbInput->dwOffset, &pOut->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesRead, pbInput->nDataAccess); else if (!SafeReadProcMem(pbInput->hProcess, pbInput->dwOffset, &pOut->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesRead, (pbInput->nDataAccess&8)!=0)) res= GetLastError(); return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITWriteProcessMemory( DWORD cbInput, WriteProcessMemoryParams *pbInput, DWORD *pcbOutput, WriteProcessMemoryResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(WriteProcessMemoryResult); WriteProcessMemoryResult *pOut= *ppbOutput= (WriteProcessMemoryResult*)LocalAlloc(LPTR, *pcbOutput); DWORD res= 0; KernelMode _km; if (pbInput->hProcess==INVALID_HANDLE_VALUE) WritePhysicalMemory(pbInput->dwOffset, &pbInput->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesWritten, pbInput->nDataAccess); else if (pbInput->hProcess==NULL) WriteMemory(pbInput->dwOffset, &pbInput->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesWritten, pbInput->nDataAccess); else if (!WriteProcessMemory(pbInput->hProcess, (void*)pbInput->dwOffset, &pbInput->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesWritten)) res= GetLastError(); return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetContext( DWORD cbInput, BYTE *pbInput, DWORD *pcbOutput, GetContextResult **ppbOutput, IRAPIStream *pStream) { WCHAR *cmdline; // debug("ITGetContext: i=%08lx(%d) o=%08lx(%08lx) s=%08lx\n", // cbInput, pbInput, pcbOutput, ppbOutput, pStream); cmdline= GetCommandLine(); GetContextResult *pOut=NULL; *pcbOutput= PTR_DIFF(pOut, pOut->wszCmdLine+wcslen(cmdline)+1); pOut= *ppbOutput= (GetContextResult*)LocalAlloc(LPTR, *pcbOutput); pOut->dwProcessId= GetCurrentProcessId(); pOut->hProcess= GetCurrentProcess(); pOut->dwThreadId= GetCurrentThreadId(); pOut->hThread= GetCurrentThread(); pOut->dwCallerTrust= CeGetCallerTrust(); pOut->dwCurrentTrust= CeGetCurrentTrust(); wcscpy(pOut->wszCmdLine, cmdline); KernelMode _km; CalcMemoryUsage(pOut->dwMemoryUsed, pOut->dwMemoryFree, pOut->dwKernelMemory); //calctotals(); //calcfree(); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetProcessList( DWORD cbInput, GetProcessListParams *pbInput, DWORD *pcbOutput, GetProcessListResult **ppbOutput, IRAPIStream *pStream) { KernelMode _km; GetProcessListResult *pOut=NULL; *pcbOutput= 0; CeProcessList list; if (!GetProcessList(list)) return ERROR_NOT_FOUND; *pcbOutput= PTR_DIFF(pOut, pOut->pe+list.size()); pOut= *ppbOutput= (GetProcessListResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("ITGetProcessList: LocalAlloc(0x%x)", *pcbOutput); *pcbOutput= 0; return GetLastError(); } pOut->nEntries= list.size(); memcpy(pOut->pe, vectorptr(list), sizeof(CEPROCESSENTRY)*list.size()); return 0; } //---------------------------------------------- class ModuleEntry { public: ModuleEntry(const MODULEENTRY32& me) { wcsncpy(entry.szModuleName, me.szModule, MAX_PATH); entry.dwMemoryBase= (DWORD)me.modBaseAddr; } ModuleEntry(const struct Module *mod) { ModuleInfo mi; FillModuleInfo(mi, mod); _snwprintf(entry.szModuleName, MAX_PATH, L"%hs", mi.name.c_str()); entry.dwMemoryBase = mi.membase; entry.dwVBase = mi.csegbase; entry.dwDBase = mi.dsegbase; entry.dwUsage = mi.usagemask; } CEMODULEENTRY entry; }; typedef std::vector ModuleEntryList; // bool GetModuleList(ModuleEntryList& list) // { // HANDLE hTH= CreateToolhelp32Snapshot(TH32CS_GETALLMODS|TH32CS_SNAPALL, 0); // if (hTH==INVALID_HANDLE_VALUE) { // error("CreateToolhelp32Snapshot"); // return false; // } // // MODULEENTRY32 me; // me.dwSize= sizeof(MODULEENTRY32); // // int procnr=0; // if (Module32First(hTH, &me)) // { // do { // list.push_back(ModuleEntry(me)); // } while (Module32Next(hTH, &me)); // } // if (GetLastError()!=ERROR_NO_MORE_FILES) { // error("Module32First/Next"); // return false; // } // // CloseToolhelp32Snapshot(hTH); // // debug("found %d modules\n", list.size()); // return true; // } bool GetMemoryModuleList(ModuleEntryList& list) { struct Module *mod= (struct Module*)KData.aInfo[KINX_MODULES]; while (mod) { list.push_back(ModuleEntry(mod)); mod= mod->pMod; } return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetModuleList( DWORD cbInput, GetModuleListParams *pbInput, DWORD *pcbOutput, GetModuleListResult **ppbOutput, IRAPIStream *pStream) { KernelMode _km; GetModuleListResult *pOut=NULL; ModuleEntryList modlist; bool bRes; // if (pbInput->bDirectRead) bRes= GetMemoryModuleList(modlist); // else // bRes= GetModuleList(modlist); if (!bRes) return GetLastError(); *pcbOutput= PTR_DIFF(pOut, pOut->me+modlist.size()); pOut= *ppbOutput= (GetModuleListResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("ITGetModuleList: LocalAlloc(0x%x)", *pcbOutput); *pcbOutput= 0; return GetLastError(); } pOut->nEntries= modlist.size(); memcpy(pOut->me, vectorptr(modlist), sizeof(CEMODULEENTRY)*modlist.size()); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITSearchMemory( DWORD cbInput, SearchMemoryParams *pbInput, DWORD *pcbOutput, SearchMemoryResult **ppbOutput, IRAPIStream *pStream) { KernelMode _km; return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetProcessHandle( DWORD cbInput, GetProcessHandleParams *pbInput, DWORD *pcbOutput, GetProcessHandleResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput=sizeof(GetProcessHandleResult); *ppbOutput=(GetProcessHandleResult*)LocalAlloc(LPTR, *pcbOutput); KernelMode _km; (*ppbOutput)->hProc= GetProcessHandle(pbInput->wszProcessName); return 0; } HANDLE GetProcessHandle(WCHAR *wszProcessName) { int slot= FindProcessSlotForName(wszProcessName); if (slot==-1) return INVALID_HANDLE_VALUE; return getProcessSlotHandle(slot); } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetThreadTimes( DWORD cbInput, GetThreadTimesParams *pbInput, DWORD *pcbOutput, GetThreadTimesResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(GetThreadTimesResult); GetThreadTimesResult *pOut= *ppbOutput= (GetThreadTimesResult *)LocalAlloc(LPTR, *pcbOutput); KernelMode _km; DWORD res= 0; if (!GetThreadTimes(pbInput->hThread, &pOut->tCreate, &pOut->tExit, &pOut->tKernel, &pOut->tUser)) res= GetLastError(); return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetProcessUsageList( DWORD cbInput, GetProcessUsageListParams *pbInput, DWORD *pcbOutput, GetProcessUsageListResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(GetProcessUsageListResult); GetProcessUsageListResult *pOut= *ppbOutput= (GetProcessUsageListResult *)LocalAlloc(LPTR, *pcbOutput); memset(pOut, 0, *pcbOutput); KernelMode _km; GetProcessUsageList(pOut); pOut->tQuery= GetTickCount(); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetThreadUsageList( DWORD cbInput, GetThreadUsageListParams *pbInput, DWORD *pcbOutput, GetThreadUsageListResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(GetThreadUsageListResult); GetThreadUsageListResult *pOut= *ppbOutput= (GetThreadUsageListResult *)LocalAlloc(LPTR, *pcbOutput); memset(pOut, 0, *pcbOutput); KernelMode _km; GetThreadUsageList(pOut, pbInput->resolve_modulenames); pOut->tQuery= GetTickCount(); return 0; } //---------------------debugger---------------------------------- typedef struct _tagDebugEvent { DWORD dwProcessId; DWORD dwThreadId; DWORD dwDebugEventCode; int len; char *description; } DebugEvent; #define MAX_DEBUG_EVENTS 256 typedef struct _tagDebuggerInfo { char magic[4]; HANDLE evStarted; HANDLE evStopped; HANDLE evBuffer; DWORD dwThreadResult; DWORD dwDebuggedProcessId; bool bFilterForProcess; bool bSysMessagesOnly; WCHAR wszExeName[MAX_PATH]; WCHAR wszCmdLine[MAX_PATH]; HANDLE hThread; DWORD dwThreadId; bool bThreadStarted; bool bThreadTerminated; bool bProcessTerminated; HMODULE hDll; DWORD dwMissedEvents; CRITICAL_SECTION bufferlock; DWORD bufused; DWORD bufrd; DWORD bufwr; DWORD bufmaxsize; DebugEvent buffer[MAX_DEBUG_EVENTS]; int wrtext; int maxtext; char *textbuffer; } DebuggerInfo; bool GetDebugEvent(DebuggerInfo *di, DebugEvent *ev); bool ProcessDebugEvent(DebuggerInfo *di, DEBUG_EVENT *sysev); int ParseDebugEvent(char *buf, int bufsize, DEBUG_EVENT *event); ITSUTILS_API HRESULT STDAPICALLTYPE ITStartDebuggingProcess( DWORD cbInput, StartDebuggingProcessParams *pbInput, DWORD *pcbOutput, StartDebuggingProcessResult **ppbOutput, IRAPIStream *pStream) { DWORD res= 0; *pcbOutput= 0; *ppbOutput= NULL; HMODULE hDll= LoadLibrary(L"ItsUtils.dll"); if (hDll==NULL) return GetLastError(); LPTHREAD_START_ROUTINE pProc= (LPTHREAD_START_ROUTINE)GetProcAddress(hDll, L"DebugThreadProc"); if (pProc==NULL) { res= GetLastError(); if (!FreeLibrary(hDll)) error("ITStartDebuggingProcess: proc not found: FreeLibrary(hDll)"); //debug("freed library: %08lx\n", hDll); return res; } //debug("loaded library: h=%08lx proc=%08lx\n", hDll, pProc); DebuggerInfo *di= (DebuggerInfo *)LocalAlloc(LPTR, sizeof(DebuggerInfo)); memcpy(di->magic, "ITDB", 4); di->evStarted= CreateEvent(NULL, false, false, NULL); // used only once di->evBuffer= INVALID_HANDLE_VALUE; // signal new buffer entry di->evStopped= INVALID_HANDLE_VALUE; // used only once di->dwThreadResult= 0; di->dwDebuggedProcessId= pbInput->dwProcessId; wcsncpy(di->wszExeName, pbInput->wszExeName, MAX_PATH); wcsncpy(di->wszCmdLine, pbInput->wszCmdLine, MAX_PATH); di->dwMissedEvents= 0; di->bFilterForProcess= pbInput->bFilterForProcess; di->bSysMessagesOnly= pbInput->bSysMessagesOnly; di->hDll= hDll; di->bufused= 0; di->bufrd= 0; di->bufwr= 0; di->bufmaxsize= MAX_DEBUG_EVENTS; di->maxtext= 1024*1024; di->wrtext= 0; di->textbuffer= (char*)LocalAlloc(LPTR, di->maxtext); di->bThreadStarted= false; di->bThreadTerminated= false; di->hThread= CreateThread(NULL, 0, pProc, di, 0, &di->dwThreadId); //debug("created debug thread: h=%08lx id=%08lx\n", di->hThread, di->dwThreadId); // wait until debug thread is active bool bOk= (WaitForSingleObject(di->evStarted, INFINITE)==WAIT_OBJECT_0); CloseHandle(di->evStarted); di->evStarted= INVALID_HANDLE_VALUE; *pcbOutput= sizeof(StartDebuggingProcessResult); StartDebuggingProcessResult *pOut= *ppbOutput= (StartDebuggingProcessResult *)LocalAlloc(LPTR, *pcbOutput); pOut->debugger= (DWORD)di; if (di->dwThreadResult) return di->dwThreadResult; else if (!di->bThreadStarted) { debug("error starting debug thread\n"); return -1; } return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITStopDebuggingProcess( DWORD cbInput, StopDebuggingProcessParams *pbInput, DWORD *pcbOutput, StopDebuggingProcessResult **ppbOutput, IRAPIStream *pStream) { DebuggerInfo *di= (DebuggerInfo *)pbInput->debugger; *pcbOutput= 0; *ppbOutput= NULL; //debug("ITStopDebuggingProcess\n"); if (IsBadReadPtr(di, sizeof(DebuggerInfo))) { debug("ITStopDebuggingProcess: di is invalid ptr: %08lx\n", di); return -1; } if (memcmp(di->magic, "ITDB", 4)) { debug("ITStopDebuggingProcess: di struct is not valid: %02x%02x%02x%02x\n", di->magic[0], di->magic[1], di->magic[2], di->magic[3]); return -1; } if (!di->bThreadTerminated) { //debug("ITStopDebuggingProcess: stopping debug thread\n"); // creation of event signals to thread that it must stop. di->evStopped= CreateEvent(NULL, true, false, NULL); // automatic event // wait 5 sec until thread really stopped, before freeing up memory. bool bOk= (WaitForSingleObject(di->evStopped, 5000)==WAIT_OBJECT_0); CloseHandle(di->evStopped); di->evStopped= INVALID_HANDLE_VALUE; DWORD nExitCode; GetExitCodeThread(di->hThread, &nExitCode); TerminateThread(di->hThread, nExitCode); } if (!CloseHandle(di->hThread)) error("stopdebug: CloseHandle(hThread)"); if (!FreeLibrary(di->hDll)) error("stopdebug: FreeLibrary(hDll)"); //debug("freed library: %08lx\n", di->hDll); memset(di->magic, 0, 4); LocalFree(di->textbuffer); LocalFree(di); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITWaitForDebugEvent( DWORD cbInput, WaitForDebugEventParams *pbInput, DWORD *pcbOutput, WaitForDebugEventResult **ppbOutput, IRAPIStream *pStream) { DWORD res=0; DebuggerInfo *di= (DebuggerInfo *)pbInput->debugger; *pcbOutput= 0; *ppbOutput= NULL; if (IsBadReadPtr(di, sizeof(DebuggerInfo))) { debug("ITWaitForDebugEvent : di is invalid ptr: %08lx\n", di); return -1; } if (memcmp(di->magic, "ITDB", 4)) { debug("ITWaitForDebugEvent : di struct is not valid: %02x%02x%02x%02x\n", di->magic[0], di->magic[1], di->magic[2], di->magic[3]); return -1; } if (!di->bThreadStarted) { debug("ITWaitForDebugEvent : debug thread not started\n"); return -1; } if (di->bThreadTerminated) { //debug("ITWaitForDebugEvent : debug thread terminated\n"); return -1; } // either there is already something in the buffer, otherwise wait for event. if (!di->bufused==0 || (WaitForSingleObject(di->evBuffer, INFINITE)==WAIT_OBJECT_0 && di->bThreadStarted && !di->bThreadTerminated)) { // wait until we are allowed to touch the buffer internals. EnterCriticalSection(&(di->bufferlock)); DebugEvent ev; if (!GetDebugEvent(di, &ev)) { debug("ITWaitForDebugEvent : no debug event found\n"); res= -1; } DWORD dwMissedEvents= di->dwMissedEvents; di->dwMissedEvents= 0; LeaveCriticalSection(&(di->bufferlock)); *pcbOutput= sizeof(WaitForDebugEventResult)+ev.len; WaitForDebugEventResult *pOut= *ppbOutput= (WaitForDebugEventResult *)LocalAlloc(LPTR, *pcbOutput); pOut->dwProcessId= ev.dwProcessId; pOut->dwThreadId= ev.dwThreadId; pOut->dwDebugEventCode= ev.dwDebugEventCode; pOut->len= ev.len; memcpy(pOut->description, ev.description, ev.len+1); pOut->dwMissedEvents= dwMissedEvents; if (!ResetEvent(di->evBuffer)) { res= GetLastError(); error(res, "ITWaitForDebugEvent : ResetEvent(evBuffer)"); } } return res; } /* struct breakpoint { DWORD originsn; DWORD type; DWORD addr; }; std::map bplist; bool SetBreakPoint(HANDLE hProc, DWORD dwAddr, int type) { DWORD bptinsn= 0xe6000001; DWORD originsn; DWORD nProcessed; if (bplist.find(dwAddr)!=bplist.end()) { // breakpoint already set return false; } if (!ReadProcessMemory(hProc, dwAddr, &originsn, sizeof(originsn), &nProcessed)) return false; if (!WriteProcessMemory(hProc, dwAddr, &bptinsn, sizeof(bptinsn), &nProcessed)) return false; bplist[dwAddr]= breakpoint(originsn, type, dwAddr); } bool RemoveBreakPoint(HANDLE hProc, DWORD dwAddr) { DWORD bptinsn= 0xe6000001; DWORD originsn; DWORD nProcessed; if (bplist.find(dwAddr)==bplist.end()) { // error: breakpoint did not exist. return false; } if (!ReadProcessMemory(hProc, dwAddr, &originsn, sizeof(originsn), &nProcessed)) return false; if (originsn!=bptinsn) { // breakpoint no longer there!! bplist.remove(dwAddr); return false; } if (!WriteProcessMemory(hProc, dwAddr, &bplist[dwAddr].originsn, sizeof(DWORD), &nProcessed)) return false; bplist.remove(dwAddr); return true; } void ProcessTasks(iterator begin, iterator end) { for (iterator i=begin ; i!=end ; ++i) { switch((*i).action) { case DBG_ADDBREAKPOINT: SetBreakPoint((*i).proc, (*i).addr, BP_BREAKPOINT); break; case DBG_REMOVEBREAKPOINT: RemoveBreakPoint((*i).proc, (*i).addr); break; case DBG_ADDTRACE: SetBreakPoint((*i).proc, (*i).addr1, BP_STARTTRACE); SetBreakPoint((*i).proc, (*i).addr2, BP_ENDTRACE); break; } } } */ ITSUTILS_API DWORD DebugThreadProc(DebuggerInfo *di) { DWORD res=0; // on the smartphone, and wm2005 the setkmode is nescesary // on ppc2003 it is not. BOOL bMode = SetKMode(TRUE); DWORD dwPerm = SetProcPermissions(0xFFFFFFFF); //debug("DebugThreadProc started\n"); // either use provided pid, or start new process if (di->dwDebuggedProcessId!=0) { if (!DebugActiveProcess(di->dwDebuggedProcessId)) { res= di->dwThreadResult= GetLastError(); } } else { PROCESS_INFORMATION pi; if (!CreateProcess(di->wszExeName, di->wszCmdLine, NULL, NULL, 0, DEBUG_PROCESS, NULL, NULL, NULL, &pi)) { res= di->dwThreadResult= GetLastError(); } else { di->dwDebuggedProcessId= pi.dwProcessId; } } di->bProcessTerminated= false; di->evBuffer= CreateEvent(NULL, false, false, NULL); // signal new buffer entry InitializeCriticalSection(&(di->bufferlock)); // tell parent process that we are initialized and ready if (di->evStarted!=INVALID_HANDLE_VALUE && !SetEvent(di->evStarted)) { res= di->dwThreadResult= GetLastError(); } di->bThreadStarted= true; DEBUG_EVENT ev; // loop until a 'stopped' event is created while(!res && di->evStopped==INVALID_HANDLE_VALUE) { if (WaitForDebugEvent(&ev, 1000)) { if (!di->bSysMessagesOnly || ev.dwDebugEventCode!=OUTPUT_DEBUG_STRING_EVENT) if (!di->bFilterForProcess || ev.dwProcessId==di->dwDebuggedProcessId) if (!ProcessDebugEvent(di, &ev)) di->dwMissedEvents++; if (di->bProcessTerminated) break; /* ProcessTasks(di->tasks.begin(), di->tasks.end()); */ if (!ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED )) res= di->dwThreadResult= GetLastError(); } } di->bThreadTerminated= true; //debug("DebugThreadProc terminated\n"); // 'stopped' event found, set it. if (di->evStopped!=INVALID_HANDLE_VALUE && !SetEvent(di->evStopped)) { res= GetLastError(); error(res, "SetEvent(evStopped)"); } // try to tell whoever is waiting for us to stop doing that. if (di->evBuffer!=INVALID_HANDLE_VALUE) { // wake up other thread to be able to see me. SetEvent(di->evBuffer); CloseHandle(di->evBuffer); di->evBuffer= INVALID_HANDLE_VALUE; } DeleteCriticalSection(&(di->bufferlock)); SetProcPermissions(dwPerm); SetKMode(bMode); return res; } bool GetDebugEvent(DebuggerInfo *di, DebugEvent *ev) { if (di->bufused==0) return false; memcpy(ev, &di->buffer[di->bufrd], sizeof(DebugEvent)); if (++di->bufrd==di->bufmaxsize) di->bufrd= 0; di->bufused--; return true; } bool ProcessDebugEvent(DebuggerInfo *di, DEBUG_EVENT *sysev) { EnterCriticalSection(&(di->bufferlock)); if (di->bufused==di->bufmaxsize) { LeaveCriticalSection(&(di->bufferlock)); return false; } DebugEvent *ev= &di->buffer[di->bufwr]; ev->dwProcessId= sysev->dwProcessId; ev->dwThreadId= sysev->dwThreadId; ev->dwDebugEventCode= sysev->dwDebugEventCode; if (di->maxtext - di->wrtext < 1024) { di->wrtext= 0; } int maxtxt= di->maxtext - di->wrtext; ev->description= di->textbuffer+di->wrtext; ev->len= ParseDebugEvent(ev->description, maxtxt, sysev); di->wrtext += ev->len+1; if (di->wrtext >= di->maxtext) di->wrtext -= di->maxtext; if (++di->bufwr==di->bufmaxsize) di->bufwr= 0; ++di->bufused; // todo: test sysev.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE if (ev->dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT && ev->dwProcessId==di->dwDebuggedProcessId) di->bProcessTerminated= true; LeaveCriticalSection(&(di->bufferlock)); if (!SetEvent(di->evBuffer)) { error("ProcessDebugEvent: SetEvent"); return false; } return true; } //--------------converting a debug event to a string int ParseDebugException(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, EXCEPTION_DEBUG_INFO *exception); int ParseDebugCreateThread(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, CREATE_THREAD_DEBUG_INFO *createThread); int ParseDebugCreateProcessInfo(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, CREATE_PROCESS_DEBUG_INFO *createProcessInfo); int ParseDebugExitThread(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, EXIT_THREAD_DEBUG_INFO *exitThread); int ParseDebugExitProcess(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, EXIT_PROCESS_DEBUG_INFO *exitProcess); int ParseDebugLoadDll(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, LOAD_DLL_DEBUG_INFO *loadDll); int ParseDebugUnloadDll(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, UNLOAD_DLL_DEBUG_INFO *unloadDll); int ParseDebugString(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, OUTPUT_DEBUG_STRING_INFO *debugString); int ParseDebugRipInfo(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, RIP_INFO *ripInfo); int ParseDebugEvent(char *buf, int bufsize, DEBUG_EVENT *event) { int n=0; switch(event->dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: n+=ParseDebugException(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.Exception); n+=AddThreadInfo(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId); break; case CREATE_THREAD_DEBUG_EVENT: n+=ParseDebugCreateThread(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.CreateThread); break; case CREATE_PROCESS_DEBUG_EVENT:n+=ParseDebugCreateProcessInfo(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.CreateProcessInfo); break; case EXIT_THREAD_DEBUG_EVENT: n+=ParseDebugExitThread(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.ExitThread); break; case EXIT_PROCESS_DEBUG_EVENT: n+=ParseDebugExitProcess(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.ExitProcess); break; case LOAD_DLL_DEBUG_EVENT: n+=ParseDebugLoadDll(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.LoadDll); break; case UNLOAD_DLL_DEBUG_EVENT: n+=ParseDebugUnloadDll(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.UnloadDll); break; case OUTPUT_DEBUG_STRING_EVENT: n+=ParseDebugString(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.DebugString); break; case RIP_EVENT: n+=ParseDebugRipInfo(buf+n, bufsize-n, event->dwProcessId, event->dwThreadId, &event->u.RipInfo); break; default: n+= _snprintf(buf+n, bufsize-n, "unknown debug event pid=%08lx tid=%08lx ev=%08lx", event->dwProcessId, event->dwThreadId, event->dwDebugEventCode); } return n; } // provide some info in case other things fail. TCHAR *StrInfo(DWORD dwProcessId, void *ptr, int len, int uni) { static TCHAR tbuf[256]; _sntprintf(tbuf, 256, L"[%08lx:%08lx L%04x uni=%d]", dwProcessId, ptr, len, uni); return tbuf; } TCHAR *ReadProcessWString(DWORD dwProcessId, void *ptr, int len) { static TCHAR buf[1024]; DWORD nCopied; if (!ReadProcessMemory((HANDLE)dwProcessId, ptr, buf, min(len, sizeof(buf)-1), &nCopied)) return 0; buf[nCopied]= 0; return buf; } char *ReadProcessString(DWORD dwProcessId, void *ptr, int len) { static char buf[1024]; DWORD nCopied; if (!ReadProcessMemory((HANDLE)dwProcessId, ptr, buf, min(len, sizeof(buf)-1), &nCopied)) return 0; buf[nCopied]= 0; return buf; } DWORD ReadProcessDword(DWORD dwProcessId, void *ptr) { DWORD dw; DWORD nCopied; if (!ReadProcessMemory((HANDLE)dwProcessId, ptr, &dw, sizeof(DWORD), &nCopied)) return 0; return dw; } TCHAR *PtrToString(DWORD dwProcessId, void *ptr, int len, int uni) { if (ptr==NULL) return L"(NULL)"; else if (uni) { TCHAR *tbuf= ReadProcessWString(dwProcessId, ptr, len); if (tbuf==NULL) return StrInfo(dwProcessId, ptr, len, uni); return tbuf; } else { static TCHAR tbuf[256]; char *buf= ReadProcessString(dwProcessId, ptr, len); if (buf==NULL) return StrInfo(dwProcessId, ptr, len, uni); _sntprintf(tbuf, 256, L"%hs", buf); return tbuf; } } TCHAR *PtrptrToString(DWORD dwProcessId, void *pptr, int len, int uni) { if (pptr==NULL) return L"((NULL))"; void *ptr= (void*)ReadProcessDword(dwProcessId, pptr); return PtrToString(dwProcessId, ptr, len, uni); } int ParseExceptionCode(char *buf, int bufsize, DWORD dwCode) { const char *str=NULL; int n=0; switch (dwCode) { case EXCEPTION_ACCESS_VIOLATION: str= "EXCEPTION_ACCESS_VIOLATION"; break; case EXCEPTION_DATATYPE_MISALIGNMENT: str= "EXCEPTION_DATATYPE_MISALIGNMENT"; break; case EXCEPTION_BREAKPOINT: str= "EXCEPTION_BREAKPOINT"; break; case EXCEPTION_SINGLE_STEP: str= "EXCEPTION_SINGLE_STEP"; break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: str= "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; break; case EXCEPTION_FLT_DENORMAL_OPERAND: str= "EXCEPTION_FLT_DENORMAL_OPERAND"; break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: str= "EXCEPTION_FLT_DIVIDE_BY_ZERO"; break; case EXCEPTION_FLT_INEXACT_RESULT: str= "EXCEPTION_FLT_INEXACT_RESULT"; break; case EXCEPTION_FLT_INVALID_OPERATION: str= "EXCEPTION_FLT_INVALID_OPERATION"; break; case EXCEPTION_FLT_OVERFLOW: str= "EXCEPTION_FLT_OVERFLOW"; break; case EXCEPTION_FLT_STACK_CHECK: str= "EXCEPTION_FLT_STACK_CHECK"; break; case EXCEPTION_FLT_UNDERFLOW: str= "EXCEPTION_FLT_UNDERFLOW"; break; case EXCEPTION_INT_DIVIDE_BY_ZERO: str= "EXCEPTION_INT_DIVIDE_BY_ZERO"; break; case EXCEPTION_INT_OVERFLOW: str= "EXCEPTION_INT_OVERFLOW"; break; case EXCEPTION_PRIV_INSTRUCTION: str= "EXCEPTION_PRIV_INSTRUCTION"; break; case EXCEPTION_IN_PAGE_ERROR: str= "EXCEPTION_IN_PAGE_ERROR"; break; case EXCEPTION_ILLEGAL_INSTRUCTION: str= "EXCEPTION_ILLEGAL_INSTRUCTION"; break; case EXCEPTION_NONCONTINUABLE_EXCEPTION: str= "EXCEPTION_NONCONTINUABLE_EXCEPTION"; break; case EXCEPTION_STACK_OVERFLOW: str= "EXCEPTION_STACK_OVERFLOW"; break; case EXCEPTION_INVALID_DISPOSITION: str= "EXCEPTION_INVALID_DISPOSITION"; break; case EXCEPTION_GUARD_PAGE: str= "EXCEPTION_GUARD_PAGE"; break; case EXCEPTION_INVALID_HANDLE: str= "EXCEPTION_INVALID_HANDLE"; break; } if (str) n+= _snprintf(buf+n, bufsize-n, " %s", str); else n+= _snprintf(buf+n, bufsize-n, " EXCEPTION_%08lx", dwCode); return n; } int ParseExceptionFlags(char *buf, int bufsize, DWORD dwFlags) { int n=0; if (dwFlags==0) { n+= _snprintf(buf+n, bufsize-n, " noflags"); return n; } n+= _snprintf(buf+n, bufsize-n, " flags="); int m=n; if (dwFlags&EXCEPTION_NONCONTINUABLE ) n+= _snprintf(buf+n, bufsize-n, "%sNONCONTINUABLE", n==m?"|":""); if (dwFlags&EXCEPTION_UNWINDING ) n+= _snprintf(buf+n, bufsize-n, "%sUNWINDING", n==m?"|":""); if (dwFlags&EXCEPTION_EXIT_UNWIND ) n+= _snprintf(buf+n, bufsize-n, "%sEXIT_UNWIND", n==m?"|":""); if (dwFlags&EXCEPTION_STACK_INVALID ) n+= _snprintf(buf+n, bufsize-n, "%sSTACK_INVALID", n==m?"|":""); if (dwFlags&EXCEPTION_NESTED_CALL ) n+= _snprintf(buf+n, bufsize-n, "%sNESTED_CALL", n==m?"|":""); if (dwFlags&EXCEPTION_TARGET_UNWIND ) n+= _snprintf(buf+n, bufsize-n, "%sTARGET_UNWIND", n==m?"|":""); if (dwFlags&EXCEPTION_COLLIDED_UNWIND) n+= _snprintf(buf+n, bufsize-n, "%sCOLLIDED_UNWIND", n==m?"|":""); const DWORD knownflags= EXCEPTION_NONCONTINUABLE|EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND|EXCEPTION_STACK_INVALID|EXCEPTION_NESTED_CALL|EXCEPTION_TARGET_UNWIND|EXCEPTION_COLLIDED_UNWIND; if (dwFlags&~knownflags) n+= _snprintf(buf+n, bufsize-n, "%s%08lx", n==m?"|":"", dwFlags&~knownflags); return n; } int ParseDebugException(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, EXCEPTION_DEBUG_INFO *exception) { int n=0; n+= _snprintf(buf+n, bufsize-n, "debugException first=%d", exception->dwFirstChance); EXCEPTION_RECORD *er= &exception->ExceptionRecord; int i=0; while (er) { if (i) n+= _snprintf(buf+n, bufsize-n, " ; "); n+= ParseExceptionCode(buf+n, bufsize-n, er->ExceptionCode); n+= ParseExceptionFlags(buf+n, bufsize-n, er->ExceptionFlags); n+= _snprintf(buf+n, bufsize-n, " @%08lx", er->ExceptionAddress); if (er->ExceptionCode==EXCEPTION_ACCESS_VIOLATION && er->NumberParameters==2) { n+= _snprintf(buf+n, bufsize-n, " RW=%08lx addr=%08lx\n", er->ExceptionInformation[0], er->ExceptionInformation[1]); } else { for(DWORD i=0 ; iNumberParameters ; i++) { n+= _snprintf(buf+n, bufsize-n, " %08lx", er->ExceptionInformation[i]); } n+= _snprintf(buf+n, bufsize-n, "\n"); } er= er->ExceptionRecord; i++; } return n; } int ParseDebugCreateThread(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, CREATE_THREAD_DEBUG_INFO *createThread) { int n=0; n+= _snprintf(buf+n, bufsize-n, "createThread(hthread=%08x base=%08x start=%08x)", createThread->hThread, createThread->lpThreadLocalBase, createThread->lpStartAddress); return n; } int ParseDebugCreateProcessInfo(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, CREATE_PROCESS_DEBUG_INFO *createProcessInfo) { int n=0; n+= _snprintf(buf+n, bufsize-n, "createProcess(file=%d hproc=%08x hthread=%08x image=%08x debug=%08x(%08x)", createProcessInfo->hFile, createProcessInfo->hProcess, createProcessInfo->hThread, createProcessInfo->lpBaseOfImage, createProcessInfo->dwDebugInfoFileOffset, createProcessInfo->nDebugInfoSize); n+= _snprintf(buf+n, bufsize-n, " base=%08x start=%08x name='%ls'", createProcessInfo->lpThreadLocalBase, createProcessInfo->lpStartAddress, PtrToString( dwProcessId, createProcessInfo->lpImageName, 128, // todo ..... what should this be ?? createProcessInfo->fUnicode)); return n; } int ParseDebugExitThread(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, EXIT_THREAD_DEBUG_INFO *exitThread) { int n=0; // todo: remember n+= _snprintf(buf+n, bufsize-n, "exitThread %08lx code=%d", dwThreadId, exitThread->dwExitCode); return n; } int ParseDebugExitProcess(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, EXIT_PROCESS_DEBUG_INFO *exitProcess) { int n=0; n+= _snprintf(buf+n, bufsize-n, "exitProcess code=%d", exitProcess->dwExitCode); return n; } int ParseDebugLoadDll(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, LOAD_DLL_DEBUG_INFO *loadDll) { int n=0; n+= _snprintf(buf+n, bufsize-n, "loadDll file=%d base=%08x debug=%08x(%08x) name='%ls'", loadDll->hFile, loadDll->lpBaseOfDll, loadDll->dwDebugInfoFileOffset, loadDll->nDebugInfoSize, PtrToString( dwProcessId, loadDll->lpImageName, 128, // todo ..... what should this be ?? loadDll->fUnicode)); return n; } int ParseDebugUnloadDll(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, UNLOAD_DLL_DEBUG_INFO *unloadDll) { int n=0; // todo: keep track of pid+dllbase to remember the module name. n+= _snprintf(buf+n, bufsize-n, "unloadDll base=%08x", unloadDll->lpBaseOfDll); return n; } int ParseDebugString(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, OUTPUT_DEBUG_STRING_INFO *debugString) { int n=0; n+= _snprintf(buf+n, bufsize-n, "%ls", PtrToString(dwProcessId, debugString->lpDebugStringData, debugString->nDebugStringLength, debugString->fUnicode)); return n; } int ParseDebugRipInfo(char *buf, int bufsize, DWORD dwProcessId, DWORD dwThreadId, RIP_INFO *ripInfo) { int n=0; n+= _snprintf(buf+n, bufsize-n, "ripinfo error=%d type=%d", ripInfo->dwError, ripInfo->dwType); return n; } //-------------------------------- int GetDiskInfo(HANDLE hDsk, DISK_INFO &info) { DWORD nReturned; // various ce versions use all possible combinations, so we try 'm all. if (DeviceIoControl(hDsk, IOCTL_DISK_GETINFO, &info, sizeof(info), NULL, 0, &nReturned, NULL)) return 1; if (DeviceIoControl(hDsk, IOCTL_DISK_GETINFO, NULL, 0, &info, sizeof(info), &nReturned, NULL)) return 2; if (DeviceIoControl(hDsk, DISK_IOCTL_GETINFO, &info, sizeof(info), NULL, 0, &nReturned, NULL)) return 3; if (DeviceIoControl(hDsk, DISK_IOCTL_GETINFO, NULL, 0, &info, sizeof(info), &nReturned, NULL)) return 4; return 0; } HANDLE OpenDisk(int n) { TCHAR diskname[16]; // todo: implement opening volume instead of physical disk when bit31 of disknr is set. if (n>=0 && n<=256) _sntprintf(diskname, 16, L"DSK%u:", n); else _sntprintf(diskname, 16, L"DSK:"); HANDLE hDsk= CreateFile( diskname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); if (hDsk==NULL || hDsk==INVALID_HANDLE_VALUE) { return NULL; } return hDsk; } /* TCHAR ss[256]; _sntprintf(ss, 256, L"req: %d %08lx %08lx", pbInput->dwDiskNr, pbInput->dwOffset, pbInput->dwSize); MessageBox(0, ss, L"req", 0); _sntprintf(ss, 256, L"reply: %d %08lx %08lx -> %d, %d, %08lx %08lx", pbInput->dwDiskNr, pbInput->dwOffset, pbInput->dwSize, out->dwNumberOfBytesRead, out->start, out->number, outsize); MessageBox(0, ss, L"reply", 0); */ bool DiskReadBlocks(HANDLE hDsk, int nStart, int nBlocks, const DISK_INFO& info, BYTE* buffer, DWORD* pnBytesRead) { SG_REQ req; req.sr_start= nStart; req.sr_num_sec= nBlocks; req.sr_num_sg= 1; req.sr_status= 0; req.sr_callback= NULL; req.sr_sglist[0].sb_len= nBlocks*info.di_bytes_per_sect; req.sr_sglist[0].sb_buf= buffer; DWORD nReturned=0; if (!DeviceIoControl(hDsk, DISK_IOCTL_READ, &req, sizeof(req), NULL, NULL, &nReturned, NULL)) return false; *pnBytesRead= nBlocks*info.di_bytes_per_sect; return true; } bool DiskWriteBlocks(HANDLE hDsk, int nStart, int nBlocks, const DISK_INFO& info, const BYTE* buffer, DWORD* pnBytesWritten) { SG_REQ req; req.sr_start= nStart; req.sr_num_sec= nBlocks; req.sr_num_sg= 1; req.sr_status= 0; req.sr_callback= NULL; req.sr_sglist[0].sb_len= nBlocks*info.di_bytes_per_sect; req.sr_sglist[0].sb_buf= (BYTE*)buffer; DWORD nReturned=0; if (!DeviceIoControl(hDsk, DISK_IOCTL_WRITE, &req, sizeof(req), NULL, NULL, &nReturned, NULL)) return false; *pnBytesWritten= nBlocks*info.di_bytes_per_sect; return true; } bool GetSDCardId(HANDLE hDsk, BYTE *cardid) { HDATA *haDsk= cvHandle2HDataPtr(hDsk); if (haDsk==NULL) { debug("haDsk==NULL\n"); return false; } fsopendev_t *dskdev= (fsopendev_t *)MapPtrProc(haDsk->pvObj, haDsk->pci->pServer); if (dskdev==NULL) { debug("dskdev==NULL\n"); return false; } BYTE *opendata= (BYTE*)MapPtrProc(dskdev->dwOpenData, haDsk->pci->pServer); if (opendata==NULL) { debug("opendata==NULL\n"); return false; } memcpy(cardid, opendata+0x40, 16); return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITSDCardInfo( DWORD cbInput, SDCardInfoParams *pbInput, DWORD *pcbOutput, SDCardInfoResult **ppbOutput, IRAPIStream *pStream) { HRESULT res= 0; *ppbOutput= NULL; *pcbOutput= 0; HANDLE hDsk= OpenDisk(pbInput->dwDiskNr); if (hDsk==NULL) return GetLastError(); DISK_INFO info; if (!GetDiskInfo(hDsk, info)) { res= GetLastError(); CloseHandle(hDsk); return res; } DWORD outsize= sizeof(SDCardInfoResult); SDCardInfoResult *out= (SDCardInfoResult*)LocalAlloc(LPTR, outsize); out->blockSize= info.di_bytes_per_sect; out->totalBlocks= info.di_total_sectors; KernelMode _km; if (!GetSDCardId(hDsk, out->cardid)) { out->cardidLength= 0; memset(out->cardid, 0, 16); } else { out->cardidLength= 16; } CloseHandle(hDsk); *ppbOutput= out; *pcbOutput= outsize; return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITReadSDCard( DWORD cbInput, ReadSDCardParams *pbInput, DWORD *pcbOutput, ReadSDCardResult **ppbOutput, IRAPIStream *pStream) { HRESULT res= 0; *ppbOutput= NULL; *pcbOutput= 0; HANDLE hDsk= OpenDisk(pbInput->dwDiskNr); if (hDsk==NULL) return GetLastError(); DISK_INFO info; if (!GetDiskInfo(hDsk, info)) { res= GetLastError(); CloseHandle(hDsk); return res; } if (pbInput->dwOffset % info.di_bytes_per_sect) { debug("ERROR: ITReadSDCard: startoffset not on sector boundary: sector nr %x ofs %04x\n", pbInput->dwOffset / info.di_bytes_per_sect, pbInput->dwOffset % info.di_bytes_per_sect); CloseHandle(hDsk); return ERROR_INVALID_PARAMETER; } if ((pbInput->dwOffset+pbInput->dwSize) % info.di_bytes_per_sect) { debug("ERROR: ITReadSDCard: endoffset not on sector boundary: sector nr %x ofs %04x\n", (pbInput->dwOffset+pbInput->dwSize)/ info.di_bytes_per_sect, (pbInput->dwOffset+pbInput->dwSize)% info.di_bytes_per_sect); CloseHandle(hDsk); return ERROR_INVALID_PARAMETER; } DWORD outsize= sizeof(ReadSDCardResult)+pbInput->dwSize; ReadSDCardResult *out= (ReadSDCardResult *)LocalAlloc(LPTR, outsize); if (!DiskReadBlocks(hDsk, pbInput->dwOffset / info.di_bytes_per_sect, pbInput->dwSize / info.di_bytes_per_sect, info, out->buffer, &out->dwNumberOfBytesRead)) { res= GetLastError(); CloseHandle(hDsk); LocalFree(out); return res; } // out->start= pbInput->dwOffset / info.di_bytes_per_sect; // out->number= pbInput->dwSize / info.di_bytes_per_sect; CloseHandle(hDsk); *ppbOutput= out; *pcbOutput= outsize; return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITWriteSDCard( DWORD cbInput, WriteSDCardParams *pbInput, DWORD *pcbOutput, WriteSDCardResult **ppbOutput, IRAPIStream *pStream) { HRESULT res= 0; *ppbOutput= NULL; *pcbOutput= 0; HANDLE hDsk= OpenDisk(pbInput->dwDiskNr); if (hDsk==NULL) return GetLastError(); DISK_INFO info; if (!GetDiskInfo(hDsk, info)) { res= GetLastError(); CloseHandle(hDsk); return res; } if (pbInput->dwOffset % info.di_bytes_per_sect) { debug("ERROR: ITWriteSDCard : startoffset not on sector boundary: sector nr %x ofs %04x\n", pbInput->dwOffset / info.di_bytes_per_sect, pbInput->dwOffset % info.di_bytes_per_sect); CloseHandle(hDsk); return ERROR_INVALID_PARAMETER; } if ((pbInput->dwOffset+pbInput->dwSize) % info.di_bytes_per_sect) { debug("ERROR: ITWriteSDCard : endoffset not on sector boundary: sector nr %x ofs %04x\n", (pbInput->dwOffset+pbInput->dwSize)/ info.di_bytes_per_sect, (pbInput->dwOffset+pbInput->dwSize)% info.di_bytes_per_sect); CloseHandle(hDsk); return ERROR_INVALID_PARAMETER; } WriteSDCardResult *out= (WriteSDCardResult *)LocalAlloc(LPTR, sizeof(WriteSDCardResult)); if (!DiskWriteBlocks(hDsk, pbInput->dwOffset / info.di_bytes_per_sect, pbInput->dwSize / info.di_bytes_per_sect, info, pbInput->buffer, &out->dwNumberOfBytesWritten)) { res= GetLastError(); CloseHandle(hDsk); LocalFree(out); return res; } CloseHandle(hDsk); *ppbOutput= out; *pcbOutput= sizeof(WriteSDCardResult); return 0; } //-------------------------------------------------------- DWORD DoMagicianFlashRom(DWORD dwOffset, DWORD dwSize, DWORD dwChecksum, BYTE *pBuffer) { struct FlashAccessCommand { DWORD dwCommand; DWORD pbDestAddr; DWORD pbSrcAddr; DWORD dwLength; } cmd; cmd.dwCommand= 0; cmd.pbDestAddr= dwOffset; cmd.pbSrcAddr= (DWORD)pBuffer; cmd.dwLength= dwSize; DWORD dwReturned; DWORD res= 0; debug("flashrom: erase %d buf=%08lx dst=%08lx len=%08lx\n", cmd.dwCommand, cmd.pbSrcAddr, cmd.pbDestAddr, cmd.dwLength); if (!KernelIoControl(0x01012a10, &cmd, sizeof(cmd), NULL, 0, &dwReturned)) { res= GetLastError(); if (res==0) res= ERROR_GEN_FAILURE; debug("flashaccess: erase: error=%08lx: %08lx\n", res, dwReturned); return res; } cmd.dwCommand= 1; cmd.pbDestAddr= dwOffset; cmd.pbSrcAddr= (DWORD)pBuffer; cmd.dwLength= dwSize; debug("flashrom: write %d buf=%08lx dst=%08lx len=%08lx\n", cmd.dwCommand, cmd.pbSrcAddr, cmd.pbDestAddr, cmd.dwLength); if (!KernelIoControl(0x01012a10, &cmd, sizeof(cmd), NULL, 0, &dwReturned)) { res= GetLastError(); if (res==0) res= ERROR_GEN_FAILURE; debug("flashaccess: write: error=%08lx: %08lx\n", res, dwReturned); return res; } return res; } #define IOCTL_HAL_OAK_START 5000 #define IOCTL_HAL_XIP_BASE IOCTL_HAL_OAK_START + 500 /*++ IOCTL_HAL_WRITE_XIP Writes an XIP region to flash Input Buffer is a WRITE_XIP_HEADER followed immediately by dwNumRecords of XIP_RECORD_INFO structures Output buffer is unused. --*/ #define IOCTL_HAL_WRITE_XIP_3 CTL_CODE(FILE_DEVICE_HAL, IOCTL_HAL_XIP_BASE + 1, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_HAL_WRITE_XIP_4 CTL_CODE(FILE_DEVICE_HAL, 0x2e, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct _WRITE_XIP_HEADER { LPVOID pvPhysAddr; // physical starting address of XIP DWORD dwLength; // length of XIP DWORD dwNumRecords; // number of records in XIP } WRITE_XIP_HEADER, *PWRITE_XIP_HEADER; typedef struct _XIP_RECORD_INFO { LPVOID pvPhysStart; // physical starting address of record, dest addr DWORD dwPhysLen; // physical len, in bytes of record DWORD dwCheckSum; // sum of all the bytes in the record data VOID UNALIGNED * pvRAMStart; // virtual address of record in RAM, source addr } XIP_RECORD_INFO, *PXIP_RECORD_INFO; DWORD DoXipFlashRom(DWORD dwOffset, DWORD dwSize, DWORD dwChecksum, BYTE *pBuffer) { struct { WRITE_XIP_HEADER hdr; XIP_RECORD_INFO info; } xipcmd; xipcmd.hdr.pvPhysAddr= (void*)dwOffset; xipcmd.hdr.dwLength= dwSize; xipcmd.hdr.dwNumRecords= 1; xipcmd.info.pvPhysStart= (void*)dwOffset; xipcmd.info.dwPhysLen= dwSize; xipcmd.info.dwCheckSum= dwChecksum; xipcmd.info.pvRAMStart= (VOID*)pBuffer; DWORD ioctlcode; if (GetWinceVersion()<4) ioctlcode=IOCTL_HAL_WRITE_XIP_3; else ioctlcode=IOCTL_HAL_WRITE_XIP_4; DWORD dwResult; DWORD dwReturned; DWORD res= 0; debug("flashrom: csum=%08lx ioctl=%08lx buf=%08lx dst=%08lx len=%08lx\n", xipcmd.info.dwCheckSum, ioctlcode, xipcmd.info.pvRAMStart, xipcmd.info.pvPhysStart, xipcmd.info.dwPhysLen); if (!KernelIoControl(ioctlcode, &xipcmd, sizeof(xipcmd), &dwResult, sizeof(DWORD), &dwReturned)) { res= GetLastError(); if (res==0) res= ERROR_GEN_FAILURE; } debug("flashxip: error=%08lx: %08lx %08lx\n", res, dwResult, dwReturned); return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITFlashROM( DWORD cbInput, FlashROMParams *pbInput, DWORD *pcbOutput, FlashROMResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(FlashROMResult); FlashROMResult *pOut= *ppbOutput= (FlashROMResult*)LocalAlloc(LPTR, *pcbOutput); KernelMode _km; DWORD res= 0; switch (pbInput->dwType) { case FLASH_TYPE_XIPFLASH: res= DoXipFlashRom(pbInput->dwOffset, pbInput->dwSize, pbInput->dwCheckSum, pbInput->buffer); break; case FLASH_TYPE_MAGICIAN: res= DoMagicianFlashRom(pbInput->dwOffset, pbInput->dwSize, pbInput->dwCheckSum, pbInput->buffer); break; default: debug("ERROR: unknown flash type %d\n", pbInput->dwType); } pOut->dwResult= res; debug("flashrom: error=%08lx: %08lx\n", res, pOut->dwResult); return res; } //------------------------------------------------------------------------------------ #define GSM_READ_BLOCK_SIZE 100 bool ReadGsmMemory(DWORD dwStart, BYTE *buf, DWORD dwLength, DWORD *pdwCopied) { DWORD nCopied= 0; DWORD addr= dwStart; GsmDevice gsm; gsm.open(); gsm.DisableRIL(); while (nCopied < dwLength) { DWORD nChunkSize= min(GSM_READ_BLOCK_SIZE -(addr%GSM_READ_BLOCK_SIZE), dwLength-nCopied); if (!gsm.ReadBlock(&buf[nCopied], addr, nChunkSize)) return false; nCopied += nChunkSize; addr += nChunkSize; } *pdwCopied= nCopied; return true; } #define GSM_WRITE_BLOCK_SIZE 4 bool WriteGsmMemory(DWORD dwStart, BYTE *buf, DWORD dwLength, DWORD *pdwCopied) { DWORD nCopied= 0; DWORD addr= dwStart; GsmDevice gsm; gsm.open(); while (nCopied < dwLength) { DWORD nChunkSize= min(GSM_WRITE_BLOCK_SIZE -(addr%GSM_WRITE_BLOCK_SIZE), dwLength-nCopied); if (!gsm.WriteBlock(addr, &buf[nCopied], nChunkSize)) return false; nCopied += nChunkSize; addr += nChunkSize; } *pdwCopied= nCopied; return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITReadGsmMemory( DWORD cbInput, ReadGsmMemoryParams *pbInput, DWORD *pcbOutput, ReadGsmMemoryResult **ppbOutput, IRAPIStream *pStream) { ReadGsmMemoryResult *pOut=NULL; *pcbOutput= PTR_DIFF(pOut, pOut->buffer+pbInput->nSize); pOut= *ppbOutput= (ReadGsmMemoryResult*)LocalAlloc(LPTR, *pcbOutput); DWORD res= 0; if (!ReadGsmMemory(pbInput->dwOffset, &pOut->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesRead)) res= GetLastError(); return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITWriteGsmMemory( DWORD cbInput, WriteGsmMemoryParams *pbInput, DWORD *pcbOutput, WriteGsmMemoryResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(WriteGsmMemoryResult); WriteGsmMemoryResult *pOut= *ppbOutput= (WriteGsmMemoryResult*)LocalAlloc(LPTR, *pcbOutput); DWORD res= 0; if (!WriteGsmMemory(pbInput->dwOffset, &pbInput->buffer[0], pbInput->nSize, &pOut->dwNumberOfBytesWritten)) res= GetLastError(); return res; } void GsmReset() { GsmDevice gsm; gsm.open(); gsm.DisableRIL(); gsm.Reset(); } void GsmStopRil() { GsmDevice gsm; gsm.open(); gsm.DisableRIL(); gsm.close(); } void GsmStartRil() { GsmDevice gsm; gsm.open(); gsm.EnableRIL(); gsm.close(); } ITSUTILS_API HRESULT STDAPICALLTYPE ITGsmControl( DWORD cbInput, GsmControlParams *pbInput, DWORD *pcbOutput, GsmControlResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; *ppbOutput= NULL; switch(pbInput->nCmd) { case GSM_RESET: GsmReset(); break; case GSM_STOPRIL: GsmStopRil(); break; case GSM_STARTRIL: GsmStartRil(); break; } return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITReboot( DWORD cbInput, BYTE *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; *ppbOutput= NULL; KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITColdboot( DWORD cbInput, BYTE *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; *ppbOutput= NULL; // this is htc-startrek specific KernelIoControl(0x1012594, NULL, 0, NULL, 0, NULL); keybd_event(0x81, 0, 0, 0); keybd_event(0x81, 0, 2, 0); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITSetSystemTime( DWORD cbInput, SetSystemTimeParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; *ppbOutput= NULL; DWORD res= 0; KernelMode _km; if (pbInput->bSetTz) { if (!SetTimeZoneInformation(&pbInput->tzinfo)) res= GetLastError(); } if (pbInput->bSetLocal) { if (!SetLocalTime(&pbInput->time)) res= GetLastError(); } else if (pbInput->bSetSystem) { if (!SetSystemTime(&pbInput->time)) res= GetLastError(); } return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetSystemTime( DWORD cbInput, GetSystemTimeParams *pbInput, DWORD *pcbOutput, GetSystemTimeResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(GetSystemTimeResult); GetSystemTimeResult *pOut = *ppbOutput= (GetSystemTimeResult*)LocalAlloc(LPTR, *pcbOutput); DWORD res= 0; KernelMode _km; pOut->tzid= GetTimeZoneInformation(&pOut->tzinfo); if (pbInput->bGetLocal) { GetLocalTime(&pOut->time); } else { GetSystemTime(&pOut->time); } return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITShowWindow( DWORD cbInput, ShowWindowParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; switch(pbInput->dwShow) { case SW_SETFOREGROUND: if (!SetForegroundWindow(pbInput->hWnd)) return GetLastError(); break; case SW_SETACTIVE: if (NULL==SetActiveWindow(pbInput->hWnd)) return GetLastError(); break; case SW_SETCAPTURE: if (NULL==SetCapture(pbInput->hWnd)) return GetLastError(); break; case SW_BRINGTOTOP: if (!BringWindowToTop(pbInput->hWnd)) return GetLastError(); break; case SW_DRAWMENUBAR: if (!DrawMenuBar(pbInput->hWnd)) return GetLastError(); break; case SW_DESTROYWINDOW: if (!DestroyWindow(pbInput->hWnd)) return GetLastError(); break; case SW_UPDATEWINDOW: if (!UpdateWindow(pbInput->hWnd)) return GetLastError(); break; case SW_HIDECARET: if (!HideCaret(pbInput->hWnd)) return GetLastError(); break; case SW_SHOWCARET: if (!ShowCaret(pbInput->hWnd)) return GetLastError(); break; case SW_SETFOCUS: if (NULL==SetFocus(pbInput->hWnd)) return GetLastError(); break; case SW_ENABLEWINDOW: if (!EnableWindow(pbInput->hWnd, TRUE)) return GetLastError(); break; case SW_DISABLEWINDOW: if (!EnableWindow(pbInput->hWnd, FALSE)) return GetLastError(); break; case SW_ENDDIALOGOK: if (!EndDialog(pbInput->hWnd, IDOK)) return GetLastError(); break; case SW_ENDDIALOGCANCEL: if (!EndDialog(pbInput->hWnd, IDCANCEL)) return GetLastError(); break; case SW_ENDDIALOGCLOSE: if (!EndDialog(pbInput->hWnd, IDCLOSE)) return GetLastError(); break; case SW_ENDDIALOGABORT: if (!EndDialog(pbInput->hWnd, IDABORT)) return GetLastError(); break; default: if (!ShowWindow(pbInput->hWnd, pbInput->dwShow)) return GetLastError(); } return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITFindWindow( DWORD cbInput, FindWindowParams *pbInput, DWORD *pcbOutput, FindWindowResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(FindWindowResult); FindWindowResult *pOut= *ppbOutput= (FindWindowResult*)LocalAlloc(LPTR, *pcbOutput); pOut->hWnd= FindWindow(pbInput->szClassName[0]?pbInput->szClassName:NULL, pbInput->szWindowName[0]?pbInput->szWindowName:NULL); if (pOut->hWnd==NULL) return GetLastError(); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITSendMessage( DWORD cbInput, SendMessageParams *pbInput, DWORD *pcbOutput, SendMessageResult **ppbOutput, IRAPIStream *pStream) { // debug("ITSendMessage(%08lx %08lx %08lx %08lx %08lx %08lx, %d)\n", // pbInput->dwFlags, pbInput->dwResultAlloc, pbInput->hWnd, // pbInput->nMsg, pbInput->wParam, pbInput->lParam, // cbInput-PTR_DIFF(pbInput, pbInput->buf)); SendMessageResult *pOut = NULL; *pcbOutput= PTR_DIFF(pOut, pOut->buf+pbInput->dwResultAlloc); pOut= *ppbOutput= (SendMessageResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) return ERROR_NOT_ENOUGH_MEMORY; WPARAM wParam = pbInput->wParam; if (pbInput->dwFlags&SMGS_WPARAM_IS_INPUTOFS) wParam += (DWORD)pbInput->buf; else if (pbInput->dwFlags&SMGS_WPARAM_IS_OUTPUTOFS) wParam += (DWORD)pOut->buf; LPARAM lParam = pbInput->lParam; if (pbInput->dwFlags&SMGS_LPARAM_IS_INPUTOFS) lParam += (DWORD)pbInput->buf; else if (pbInput->dwFlags&SMGS_LPARAM_IS_OUTPUTOFS) lParam += (DWORD)pOut->buf; KernelMode _km; DWORD res= 0; if (pbInput->dwFlags&SMGS_POSTMESSAGE) { // debug("PostMessage(%08lx, %08lx, %08lx, %08lx) [%x]\n", // pbInput->hWnd, pbInput->nMsg, wParam, lParam, pbInput->dwFlags&15); if (!PostMessage(pbInput->hWnd, pbInput->nMsg, wParam, lParam)) res= GetLastError(); pOut->lResult= 0; } else { // debug("SendMessage(%08lx, %08lx, %08lx, %08lx) [%x]\n", // pbInput->hWnd, pbInput->nMsg, wParam, lParam, pbInput->dwFlags&15); pOut->lResult= SendMessage(pbInput->hWnd, pbInput->nMsg, wParam, lParam); } if (pbInput->dwFlags&SMGS_WAITWINDOW) { DWORD pid; GetWindowThreadProcessId(pbInput->hWnd, &pid); HANDLE hProc= OpenProcess(0,0, pid); if (WAIT_TIMEOUT==WaitForSingleObject(hProc, 20000)) return WAIT_TIMEOUT; CloseHandle(hProc); } return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetForegroundWindow( DWORD cbInput, BYTE *pbInput, DWORD *pcbOutput, GetForegroundWindowResult **ppbOutput, IRAPIStream *pStream) { GetForegroundWindowResult *pOut=NULL; *pcbOutput= sizeof(GetForegroundWindowResult); pOut= *ppbOutput= (GetForegroundWindowResult*)LocalAlloc(LPTR, *pcbOutput); pOut->hwnd= GetForegroundWindow(); return 0; } DWORD GetGwesVMbase() { static DWORD gwesbase= 0; if (gwesbase) return gwesbase; int gwesslot= FindProcessSlotForName(L"gwes.exe"); if (gwesslot==-1) return 0; gwesbase= getProcessSlotVMBase(gwesslot); return gwesbase; } DWORD ReadGwesDword(DWORD pdw) { return *(DWORD*)MapPtrWithBits(pdw, GetGwesVMbase()); } void CopyGwesString(WCHAR *str, DWORD pstr, int maxsize) { if (pstr==NULL) { str[0]= 0; return; } wcsncpy(str, (WCHAR*)MapPtrWithBits(pstr, GetGwesVMbase()), maxsize); } void ReadGwesData(void *dst, DWORD src, int size) { memcpy(dst, (void*)MapPtrWithBits(src, GetGwesVMbase()), size); } class WindowInfo { public: WindowInfo(DWORD hwnd, int level) { memset(&info, 0, sizeof(info)); info.hwnd= (HWND)hwnd; info.level= level; info.nextsibling= (HWND)ReadGwesDword(hwnd+4*0); info.parent= (HWND)ReadGwesDword(hwnd+4*1); info.firstchild= (HWND)ReadGwesDword(hwnd+4*2); // 0x03 magic 'WNDW' // 0x04 parentB // 0x05 1stchldB // 0x06 nextsibB // 0x07 ? ReadGwesData(&info.wrect, hwnd+4*8, sizeof(RECT)); ReadGwesData(&info.crect, hwnd+4*12, sizeof(RECT)); // 0x10 type pw1 ( 0x50 sized struct ) // 0x11 type pw1 ( 0x50 sized struct ) // 0x12 type pw1 ( 0x50 sized struct ) // 0x13 // 0x14 // 0x15 // 0x16 // 0x17 type (0x28 sized struct) // 0x18 // 0x19 type (0x68 sized struct) CopyGwesString(info.wtitle, ReadGwesDword(hwnd+0x1a*4), 32); if (info.wtitle[0]==0xffff || info.wtitle[1]==0xffff) { debug("%08lx title: %s\n", hwnd, hexdump((BYTE*)info.wtitle, 32, 2).c_str()); // todo: not sure what this means, wtitle contains { 0xffff, 0x10, 0 ... } // maybe it is a resource reference info.wtitle[0]= '?'; info.wtitle[1]= '?'; info.wtitle[2]= '?'; } info.wtitle[31]=0; info.msgq= ReadGwesDword(hwnd+4*0x1b); info.ime= ReadGwesDword(hwnd+4*0x1c); info.style= ReadGwesDword(hwnd+4*0x1d); info.exstyle= ReadGwesDword(hwnd+4*0x1e); DWORD hcls= ReadGwesDword(hwnd+0x1f*4); // 0x20 window id info.usrdata= ReadGwesDword(hwnd+4*0x21); info.pid= ReadGwesDword(hwnd+4*0x22); info.tid= ReadGwesDword(hwnd+4*0x23); info.pid2= ReadGwesDword(hwnd+4*0x24); info.wndproc= ReadGwesDword(hwnd+4*0x25); // 0x26 // 0x27 // 0x28 // 0x29 // 0x2a // 0x2b // 0x2c // 0x2d if (hcls) { CopyGwesString(info.wclass, ReadGwesDword(hcls+5*4), 32); info.wclass[31]=0; info.nlongs= ReadGwesDword(hcls)>>18; if (info.nlongs>8) { // truncating window longs to 8. info.nlongs= 8; } ReadGwesData(info.wlongs, hwnd+0x2e*4, info.nlongs*sizeof(DWORD)); } } ITSWindowInfo info; }; typedef std::vector WindowInfoList; DWORD FindWndRoot() { DWORD hWnd= (DWORD)GetForegroundWindow(); if (hWnd==NULL) return NULL; DWORD hParent; while (hParent=ReadGwesDword(hWnd+4)) hWnd= hParent; return hWnd; } bool GetWindowList(DWORD hwnd, WindowInfoList& list, int level) { if (hwnd==NULL) hwnd= FindWndRoot(); else hwnd= ReadGwesDword(hwnd+4*2); // first child while (hwnd) { list.push_back(WindowInfo(hwnd, level)); GetWindowList(hwnd, list, level+1); hwnd= ReadGwesDword(hwnd); } return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetWindowList( DWORD cbInput, BYTE *pbInput, DWORD *pcbOutput, GetWindowListResult **ppbOutput, IRAPIStream *pStream) { GetWindowListResult *pOut = *ppbOutput =NULL; *pcbOutput= 0; KernelMode _km; WindowInfoList list; if (!GetWindowList(NULL, list, 0)) { return ERROR_NOT_FOUND; } *pcbOutput= PTR_DIFF(pOut, pOut->info+list.size()); pOut= *ppbOutput= (GetWindowListResult*)LocalAlloc(LPTR, *pcbOutput); pOut->count= list.size(); memcpy(pOut->info, vectorptr(list), sizeof(WindowInfo)*list.size()); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITCallAddress( DWORD cbInput, CallAddressParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; *ppbOutput= NULL; typedef void (*calltarget_fn)(); calltarget_fn calltarget= (calltarget_fn)pbInput->dwAddress; KernelMode _km; // todo: if (pbInput->hProcess==INVALID_HANDLE_VALUE) -> call physical address // if (pbInput->hProcess==NULL) -> call virtual address // else call to address in process space calltarget(); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITRegistryFlush( DWORD cbInput, BYTE *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; *ppbOutput= NULL; LONG res; res= RegFlushKey(HKEY_CLASSES_ROOT); if (res) error("RegFlushKey(HKEY_CLASSES_ROOT)\n"); res= RegFlushKey(HKEY_CURRENT_USER); if (res) error("RegFlushKey(HKEY_CURRENT_USER)\n"); res= RegFlushKey(HKEY_LOCAL_MACHINE); if (res) error("RegFlushKey(HKEY_LOCAL_MACHINE)\n"); res= RegFlushKey(HKEY_USERS); if (res) error("RegFlushKey(HKEY_USERS)\n"); return 0; } typedef LPVOID (*FNCompressAlloc)(DWORD AllocSize); typedef VOID (*FNCompressFree)(LPVOID Address); typedef DWORD (*FNCompressOpen)( DWORD dwParam1, DWORD MaxOrigSize, FNCompressAlloc AllocFn, FNCompressFree FreeFn, DWORD dwUnknown); typedef DWORD (*FNCompressConvert)( DWORD ConvertStream, LPVOID CompAdr, DWORD CompSize, LPCVOID OrigAdr, DWORD OrigSize); typedef VOID (*FNCompressClose)( DWORD ConvertStream); LPVOID Compress_AllocFunc(DWORD AllocSize) { return LocalAlloc(LPTR, AllocSize); } VOID Compress_FreeFunc(LPVOID Address) { LocalFree(Address); } ITSUTILS_API HRESULT STDAPICALLTYPE ITS_XPRLZX_Compress( DWORD cbInput, CompressParams *pbInput, DWORD *pcbOutput, CompressResult **ppbOutput, IRAPIStream *pStream) { DWORD dwRes= 0; CompressResult *pOut= *ppbOutput= NULL; *pcbOutput= 0; HMODULE hDll= LoadLibrary(L"cecompr.dll"); if (hDll==NULL || hDll==INVALID_HANDLE_VALUE) { dwRes= 1; error("LoadLibrary"); return dwRes; } //debug("loaded cecompr.dll = %08lx\n", hDll); FNCompressOpen CompressOpen= NULL; FNCompressConvert CompressConvert= NULL; FNCompressClose CompressClose= NULL; switch(pbInput->dwType) { case ITSCOMP_XPR_DECODE: CompressOpen= (FNCompressOpen)GetProcAddress(hDll, L"XPR_DecompressOpen"); CompressConvert= (FNCompressConvert)GetProcAddress(hDll, L"XPR_DecompressDecode"); CompressClose= (FNCompressClose)GetProcAddress(hDll, L"XPR_DecompressClose"); break; case ITSCOMP_XPR_ENCODE: CompressOpen= (FNCompressOpen)GetProcAddress(hDll, L"XPR_CompressOpen"); CompressConvert= (FNCompressConvert)GetProcAddress(hDll, L"XPR_CompressEncode"); CompressClose= (FNCompressClose)GetProcAddress(hDll, L"XPR_CompressClose"); break; case ITSCOMP_LZX_DECODE: CompressOpen= (FNCompressOpen)GetProcAddress(hDll, L"LZX_DecompressOpen"); CompressConvert= (FNCompressConvert)GetProcAddress(hDll, L"LZX_DecompressDecode"); CompressClose= (FNCompressClose)GetProcAddress(hDll, L"LZX_DecompressClose"); break; case ITSCOMP_LZX_ENCODE: CompressOpen= (FNCompressOpen)GetProcAddress(hDll, L"LZX_CompressOpen"); CompressConvert= (FNCompressConvert)GetProcAddress(hDll, L"LZX_CompressEncode"); CompressClose= (FNCompressClose)GetProcAddress(hDll, L"LZX_CompressClose"); break; } if (CompressOpen==NULL || CompressConvert==NULL || CompressClose==NULL) { dwRes= 2; debug("error loading funcs %d %08lx %08lx %08lx\n", pbInput->dwType, CompressOpen, CompressConvert, CompressClose); FreeLibrary(hDll); return dwRes; } //debug("loaded funcs %08lx %08lx %08lx\n", CompressOpen, CompressConvert, CompressClose); DWORD stream= CompressOpen(0x10000, pbInput->dwMaxBlockSize, Compress_AllocFunc, Compress_FreeFunc, 0); if (stream==NULL || stream==0xFFFFFFFF) { error("CompressOpen(%d)", pbInput->dwMaxBlockSize); dwRes= 3; FreeLibrary(hDll); return dwRes; } //debug("stream: %08lx\n", stream); BYTE *buf= (BYTE*)LocalAlloc(LPTR, pbInput->dwMaxBlockSize); if (buf==NULL) { error("LocalAlloc(%d)", pbInput->dwMaxBlockSize); dwRes= 4; CompressClose(stream); FreeLibrary(hDll); return dwRes; } //debug("allocated %08lx bytes : %08lx\n", pbInput->dwMaxBlockSize, buf); DWORD res= CompressConvert(stream, buf, pbInput->outlength, pbInput->data, pbInput->insize); if (res==0 || res==0xffffffff) { dwRes= 5; error("CompressConvert(max=%d out=%d in=%d)", pbInput->dwMaxBlockSize, pbInput->outlength, pbInput->insize); LocalFree(buf); CompressClose(stream); FreeLibrary(hDll); return dwRes; } //debug("converted to %08lx\n", res); *pcbOutput= sizeof(CompressResult)+res; pOut= *ppbOutput= (CompressResult*)LocalAlloc(LPTR, *pcbOutput); memcpy(pOut->data, buf, res); pOut->outlength= res; LocalFree(buf); CompressClose(stream); FreeLibrary(hDll); return dwRes; } #include "smsfunc.h" ITSUTILS_API HRESULT STDAPICALLTYPE ITSendSms( DWORD cbInput, SendSmsParams *pbInput, DWORD *pcbOutput, SendSmsResult **ppbOutput, IRAPIStream *pStream) { smsfunc sms; if (!sms.load()) return GetLastError(); if (!sms.send(pbInput->msg, pbInput->number)) return GetLastError(); *pcbOutput= 0; *ppbOutput= NULL; return 0; } #include "rilfunc.h" ITSUTILS_API HRESULT STDAPICALLTYPE ITDialNumber( DWORD cbInput, DialNumberParams *pbInput, DWORD *pcbOutput, DialNumberResult **ppbOutput, IRAPIStream *pStream) { rilfunc ril; if (!ril.load()) return GetLastError(); if (!ril.dial(pbInput->number)) return GetLastError(); *pcbOutput= 0; *ppbOutput= NULL; return 0; }