#include #include #include // see // c:/Program Files/Windows Mobile 6 SDK/PocketPC/Include/Armv4i/devload.h #include #include "kernelmisc.h" #include "stringutils.h" #include "devicedriverloader.h" #include "RegistryFunctions.h" #define BINLOGBUFFERSIZE 0x100000 #define TIMESTAMP_INTERVAL 10000 // 2 ways of connecting to the old device: // - DONE: via normal dev interface // - DONE: loaded as dll // done: make attach unique id to each log entry, to make it easier to group them together in the log // done: register as 'naked' device, to make it easier to add it as any kind of device. // todo: added special ioctl, which saves/flushes all logs to disk // todo: add 'merged' log option. // todo: improve stream-logfile naming /* # rdo1 -> logdev # target=rdo2 # rdo2 -> radio installdev: ../build/logdev.dll pput -f ../build/logdev.dll "%CSIDL_WINDOWS%" pregutl -c HKLM\\Drivers\\BuiltIn\\Thunkdev pregutl -s HKLM\\Drivers\\BuiltIn\\Thunkdev :Dll=sz:radio.dll :Index=dword:00000002 :Order=dword:00000002 :Prefix=sz:RDO :Priority256=dword:00000093 pregutl -s HKLM\\Drivers\\BuiltIn\\QRADIO :Dll=sz:logdev.dll :target=sz:RDO2: [HKLM\drivers\active\15] BusName="BuiltInPhase1_0_1_0" BusParent=dword:000323d0 Hnd=dword:0003d6c0 InterfaceType=dword:00000000 Key="Drivers\BuiltIn\Thunkdev" Name="RDO2:" [HKLM\Drivers\BuiltIn\Thunkdev] Dll="radio.dll" Index=dword:00000002 Order=dword:00000002 Prefix="RDO" Priority256=dword:00000093 */ // performance: // // (verbose=4, target=drivers\builtin\thunkdev) // c3800000 01800000 01800000 c3805000 00000008 virser_data.dll // 6f1b2d32 01802cf0 95 95 8c095880 8c095880 08a4fe20 0.0 8.2 afa17df2: device.exe 20 // c3880000 01880000 01880000 c3891000 00000008 radio.dll // 8f937fca 01887e2c 5f 5f 8c095880 8c095880 083dfe1c 0.0 5.4 afa17df2: device.exe 20 // ef910a4e 01887fac 67 67 8c095880 8c095880 0840fdf0 0.0 1.0 afa17df2: device.exe 20 // c3940000 01940000 01940000 c394e000 00000008 wavedev.dll // af826882 01947d2c 63 63 8c095880 8c095880 0859fe1c 0.0 5.5 afa17df2: device.exe 20 // no logging device: // c3800000 01800000 01800000 c3805000 00000008 virser_data.dll // 2f02efa2 01802cf0 95 95 8c095880 8c095880 08a8fe20 0.0 0.6 efa16df2: device.exe 20 // c3880000 01880000 01880000 c3891000 00000008 radio.dll // 0f946fca 01887e2c 5f 5f 8c095880 8c095880 083bfe1c 0.0 2.8 efa16df2: device.exe 20 // 0f926e62 01887fac 67 67 8c095880 8c095880 0840fdf0 0.0 0.8 efa16df2: device.exe 20 // c3940000 01940000 01940000 c394e000 00000008 wavedev.dll // 0f8399f6 01947d2c 63 63 8c095880 8c095880 0859fe1c 0.0 5.5 efa16df2: device.exe 20 // (verbose=4, target=RDO2) // c3800000 01800000 01800000 c3805000 00000008 virser_data.dll // 8f3d72ae 01802cf0 95 95 8c095880 8c095880 08a3fe20 0.0 8.4 afa1adf2: device.exe 20 // c3880000 01880000 01880000 c3891000 00000008 radio.dll // 8f9618ba 01887e2c 5f 5f 8c095880 8c095880 0835fe1c 0.0 5.2 afa1adf2: device.exe 20 // 6f92ae62 01887fac 67 67 8c095880 8c095880 0840fdf0 0.0 1.0 afa1adf2: device.exe 20 // c3940000 01940000 01940000 c394e000 00000008 wavedev.dll // cf83dab2 01947d2c 63 63 8c096188 8c096188 0859fe44 0.0 6.0 afa1adf2: device.exe 20 // (verbose=0x14, target=drivers\builtin\thunkdev) // c3800000 01800000 01800000 c3805000 00000008 virser_data.dll // 6e4a3f8a 01802cf0 95 95 8c095880 8c095880 0921fe20 0.0 2.5 afa1adf2: device.exe 20 // c3880000 01880000 01880000 c3891000 00000008 radio.dll // cf93bd3a 01887e2c 5f 5f 8c095880 8c095880 083cfe1c 0.0 5.3 afa1adf2: device.exe 20 // 4f914936 01887fac 67 67 8c095880 8c095880 0840fdf0 0.0 0.8 afa1adf2: device.exe 20 // c3940000 01940000 01940000 c394e000 00000008 wavedev.dll // cf728576 01947d2c 63 63 8c095880 8c095880 086afe1c 0.0 5.8 afa1adf2: device.exe 20 // (verbose=0x14, target=drivers\builtin\thunkdev) // c3800000 01800000 01800000 c3805000 00000008 virser_data.dll // ceba1152 01802cf0 95 95 8c095880 8c095880 091efe20 0.0 0.8 afa18df2: device.exe 20 // c3880000 01880000 01880000 c3891000 00000008 radio.dll // ef933f22 01887e2c 5f 5f 8c095880 8c095880 083cfe1c 0.0 3.0 afa18df2: device.exe 20 // 2f912936 01887fac 67 67 8c095880 8c095880 0840fdf0 0.0 0.8 afa18df2: device.exe 20 // c3940000 01940000 01940000 c394e000 00000008 wavedev.dll // 0f7255ba 01947d2c 63 63 8c095880 8c095880 086afe1c 0.0 5.6 afa18df2: device.exe 20 // // some notes: // Read's are usually from a reader-thread in virser_atcmd.dll or virser_data.dll // Write's are directly from threads in spcore or rilgsm // //------------------------------------------------------------------- #define EXPORT __declspec(dllexport) extern "C" { EXPORT DWORD Init( DWORD dwRegContext); EXPORT BOOL Close( DWORD dwHandle); EXPORT BOOL Deinit( DWORD dwDrvContext); EXPORT DWORD Open( DWORD dwdrvcontext, DWORD dwAccess, DWORD dwShareMode); EXPORT BOOL IOControl( DWORD dwHandle, DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned); EXPORT DWORD Read(DWORD dwHandle, LPVOID pBuffer, DWORD dwNumBytes); EXPORT DWORD Write(DWORD dwHandle, LPCVOID pBuffer, DWORD dwNumBytes); EXPORT DWORD Seek(DWORD dwHandle, long lDistance, DWORD dwMoveMethod); EXPORT void PowerUp(DWORD dwDrvContext); EXPORT void PowerDown(DWORD dwDrvContext); } //------------------------------------------------------------------- #define VERBOSE_IOCONTROL 1 #define VERBOSE_READWRITE 2 #define VERBOSE_BINARY 4 #define VERBOSE_FLUSHOFTEN 8 // buffers are flushed to disk either every write, or every 64 writes #define VERBOSE_MEMBUFFER 0x10 #define VERBOSE_THREADINFO 0x20 // 1 : log iocontrol // 2 : log read/write // 4 : log binary // 8 : flush every write //10 : log to memorybuffer //20 : log thread info static DWORD verbose; #if 0 HANDLE hLog; int nlogs; void openlog() { if (hLog!=NULL && hLog!=INVALID_HANDLE_VALUE) return; hLog= CreateFile(_T("\\logdev.log"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); if (hLog==INVALID_HANDLE_VALUE) { hLog= NULL; OutputDebugString(_T("error opening logdev.log\n")); } } void closelog() { CloseHandle(hLog); hLog=NULL; } void writelog(char *data, int size) { DWORD nWritten; WriteFile(hLog, data, size, &nWritten, 0); if ( ((verbose&VERBOSE_FLUSHOFTEN)!=0) || (((++nlogs)&0x3f)==0) ) FlushFileBuffers(hLog); } void log(char *msg, ...) { va_list ap; char buf[1024]; va_start(ap, msg); int n= _vsnprintf(buf, 1024, msg, ap); buf[1024]=0; va_end(ap); writelog(buf, n); } #endif #define log printf int hexchar(BYTE c) { return '0'+c+(c>9?7:0); } int hexdata(char *line, BYTE *buf, int size) { for (int i=0 ; i<16 ; i++) { line[i*3]=' '; if (i>4); line[i*3+2]=hexchar(buf[i]&0xf); } else { line[i*3+1]=' '; line[i*3+2]=' '; } } line[48]=0; return 48; } int ascdata(char *line, BYTE *buf, int size) { for (int i=0 ; i<16 ; i++) { if (i0x7e)) ? '.' : buf[i]; else line[i]=' '; } line[16]=0; return 16; } void hexdump(DWORD t, char *tag, BYTE *buf, int size) { char line[128]; for (int ofs=0 ; ofs ThreadMap; //ThreadMap threadmap; typedef std::set ThreadSet; ThreadSet threadset; HDATA *cvHandle2HDataPtr(HANDLE h) { return (HDATA *)(KData.handleBase+((DWORD)h&HANDLE_ADDRESS_MASK)); } std::string dumpprocinfo(PROCESS*p) { return stringformat("proc{%08lx '%ls' %ls}", p->hProc, p->lpszProcName, p->pcmdline); } std::string dumpcallstack(CALLSTACK *p) { return stringformat("cs{ret=%08lx sp=%08lx %s}", p->retAddr, p->dwPrevSP, dumpprocinfo(p->pprcLast).c_str()); } void dumpthreadinfo(DWORD tid) { if ((verbose&VERBOSE_THREADINFO)==0) return; if (threadset.find(tid)!=threadset.end()) return; threadset.insert(tid); HDATA *pHandle= cvHandle2HDataPtr((HANDLE)tid); THREAD *thrd= (THREAD*)pHandle->pvObj; log("LD-threadinfo %08lx->%08lx, cur=%s owner=%s\n", tid, thrd, dumpprocinfo(thrd->pProc).c_str(), dumpprocinfo(thrd->pOwnerProc).c_str()); log("LD-thread-callstack: "); for (struct CALLSTACK *ps = thrd->pcstkTop ; ps ; ps= ps->pcstkNext) log("LD-%s\n", dumpcallstack(ps).c_str()); } //------------------------------------------------------------------- BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { KernelMode _km; if (ul_reason_for_call==DLL_PROCESS_ATTACH) { #if 0 openlog(); #endif log("LD-%08lx: dllmain hm=%08lx ul=%08lx lp=%08lx\n", GetCurrentThreadId(), hModule, ul_reason_for_call, lpReserved); } else if (ul_reason_for_call==DLL_PROCESS_DETACH) { #if 0 closelog(); #endif } dumpthreadinfo(GetCurrentThreadId()); return TRUE; } //------------------------------------------------------------------- #define MYMAGIC 0x98761234 #define FILEDEVICE ((devicedriverloader*)1) #define MAX_HANDLES 256 struct handle_info { DWORD dwMagic; devicedriverloader *drv; union { HANDLE hTarget; DWORD dwTarget; }; DWORD idx; HANDLE hLog; CRITICAL_SECTION lock; BYTE *buffer; BYTE *bufptr; BYTE *bufend; DWORD tLastTimestamp; }; struct handle_info *handles[MAX_HANDLES]; BOOL CheckHandle(const char *fn,struct handle_info *hi) { if (hi->dwMagic!=MYMAGIC || handles[hi->idx]!=hi) { log("LD-%08lx %s: ERROR %08lx not a valid handle: magic=%08lx, idx=%d list:%08lx\n", GetCurrentThreadId(), fn, hi, hi->dwMagic, hi->idx, (hi->idxidx]:0); SetLastError(ERROR_INVALID_HANDLE); return FALSE; } return TRUE; } void openbinlog(struct handle_info *hi) { InitializeCriticalSection(&(hi->lock)); EnterCriticalSection(&(hi->lock)); hi->hLog= CreateFile(ToWString(stringformat("\\log-%08lx.log", hi->hTarget)).c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); if (hi->hLog==INVALID_HANDLE_VALUE) { hi->hLog= NULL; LeaveCriticalSection(&(hi->lock)); return; } if (verbose&VERBOSE_MEMBUFFER) { hi->buffer= (BYTE*)LocalAlloc(LMEM_FIXED, BINLOGBUFFERSIZE); hi->bufptr= hi->buffer; if (hi->buffer) { hi->bufend= hi->buffer+ BINLOGBUFFERSIZE; } else { hi->bufend= NULL; } } LeaveCriticalSection(&(hi->lock)); } void closebinlog(struct handle_info *hi) { EnterCriticalSection(&(hi->lock)); if ((verbose&VERBOSE_MEMBUFFER)!=0 && hi->buffer) { DWORD n; WriteFile(hi->hLog, hi->buffer, hi->bufptr-hi->buffer, &n, 0); hi->bufptr= hi->buffer; } if (hi->hLog!=NULL && hi->hLog!=INVALID_HANDLE_VALUE) CloseHandle(hi->hLog); hi->hLog= NULL; LeaveCriticalSection(&(hi->lock)); DeleteCriticalSection(&(hi->lock)); } void flushbinlog(struct handle_info *hi) { EnterCriticalSection(&(hi->lock)); if ((verbose&VERBOSE_MEMBUFFER)!=0 && hi->buffer) { DWORD n; WriteFile(hi->hLog, hi->buffer, hi->bufptr-hi->buffer, &n, 0); hi->bufptr= hi->buffer; } FlushFileBuffers(hi->hLog); LeaveCriticalSection(&(hi->lock)); } #define LOGTYPE_WRITE 0 #define LOGTYPE_READ 1 #define LOGTYPE_STAMP 2 void binarylog(struct handle_info *hi, DWORD tick, DWORD type, BYTE *data, DWORD size); void logtimestamp(struct handle_info *hi) { SYSTEMTIME st; DWORD t= GetTickCount(); if (t-hi->tLastTimestamp < TIMESTAMP_INTERVAL) return; GetSystemTime(&st); binarylog(hi, t, LOGTYPE_STAMP, (BYTE*)&st, sizeof(st)); hi->tLastTimestamp= t; } void binarylog(struct handle_info *hi, DWORD tick, DWORD type, BYTE *data, DWORD size) { DWORD n; if (hi->hLog==NULL) return; EnterCriticalSection(&(hi->lock)); if ((verbose&VERBOSE_MEMBUFFER)!=0 && hi->buffer) { if (hi->bufptr+12+sizebufend) { memcpy(hi->bufptr, &tick, sizeof(DWORD)); hi->bufptr+=sizeof(DWORD); memcpy(hi->bufptr, &type, sizeof(DWORD)); hi->bufptr+=sizeof(DWORD); memcpy(hi->bufptr, &size, sizeof(DWORD)); hi->bufptr+=sizeof(DWORD); memcpy(hi->bufptr, data, size); hi->bufptr+=size; } // todo: log note that we stopped logging due to buffer full } else { WriteFile(hi->hLog, (BYTE*)&tick, sizeof(DWORD), &n, 0); WriteFile(hi->hLog, (BYTE*)&type, sizeof(DWORD), &n, 0); WriteFile(hi->hLog, (BYTE*)&size, sizeof(DWORD), &n, 0); WriteFile(hi->hLog, data, size, &n, 0); } LeaveCriticalSection(&(hi->lock)); if (type!=LOGTYPE_STAMP) logtimestamp(hi); } bool isFileDevice(devicedriverloader*d) { return (DWORD(d)&1)==1; } TCHAR *getFileDevice(devicedriverloader*d) { return (TCHAR*)(DWORD(d)&~1); } //------------------------------------------------------------------- DWORD Init( DWORD dwRegContext) { KernelMode _km; // todo: change this to: // HKEY hDevkey= OpenDeviceKey(dwRegContext); // ReadRegistryString(hDevkey, NULL, _T("target"), targetdev, MAX_PATH) // targetdev is either a devicename ( like 'RDO2:' ) // or a devicekey ( like 'Drivers\BuiltIn\QRADIO' ) TCHAR targetdev[MAX_PATH]; TCHAR devkey[MAX_PATH]; if (!ReadRegistryString(HKEY_LOCAL_MACHINE, (LPTSTR)dwRegContext, _T("Key"), devkey, MAX_PATH)) { log("LD-%08lx Init: ERROR getting target device key from %ls\n", GetCurrentThreadId(), dwRegContext); return NULL; } if (!ReadRegistryString(HKEY_LOCAL_MACHINE, devkey, _T("target"), targetdev, MAX_PATH)) { log("LD-%08lx Init: ERROR getting target device name\n", GetCurrentThreadId()); return NULL; } if (!ReadRegistryDword(HKEY_LOCAL_MACHINE, devkey, _T("verbose"), &verbose)) verbose=0; if (_tcschr(targetdev, '\\')==NULL && targetdev[_tcslen(targetdev)-1]==':') { // is devicename ->handled by Open log("LD-%08lx %08lx: Init(%ls): file dev=%ls\n", GetCurrentThreadId(), GetTickCount(), dwRegContext, targetdev); dumpthreadinfo(GetCurrentThreadId()); TCHAR *tname= _tcsdup(targetdev); return ((DWORD)tname)|1; } else { log("LD-%08lx %08lx: Init(%ls): thnk dev=%ls\n", GetCurrentThreadId(), GetTickCount(), dwRegContext, targetdev); devicedriverloader *drv= new devicedriverloader(); if (!drv->load((const TCHAR*)dwRegContext)) { delete drv; drv= NULL; } return (DWORD)drv; } } BOOL Close( DWORD Handle) { KernelMode _km; struct handle_info *hi= (struct handle_info *)Handle; if (!CheckHandle("Close", hi)) return FALSE; DWORD t0, t1; DWORD stat=ERROR_INVALID_HANDLE; BOOL rc=FALSE; if (hi->hTarget!=NULL && hi->hTarget!=INVALID_HANDLE_VALUE) { SetLastError(0); t0= GetTickCount(); if (!isFileDevice(hi->drv)) rc= hi->drv->DrvClose(hi->dwTarget); else rc= CloseHandle(hi->hTarget); stat=GetLastError(); t1= GetTickCount(); log("LD%08lx-%08lx t:%08lx-%08lx Close(%08lx:%08lx) -> %08lx (stat=%08lx)\n", hi->drv, GetCurrentThreadId(), t0, t1, hi, hi->hTarget, rc, stat); } else { log("LD%08lx-%08lx Close: ERROR handle not open: %08lx:%08lx\n", hi->drv, GetCurrentThreadId(), hi, hi->hTarget); } if (verbose&VERBOSE_BINARY) closebinlog(hi); handles[hi->idx]=NULL; LocalFree(hi); SetLastError(stat); return rc; } BOOL Deinit( DWORD dwDrvContext) { KernelMode _km; for(int i=0 ; idrv= drv; hi->idx= i; hi->dwMagic= MYMAGIC; hi->tLastTimestamp=0; SetLastError(0); DWORD t0= GetTickCount(); if (!isFileDevice(drv)) hi->dwTarget= drv->open(dwAccess, dwShareMode); else hi->hTarget= CreateFile(getFileDevice(drv), dwAccess, dwShareMode, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); DWORD stat= GetLastError(); DWORD t1= GetTickCount(); if (verbose&VERBOSE_BINARY) openbinlog(hi); log("LD%08lx-%08lx t:%08lx-%08lx Open(%ls, %08lx,%08lx) -> %08lx:%08lx (stat=%08lx)\n", drv, GetCurrentThreadId(), t0, t1, getFileDevice(drv), dwAccess, dwShareMode, hi, hi->hTarget, stat); if (hi->hTarget==INVALID_HANDLE_VALUE) { Close((DWORD)hi); hi=NULL; } dumpthreadinfo(GetCurrentThreadId()); SetLastError(stat); return (DWORD)hi; } BOOL IOControl( DWORD Handle, DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned) { KernelMode _km; struct handle_info *hi= (struct handle_info *)Handle; if (!CheckHandle("IOControl", hi)) return FALSE; if (dwIoControlCode==0x47534d4b) { if (verbose&VERBOSE_BINARY) flushbinlog(hi); return TRUE; } BYTE *origInBuf= (BYTE*)LocalAlloc(LMEM_FIXED, nInBufSize); memcpy(origInBuf, pInBuf, nInBufSize); SetLastError(0); DWORD t0= GetTickCount(); BOOL rc; if (!isFileDevice(hi->drv)) rc = hi->drv->DrvIOControl(hi->dwTarget, dwIoControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned); else rc= DeviceIoControl(hi->hTarget, dwIoControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned, NULL); DWORD stat=GetLastError(); DWORD t1= GetTickCount(); if (verbose&VERBOSE_IOCONTROL) { log("LD%08lx-%08lx t:%08lx-%08lx devio(%08lx:%08lx, %08lx, %08lx, %08lx, %08lx, %08lx, %08lx:%d) -> %08lx ( stat=%08lx )\n", hi->drv, GetCurrentThreadId(), t0, t1, hi,hi->hTarget, dwIoControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned, pBytesReturned?*pBytesReturned:0, rc, stat); hexdump(t0, "in0", origInBuf, nInBufSize); if (memcmp(origInBuf, pInBuf, nInBufSize)) hexdump(t0, "in1", pInBuf, nInBufSize); hexdump(t0, "out", pOutBuf, nOutBufSize); dumpthreadinfo(GetCurrentThreadId()); } LocalFree(origInBuf); SetLastError(stat); return rc; } DWORD Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes) { KernelMode _km; struct handle_info *hi= (struct handle_info *)Handle; if (!CheckHandle("Read", hi)) return 0xFFFFFFFF; DWORD nRead=0; SetLastError(0); DWORD t0= GetTickCount(); BOOL rc; if (!isFileDevice(hi->drv)) { nRead= hi->drv->DrvRead(hi->dwTarget, pBuffer, dwNumBytes); rc= (nRead!=0xFFFFFFFF); } else rc= ReadFile(hi->hTarget, pBuffer, dwNumBytes, &nRead, NULL); DWORD stat=GetLastError(); DWORD t1= GetTickCount(); if ((verbose&VERBOSE_READWRITE)==0) { // don't log } else if (nRead==0 && rc) { // don't log } else if (rc && nRead) { log("LD%08lx-%08lx t:%08lx-%08lx: Read(%08lx:%08lx, %08lx, %08lx) -> %08lx, n=%08lx, stat=%08lx\n", hi->drv, GetCurrentThreadId(), t0, t1, hi, hi->hTarget, pBuffer, dwNumBytes, rc, nRead, stat); hexdump(t0, "Read", (BYTE*)pBuffer, nRead); dumpthreadinfo(GetCurrentThreadId()); } else if (!rc) { log("LD%08lx-%08lx t:%08lx-%08lx: Read(%08lx:%08lx, %08lx, %08lx) -> %08lx, n=%08lx, stat=%08lx\n", hi->drv, GetCurrentThreadId(), t0, t1, hi, hi->hTarget, pBuffer, dwNumBytes, rc, nRead, stat); dumpthreadinfo(GetCurrentThreadId()); } if ((verbose&VERBOSE_BINARY)!=0 && nRead) binarylog(hi, t0, LOGTYPE_READ, (BYTE*)pBuffer, nRead); SetLastError(stat); if (rc) return nRead; else return 0xFFFFFFFF; } DWORD Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes) { KernelMode _km; struct handle_info *hi= (struct handle_info *)Handle; if (!CheckHandle("Write", hi)) return 0xFFFFFFFF; DWORD nWritten=0; SetLastError(0); DWORD t0= GetTickCount(); BOOL rc; if (!isFileDevice(hi->drv)) { nWritten= hi->drv->DrvWrite(hi->dwTarget, pBuffer, dwNumBytes); rc= (nWritten!=0xFFFFFFFF); } else rc= WriteFile(hi->hTarget, pBuffer, dwNumBytes, &nWritten, NULL); DWORD stat=GetLastError(); DWORD t1= GetTickCount(); if ((verbose&VERBOSE_READWRITE)==0) { // don't log } else { log("LD%08lx-%08lx %08lx-%08lx: Writ(%08lx:%08lx, %08lx, %08lx) -> %08lx, n=%08lx, stat=%08lx\n", hi->drv, GetCurrentThreadId(), t0, t1, hi, hi->hTarget, pBuffer, dwNumBytes, rc, nWritten, stat); if (rc && nWritten) hexdump(t0, "Writ", (BYTE*)pBuffer, dwNumBytes); dumpthreadinfo(GetCurrentThreadId()); } if (verbose&VERBOSE_BINARY) binarylog(hi, t0, LOGTYPE_WRITE, (BYTE*)pBuffer, dwNumBytes); SetLastError(stat); if (rc) return nWritten; else return 0xFFFFFFFF; } DWORD Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod) { KernelMode _km; struct handle_info *hi= (struct handle_info *)Handle; if (!CheckHandle("IOControl", hi)) return 0xFFFFFFFF; SetLastError(0); DWORD t0= GetTickCount(); DWORD rc; if (!isFileDevice(hi->drv)) rc= hi->drv->DrvSeek(hi->dwTarget, lDistance, dwMoveMethod); else rc= SetFilePointer(hi->hTarget, lDistance, 0, dwMoveMethod); DWORD stat=GetLastError(); DWORD t1= GetTickCount(); log("LD%08lx-%08lx t:%08lx-%08lx: Seek(%08lx:%08lx, %08lx, %08lx) -> %08lx, stat=%08lx\n", hi->drv, GetCurrentThreadId(), t0, t1, hi, hi->hTarget, lDistance, dwMoveMethod, rc, stat); SetLastError(stat); return rc; } void PowerUp(DWORD dwDrvContext) { KernelMode _km; log("LD%08lx-%08lx %08lx: powerup\n", dwDrvContext, GetCurrentThreadId(), GetTickCount()); devicedriverloader *drv= (devicedriverloader *)dwDrvContext; if (drv) drv->DrvPowerUp(drv->_dwDriver); } void PowerDown(DWORD dwDrvContext) { KernelMode _km; log("LD%08lx-%08lx %08lx: powerdown\n", dwDrvContext, GetCurrentThreadId(), GetTickCount()); devicedriverloader *drv= (devicedriverloader *)dwDrvContext; if (drv) drv->DrvPowerDown(drv->_dwDriver); }