⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdiobj.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
            /* FIXME */
            Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
            if(NT_SUCCESS(Status))
            {
              W32Process = (PW32PROCESS)OldProcess->Win32Process;
              if(W32Process != NULL)
              {
                InterlockedDecrement(&W32Process->GDIObjects);
              }
              ObDereferenceObject(OldProcess);
            }
          }

          /* remove the process id lock and make it global */
          (void)InterlockedExchangePointer(&Entry->ProcessId, GDI_GLOBAL_PROCESS);

          *hObj = (HGDIOBJ)((ULONG)(*hObj) | GDI_HANDLE_STOCK_MASK);

          /* we're done, successfully converted the object */
          return TRUE;
        }
        else
        {
#ifdef GDI_DEBUG
          if(++Attempts > 20)
          {
            if(GdiHdr->lockfile != NULL)
            {
              DPRINT1("[%d]Locked %s:%i by 0x%x (we're 0x%x)\n", Attempts, GdiHdr->lockfile, GdiHdr->lockline, PrevThread, Thread);
            }
          }
#endif
          /* WTF?! The object is already locked by a different thread!
             Release the lock, wait a bit and try again!
             FIXME - we should give up after some time unless we want to wait forever! */
          (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId);

          DelayExecution();
          goto LockHandle;
        }
      }
      else
      {
        DPRINT1("Attempted to convert object 0x%x that is deleted! Should never get here!!!\n", hObj);
      }
    }
    else if(PrevProcId == LockedProcessId)
    {
#ifdef GDI_DEBUG
    if(++Attempts > 20)
    {
      DPRINT1("[%d]Waiting on 0x%x\n", Attempts, hObj);
    }
#endif
      /* the object is currently locked, wait some time and try again.
         FIXME - we shouldn't loop forever! Give up after some time! */
      DelayExecution();
      /* try again */
      goto LockHandle;
    }
    else
    {
      DPRINT1("Attempted to convert invalid handle: 0x%x\n", hObj);
    }
  }

  return FALSE;
}

void INTERNAL_CALL
GDIOBJ_SetOwnership(PGDI_HANDLE_TABLE HandleTable, HGDIOBJ ObjectHandle, PEPROCESS NewOwner)
{
  PGDI_TABLE_ENTRY Entry;
  HANDLE ProcessId, LockedProcessId, PrevProcId;
  PETHREAD Thread;
#ifdef GDI_DEBUG
  ULONG Attempts = 0;
#endif

  DPRINT("GDIOBJ_SetOwnership: hObj: 0x%x, NewProcess: 0x%x\n", ObjectHandle, (NewOwner ? PsGetProcessId(NewOwner) : 0));

  Thread = PsGetCurrentThread();

  if(!GDI_HANDLE_IS_STOCKOBJ(ObjectHandle))
  {
    ProcessId = PsGetCurrentProcessId();
    LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);

    Entry = GDI_HANDLE_GET_ENTRY(HandleTable, ObjectHandle);

LockHandle:
    /* lock the object, we must not convert stock objects, so don't check!!! */
    PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, ProcessId, LockedProcessId);
    if(PrevProcId == ProcessId)
    {
      PETHREAD PrevThread;

      if((Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && Entry->KernelData != NULL)
      {
        PGDIOBJHDR GdiHdr = GDIBdyToHdr(Entry->KernelData);

        PrevThread = GdiHdr->LockingThread;
        if(GdiHdr->Locks == 0 || PrevThread == Thread)
        {
          PEPROCESS OldProcess;
          PW32PROCESS W32Process;
          NTSTATUS Status;

          /* dereference the process' object counter */
          /* FIXME */
          if((ULONG_PTR)PrevProcId & ~0x1)
          {
            Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
            if(NT_SUCCESS(Status))
            {
              W32Process = (PW32PROCESS)OldProcess->Win32Process;
              if(W32Process != NULL)
              {
                InterlockedDecrement(&W32Process->GDIObjects);
              }
              ObDereferenceObject(OldProcess);
            }
          }

          if(NewOwner != NULL)
          {
            ProcessId = PsGetProcessId(NewOwner);

            /* Increase the new process' object counter */
            W32Process = (PW32PROCESS)NewOwner->Win32Process;
            if(W32Process != NULL)
            {
              InterlockedIncrement(&W32Process->GDIObjects);
            }
          }
          else
            ProcessId = 0;

          /* remove the process id lock and change it to the new process id */
          (void)InterlockedExchangePointer(&Entry->ProcessId, ProcessId);

          /* we're done! */
          return;
        }
        else
        {
#ifdef GDI_DEBUG
          if(++Attempts > 20)
          {
            if(GdiHdr->lockfile != NULL)
            {
              DPRINT1("[%d]Locked from %s:%i by 0x%x (we're 0x%x)\n", Attempts, GdiHdr->lockfile, GdiHdr->lockline, PrevThread, Thread);
            }
          }
#endif
          /* WTF?! The object is already locked by a different thread!
             Release the lock, wait a bit and try again! DO reset the pid lock
             so we make sure we don't access invalid memory in case the object is
             being deleted in the meantime (because we don't have aquired a reference
             at this point).
             FIXME - we should give up after some time unless we want to wait forever! */
          (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId);

          DelayExecution();
          goto LockHandle;
        }
      }
      else
      {
        DPRINT1("Attempted to change ownership of an object 0x%x currently being destroyed!!!\n", ObjectHandle);
      }
    }
    else if(PrevProcId == LockedProcessId)
    {
#ifdef GDI_DEBUG
    if(++Attempts > 20)
    {
      DPRINT1("[%d]Waiting on 0x%x\n", Attempts, ObjectHandle);
    }
#endif
      /* the object is currently locked, wait some time and try again.
         FIXME - we shouldn't loop forever! Give up after some time! */
      DelayExecution();
      /* try again */
      goto LockHandle;
    }
    else if(((ULONG_PTR)PrevProcId & ~0x1) == 0)
    {
      /* allow changing ownership of global objects */
      ProcessId = NULL;
      LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
      goto LockHandle;
    }
    else if((HANDLE)((ULONG_PTR)PrevProcId & ~0x1) != PsGetCurrentProcessId())
    {
      DPRINT1("Attempted to change ownership of object 0x%x (pid: 0x%x) from pid 0x%x!!!\n", ObjectHandle, (ULONG_PTR)PrevProcId & ~0x1, PsGetCurrentProcessId());
    }
    else
    {
      DPRINT1("Attempted to change owner of invalid handle: 0x%x\n", ObjectHandle);
    }
  }
}

void INTERNAL_CALL
GDIOBJ_CopyOwnership(PGDI_HANDLE_TABLE HandleTable, HGDIOBJ CopyFrom, HGDIOBJ CopyTo)
{
  PGDI_TABLE_ENTRY FromEntry;
  PETHREAD Thread;
  HANDLE FromProcessId, FromLockedProcessId, FromPrevProcId;
#ifdef GDI_DEBUG
  ULONG Attempts = 0;
#endif

  DPRINT("GDIOBJ_CopyOwnership: from: 0x%x, to: 0x%x\n", CopyFrom, CopyTo);

  Thread = PsGetCurrentThread();

  if(!GDI_HANDLE_IS_STOCKOBJ(CopyFrom) && !GDI_HANDLE_IS_STOCKOBJ(CopyTo))
  {
    FromEntry = GDI_HANDLE_GET_ENTRY(HandleTable, CopyFrom);

    FromProcessId = (HANDLE)((ULONG_PTR)FromEntry->ProcessId & ~0x1);
    FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1);

LockHandleFrom:
    /* lock the object, we must not convert stock objects, so don't check!!! */
    FromPrevProcId = InterlockedCompareExchangePointer(&FromEntry->ProcessId, FromProcessId, FromLockedProcessId);
    if(FromPrevProcId == FromProcessId)
    {
      PETHREAD PrevThread;
      PGDIOBJHDR GdiHdr;

      if((FromEntry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && FromEntry->KernelData != NULL)
      {
        GdiHdr = GDIBdyToHdr(FromEntry->KernelData);

        /* save the pointer to the calling thread so we know it was this thread
           that locked the object */
        PrevThread = GdiHdr->LockingThread;
        if(GdiHdr->Locks == 0 || PrevThread == Thread)
        {
          /* now let's change the ownership of the target object */

          if(((ULONG_PTR)FromPrevProcId & ~0x1) != 0)
          {
            PEPROCESS ProcessTo;
            /* FIXME */
            if(NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1), &ProcessTo)))
            {
              GDIOBJ_SetOwnership(HandleTable, CopyTo, ProcessTo);
              ObDereferenceObject(ProcessTo);
            }
          }
          else
          {
            /* mark the object as global */
            GDIOBJ_SetOwnership(HandleTable, CopyTo, NULL);
          }

          (void)InterlockedExchangePointer(&FromEntry->ProcessId, FromPrevProcId);
        }
        else
        {
#ifdef GDI_DEBUG
          if(++Attempts > 20)
          {
            if(GdiHdr->lockfile != NULL)
            {
              DPRINT1("[%d]Locked from %s:%i by 0x%x (we're 0x%x)\n", Attempts, GdiHdr->lockfile, GdiHdr->lockline, PrevThread, Thread);
            }
          }
#endif
          /* WTF?! The object is already locked by a different thread!
             Release the lock, wait a bit and try again! DO reset the pid lock
             so we make sure we don't access invalid memory in case the object is
             being deleted in the meantime (because we don't have aquired a reference
             at this point).
             FIXME - we should give up after some time unless we want to wait forever! */
          (void)InterlockedExchangePointer(&FromEntry->ProcessId, FromPrevProcId);

          DelayExecution();
          goto LockHandleFrom;
        }
      }
      else
      {
        DPRINT1("Attempted to copy ownership from an object 0x%x currently being destroyed!!!\n", CopyFrom);
      }
    }
    else if(FromPrevProcId == FromLockedProcessId)
    {
#ifdef GDI_DEBUG
    if(++Attempts > 20)
    {
      DPRINT1("[%d]Waiting on 0x%x\n", Attempts, CopyFrom);
    }
#endif
      /* the object is currently locked, wait some time and try again.
         FIXME - we shouldn't loop forever! Give up after some time! */
      DelayExecution();
      /* try again */
      goto LockHandleFrom;
    }
    else if((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1) != PsGetCurrentProcessId())
    {
      /* FIXME - should we really allow copying ownership from objects that we don't even own? */
      DPRINT1("WARNING! Changing copying ownership of object 0x%x (pid: 0x%x) to pid 0x%x!!!\n", CopyFrom, (ULONG_PTR)FromPrevProcId & ~0x1, PsGetCurrentProcessId());
      FromProcessId = (HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1);
      FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1);
      goto LockHandleFrom;
    }
    else
    {
      DPRINT1("Attempted to copy ownership from invalid handle: 0x%x\n", CopyFrom);
    }
  }
}

PVOID INTERNAL_CALL
GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process)
{
    PVOID MappedView = NULL;
    NTSTATUS Status;
    LARGE_INTEGER Offset;
    ULONG ViewSize = sizeof(GDI_HANDLE_TABLE);

    Offset.QuadPart = 0;

    ASSERT(SectionObject != NULL);
    ASSERT(Process != NULL);

    Status = MmMapViewOfSection(SectionObject,
                                Process,
                                &MappedView,
                                0,
                                0,
                                &Offset,
                                &ViewSize,
                                ViewUnmap,
                                SEC_NO_CHANGE,
                                PAGE_READONLY);

    if (!NT_SUCCESS(Status))
        return NULL;

    return MappedView;
}

W32KAPI
HANDLE
APIENTRY
NtGdiCreateClientObj(
    IN ULONG ulType
    )
{
  UNIMPLEMENTED;
  return 0;
}

W32KAPI
BOOL
APIENTRY
NtGdiDeleteClientObj(
    IN HANDLE h
    )
{
  UNIMPLEMENTED;
  return 0;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -