www.pudn.com > He4Hook215b6.rar > Misc.cpp


#include "Misc.h" 
 
#ifdef __MISC_USE_KHEAP 
 KHEAP               hKHeapMiscDefault = NULL; 
#endif //__MISC_USE_KHEAP 
 
// 
// Функции для работы с памятью 
// 
 
BOOLEAN AllocateSharedMemory(PSHARED_MEMORY lpSharedMemory, POOL_TYPE PoolType, ULONG dwSizeRegion) 
{ 
  if (!_MmIsAddressValid(lpSharedMemory)) 
    return FALSE; 
  if (!dwSizeRegion) 
    return FALSE; 
 
  memset(lpSharedMemory, 0, sizeof(SHARED_MEMORY)); 
 
  #ifndef __MISC_USE_KHEAP 
  lpSharedMemory->m_lpKernelMemory = ExAllocatePool(PoolType, dwSizeRegion); 
  #else 
  lpSharedMemory->m_lpKernelMemory = (CHAR*) _AllocatePoolFromKHeap(hKHeapMiscDefault, dwSizeRegion); 
  #endif //!__MISC_USE_KHEAP 
  if (!lpSharedMemory->m_lpKernelMemory) 
    return FALSE; 
 
  lpSharedMemory->m_Mdl = IoAllocateMdl(lpSharedMemory->m_lpKernelMemory, dwSizeRegion, FALSE, FALSE, NULL); 
  if (!lpSharedMemory->m_Mdl) 
  { 
    #ifndef __MISC_USE_KHEAP 
    ExFreePool(lpSharedMemory->m_lpKernelMemory); 
    #else 
    FreePoolToKHeap(hKHeapMiscDefault, lpSharedMemory->m_lpKernelMemory); 
    #endif //!__MISC_USE_KHEAP 
    memset(lpSharedMemory, 0, sizeof(SHARED_MEMORY)); 
    return FALSE; 
  } 
 
  MmBuildMdlForNonPagedPool(lpSharedMemory->m_Mdl); 
 
  lpSharedMemory->m_lpUserPage = MmMapLockedPages(lpSharedMemory->m_Mdl, UserMode); 
  lpSharedMemory->m_lpUserMemory = (PVOID) (((ULONG)PAGE_ALIGN(lpSharedMemory->m_lpUserPage))+MmGetMdlByteOffset(lpSharedMemory->m_Mdl)); 
  if (!_MmIsAddressValid(lpSharedMemory->m_lpUserMemory)) 
  { 
    MmUnmapLockedPages(lpSharedMemory->m_lpUserPage, lpSharedMemory->m_Mdl); 
    IoFreeMdl(lpSharedMemory->m_Mdl); 
    #ifndef __MISC_USE_KHEAP 
    ExFreePool(lpSharedMemory->m_lpKernelMemory); 
    #else 
    FreePoolToKHeap(hKHeapMiscDefault, lpSharedMemory->m_lpKernelMemory); 
    #endif //!__MISC_USE_KHEAP 
    memset(lpSharedMemory, 0, sizeof(SHARED_MEMORY)); 
    return FALSE; 
  } 
  lpSharedMemory->m_dwSizeRegion = dwSizeRegion; 
 
  return TRUE; 
} 
 
BOOLEAN FreeSharedMemory(PSHARED_MEMORY lpSharedMemory) 
{ 
  if (!_MmIsAddressValid(lpSharedMemory)) 
    return FALSE; 
  if (!_MmIsAddressValid(lpSharedMemory->m_lpUserMemory)) 
    return FALSE; 
  if (!_MmIsAddressValid(lpSharedMemory->m_lpKernelMemory)) 
    return FALSE; 
 
  MmUnmapLockedPages(lpSharedMemory->m_lpUserPage, lpSharedMemory->m_Mdl); 
  IoFreeMdl(lpSharedMemory->m_Mdl); 
  #ifndef __MISC_USE_KHEAP 
  ExFreePool(lpSharedMemory->m_lpKernelMemory); 
  #else 
  FreePoolToKHeap(hKHeapMiscDefault, lpSharedMemory->m_lpKernelMemory); 
  #endif //!__MISC_USE_KHEAP 
  memset(lpSharedMemory, 0, sizeof(SHARED_MEMORY)); 
 
  return TRUE; 
} 
 
PVOID 
MapUserAddressToKernel( 
   IN PVOID pUserModeAddress, 
   IN ULONG ulSize, 
   OUT PMDL* ppMdl 
   ) 
{ 
 PMDL  pUserModeMdl = NULL; 
 PVOID pMappedKernelAddr = NULL; 
 
 if (ppMdl == NULL) 
   return NULL; 
 
 __try 
 { 
   pUserModeMdl = IoAllocateMdl(pUserModeAddress, ulSize, FALSE, FALSE, NULL); 
   if (pUserModeMdl != NULL) 
   { 
     MmProbeAndLockPages(pUserModeMdl, KernelMode, IoModifyAccess); 
     pMappedKernelAddr = MmMapLockedPages(pUserModeMdl, KernelMode);   
     if (pMappedKernelAddr != NULL) 
     { 
       pMappedKernelAddr = (PVOID) (((ULONG)PAGE_ALIGN(pMappedKernelAddr))+MmGetMdlByteOffset(pUserModeMdl)); 
       *ppMdl = pUserModeMdl; 
     } 
     else 
     { 
       UnmapMappedKernelAddress(pUserModeMdl); 
     } 
   } 
 } 
 __except(EXCEPTION_EXECUTE_HANDLER) 
 { 
   if (pUserModeMdl != NULL) 
     IoFreeMdl(pUserModeMdl); 
   pMappedKernelAddr = NULL; 
 } 
   
 return pMappedKernelAddr; 
} 
 
 
VOID 
UnmapMappedKernelAddress( 
   IN PMDL pMdl 
   ) 
{ 
  if (pMdl == NULL) 
    return; 
 
  MmUnlockPages(pMdl); 
  IoFreeMdl(pMdl); 
} 
 
BOOLEAN IsBadWritePtr(PVOID Address, ULONG Length, ULONG Alignment) 
{ 
  __try 
  { 
    ProbeForWrite(Address, Length, Alignment); 
  } 
  __except(EXCEPTION_EXECUTE_HANDLER) 
  { 
    return TRUE; 
  } 
  return FALSE; 
} 
 
BOOLEAN _MmIsAddressValid(PVOID Address) 
{ 
  if (!Address) 
    return FALSE; 
  return MmIsAddressValid(Address); 
} 
 
// 
// функции для работы с объектами ядра 
// 
 
//---------------------------------------------------------------------- 
// 
// GetPointer 
// 
// Translates a handle to an object pointer. 
// 
//---------------------------------------------------------------------- 
POBJECT GetPointer(HANDLE handle) 
{ 
  POBJECT         pKey; 
  NTSTATUS        NtStatus; 
 
  // 
  // Ignore null handles 
  // 
  if (!handle && KeGetCurrentIrql() != PASSIVE_LEVEL) 
    return NULL; 
 
  // 
  // Get the pointer the handle refers to 
  // 
  NtStatus = ObReferenceObjectByHandle(handle, 0, NULL, KernelMode, &pKey, NULL); 
  if (NtStatus != STATUS_SUCCESS) 
  { 
    DbgPrintMisc(("He4hookInv: GetPointer: Error %08x getting key pointer\n", NtStatus)); 
    pKey = NULL; 
  }  
 
  return pKey; 
} 
 
 
//---------------------------------------------------------------------- 
// 
// ReleasePointer 
// 
// Dereferences the object. 
// 
//---------------------------------------------------------------------- 
VOID ReleasePointer(POBJECT object) 
{ 
  if (object && KeGetCurrentIrql() == PASSIVE_LEVEL) 
    ObDereferenceObject(object); 
} 
 
ULONG GetObjectName(HANDLE hObject, PWSTR lpwszName, ULONG dwSize) 
{ 
  CHAR                   *tmpname;//[0x400]; 
  PUNICODE_STRING         fullUniName; 
  NTSTATUS                NtStatus; 
  ULONG                   dwObjectNameLen = 0; //(by bytes) 
 
  DbgPrintMisc(("He4hookInv: GetObjectName started!!!!!!!\n")); 
 
  if (!lpwszName || !dwSize || KeGetCurrentIrql() > PASSIVE_LEVEL) 
    return 0; 
 
  // 
  // Translate the hkey into a pointer 
  // 
  lpwszName[0] = 0; 
 
  #ifndef __MISC_USE_KHEAP 
  tmpname = (CHAR*) ExAllocatePool(NonPagedPool, dwSize+sizeof(UNICODE_STRING)); 
  #else 
  tmpname = (CHAR*) _AllocatePoolFromKHeap(hKHeapMiscDefault, dwSize+sizeof(UNICODE_STRING)); 
  #endif //!__MISC_USE_KHEAP 
  if (!_MmIsAddressValid(tmpname)) 
    return 0; 
  tmpname[0] = 0; 
 
  NtStatus = ZwQueryObject(hObject, NameObjectInfo, tmpname, dwSize+sizeof(UNICODE_STRING), NULL); 
 
  if (NT_SUCCESS(NtStatus)) 
  { 
    fullUniName = &(((PNAME_OBJECT_INFO)tmpname)->Name); 
    dwObjectNameLen = fullUniName->Length; 
    if (dwSize < (sizeof(WCHAR)+dwObjectNameLen)) 
    { 
      DbgPrintMisc(("He4hookInv: GetObjectName ended - ERROR!!!!!!!\n")); 
      #ifndef __MISC_USE_KHEAP 
      ExFreePool(tmpname); 
      #else 
      FreePoolToKHeap(hKHeapMiscDefault, tmpname); 
      #endif //!__MISC_USE_KHEAP 
      return 0; 
    } 
//    memset(lpwszName, 0, (sizeof(WCHAR)+fullUniName->Length)); 
    memcpy(lpwszName, fullUniName->Buffer, dwObjectNameLen); 
    lpwszName[dwObjectNameLen/sizeof(WCHAR)] = 0; 
  } 
 
  #ifndef __MISC_USE_KHEAP 
  ExFreePool(tmpname); 
  #else 
  FreePoolToKHeap(hKHeapMiscDefault, tmpname); 
  #endif //!__MISC_USE_KHEAP 
 
  DbgPrintMisc(("He4hookInv: GetObjectName ended - OK!!!!!!!\n")); 
 
  return dwObjectNameLen;  
} 
 
ULONG GetObjectNameByObjectAttributes(POBJECT_ATTRIBUTES ObjectAttributes, PWSTR fullPathName, ULONG nfullPathNameSize) 
{ 
  ULONG                   dwDirSize, dwNtPathNameLen; 
  int                     nObjectNameLen = 0; 
  PWSTR                   DosPathName; 
  NTSTATUS                NtStatus; 
  PWSTR                   pwszObjectName = NULL; 
 
  if ( 
      !_MmIsAddressValid(ObjectAttributes) || 
      !_MmIsAddressValid(fullPathName)     || 
      !nfullPathNameSize 
     ) 
    return 0; 
 
  fullPathName[0] = 0; 
  dwDirSize = 0; 
 
  if (_MmIsAddressValid(ObjectAttributes->ObjectName)) 
  { 
    if (ObjectAttributes->ObjectName->Length != 0) 
    { 
      if (_MmIsAddressValid(ObjectAttributes->ObjectName->Buffer)) 
      { 
        pwszObjectName = ObjectAttributes->ObjectName->Buffer; 
        nObjectNameLen = ObjectAttributes->ObjectName->Length; 
      } 
    } 
  } 
 
  #ifndef __MISC_USE_KHEAP 
  DosPathName = (PWSTR) ExAllocatePool(NonPagedPool, nfullPathNameSize); 
  #else 
  DosPathName = (PWSTR) _AllocatePoolFromKHeap(hKHeapMiscDefault, nfullPathNameSize); 
  #endif //!__MISC_USE_KHEAP 
//  DosPathName = (PWSTR)_AllocatePoolFromKHeap(hKHeapFSDefault, nfullPathNameSize); 
  if (DosPathName == NULL) 
    return 0; 
 
  DosPathName[0] = 0; 
 
  DbgPrintMisc(("  GetFileNameByObjectAttributes: Attributes => %08x !!!\n", ObjectAttributes->Attributes)); 
 
  if (ObjectAttributes->RootDirectory) 
  { 
    dwDirSize = GetObjectName(ObjectAttributes->RootDirectory, DosPathName, nfullPathNameSize); 
  } 
 
  if (dwDirSize > 3 && pwszObjectName != NULL) 
  { 
    if ( 
        DosPathName[(dwDirSize/sizeof(WCHAR))-1] == L'\\' && 
        (pwszObjectName[0] == L'\\' || pwszObjectName[0] == L'/') 
       ) 
    { 
      DosPathName[(dwDirSize/sizeof(WCHAR))-1] = 0; 
      dwDirSize -= sizeof(WCHAR); 
    } 
    else 
    { 
      if ( 
          DosPathName[(dwDirSize/sizeof(WCHAR))-1] != L'\\' && 
          (pwszObjectName[0] != L'\\' || pwszObjectName[0] != L'/') 
         ) 
      { 
        if (dwDirSize <= (nfullPathNameSize-2*sizeof(WCHAR))) 
        { 
          DosPathName[(dwDirSize/sizeof(WCHAR))] = L'\\'; 
          DosPathName[(dwDirSize/sizeof(WCHAR))+1] = 0; 
          dwDirSize += sizeof(WCHAR); 
        } 
      } 
    } 
  } 
 
  if (pwszObjectName != NULL) 
  { 
    if (nfullPathNameSize > (nObjectNameLen+dwDirSize)) 
    { 
      memcpy(((PCHAR)DosPathName+dwDirSize), pwszObjectName, nObjectNameLen); 
      ((PWSTR)((PCHAR)DosPathName+dwDirSize))[nObjectNameLen/sizeof(WCHAR)] = 0; 
    } 
  } 
 
  dwNtPathNameLen = DosPathNameToNtPathName(DosPathName, fullPathName, nfullPathNameSize, 255, NULL); 
 
  #ifndef __MISC_USE_KHEAP 
  ExFreePool(DosPathName); 
  #else 
  FreePoolToKHeap(hKHeapMiscDefault, DosPathName); 
  #endif //!__MISC_USE_KHEAP 
  //FreePoolToKHeap(hKHeapFSDefault, DosPathName); 
 
  return dwNtPathNameLen; 
} 
 
ULONG GetObjectNameByFileObject(PFILE_OBJECT fileObject, PWSTR fullPathName, ULONG nfullPathNameSize) 
{ 
  ULONG               pathLen, dwVolumeLen; 
  PWSTR               pathOffset; 
  PFILE_OBJECT        relatedFileObject; 
//  ANSI_STRING         componentName; 
  PDEVICE_OBJECT      pDeviceObject; 
  PUNICODE_STRING     fullUniName; 
  UNICODE_STRING      FileNameUnicodeString; 
  ULONG               dwFreeSize = nfullPathNameSize; 
  ULONG               dwFullPathLen = 0; 
 
  if ( 
      KeGetCurrentIrql() > PASSIVE_LEVEL || 
      !_MmIsAddressValid(fileObject) || 
      !_MmIsAddressValid(fullPathName)     || 
      !fileObject 
     ) 
    return 0; 
 
  fullPathName[0] = 0; 
  dwVolumeLen = 0; 
 
  __try 
  { 
    pDeviceObject = GetVolumeDeviceObject(fileObject); 
    if (pDeviceObject == NULL) 
    { 
      pDeviceObject = IoGetRelatedDeviceObject(fileObject); 
    } 
 
    fullUniName = (PUNICODE_STRING)fullPathName; 
    fullUniName->MaximumLength = (USHORT)(nfullPathNameSize*sizeof(WCHAR) - sizeof(UNICODE_STRING)); 
 
    if (NT_SUCCESS(ObQueryNameString(pDeviceObject, (POBJECT_NAME_INFORMATION)fullUniName, fullUniName->MaximumLength, &pathLen))) 
    { 
      dwVolumeLen = fullUniName->Length; 
      memmove(fullPathName, fullUniName->Buffer, dwVolumeLen); 
      fullPathName[dwVolumeLen/sizeof(WCHAR)] = 0; 
    } 
    else 
    { 
      return 0; 
    } 
 
//    strcat(fullPathName, "\\"); 
    dwFreeSize -= dwVolumeLen; 
 
    if (!fileObject->FileName.Length || fileObject->FileName.Length > dwFreeSize) 
    { 
//      RtlInitUnicodeString(&FileNameUnicodeString, fullPathName); 
//      RtlUnicodeStringToAnsiString( &componentName, &FileNameUnicodeString, TRUE );     
//      DbgPrint ("%s\n", componentName.Buffer); 
//      RtlFreeAnsiString( &componentName ); 
 
      return wcslen(fullPathName)*sizeof(WCHAR); 
    } 
 
  } 
  __except(EXCEPTION_EXECUTE_HANDLER) 
  { 
    return 0; 
  } 
 
  __try 
  { 
    pathLen = fileObject->FileName.Length/sizeof(WCHAR) + 1; 
 
    relatedFileObject = fileObject->RelatedFileObject; 
   
    if (fileObject->FileName.Buffer[0] != L'\\' ) 
    { 
      while (relatedFileObject) 
      { 
        if ((pathLen + relatedFileObject->FileName.Length/sizeof(WCHAR) + 1) >= dwFreeSize) 
        { 
          break; 
        } 
        pathLen += relatedFileObject->FileName.Length/sizeof(WCHAR) + 1; 
        relatedFileObject = relatedFileObject->RelatedFileObject; 
      } 
    } 
 
    if (dwFreeSize == nfullPathNameSize) 
      wcscpy(fullPathName, L"\\"); 
   
    pathOffset = fullPathName + dwVolumeLen/sizeof(WCHAR) - 1 + pathLen - fileObject->FileName.Length/sizeof(WCHAR); 
    memcpy(pathOffset, fileObject->FileName.Buffer, fileObject->FileName.Length); 
    pathOffset[fileObject->FileName.Length/sizeof(WCHAR)] = 0; 
 
    relatedFileObject = fileObject->RelatedFileObject; 
   
    if (fileObject->FileName.Buffer[0] != L'\\') 
    { 
      while (relatedFileObject) 
      { 
        *(pathOffset - 1) = L'\\'; 
        pathOffset -= relatedFileObject->FileName.Length/sizeof(WCHAR) + 1; 
 
        if (pathOffset <= fullPathName) 
        { 
          break; 
        } 
        memcpy(pathOffset, relatedFileObject->FileName.Buffer, relatedFileObject->FileName.Length); 
 
        relatedFileObject = relatedFileObject->RelatedFileObject; 
      } 
    }   
 
    dwFullPathLen = wcslen(fullPathName)*sizeof(WCHAR); 
 
//    if (fullPathName[dwVolumeLen/sizeof(WCHAR)] == L'\\' && fullPathName[dwVolumeLen/sizeof(WCHAR)+1] == L'\\') 
//    { 
//      memmove(&fullPathName[dwVolumeLen/sizeof(WCHAR)], &fullPathName[dwVolumeLen/sizeof(WCHAR)+1], pathLen*sizeof(WCHAR)); 
//    } 
 
    pathOffset = wcsstr(fullPathName, L"\\\\"); 
    while (pathOffset) 
    { 
      memmove(pathOffset, &pathOffset[1], wcslen(pathOffset)*sizeof(WCHAR)); 
      pathOffset = wcsstr(pathOffset, L"\\\\"); 
    } 
 
//    RtlInitUnicodeString(&FileNameUnicodeString, fullPathName); 
//    RtlUnicodeStringToAnsiString( &componentName, &FileNameUnicodeString, TRUE );     
//    DbgPrint ("%s\n", componentName.Buffer); 
//    RtlFreeAnsiString( &componentName ); 
 
  } 
  __except(EXCEPTION_EXECUTE_HANDLER) 
  { 
    DbgPrintMisc(("GetFullPath: EXCEPTION\n")); 
  } 
 
  return dwFullPathLen; 
} 
 
PVOID GetObjectByPath(PWSTR pwszObjectName, PVOID pObjectType) 
{ 
  PVOID              pObject = NULL; 
  UNICODE_STRING     DeviceName; 
  NTSTATUS           NtStatus = 0; 
//  ANSI_STRING        FileNameAnsi; 
 
  if (!pwszObjectName || KeGetCurrentIrql() > PASSIVE_LEVEL) 
    return pObject; 
 
 
  RtlInitUnicodeString(&DeviceName, pwszObjectName); 
 
//  RtlUnicodeStringToAnsiString(&FileNameAnsi, &DeviceName, TRUE); 
//  if (strlen(FileNameAnsi.Buffer)) 
//    DbgPrint ("%s\n", FileNameAnsi.Buffer); 
//  RtlFreeAnsiString(&FileNameAnsi); 
 
 
  __try 
  { 
    NtStatus = ObReferenceObjectByName(&DeviceName, OBJ_CASE_INSENSITIVE, NULL, 0, (POBJECT_TYPE)pObjectType, KernelMode, NULL, (PVOID*)&pObject); 
  } 
  __except(EXCEPTION_EXECUTE_HANDLER) 
  { 
    NtStatus = STATUS_ACCESS_VIOLATION; 
//    DbgPrint ("EXCEPTION into ObReferenceObjectByName\n"); 
  } 
//NTSYSAPI 
//NTSTATUS 
//NTAPI 
//ObReferenceObjectByName( 
//    IN PUNICODE_STRING ObjectPath, 
//    IN ULONG Attributes, 
//    IN PACCESS_STATE PassedAccessState OPTIONAL, 
//    IN ACCESS_MASK DesiredAccess OPTIONAL, 
//    IN POBJECT_TYPE ObjectType, 
//    IN KPROCESSOR_MODE AccessMode, 
//    IN OUT PVOID ParseContext OPTIONAL, 
//    OUT PVOID *ObjectPtr 
//    );   
  if (NT_SUCCESS(NtStatus)) 
  { 
    ObDereferenceObject((PVOID)pObject); 
  } 
//  DbgPrint ("He4HookInv: GetObjectByPath: pObject = %08X!!!\n", pObject); 
 
  return pObject; 
} 
 
POBJECT_NAME GetNameOfObject(PVOID pObject) 
{ 
  POBJECT_NAME    pObjectName = NULL; 
  POBJECT_HEADER  pObjectHdr; 
 
  if (_MmIsAddressValid(pObject)) 
  { 
    pObjectHdr = (POBJECT_HEADER) ((PBYTE)pObject - SIZE_OF_OBJECT_HEADER); 
    if (_MmIsAddressValid(pObjectHdr)) 
    { 
      if (pObjectHdr->SubHeaderInfo.NameOffset != 0) 
      { 
        pObjectName = (POBJECT_NAME) ((PBYTE)pObjectHdr - pObjectHdr->SubHeaderInfo.NameOffset); 
      } 
    } 
  } 
 
  return pObjectName; 
} 
 
// 
// функции для работы с объектами файловых систем 
// 
 
BOOLEAN GetFileNameNative(HANDLE hObject, PWSTR lpwszName, ULONG dwSize) 
{ 
  PFILE_OBJECT     pFileObject; 
  PDEVICE_OBJECT   pDeviceObject; 
  BOOLEAN          bRes = FALSE; 
  PFILE_NAME_INFORMATION FileName; 
 
  FileName = (PFILE_NAME_INFORMATION) ExAllocatePool(NonPagedPool, 2*dwSize); 
  if (!_MmIsAddressValid(FileName)) 
    return bRes; 
 
  pFileObject = (PFILE_OBJECT) GetPointer(hObject); 
  if (_MmIsAddressValid(pFileObject)) 
  { 
    pDeviceObject = IoGetRelatedDeviceObject(pFileObject); 
    if (_MmIsAddressValid(pDeviceObject)) 
    { 
      bRes = FilemonQueryFileName(pDeviceObject, pFileObject, FileName, dwSize); 
      if (bRes) 
      { 
        memset(lpwszName, 0, dwSize); 
        memcpy(lpwszName, FileName->FileName, FileName->FileNameLength); 
      } 
    } 
    ReleasePointer((POBJECT)pFileObject); 
  } 
 
  ExFreePool(FileName); 
 
  return bRes; 
} 
 
NTSTATUS FilemonQueryFileNameComplete(PDEVICE_OBJECT DeviceObject, 
                                      PIRP Irp, 
                                      PVOID Context) 
{ 
  // 
  // Copy the status information back into the "user" IOSB. 
  // 
  *Irp->UserIosb = Irp->IoStatus; 
 
//  if( !NT_SUCCESS(Irp->IoStatus.Status) ) { 
// 
//      DbgPrint(("   ERROR ON IRP: %x\n", Irp->IoStatus.Status )); 
//  } 
   
  // 
  // Set the user event - wakes up the mainline code doing this. 
  // 
  KeSetEvent(Irp->UserEvent, 0, FALSE); 
   
  // 
  // Free the IRP now that we are done with it. 
  // 
  IoFreeIrp(Irp); 
   
  // 
  // We return STATUS_MORE_PROCESSING_REQUIRED because this "magic" return value 
  // tells the I/O Manager that additional processing will be done by this driver 
  // to the IRP - in fact, it might (as it is in this case) already BE done - and 
  // the IRP cannot be completed. 
  // 
  return STATUS_MORE_PROCESSING_REQUIRED; 
} 
 
 
//---------------------------------------------------------------------- 
// 
// FilemonQueryFileName 
// 
// This function retrieves the "standard" information for the 
// underlying file system, asking for the filename in particular. 
// 
//---------------------------------------------------------------------- 
BOOLEAN FilemonQueryFileName(PDEVICE_OBJECT DeviceObject,  
                             PFILE_OBJECT FileObject, 
                             PFILE_NAME_INFORMATION FileName, ULONG FileNameLength) 
{ 
  PIRP irp; 
  KEVENT event; 
  IO_STATUS_BLOCK IoStatusBlock; 
  PIO_STACK_LOCATION ioStackLocation; 
 
//  DbgPrint(("Getting file name for %x\n", FileObject)); 
 
  // 
  // Initialize the event 
  // 
  KeInitializeEvent(&event, SynchronizationEvent, FALSE); 
 
  // 
  // Allocate an irp for this request.  This could also come from a  
  // private pool, for instance. 
  // 
  irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 
 
  if (!irp) 
  { 
    // 
    // Failure! 
    // 
    return FALSE; 
  } 
   
  // 
  // Build the IRP's main body 
  //   
  irp->AssociatedIrp.SystemBuffer = FileName; 
  irp->UserEvent = &event; 
  irp->UserIosb = &IoStatusBlock; 
  irp->Tail.Overlay.Thread = PsGetCurrentThread(); 
  irp->Tail.Overlay.OriginalFileObject = FileObject; 
  irp->RequestorMode = KernelMode; 
  irp->Flags = 0; 
 
  // 
  // Set up the I/O stack location. 
  // 
  ioStackLocation = IoGetNextIrpStackLocation(irp); 
  ioStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION; 
  ioStackLocation->DeviceObject = DeviceObject; 
  ioStackLocation->FileObject = FileObject; 
  ioStackLocation->Parameters.QueryFile.Length = FileNameLength; 
  ioStackLocation->Parameters.QueryFile.FileInformationClass = FileNameInformation; 
 
  // 
  // Set the completion routine. 
  // 
  IoSetCompletionRoutine(irp, FilemonQueryFileNameComplete, 0, TRUE, TRUE, TRUE); 
 
  // 
  // Send it to the FSD 
  // 
  (void) IoCallDriver(DeviceObject, irp); 
 
  // 
  // Wait for the I/O 
  // 
  KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); 
 
  // 
  // Done! Note that since our completion routine frees the IRP we cannot  
  // touch the IRP now. 
  // 
  return NT_SUCCESS( IoStatusBlock.Status ); 
} 
 
NTSTATUS 
NativeQueryDirectoryFileComplete( 
   PDEVICE_OBJECT DeviceObject, 
   PIRP Irp, 
   PVOID Context 
   ) 
{ 
  *Irp->UserIosb = Irp->IoStatus; 
 
  KeSetEvent(Irp->UserEvent, 0, FALSE); 
   
  IoFreeIrp(Irp); 
   
  return STATUS_MORE_PROCESSING_REQUIRED; 
} 
 
NTSTATUS 
NativeQueryDirectoryFile( 
   PDRIVER_DISPATCH pMajorFunction, 
   PDEVICE_OBJECT pDeviceObject, 
   PFILE_OBJECT pFileObject, 
   PIO_STATUS_BLOCK pIoStatusBlock, 
   PVOID Buffer, 
   ULONG BufferLength, 
   FILE_INFORMATION_CLASS DirectoryInfoClass, 
   BOOLEAN ByOne, 
   PUNICODE_STRING pSearchTemplate, 
   BOOLEAN Reset, 
   BOOLEAN Index, 
   ULONG dwIndex 
   ) 
{ 
  PIRP irp; 
  KEVENT event; 
  PIO_STACK_LOCATION ioStackLocation; 
  PQUERY_DIRECTORY pQueryDir; 
 
  KeInitializeEvent(&event, SynchronizationEvent, FALSE); 
 
  irp = IoAllocateIrp(pDeviceObject->StackSize, FALSE); 
  if (!irp) 
    return STATUS_NO_MEMORY; 
 
  irp->MdlAddress = NULL; 
  irp->UserBuffer = Buffer; 
  irp->AssociatedIrp.SystemBuffer = Buffer; 
  irp->UserEvent = &event; 
  irp->UserIosb = pIoStatusBlock; 
  irp->Tail.Overlay.Thread = PsGetCurrentThread(); 
  irp->Tail.Overlay.OriginalFileObject = pFileObject; 
  irp->RequestorMode = KernelMode; 
  irp->Flags = 0; 
 
  ioStackLocation = IoGetNextIrpStackLocation(irp); 
  ioStackLocation->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; 
  ioStackLocation->MinorFunction = IRP_MN_QUERY_DIRECTORY; 
  ioStackLocation->DeviceObject = pDeviceObject; 
  ioStackLocation->FileObject = pFileObject; 
  ioStackLocation->Flags = 0; 
  if (ByOne) 
    ioStackLocation->Flags |= SL_RETURN_SINGLE_ENTRY; 
  if (Reset) 
    ioStackLocation->Flags |= SL_RESTART_SCAN; 
  if (Index) 
    ioStackLocation->Flags |= SL_INDEX_SPECIFIED; 
 
  pQueryDir = (PQUERY_DIRECTORY)&ioStackLocation->Parameters; 
  pQueryDir->Length = BufferLength; 
  pQueryDir->FileName = pSearchTemplate; 
  pQueryDir->FileInformationClass = DirectoryInfoClass; 
  pQueryDir->FileIndex = dwIndex; 
 
  IoSetCompletionRoutine(irp, NativeQueryDirectoryFileComplete, 0, TRUE, TRUE, TRUE); 
 
  if (pMajorFunction == NULL) 
  { 
    (void) IoCallDriver(pDeviceObject, irp); 
  } 
  else 
  { 
    --(irp->CurrentLocation); 
    if (irp->CurrentLocation <= 0) 
    { 
      KeBugCheckEx(NO_MORE_IRP_STACK_LOCATIONS, (ULONG)irp, 0, 0, 0); 
    } 
 
    --(irp->Tail.Overlay.CurrentStackLocation); 
 
    irp->Tail.Overlay.CurrentStackLocation->DeviceObject = pDeviceObject; 
    pMajorFunction(pDeviceObject, irp); 
  } 
 
  KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); 
 
  return pIoStatusBlock->Status; 
} 
 
PDEVICE_OBJECT GetVolumeDeviceObject(PFILE_OBJECT pFileObject) 
{ 
  PDEVICE_OBJECT pVolumeDeviceObject = NULL; 
 
  if (pFileObject != NULL) 
  { 
    if (pFileObject->Vpb != NULL) 
    { 
      pVolumeDeviceObject = pFileObject->Vpb->RealDevice; 
    } 
    else 
    { 
      if (pFileObject->DeviceObject != NULL && pFileObject->DeviceObject->Vpb != NULL) 
        pVolumeDeviceObject = pFileObject->DeviceObject->Vpb->RealDevice; 
    } 
  } 
 
  return pVolumeDeviceObject; 
} 
 
// 
// разное 
// 
 
BOOLEAN GetDirectoryFromPath(PWSTR lpwszFullFileName, ULONG dwSize) 
{ 
  ULONG i; 
 
  if (!_MmIsAddressValid(lpwszFullFileName) || !dwSize) 
    return FALSE; 
 
  i = dwSize; 
  while(1) 
  { 
    if (i == 0) 
      break; 
    if (lpwszFullFileName[i] == L'\\') 
    { 
      lpwszFullFileName[i] = 0; 
      break; 
    } 
    --i; 
  } 
 
  return TRUE; 
} 
 
BOOLEAN GetDirectoryFromPathA(CHAR *lpszFullFileName, ULONG dwSize) 
{ 
  ULONG i; 
 
  if (!_MmIsAddressValid(lpszFullFileName) || !dwSize) 
    return FALSE; 
 
  i = dwSize; 
  while(1) 
  { 
    if (i == 0) 
      break; 
    if (lpszFullFileName[i] == '\\') 
    { 
      lpszFullFileName[i] = 0; 
      break; 
    } 
    --i; 
  } 
 
  return TRUE; 
} 
 
int GetToken(WCHAR *lpInBuf, int dwInBufSize, WCHAR *lpOutBuf, int dwOutBufSize, WCHAR *lpDeliver, int nDeliverCount, int nNumber) 
{ 
  int      Count = 0, k, i, j; 
  BOOLEAN  bFlagExit; 
 
  if (!lpOutBuf || !lpInBuf || !lpDeliver) 
    return 0; 
  *lpOutBuf = 0; 
//  memset(lpOutBuf, 0, sizeof(WCHAR)*dwOutBufSize); 
 
  for (i=0; i= dwInBufSize)  
        { 
          ++j; 
          break; 
        } 
      } 
      lpOutBuf[j] = 0; 
      return j; 
    } 
  } 
 
  return 0; 
} 
 
NTQUERYDIRECTORYOBJECT GetPtrToZwQueryDirectoryObject(void) 
{ 
  static NTQUERYDIRECTORYOBJECT pFn = NULL; 
  LPSSDT                 lpSSDT; 
  LPSSD                  lpSSD; 
  ULONG                  dwNtBuildNumber; 
 
  if (pFn == NULL) 
  { 
    lpSSDT = (LPSSDT) KeServiceDescriptorTable; 
    lpSSD = &(lpSSDT->SystemServiceDescriptors[0]); 
     
    dwNtBuildNumber = (*NtBuildNumber) & 0x00ffffff; 
    switch (dwNtBuildNumber) 
    { 
      case 1381: // WinNT 4.0 
           pFn = (NTQUERYDIRECTORYOBJECT) *((PVOID*)(lpSSD->lpSystemServiceTableAddressTable)+0x66); 
           break; 
      case 2195: // Win2K 
           pFn = (NTQUERYDIRECTORYOBJECT) *((PVOID*)(lpSSD->lpSystemServiceTableAddressTable)+0x7e); 
           break; 
      default: 
           if (dwNtBuildNumber >= 1946) 
             pFn = (NTQUERYDIRECTORYOBJECT) *((PVOID*)(lpSSD->lpSystemServiceTableAddressTable)+0x7e); 
           else 
             pFn = NULL; 
           break; 
    } 
  } 
 
  return pFn; 
} 
 
 
// 
// оптимизация по скорости 
// 
SHARED_MEMORY* InitQueryObjectNameType(void) 
{ 
  BOOLEAN               bRes; 
  SHARED_MEMORY*        pSharedBuffer = NULL; 
 
  #ifdef __MISC_USE_KHEAP 
  pSharedBuffer = (SHARED_MEMORY*)_AllocatePoolFromKHeap(hKHeapMiscDefault, sizeof(SHARED_MEMORY)); 
  #else 
  pSharedBuffer = ExAllocatePool(NonPagedPool, sizeof(SHARED_MEMORY)); 
  #endif 
  if (pSharedBuffer != NULL) 
  { 
    bRes = AllocateSharedMemory(pSharedBuffer, NonPagedPool, 2048+4+4); 
    if (bRes == FALSE) 
    { 
      #ifdef __MISC_USE_KHEAP 
      FreePoolToKHeap(hKHeapMiscDefault, pSharedBuffer); 
      #else 
      ExFreePool(pSharedBuffer); 
      #endif 
      pSharedBuffer = NULL; 
    } 
  } 
 
  return pSharedBuffer; 
} 
 
// 
// оптимизация по скорости 
// 
void DeinitQueryObjectNameType(SHARED_MEMORY* pSharedBuffer) 
{ 
  if (_MmIsAddressValid(pSharedBuffer)) 
  { 
    FreeSharedMemory(pSharedBuffer); 
    #ifdef __MISC_USE_KHEAP 
    FreePoolToKHeap(hKHeapMiscDefault, pSharedBuffer); 
    #else 
    ExFreePool(pSharedBuffer); 
    #endif 
  } 
} 
 
BOOLEAN QueryObjectNameType(PVOID pObjTypeInfo, ULONG dwSizeOfObjTypeInfo, HANDLE hDir, PWSTR pwszObjectName, SHARED_MEMORY* pSharedBuffer) 
{ 
  CHAR*                  Buf; 
  POBJECT_NAMETYPE_INFO  pObjName; 
  ULONG*                 pObjectIndex = 0; 
  ULONG*                 pLengthReturned = 0; 
  ULONG                  Index = 0; 
  BOOLEAN                bFirst = TRUE; 
  int                    i; 
  NTQUERYDIRECTORYOBJECT pZwQueryDirectoryObject = 0; 
 
  if ( 
      !_MmIsAddressValid(pObjTypeInfo) || 
      !_MmIsAddressValid(pwszObjectName) || 
      !_MmIsAddressValid(pSharedBuffer) 
     ) 
    return FALSE; 
      
 
  pZwQueryDirectoryObject = GetPtrToZwQueryDirectoryObject(); 
  if (!_MmIsAddressValid(pZwQueryDirectoryObject)) 
  { 
    return FALSE; 
  } 
 
  Buf = (CHAR*)pSharedBuffer->m_lpUserMemory; 
  pObjName = (POBJECT_NAMETYPE_INFO) Buf; 
  pObjectIndex = (ULONG*)(Buf+2048); 
  pLengthReturned = (ULONG*)(Buf+2048+4); 
 
  while (pZwQueryDirectoryObject(hDir, Buf, 2048, ObjectArray, bFirst, pObjectIndex, pLengthReturned) >= 0) 
  { 
    bFirst = FALSE; 
    for (i=0; Index<*pObjectIndex; ++Index, ++i) 
    { 
      if (!_wcsnicmp(pObjName[i].ObjectName.Buffer, pwszObjectName, pObjName[i].ObjectName.Length/sizeof(WCHAR))) 
      { 
        *pObjectIndex = Index; 
        if (pZwQueryDirectoryObject(hDir, Buf, dwSizeOfObjTypeInfo, ObjectByOne, bFirst, pObjectIndex, pLengthReturned) == STATUS_SUCCESS) 
        { 
          memcpy(pObjTypeInfo, Buf, *pLengthReturned); 
          ((POBJECT_NAMETYPE_INFO)pObjTypeInfo)->ObjectName.Buffer = (PWSTR)((DWORD)pObjTypeInfo+((DWORD)(pObjName->ObjectName.Buffer)-(DWORD)pObjName)); 
          ((POBJECT_NAMETYPE_INFO)pObjTypeInfo)->ObjectType.Buffer = (PWSTR)((DWORD)pObjTypeInfo+((DWORD)(pObjName->ObjectType.Buffer)-(DWORD)pObjName)); 
          return TRUE; 
        } 
        return FALSE; 
      } 
    } 
  } 
   
  return FALSE; 
} 
 
ULONG DosPathNameToNtPathName(PWSTR pwszDosPath, PWSTR pwszNtPath, ULONG dwSizeNtPathByBytes, ULONG dwRecursiveDeep, PULONG pdwObjectSizeByBytes) 
{ 
  ULONG                 dwSizeOfNtPath = 0; 
  ULONG                 dwSizeOfDosPath; 
  PWSTR                 pwszCurrentDir, pwszPtrCurDir; 
  PWSTR                 pwszPtrDosPath, pwszPtr; 
  UNICODE_STRING        dirString; 
  OBJECT_ATTRIBUTES     dirAttr; 
  HANDLE                hDir; 
  NTSTATUS              NtStatus; 
  char                  Buf[512]; 
  POBJECT_NAMETYPE_INFO pObjName = (POBJECT_NAMETYPE_INFO) Buf; 
  ULONG                 dwRestDosPath, dwFreeCurDir, dwSizeToken; 
  ULONG                 _dwSizeNtPathByBytes = dwSizeNtPathByBytes; 
  HANDLE                hSymLink; 
  UNICODE_STRING        SymLinkString; 
  OBJECT_ATTRIBUTES     SymAttr; 
  ULONG                 dwSizeSymLinkObj = 0; 
  PWSTR                 pwszNewNtPath; 
  SHARED_MEMORY*        pSharedBuffer = NULL; 
 
//  return dwSizeOfNtPath; 
 
  DbgPrintMisc(("DosPathNameToNtPathName - start\n")); 
  
  if (KeGetCurrentIrql() > PASSIVE_LEVEL) 
    return dwSizeOfNtPath; 
 
  if (!_MmIsAddressValid(pwszNtPath)) 
    return dwSizeOfNtPath; 
  memset(pwszNtPath, 0, dwSizeNtPathByBytes); 
 
  dwSizeOfDosPath = wcslen(pwszDosPath); 
  if (dwSizeOfDosPath <= 1) 
    return dwSizeOfNtPath; 
 
  #ifdef __MISC_USE_KHEAP 
  pwszCurrentDir = (PWSTR)_AllocatePoolFromKHeap(hKHeapMiscDefault, sizeof(L"\\??\\")+(dwSizeOfDosPath+1)*sizeof(WCHAR)); 
  #else 
  pwszCurrentDir = ExAllocatePool(NonPagedPool, sizeof(L"\\??\\")+(dwSizeOfDosPath+1)*sizeof(WCHAR)); 
  #endif 
  if(!pwszCurrentDir) 
     return dwSizeOfNtPath; 
 
  memset(pwszCurrentDir, 0, sizeof(L"\\??\\")+(dwSizeOfDosPath+1)*sizeof(WCHAR)); 
 
  if (pwszDosPath[1] == L':') 
    wcscpy(pwszCurrentDir, L"\\??"); 
  else 
    wcscpy(pwszCurrentDir, L"\\"); 
 
  wcscpy(pwszNtPath, L"\\"); 
 
  pSharedBuffer = InitQueryObjectNameType();  // need for optimize by speed QueryObjectNameType() !!!!!!! 
 
  RtlInitUnicodeString(&dirString, pwszCurrentDir); 
  InitializeObjectAttributes(&dirAttr, &dirString, OBJ_CASE_INSENSITIVE, NULL, NULL); 
  NtStatus = ZwOpenDirectoryObject(&hDir, DIRECTORY_QUERY, &dirAttr); 
  if (NtStatus == STATUS_SUCCESS) 
  { 
    // хрен его знает - NT понимает оба разделителя '\', '/' 
    // однако путь до ядра доходит вроде уже обработанный и все разделители 
    // в нем '\'. однако я не уверен - поэтому добавил эту вещь. 
    pwszPtr = pwszDosPath; 
    while (*pwszPtr) 
    { 
      if (*pwszPtr == L'/') 
        *pwszPtr = L'\\'; 
      ++pwszPtr; 
    } 
 
    if (pwszDosPath[1] == L':') 
      wcscat(pwszCurrentDir, L"\\"); 
    pwszPtrCurDir = pwszCurrentDir + wcslen(pwszCurrentDir); 
    pwszPtrDosPath = pwszDosPath; 
    if (pwszPtrDosPath[0] == L'\\') 
      ++pwszPtrDosPath; 
    dwFreeCurDir = ((sizeof(L"\\??\\")/sizeof(WCHAR))+dwSizeOfDosPath+1) - (pwszPtrCurDir - pwszCurrentDir); 
    dwRestDosPath = dwSizeOfDosPath - (pwszPtrDosPath - pwszDosPath); 
     
    while ((dwSizeToken = GetToken(pwszPtrDosPath, dwRestDosPath,  pwszPtrCurDir, dwFreeCurDir, L"\\", 1, 0))) 
    { 
      dwFreeCurDir -= dwSizeToken; 
      if (dwFreeCurDir != 0) 
        --dwFreeCurDir;//sizeof(L'\\'); 
      dwRestDosPath -= dwSizeToken; 
      if (dwRestDosPath != 0) 
        --dwRestDosPath;//sizeof(L'\\'); 
 
      if (QueryObjectNameType(Buf, sizeof(Buf), hDir, pwszPtrCurDir, pSharedBuffer)) 
      { 
        if (!wcsncmp(pObjName->ObjectType.Buffer, L"Directory", pObjName->ObjectType.Length/sizeof(WCHAR))) 
        { 
          if (_dwSizeNtPathByBytes < ((wcslen(pObjName->ObjectName.Buffer)+2)*sizeof(WCHAR))) 
          { 
            dwSizeOfNtPath = 0; 
            break; 
          } 
          wcscat(pwszNtPath, pObjName->ObjectName.Buffer); 
          wcscat(pwszNtPath, L"\\"); 
          _dwSizeNtPathByBytes -= ((wcslen(pObjName->ObjectName.Buffer)+1)*sizeof(WCHAR)); 
 
          ZwClose(hDir); 
          RtlInitUnicodeString(&dirString, pwszCurrentDir); 
          InitializeObjectAttributes(&dirAttr, &dirString, OBJ_CASE_INSENSITIVE, NULL, NULL); 
          NtStatus = ZwOpenDirectoryObject(&hDir, DIRECTORY_QUERY, &dirAttr); 
          if (NtStatus != STATUS_SUCCESS) 
          { 
            dwSizeOfNtPath = 0; 
            break; 
          } 
        } 
        else 
        { 
          if (!wcsncmp(pObjName->ObjectType.Buffer, L"SymbolicLink", pObjName->ObjectType.Length/sizeof(WCHAR))) 
          { 
            dwSizeOfNtPath = 0; 
 
            RtlInitUnicodeString(&SymLinkString, pObjName->ObjectName.Buffer); 
            InitializeObjectAttributes(&SymAttr, &SymLinkString, OBJ_CASE_INSENSITIVE, hDir, NULL); 
            if (ZwOpenSymbolicLinkObject(&hSymLink, SYMBOLIC_LINK_QUERY, &SymAttr) == STATUS_SUCCESS) 
            { 
              SymLinkString.Buffer = (PWSTR)pwszNtPath; 
              SymLinkString.Length = 0; 
              SymLinkString.MaximumLength = (WORD)dwSizeNtPathByBytes - wcslen(pwszPtrDosPath)*sizeof(WCHAR); 
 
              if (ZwQuerySymbolicLinkObject(hSymLink, &SymLinkString, &dwSizeSymLinkObj) == STATUS_SUCCESS) 
              { 
                if (pwszNtPath[0] == L'\\' && memcmp(pwszDosPath, pwszNtPath, SymLinkString.Length)) 
                { 
                  if (_dwSizeNtPathByBytes < (wcslen(pwszPtrDosPath+dwSizeToken)*sizeof(WCHAR))) 
                  { 
                    dwSizeOfNtPath = 0; 
                    ZwClose(hSymLink); 
                    break; 
                  } 
                  wcscat(pwszNtPath, pwszPtrDosPath+dwSizeToken); 
                  #ifdef __MISC_USE_KHEAP 
                  pwszNewNtPath = (PWSTR) _AllocatePoolFromKHeap(hKHeapMiscDefault, dwSizeNtPathByBytes); 
                  #else 
                  pwszNewNtPath= (PWSTR) ExAllocatePool(NonPagedPool, dwSizeNtPathByBytes); 
                  #endif 
                  if (pwszNewNtPath) 
                  { 
                    DbgPrintMisc(("DosPathNameToNtPathName - recursive start\n")); 
                    if (dwRecursiveDeep != 0) 
                    { 
                      dwSizeOfNtPath = DosPathNameToNtPathName(pwszNtPath, pwszNewNtPath, dwSizeNtPathByBytes, --dwRecursiveDeep, pdwObjectSizeByBytes); 
                      if (dwSizeOfNtPath) 
                      { 
                        wcscpy(pwszNtPath, pwszNewNtPath); 
                      } 
                    } 
                    #ifdef __MISC_USE_KHEAP 
                    FreePoolToKHeap(hKHeapMiscDefault, pwszNewNtPath); 
                    #else 
                    ExFreePool(pwszNewNtPath); 
                    #endif 
                  } 
                } 
              } 
              ZwClose(hSymLink); 
            } 
            break; 
          } 
          else  // не директория и не ссылка 
          { 
            if (_MmIsAddressValid(pdwObjectSizeByBytes)) // возвращается длина имени объекта которому принадлежит остаток пути 
            { 
              *pdwObjectSizeByBytes = wcslen(pwszNtPath)*sizeof(WCHAR); 
            } 
 
            wcscat(pwszNtPath, pwszPtrDosPath); 
            dwSizeOfNtPath = wcslen(pwszNtPath)*sizeof(WCHAR); 
            break; 
          } 
        } 
      } 
      else 
      { 
        dwSizeOfNtPath = 0; 
        break; 
      } 
 
      wcscat(pwszPtrCurDir, L"\\"); 
      pwszPtrCurDir += dwSizeToken + 1; // add wcslen(L"\\"); 
      pwszPtrDosPath += dwSizeToken + 1; 
    } 
    ZwClose(hDir); 
  } 
 
  DeinitQueryObjectNameType(pSharedBuffer); 
 
  #ifdef __MISC_USE_KHEAP 
  FreePoolToKHeap(hKHeapMiscDefault, pwszCurrentDir); 
  #else 
  ExFreePool(pwszCurrentDir); 
  #endif 
 
  DbgPrintMisc(("DosPathNameToNtPathName - end\n")); 
 
  return dwSizeOfNtPath; 
} 
 
VOID FlushInstuctionCache(VOID) 
{ 
  ULONG                 pNextInstr; 
 
//  __asm _emit 0eah // data into code 
  __asm 
  { 
    push eax 
    mov  eax, offset __NextInstr 
    mov  [pNextInstr], eax 
    pop  eax 
    jmp  dword ptr [pNextInstr] 
  } 
__NextInstr: 
 
  return; 
} 
 
//PDEVICE_OBJECT GetOwnDeviceObject(PDEVICE_OBJECT DeviceObject) 
//{ 
//  __asm int 1h 
//  while (_MmIsAddressValid(DeviceObject)) 
//  { 
//    if (_MmIsAddressValid(DeviceObject->DeviceObjectExtension)) 
//    { 
//      if (_MmIsAddressValid(DeviceObject->DeviceObjectExtension->DeviceObject)) 
//      { 
//        __asm int 1h 
//        if (DeviceObject != DeviceObject->DeviceObjectExtension->DeviceObject) 
//          DeviceObject = DeviceObject->DeviceObjectExtension->DeviceObject; 
//        else 
//          break; 
//      } 
//      else 
//        break; 
//    } 
//    else 
//    { 
//      break; 
//    } 
//  } 
// 
//  return DeviceObject; 
//} 
 
PDEVICE_OBJECT GetOwnDeviceObject(PDEVICE_OBJECT DeviceObject) 
{ 
  PDRIVER_OBJECT pDriverObject; 
  PDEVICE_OBJECT pDevice, pDeviceAttached; 
  BOOLEAN        bFind = FALSE; 
 
  #if 0 
  if (!_MmIsAddressValid(DeviceObject)) 
    return NULL; 
 
  pDriverObject = DeviceObject->DriverObject; 
 
  if (!_MmIsAddressValid(pDriverObject)) 
    return NULL; 
 
  pDevice = pDriverObject->DeviceObject; 
  while (_MmIsAddressValid(pDevice)) 
  { 
    pDeviceAttached = pDevice; 
    while (_MmIsAddressValid(pDeviceAttached)) 
    { 
      if (pDeviceAttached->AttachedDevice == DeviceObject) 
      { 
        DeviceObject = GetOwnDeviceObject(pDeviceAttached); 
        bFind = TRUE; 
        break; 
      } 
      pDeviceAttached = pDeviceAttached->AttachedDevice; 
    } 
    if (bFind == TRUE) 
      break; 
 
    pDevice = pDevice->NextDevice; 
  } 
  #endif 
 
  if (!DeviceObject) 
    return NULL; 
 
  pDriverObject = DeviceObject->DriverObject; 
 
  if (!pDriverObject) 
    return NULL; 
 
  pDevice = pDriverObject->DeviceObject; 
  while (pDevice) 
  { 
    pDeviceAttached = pDevice; 
    while (pDeviceAttached) 
    { 
      if (pDeviceAttached->AttachedDevice == DeviceObject) 
      { 
        DeviceObject = GetOwnDeviceObject(pDeviceAttached); 
        bFind = TRUE; 
        break; 
      } 
      pDeviceAttached = pDeviceAttached->AttachedDevice; 
    } 
    if (bFind == TRUE) 
      break; 
 
    pDevice = pDevice->NextDevice; 
  } 
 
  return DeviceObject; 
} 
 
PDEVICE_OBJECT GetOwnDeviceObjectFromIrp(PIRP pIrp) 
{ 
  PDEVICE_OBJECT      pDevice = NULL; 
  CHAR                CurrentLocation; 
  PIO_STACK_LOCATION  CurrentIrpStack; 
 
  if (pIrp == NULL) 
    return pDevice; 
 
  CurrentLocation = pIrp->CurrentLocation; 
  CurrentIrpStack = IoGetCurrentIrpStackLocation(pIrp); 
 
  pDevice = CurrentIrpStack->DeviceObject; 
  while (--CurrentLocation) 
  { 
    --CurrentIrpStack; 
    if (CurrentIrpStack->DeviceObject != NULL) 
      pDevice = CurrentIrpStack->DeviceObject; 
  } 
 
  return pDevice; 
} 
 
NTSTATUS DefaultDriverObjectDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 
{ 
  Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 
 
  IoCompleteRequest(Irp, IO_NO_INCREMENT); 
 
  return STATUS_INVALID_DEVICE_REQUEST; 
} 
 
PDRIVER_OBJECT CreateInvisibleDriverObject(PVOID pBaseAddress, ULONG dwDriverSize, HANDLE hSystemImage, PDRIVER_INITIALIZE DriverEntry) 
{ 
  NTSTATUS          NtStatus; 
  OBJECT_ATTRIBUTES ObjectAttributes; 
  WCHAR             DriverName[] = L"\\Driver\\HiddenDriver"; 
  UNICODE_STRING    UniDriverName; 
  PDRIVER_OBJECT    pObjectBody = NULL; 
  HANDLE            hDriver; 
  int               i; 
 
  RtlInitUnicodeString(&UniDriverName, DriverName); 
  InitializeObjectAttributes(&ObjectAttributes, NULL/*&UniDriverName*/, OBJ_PERMANENT, NULL, NULL); 
 
  NtStatus = ObCreateObject(KernelMode, (POBJECT_TYPE)IoDriverObjectType, &ObjectAttributes,    
                            KernelMode, 0, sizeof(DRIVER_OBJECT) + sizeof(DRIVER_EXTENSION), 
                            0, 0, (PVOID*)&pObjectBody); 
  if (NtStatus != STATUS_SUCCESS) 
  { 
    DbgPrint ("CreateInvisibleDriverObject: NtStatus = %08x \n", NtStatus); 
    return NULL; 
  } 
 
  memset(pObjectBody, 0, sizeof(DRIVER_OBJECT) + sizeof(DRIVER_EXTENSION)); 
 
  pObjectBody->DriverExtension = (PDRIVER_EXTENSION)((PCHAR)pObjectBody + sizeof(DRIVER_OBJECT)); 
  pObjectBody->DriverExtension->DriverObject = pObjectBody; // ?????? 
 
  pObjectBody->DriverStart = pBaseAddress; 
  pObjectBody->DriverSize = dwDriverSize; 
  pObjectBody->DriverSection = hSystemImage; 
 
  pObjectBody->DriverInit = DriverEntry; 
 
  for (i = 0; iMajorFunction[i] = DefaultDriverObjectDispatch; 
 
  pObjectBody->Type = IO_TYPE_DRIVER; 
  pObjectBody->Size = sizeof(DRIVER_OBJECT); 
 
  NtStatus = ObInsertObject(pObjectBody, NULL, 1, 0, 0, &hDriver); 
  if (NtStatus != STATUS_SUCCESS) 
  { 
    // delete object 
    DbgPrint ("CreateInvisibleDriverObject: NtStatus = %08x \n", NtStatus); 
    return NULL; 
  } 
 
  return pObjectBody; 
} 
 
HANDLE LoadDevice(PWSTR pwszDeviceFileName) 
{ 
  SYSTEM_LOAD_DRIVER  LoadDriverInfo; 
  NTSTATUS            NtStatus; 
 
  if (pwszDeviceFileName == NULL) 
    return NULL; 
 
  memset(&LoadDriverInfo, 0, sizeof(LoadDriverInfo)); 
 
  RtlInitUnicodeString(&LoadDriverInfo.usImageFile, pwszDeviceFileName); 
 
  NtStatus = ZwSetSystemInformation(SystemLoadDriver, &LoadDriverInfo, sizeof(LoadDriverInfo)); 
 
  DbgPrint ("Loadevice: \n  pBaseAddress = %08x\n  hSystemImage = %08x\n  pEntryPoint = %08x\n  pDirectoryEntry = %08x\n", 
                             LoadDriverInfo.pBaseAddress, LoadDriverInfo.hSystemImage, LoadDriverInfo.pEntryPoint, LoadDriverInfo.pDirectoryEntry); 
 
//  if (NtStatus == STATUS_SUCCESS) 
//    *((CHAR*)LoadDriverInfo.pBaseAddress) = 'M'; 
 
  return LoadDriverInfo.hSystemImage; 
} 
 
NTSTATUS UnloadDevice(HANDLE hSystemImage) 
{ 
  SYSTEM_UNLOAD_DRIVER  UnLoadDriverInfo; 
  NTSTATUS              NtStatus; 
 
  UnLoadDriverInfo.hSystemImage = hSystemImage; 
 
  NtStatus = ZwSetSystemInformation(SystemUnloadDriver, &UnLoadDriverInfo, sizeof(UnLoadDriverInfo)); 
 
  return NtStatus; 
} 
 
BOOLEAN DeleteItemFromQueryDirectoryBuffer(PFQD_SmallCommonBlock pQueryDirPrev, PFQD_SmallCommonBlock pQueryDir, PVOID Buffer, ULONG BufferLength, PIO_STATUS_BLOCK IoStatusBlock, FILE_INFORMATION_CLASS DirectoryInfoClass, NTSTATUS* NtStatus) 
{ 
  BOOLEAN               bRes = FALSE; 
  PFQD_SmallCommonBlock pQueryDirSave; 
  ULONG                 dwSizeItem; 
 
  if (pQueryDir->NextEntryOffset == 0) 
  { 
    if (pQueryDir != Buffer) 
    { 
      pQueryDirPrev->NextEntryOffset = 0; 
      if (_MmIsAddressValid(IoStatusBlock)) 
      { 
        dwSizeItem = 0; 
        switch (DirectoryInfoClass) 
        { 
          case 0: 
               dwSizeItem = (SIZE_OF_FILE_NAMES_INFORMATION + ((PFILE_NAMES_INFORMATION)pQueryDir)->FileNameLength); 
               break; 
          case FileDirectoryInformation: 
               dwSizeItem = (SIZE_OF_FILE_DIRECTORY_INFORMATION + ((PFILE_DIRECTORY_INFORMATION)pQueryDir)->CommonBlock.FileNameLength); 
               break; 
          case FileFullDirectoryInformation: 
               dwSizeItem = (SIZE_OF_FILE_FULL_DIR_INFORMATION + ((PFILE_FULL_DIR_INFORMATION)pQueryDir)->CommonBlock.FileNameLength); 
               break; 
          case FileBothDirectoryInformation: 
               dwSizeItem = (SIZE_OF_FILE_BOTH_DIR_INFORMATION + ((PFILE_BOTH_DIR_INFORMATION)pQueryDir)->CommonBlock.FileNameLength); 
               break; 
        } 
        if (IoStatusBlock->Information > dwSizeItem) 
        { 
          IoStatusBlock->Information -= dwSizeItem; 
//          memset(pQueryDir, 0, dwSizeItem); 
        } 
        else 
        { 
          *NtStatus = STATUS_NO_MORE_FILES; 
          IoStatusBlock->Status = STATUS_NO_MORE_FILES; 
          IoStatusBlock->Information = 0; 
        } 
      } 
    } 
    else 
    { 
      *NtStatus = STATUS_NO_MORE_FILES; 
      if (_MmIsAddressValid(IoStatusBlock)) 
      { 
        IoStatusBlock->Status = STATUS_NO_MORE_FILES; 
        IoStatusBlock->Information = 0; 
      } 
    } 
    bRes = TRUE; 
  } 
  else 
  { 
    pQueryDirSave = pQueryDir; 
    if (_MmIsAddressValid(IoStatusBlock)) 
    { 
      if (IoStatusBlock->Information >= pQueryDir->NextEntryOffset) 
        IoStatusBlock->Information -= pQueryDir->NextEntryOffset; 
      else 
        IoStatusBlock->Information = 0; 
    } 
    pQueryDir = (PFQD_SmallCommonBlock)((CHAR*)pQueryDir + pQueryDir->NextEntryOffset); 
    memmove(pQueryDirSave, pQueryDir, BufferLength - ((CHAR*)pQueryDir-(CHAR*)Buffer)); 
  } 
 
  return bRes; 
} 
 
LPSSDT FindShadowTable(void) 
{ 
  BYTE*       pCheckArea = (BYTE*) KeAddSystemServiceTable; 
  int         i; 
  PSRVTABLE   pSrvTable = NULL; 
 
  for (i=0; i<100; i++) 
  { 
    __try 
    { 
      pSrvTable = *(PSRVTABLE*)pCheckArea; 
      if ( 
          !MmIsAddressValid(pSrvTable)            || 
          (pSrvTable == KeServiceDescriptorTable) || 
          (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0) 
         ) 
      { 
        pCheckArea++; 
        pSrvTable = NULL; 
      } 
    } 
    __except(EXCEPTION_EXECUTE_HANDLER) 
    { 
      pSrvTable = NULL; 
    } 
    if (pSrvTable) 
      break; 
  } 
 
  if (pSrvTable == NULL) 
  { 
    pSrvTable = (PSRVTABLE)((char*)KeServiceDescriptorTable-0x230); 
    if (MmIsAddressValid(pSrvTable)) 
    { 
      __try 
      { 
        if (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0) 
          pSrvTable = NULL; 
      } 
      __except(EXCEPTION_EXECUTE_HANDLER) 
      { 
        pSrvTable = NULL; 
      } 
    } 
    else 
    { 
      pSrvTable = NULL; 
    } 
  } 
 
  return (LPSSDT)pSrvTable; 
} 
 
 
#if 0 
ULONG GetFullPathbyFileObjectA(PFILE_OBJECT fileObject, PCHAR fullPathName, ULONG nfullPathNameSize) 
{ 
  ULONG               pathLen; 
  PCHAR               pathOffset; 
  PFILE_OBJECT        relatedFileObject; 
  ANSI_STRING         componentName; 
  PDEVICE_OBJECT      pDeviceObject; 
  PUNICODE_STRING     fullUniName; 
  ULONG               dwFreeSize = nfullPathNameSize; 
 
  if (!fullPathName || !nfullPathNameSize) 
    return 0; 
 
  fullPathName[0] = 0; 
 
  try 
  { 
    if (fileObject == 0) 
    { 
      return 0; 
    } 
 
    pDeviceObject = GetVolumeDeviceObject(fileObject); 
    if (pDeviceObject == NULL) 
    { 
      pDeviceObject = IoGetRelatedDeviceObject(fileObject); 
    } 
 
    fullUniName = (PUNICODE_STRING)_AllocatePoolFromKHeap(hKHeapDHDefault, nfullPathNameSize*sizeof(WCHAR)+sizeof(UNICODE_STRING)); 
    fullUniName->MaximumLength = (USHORT)nfullPathNameSize*sizeof(WCHAR); 
 
    if (NT_SUCCESS(ObQueryNameString(pDeviceObject, (POBJECT_NAME_INFORMATION)fullUniName, fullUniName->MaximumLength, &pathLen))) 
    { 
      RtlUnicodeStringToAnsiString( &componentName, fullUniName, TRUE );  
      if (componentName.Buffer[0]) 
      {          
        strncatZ(fullPathName, componentName.Buffer, fullUniName->MaximumLength - 2); 
        DbgPrint ("%s\n", fullPathName); 
      } 
      RtlFreeAnsiString(&componentName); 
    } 
    else 
    { 
      return 0; 
    } 
 
    if (!fileObject->FileName.Length || fileObject->FileName.Length > nfullPathNameSize) 
    { 
      return strlen(fullPathName); 
    } 
 
//    strcat(fullPathName, "\\"); 
    dwFreeSize -= strlen(fullPathName); 
  } 
  except(EXCEPTION_EXECUTE_HANDLER) 
  { 
    return 0; 
  } 
 
  try 
  { 
    pathLen = fileObject->FileName.Length/sizeof(WCHAR) + 1; 
 
    relatedFileObject = fileObject->RelatedFileObject; 
   
    if (fileObject->FileName.Buffer[0] != L'\\' ) 
    { 
      while (relatedFileObject) 
      { 
        if ((pathLen + relatedFileObject->FileName.Length/sizeof(WCHAR) + 1) >= dwFreeSize) 
        { 
          break; 
        } 
        pathLen += relatedFileObject->FileName.Length/sizeof(WCHAR) + 1; 
        relatedFileObject = relatedFileObject->RelatedFileObject; 
      } 
    } 
 
    if (dwFreeSize == nfullPathNameSize) 
      sprintf(fullPathName, "\\"); 
   
    pathOffset = fullPathName + strlen(fullPathName) - sizeof(char) + pathLen - fileObject->FileName.Length/sizeof(WCHAR); 
    RtlUnicodeStringToAnsiString( &componentName, &fileObject->FileName, TRUE );     
    strncpy( pathOffset, componentName.Buffer, componentName.Length + 1 ); 
    RtlFreeAnsiString( &componentName ); 
 
    relatedFileObject = fileObject->RelatedFileObject; 
   
    if (fileObject->FileName.Buffer[0] != L'\\') 
    { 
      while (relatedFileObject) 
      { 
        *(pathOffset - 1) = '\\'; 
        pathOffset -= relatedFileObject->FileName.Length/sizeof(WCHAR) + 1; 
 
        if (pathOffset <= fullPathName) 
        { 
          break; 
        } 
        RtlUnicodeStringToAnsiString(&componentName, &relatedFileObject->FileName, TRUE); 
        strncpy(pathOffset, componentName.Buffer, componentName.Length); 
        RtlFreeAnsiString(&componentName); 
 
        relatedFileObject = relatedFileObject->RelatedFileObject; 
      } 
    }   
 
  } 
  except(EXCEPTION_EXECUTE_HANDLER) 
  { 
     DbgPrint ("He4Hook: GetFullPath: EXCEPTION\n"); 
  } 
 
//  __asm int 1h 
  return strlen(fullPathName); 
} 
#endif //0