//////////////////////////////////////////////////////////////////// // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine // All rights reserved // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// #ifndef UDF_FORMAT_MEDIA ULONG LockMode = 0; BOOLEAN opt_invalidate_volume = FALSE; #endif //UDF_FORMAT_MEDIA #ifndef CDRW_W32 #ifndef UDF_FORMAT_MEDIA BOOLEAN open_as_device = FALSE; #endif //UDF_FORMAT_MEDIA #ifdef USE_SKIN_MODEL PSKIN_API SkinAPI = NULL; PSKIN_API SkinLoad( PWCHAR path, HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance int nCmdShow // show state ) { HMODULE hm; PSKIN_API Skin; PSKIN_API (__stdcall *SkinInit) (VOID); hm = LoadLibraryW(path); if(!hm) return NULL; SkinInit = (PSKIN_API(__stdcall *)(void))GetProcAddress(hm, "SkinInit"); if(!SkinInit) return NULL; Skin = SkinInit(); if(!Skin) return NULL; Skin->Init(hInstance, hPrevInstance, nCmdShow); return Skin; } #endif //USE_SKIN_MODEL #ifdef _BROWSE_UDF_ #ifndef LIBUDF extern PVCB Vcb; #endif // LIBUDF #endif //_BROWSE_UDF_ #ifdef LIBUDF #define _lphUdf ((PUDF_VOL_HANDLE_I)(DeviceObject->lpContext)) #endif //LIBUDF #ifdef LIBUDFFMT #define _lphUdf (DeviceObject->cbio) #endif //LIBUDFFMT #ifndef CDRW_W32 NTSTATUS UDFPhSendIOCTL( IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer , IN ULONG InputBufferLength, OUT PVOID OutputBuffer , IN ULONG OutputBufferLength, IN BOOLEAN OverrideVerify, OUT PVOID Iosb OPTIONAL ) { ULONG real_read; #if !defined(LIBUDF) && !defined(LIBUDFFMT) ULONG ret; ULONG RC = DeviceIoControl(DeviceObject->h,IoControlCode, InputBuffer,InputBufferLength, OutputBuffer,OutputBufferLength, &real_read,NULL); if (!RC) { ret = GetLastError(); } return RC ? 1 : -1; #else // LIBUDF ULONG RC = _lphUdf->lpIOCtlFunc(_lphUdf->lpParameter,IoControlCode, InputBuffer,InputBufferLength, OutputBuffer,OutputBufferLength, &real_read); return RC; #endif // LIBUDF } // end UDFPhSendIOCTL() NTSTATUS UDFPhReadSynchronous( PDEVICE_OBJECT DeviceObject, // the physical device object PVOID Buffer, ULONG Length, LONGLONG Offset, PULONG ReadBytes, ULONG Flags ) { #if !defined(LIBUDF) && !defined(LIBUDFFMT) NTSTATUS RC; // UDFPrint(("UDFPhRead: Length: %x Lba: %lx\n",Length>>0xb,Offset>>0xb)); LONG HiOffs = (ULONG)(Offset >> 32); RC = SetFilePointer(DeviceObject->h,(ULONG)Offset,&HiOffs,FILE_BEGIN); if(RC == INVALID_SET_FILE_POINTER) { if(GetLastError() != NO_ERROR) { UDFPrint(("UDFPhReadSynchronous: error %x\n", GetLastError())); return STATUS_END_OF_FILE; } } RC = ReadFile(DeviceObject->h,Buffer,Length,ReadBytes,NULL); if(NT_SUCCESS(RC) && (!(*ReadBytes))) { RC = GetLastError(); return STATUS_END_OF_FILE; } return STATUS_SUCCESS; #else // LIBUDF return _lphUdf->lpReadFunc(_lphUdf->lpParameter, Buffer, Length, Offset, ReadBytes); #endif //defined LIBUDF || defined LIBUDFFMT } // end UDFPhReadSynchronous() NTSTATUS UDFPhWriteSynchronous( PDEVICE_OBJECT DeviceObject, // the physical device object PVOID Buffer, ULONG Length, LONGLONG Offset, PULONG WrittenBytes, ULONG Flags ) { #if !defined(LIBUDF) && !defined(LIBUDFFMT) NTSTATUS RC = STATUS_SUCCESS; LONG HiOffs = (ULONG)(Offset >> 32); PVOID Buffer2 = NULL; PVOID Buffer3 = NULL; RC = SetFilePointer(DeviceObject->h,(ULONG)Offset,&HiOffs,FILE_BEGIN); if(RC == INVALID_SET_FILE_POINTER) { if(GetLastError() != NO_ERROR) { UDFPrint(("UDFPhWriteSynchronous: error %x\n", GetLastError())); return STATUS_END_OF_FILE; } } Buffer2 = ExAllocatePool(NonPagedPool, Length+0x10000); Buffer3 = (PVOID)( ((ULONG)Buffer2 + 0xffff) & ~0xffff); RtlCopyMemory(Buffer3, Buffer, Length); RC = WriteFile(DeviceObject->h,Buffer3,Length,WrittenBytes,NULL); if(!RC || !(*WrittenBytes)) { RC = GetLastError(); UDFPrint(("UDFPhWriteSynchronous: EOF, error %x\n", RC)); RC = STATUS_END_OF_FILE; } else { RC = STATUS_SUCCESS; } if(Buffer2) ExFreePool(Buffer2); return RC; #else // LIBUDF return _lphUdf->lpWriteFunc(_lphUdf->lpParameter, Buffer, Length, Offset, WrittenBytes); #endif // LIBUDF } // end UDFPhWriteSynchronous() #if 0 NTSTATUS UDFPhWriteVerifySynchronous( PDEVICE_OBJECT DeviceObject, // the physical device object PVOID Buffer, ULONG Length, LONGLONG Offset, PULONG WrittenBytes, ULONG Flags ) { NTSTATUS RC; PUCHAR v_buff = NULL; ULONG ReadBytes; RC = UDFPhWriteSynchronous(DeviceObject, Buffer, Length, Offset, WrittenBytes, 0); if(!Verify) return RC; v_buff = (PUCHAR)DbgAllocatePool(NonPagedPool, Length); if(!v_buff) return RC; RC = UDFPhSendIOCTL( IOCTL_CDRW_SYNC_CACHE, DeviceObject, NULL,0, NULL,0, FALSE, NULL); RC = UDFPhReadSynchronous(DeviceObject, v_buff, Length, Offset, &ReadBytes, 0); if(!NT_SUCCESS(RC)) { BrutePoint(); DbgFreePool(v_buff); return RC; } if(RtlCompareMemory(v_buff, Buffer, ReadBytes) == Length) { DbgFreePool(v_buff); return RC; } BrutePoint(); DbgFreePool(v_buff); return STATUS_LOST_WRITEBEHIND_DATA; } // end UDFPhWriteVerifySynchronous() #endif VOID set_image_size( HANDLE h, // ULONG LBA) int64 len) { LONG offh = (ULONG)(len >> 32); //( (LONGLONG)LBA >> (32-Vcb->BlockSizeBits) ); SetFilePointer((HANDLE)h, (ULONG)(len /*(LBA << Vcb->BlockSizeBits)*/ ), &offh, FILE_BEGIN); SetEndOfFile(h); offh = 0; SetFilePointer((HANDLE)h, 0, &offh, FILE_BEGIN); } // end set_image_size() int64 get_file_size( HANDLE h ) { LONG hsz = 0; LONG lsz; lsz = SetFilePointer(h, 0, &hsz, FILE_END); return (((int64)hsz) << 32) | lsz; } // end get_file_size() int64 set_file_pointer( HANDLE h, int64 sz ) { ULONG hsz = (ULONG)(sz >> 32); ULONG lsz = (ULONG)sz; lsz = SetFilePointer(h, lsz, (PLONG)&hsz, FILE_BEGIN); return (((int64)hsz) << 32) | lsz; } // end set_file_pointer() #endif //CDRW_W32 #ifndef LIBUDF #ifndef UDF_FORMAT_MEDIA ULONG write( PVCB Vcb, HANDLE h, PCHAR buff, ULONG len) { ULONG written; LONG offh = 0; ULONG offl = SetFilePointer((HANDLE)h, 0, &offh, FILE_CURRENT); // ULONG Lba = (ULONG)((((LONGLONG)offh << 32) + offl) >> Vcb->BlockSizeBits); UDFWriteData(Vcb, FALSE, (((LONGLONG)offh)<<32)+offl, len, FALSE, buff, &written); SetFilePointer((HANDLE)h, offl, &offh, FILE_BEGIN); offh = 0; SetFilePointer((HANDLE)h, written, &offh, FILE_CURRENT); return written; } // end write() #endif //UDF_FORMAT_MEDIA #endif // LIBUDF #endif //CDRW_W32 #ifdef NT_NATIVE_MODE BOOL Privilege( LPTSTR pszPrivilege, BOOL bEnable ) { #ifndef NT_NATIVE_MODE HANDLE hToken; TOKEN_PRIVILEGES tp; // obtain the token, first check the thread and then the process if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE, &hToken)) { if (GetLastError() == ERROR_NO_TOKEN) { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return FALSE; } } else { return FALSE; } } // get the luid for the privilege if (!LookupPrivilegeValue(NULL, pszPrivilege, &tp.Privileges[0].Luid)) { CloseHandle(hToken); return FALSE; } tp.PrivilegeCount = 1; if (bEnable) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // enable or disable the privilege if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0)) { CloseHandle(hToken); return FALSE; } if (!CloseHandle(hToken)) return FALSE; #endif //NT_NATIVE_MODE return TRUE; } // end Privilege() #endif //NT_NATIVE_MODE #ifndef LIBUDF extern "C" ULONG MyLockVolume( HANDLE h, ULONG* pLockMode // OUT ) { ULONG RC; ULONG returned; (*pLockMode) = -1; #ifndef CDRW_W32 RC = DeviceIoControl(h,IOCTL_UDF_LOCK_VOLUME_BY_PID,NULL,0,NULL,0,&returned,NULL); if(RC) { (*pLockMode) = IOCTL_UDF_LOCK_VOLUME_BY_PID; return STATUS_SUCCESS; } #endif //CDRW_W32 RC = DeviceIoControl(h,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&returned,NULL); if(RC) { (*pLockMode) = FSCTL_LOCK_VOLUME; return STATUS_SUCCESS; } return STATUS_UNSUCCESSFUL; } // MyLockVolume() extern "C" ULONG MyUnlockVolume( HANDLE h, ULONG* pLockMode // IN ) { ULONG returned; #ifndef CDRW_W32 if((*pLockMode) == IOCTL_UDF_LOCK_VOLUME_BY_PID) { return DeviceIoControl(h,IOCTL_UDF_UNLOCK_VOLUME_BY_PID,NULL,0,NULL,0,&returned,NULL); } #endif //CDRW_W32 return DeviceIoControl(h,FSCTL_UNLOCK_VOLUME,NULL,0,NULL,0,&returned,NULL); } // MyUnlockVolume() void my_retrieve_vol_type( #ifndef CDRW_W32 PVCB Vcb, #endif PWCHAR fn ) { #ifndef CDRW_W32 if(wcslen(fn) == 2 && fn[1] == ':') { ULONG DevType = GetDriveTypeW(fn); UDFPrint((" DevType %x\n", DevType)); switch(DevType) { case DRIVE_CDROM: Vcb->PhDeviceType = FILE_DEVICE_CD_ROM; break; default: Vcb->PhDeviceType = FILE_DEVICE_DISK; break; } } if(wcslen(fn) == 2 && fn[1] == ';') { UserPrint(("Warrning: File name is similar to drive letter.\n" " Don't you type semicolon ';' instead of colon ':' ?\n")); } #endif //CDRW_W32 } // end my_retrieve_vol_type() #ifdef NT_NATIVE_MODE #define GetLastError() ((ULONG)(-1)) #endif //NT_NATIVE_MODE #define MAX_INVALIDATE_VOLUME_RETRY 8 extern "C" HANDLE my_open( #ifndef CDRW_W32 PVCB Vcb, #endif PWCHAR fn ) { HANDLE h/*, h2*/; WCHAR deviceNameBuffer[0x200]; WCHAR FSNameBuffer[0x200]; // CCHAR RealDeviceName[0x200]; // WCHAR DeviceName[MAX_PATH+1]; ULONG RC; ULONG retry; ULONG i; BOOLEAN CantLock = FALSE; PULONG pLockMode; #ifdef NT_NATIVE_MODE IO_STATUS_BLOCK ioStatus; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING uniFilename; #endif //NT_NATIVE_MODE ULONG returned; #ifndef CDRW_W32 #ifdef UDF_FORMAT_MEDIA PUDFFmtState fms = Vcb->fms; fms-> #endif open_as_device = TRUE; #endif //CDRW_W32 pLockMode = & #ifdef UDF_FORMAT_MEDIA fms-> #endif LockMode; // make several retries to workaround smart applications, // those attempts to work with volume immediately after arrival retry = 1 + #ifdef UDF_FORMAT_MEDIA fms-> #endif opt_invalidate_volume ? 0 : MAX_INVALIDATE_VOLUME_RETRY; #ifndef NT_NATIVE_MODE swprintf(deviceNameBuffer, L"%ws\\", fn); UDFPrint(("my_open: %S\n", fn)); i = sizeof(FSNameBuffer)/sizeof(FSNameBuffer[0]); if(GetVolumeInformationW(deviceNameBuffer, NULL, 0, &returned, &returned, &returned, FSNameBuffer, i)) { UDFPrint(("my_open: FS: %S\n", FSNameBuffer)); if(!wcscmp(FSNameBuffer, L"Unknown")) { retry++; } } else { UDFPrint(("my_open: FS: ???\n")); } UDFPrint(("my_open: retry %d times\n", retry)); #endif //NT_NATIVE_MODE do { // open as device #ifndef NT_NATIVE_MODE swprintf(deviceNameBuffer, L"\\\\.\\%ws", fn); if(wcslen(fn) == 2 && fn[1] == ';') { UserPrint(("Warrning: File name is similar to drive letter.\n" " Don't you type semicolon ';' instead of colon ':' ?\n")); } h = (HANDLE)(-1); for(i=0; i<4; i++) { if(h == ((HANDLE)-1)) { h = CreateFileW(deviceNameBuffer, GENERIC_READ | GENERIC_WRITE, ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL); if(h != ((HANDLE)-1)) { UDFPrint((" opened i=%x\n", i)); } } } #else //NT_NATIVE_MODE uniFilename.Length = swprintf(deviceNameBuffer, L"\\??\\%ws", fn); uniFilename.Buffer = deviceNameBuffer; uniFilename.Length *= sizeof(WCHAR); uniFilename.MaximumLength = uniFilename.Length + sizeof(WCHAR); h = (HANDLE)(-1); for(i=0; i<4; i++) { InitializeObjectAttributes(&ObjectAttributes, &uniFilename, OBJ_CASE_INSENSITIVE, NULL, NULL); if(h == ((HANDLE)-1)) { RC = NtCreateFile(&h, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &ObjectAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE), FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED | FILE_WRITE_THROUGH | FILE_NO_INTERMEDIATE_BUFFERING, NULL, 0); if(!NT_SUCCESS(RC)) { UDFPrint((" opened i2=%x\n", i)); h = ((HANDLE)-1); } } } #endif //NT_NATIVE_MODE if(h != ((HANDLE)-1)) { #ifndef CDRW_W32 #ifdef UDF_FORMAT_MEDIA if(fms->opt_flush || fms->opt_probe) { return h; } #endif //UDF_FORMAT_MEDIA my_retrieve_vol_type(Vcb, fn); #else my_retrieve_vol_type(fn); #endif //CDRW_W32 if(!NT_SUCCESS(MyLockVolume(h,pLockMode))) { #ifndef CDRW_W32 if(retry < MAX_INVALIDATE_VOLUME_RETRY) { retry++; if(!Privilege(SE_TCB_NAME, TRUE)) { UDFPrint(("SE_TCB privilege not held\n")); } else if(DeviceIoControl(h,FSCTL_INVALIDATE_VOLUMES,&h,sizeof(h),NULL,0,&returned,NULL) ) { UDFPrint((" FSCTL_INVALIDATE_VOLUMES ok, status %x\n", GetLastError())); CloseHandle(h); continue; } else { //#ifndef CDRW_W32 UDFPrint((" FSCTL_INVALIDATE_VOLUMES failed, error %x\n", GetLastError())); RC = GetLastError(); if(DeviceIoControl(h,IOCTL_UDF_INVALIDATE_VOLUMES,&h,sizeof(h),NULL,0,&returned,NULL) ) { UDFPrint((" IOCTL_UDF_INVALIDATE_VOLUMES ok, status %x\n", GetLastError())); CloseHandle(h); continue; } UDFPrint((" IOCTL_UDF_INVALIDATE_VOLUMES, error %x\n", GetLastError())); //#endif //CDRW_W32 } UserPrint(("can't lock volume, retry\n")); CloseHandle(h); continue; } #endif //CDRW_W32 UserPrint(("can't lock volume\n")); #ifndef NT_NATIVE_MODE // In native mode the volume can be not mounted yet !!! CantLock = TRUE; CloseHandle(h); h = NULL; goto try_as_file; #endif //NT_NATIVE_MODE } //#ifndef CDRW_W32 if(!DeviceIoControl(h,FSCTL_ALLOW_EXTENDED_DASD_IO,NULL,0,NULL,0,&returned,NULL)) { UDFPrint(("Warning: can't allow extended DASD i/o\n")); } //#endif //CDRW_W32 UDFPrint((" opened, h=%x\n", h)); return h; } RC = GetLastError(); #ifndef NT_NATIVE_MODE h = CreateFileW(deviceNameBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); #else //NT_NATIVE_MODE RC = NtCreateFile(&h, GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &ObjectAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED | FILE_WRITE_THROUGH, NULL, 0); if(!NT_SUCCESS(RC)) { h = ((HANDLE)-1); } #endif //NT_NATIVE_MODE if(h != ((HANDLE)-1)) { UDFPrint((" opened R/O, h=%x\n", h)); #ifndef CDRW_W32 my_retrieve_vol_type(Vcb, fn); #else my_retrieve_vol_type(fn); #endif UserPrint(("read-only open\n")); if(!NT_SUCCESS(MyLockVolume(h,pLockMode))) { #ifndef CDRW_W32 if(retry < MAX_INVALIDATE_VOLUME_RETRY) { retry++; if(!Privilege(SE_TCB_NAME, TRUE)) { UDFPrint(("SE_TCB privilege not held\n")); } else if(DeviceIoControl(h,FSCTL_INVALIDATE_VOLUMES,&h,sizeof(h),NULL,0,&returned,NULL) ) { CloseHandle(h); continue; } UserPrint(("can't lock read-only volumem retry")); CloseHandle(h); continue; } #endif //CDRW_W32 UserPrint(("can't lock read-only volume")); #ifndef NT_NATIVE_MODE CantLock = TRUE; CloseHandle(h); h = NULL; goto try_as_file; #endif //NT_NATIVE_MODE } // write_cdfs = TRUE; // DeviceIoControl(h,FSCTL_DISMOUNT_VOLUME,NULL,0,NULL,0,&returned,NULL); return h; } #ifndef NT_NATIVE_MODE try_as_file: #endif //NT_NATIVE_MODE #ifndef CDRW_W32 #ifdef UDF_FORMAT_MEDIA fms-> #endif open_as_device = FALSE; // open as plain file Vcb->PhDeviceType = FILE_DEVICE_DISK; #endif //CDRW_W32 UserPrint(("try image file\n")); #ifndef NT_NATIVE_MODE h = CreateFileW(fn, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); #else //NT_NATIVE_MODE RC = NtCreateFile(&h, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED | FILE_WRITE_THROUGH, NULL, 0); if(!NT_SUCCESS(RC)) { h = ((HANDLE)-1); } #endif //NT_NATIVE_MODE if(h == ((HANDLE)-1)) { RC = GetLastError(); if(CantLock) { #ifndef CDRW_W32 my_exit( #ifdef UDF_FORMAT_MEDIA fms, #endif MKUDF_CANT_LOCK_VOL); #else return NULL; #endif //CDRW_W32 } #ifndef CDRW_W32 UserPrint(("error opening device or image file")); my_exit( #ifdef UDF_FORMAT_MEDIA fms, #endif MKUDF_CANT_OPEN_FILE); #else return NULL; #endif //CDRW_W32 } UDFPrint((" opened as file, h=%x\n", h)); break; } while(TRUE); return h; } // end my_open() #endif //LIBUDF #ifndef CDRW_W32 uint64 udf_lseek64( HANDLE fd, uint64 offset, int whence) { LONG offh = (ULONG)(offset>>32); LONG offl; offl = SetFilePointer(fd, (ULONG)offset, &offh, whence); if(offl == -1 && offh == -1) { return -1; } return (((uint64)offh) << 32) | (uint64)offl; } // end udf_lseek64() #ifdef LIBUDFFMT BOOLEAN udf_get_sizes( IN PDEVICE_OBJECT DeviceObject, IN ULONG* blocks ) { ULONG bs; int64 sz; ULONG RC; RC = _lphUdf->lpGetSizeFunc(_lphUdf->lpParameter, &sz, &bs); (*blocks) = (ULONG)(sz/bs); return(OS_SUCCESS(RC)); } #endif //LIBUDFFMT #include "string_lib.cpp" #ifdef _BROWSE_UDF_ #ifndef LIBUDF ULONG UDFGetDevType( PDEVICE_OBJECT DeviceObject ) { if(DeviceObject && DeviceObject == Vcb->TargetDeviceObject) { return Vcb->PhDeviceType; } return FILE_DEVICE_DISK; } // end UDFGetDevType() #else // LIBUDF ULONG UDFGetDevType( PDEVICE_OBJECT DeviceObject ) { #define lphUdf ((PUDF_VOL_HANDLE_I)(DeviceObject->lpContext)) return lphUdf->bHddDevice ? FILE_DEVICE_DISK : FILE_DEVICE_CD_ROM; #undef lphUdf } // end UDFGetDevType() #endif // LIBUDF #endif //_BROWSE_UDF_ #endif //CDRW_W32 #ifndef NT_NATIVE_MODE #ifdef PRINT_DBG_CONSOLE CHAR dbg_print_tmp_buff[2048]; BOOLEAN was_enter = TRUE; extern "C" VOID PrintDbgConsole( PCHAR DebugMessage, ... ) { int len; va_list ap; va_start(ap, DebugMessage); if(was_enter) { strcpy(&dbg_print_tmp_buff[0], JS_DBG_PREFIX); len = _vsnprintf(&dbg_print_tmp_buff[sizeof(JS_DBG_PREFIX)-1], 2047-sizeof(JS_DBG_PREFIX), DebugMessage, ap); } else { len = _vsnprintf(&dbg_print_tmp_buff[0], 2047, DebugMessage, ap); } dbg_print_tmp_buff[2047] = 0; if(len > 0 && (dbg_print_tmp_buff[len-1] == '\n' || dbg_print_tmp_buff[len-1] == '\r') ) { was_enter = TRUE; } else { was_enter = FALSE; } OutputDebugString(&dbg_print_tmp_buff[0]); va_end(ap); } // end PrintDbgConsole() #else // PRINT_DBG_CONSOLE VOID PrintDbgConsole( PCHAR DebugMessage, ... ) { } // end ClassDebugPrint() #endif //PRINT_DBG_CONSOLE BOOLEAN RtlTimeFieldsToTime( IN PTIME_FIELDS TimeFields, IN PLARGE_INTEGER Time ) { SYSTEMTIME st; st.wYear = TimeFields->Year; st.wMonth = TimeFields->Month; st.wDayOfWeek = 0; st.wDay = TimeFields->Day; st.wHour = TimeFields->Hour; st.wMinute = TimeFields->Minute; st.wSecond = TimeFields->Second; st.wMilliseconds = TimeFields->Milliseconds; return SystemTimeToFileTime(&st, (PFILETIME)Time); } // end RtlTimeFieldsToTime() BOOLEAN RtlTimeToTimeFields( IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields ) { SYSTEMTIME st; BOOLEAN retval; retval = FileTimeToSystemTime((PFILETIME)Time, &st); TimeFields->Year = st.wYear; TimeFields->Month = st.wMonth; TimeFields->Weekday = st.wDayOfWeek; TimeFields->Day = st.wDay; TimeFields->Hour = st.wHour; TimeFields->Minute = st.wMinute; TimeFields->Second = st.wSecond; TimeFields->Milliseconds = st.wMilliseconds; return retval; } // end () #endif //NT_NATIVE_MODE #ifdef USE_THREAD_HEAPS HANDLE MemLock = NULL; VOID ExInitThreadPools() { MemLock = CreateMutex(NULL, 0, NULL); } VOID ExDeInitThreadPools() { if(MemLock) CloseHandle(MemLock); } #define MAX_THREADS_WITH_OWN_POOL 128 typedef struct _THREAD_POOL_LIST_ITEM { HANDLE HeapHandle; ULONG ThreadId; } THREAD_POOL_LIST_ITEM, *PTHREAD_POOL_LIST_ITEM; ULONG LastThreadPool = -1; THREAD_POOL_LIST_ITEM ThreadPoolList[MAX_THREADS_WITH_OWN_POOL]; extern "C" PVOID #ifdef KERNEL_MODE_MM_BEHAVIOR _ExAllocatePool_( #else ExAllocatePool( #endif ULONG MemoryType, ULONG Size ) { ULONG i; ULONG ThreadId = GetCurrentThreadId(); BOOLEAN found = FALSE; WaitForSingleObject(MemLock,-1); for(i=0; i<(LastThreadPool+1); i++) { if(ThreadPoolList[i].ThreadId == ThreadId) { found = TRUE; break; } } if(found) { ReleaseMutex(MemLock); return HeapAlloc(ThreadPoolList[i].HeapHandle, HEAP_NO_SERIALIZE, Size); } for(i=0; i<(LastThreadPool+1); i++) { if(ThreadPoolList[i].ThreadId == -1) { break; } } if(i>=MAX_THREADS_WITH_OWN_POOL) { ReleaseMutex(MemLock); return NULL; } ThreadPoolList[i].ThreadId = ThreadId; ThreadPoolList[i].HeapHandle = HeapCreate(HEAP_NO_SERIALIZE, 128*PAGE_SIZE, 0); if(!ThreadPoolList[i].HeapHandle) { ThreadPoolList[i].ThreadId = -1; ReleaseMutex(MemLock); return NULL; } if(i+1 > LastThreadPool+1) LastThreadPool = i; ReleaseMutex(MemLock); return HeapAlloc(ThreadPoolList[i].HeapHandle, HEAP_NO_SERIALIZE, Size); } // end ExAllocatePool() extern "C" VOID #ifdef KERNEL_MODE_MM_BEHAVIOR _ExFreePool_( #else ExFreePool( #endif PVOID Addr ) { ULONG ThreadId = GetCurrentThreadId(); ULONG i; WaitForSingleObject(MemLock,-1); for(i=0; i<(LastThreadPool+1); i++) { if(ThreadPoolList[i].ThreadId == ThreadId) { break; } } if(i+1 > LastThreadPool+1) { // Not found BrutePoint(); //__asm int 3; return; } HeapFree(ThreadPoolList[i].HeapHandle, HEAP_NO_SERIALIZE, Addr); ReleaseMutex(MemLock); } // end ExFreePool() extern "C" VOID ExFreeThreadPool() { ULONG ThreadId = GetCurrentThreadId(); ULONG i; WaitForSingleObject(MemLock,-1); for(i=0; i<(LastThreadPool+1); i++) { if(ThreadPoolList[i].ThreadId == ThreadId) { break; } } if(i+1 > LastThreadPool+1) { // Not found BrutePoint(); //__asm int 3; return; } HeapDestroy(ThreadPoolList[i].HeapHandle); ThreadPoolList[i].HeapHandle = INVALID_HANDLE_VALUE; ThreadPoolList[i].ThreadId = -1; ReleaseMutex(MemLock); } #endif //USE_THREAD_HEAPS #if defined(KERNEL_MODE_MM_BEHAVIOR) extern "C" PVOID ExAllocatePool( ULONG MemoryType, ULONG Size ) { PVOID Addr; PVOID uAddr; if(Size < PAGE_SIZE) { #ifdef USE_THREAD_HEAPS Addr = _ExAllocatePool_(MemoryType, Size+8); #else Addr = GlobalAlloc(GMEM_DISCARDABLE, Size+8); #endif if(!Addr) return NULL; uAddr = ((PCHAR)Addr)+8; } else { #ifdef USE_THREAD_HEAPS Addr = _ExAllocatePool_(MemoryType, Size+PAGE_SIZE*2); #else Addr = GlobalAlloc(GMEM_DISCARDABLE, Size+PAGE_SIZE*2); #endif if(!Addr) return NULL; uAddr = (PVOID)(((ULONG)(((PCHAR)Addr)+PAGE_SIZE)) & ~(PAGE_SIZE-1)); } *(((PULONG)uAddr)-2) = (ULONG)Addr; *(((PULONG)uAddr)-1) = 0xFEDCBA98; return uAddr; } // end ExAllocatePool() extern "C" VOID ExFreePool( PVOID uAddr ) { PVOID Addr; if(*(((PULONG)uAddr)-1) == 0xFEDCBA98) { Addr = (PVOID)(*(((PULONG)uAddr)-2)); #ifdef USE_THREAD_HEAPS _ExFreePool_(Addr); #else GlobalFree(Addr); #endif return; } BrutePoint(); } // end ExFreePool() #endif //defined(KERNEL_MODE_MM_BEHAVIOR) || defined(NT_NATIVE_MODE) #ifdef _lphUdf #undef _lphUdf #endif //_lphUdf extern "C" BOOLEAN ProbeMemory( PVOID MemPtr, ULONG Length, BOOLEAN ForWrite ) { ULONG i; UCHAR a; if(!MemPtr && !Length) return TRUE; if(!MemPtr || !Length) return FALSE; _SEH2_TRY { a = ((PCHAR)MemPtr)[Length-1]; if(ForWrite) { ((PCHAR)MemPtr)[Length-1] = a; } for(i=0; i