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

📄 class.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
            /* make a copy of the string */
            if (pszMenuNameBuffer != NULL)
            {
                Class->MenuNameIsString = TRUE;

                Class->MenuName = pszMenuNameBuffer;
                RtlCopyMemory(Class->MenuName,
                              MenuName->Buffer,
                              MenuName->Length);
                Class->MenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;

                pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1;
            }
            else
                Class->MenuName = MenuName->Buffer;

            /* save an ansi copy of the string */
            if (pszMenuNameBuffer != NULL)
            {
                ANSI_STRING AnsiString;

                Class->AnsiMenuName = (PSTR)pszMenuNameBuffer;
                AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName);
                AnsiString.Buffer = Class->AnsiMenuName;
                Status = RtlUnicodeStringToAnsiString(&AnsiString,
                                                      MenuName,
                                                      FALSE);
                if (!NT_SUCCESS(Status))
                {
                    DPRINT1("Failed to convert unicode menu name to ansi!\n");

                    /* life would've been much prettier if ntoskrnl exported RtlRaiseStatus()... */
                    _SEH_LEAVE;
                }
            }
            else
                Class->AnsiMenuName = (PSTR)MenuName->Buffer;

            if (!(dwFlags & REGISTERCLASS_ANSI))
                Class->Unicode = TRUE;

            if (Class->Style & CS_GLOBALCLASS)
                Class->Global = TRUE;
        }
        _SEH_HANDLE
        {
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;

        if (!NT_SUCCESS(Status))
        {
            DPRINT1("Failed creating the class: 0x%x\n", Status);

            SetLastNtError(Status);

            if (pszMenuName != NULL)
                UserHeapFree(pszMenuName);

            DesktopHeapFree(Desktop,
                            Class);
            Class = NULL;

            IntDeregisterClassAtom(Atom);
        }
    }
    else
    {
NoMem:
        DPRINT1("Failed to allocate class on Desktop 0x%p\n", Desktop);

        if (pszMenuName != NULL)
            UserHeapFree(pszMenuName);

        IntDeregisterClassAtom(Atom);

        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
    }

    return Class;
}

static PWINDOWCLASS
IntFindClass(IN RTL_ATOM Atom,
             IN HINSTANCE hInstance,
             IN PWINDOWCLASS *ClassList,
             OUT PWINDOWCLASS **Link  OPTIONAL)
{
    PWINDOWCLASS Class, *PrevLink = ClassList;

    Class = *PrevLink;
    while (Class != NULL)
    {
        if (Class->Atom == Atom &&
            (hInstance == NULL || Class->hInstance == hInstance) &&
            !Class->Destroying)
        {
            ASSERT(Class->Base == Class);

            if (Link != NULL)
                *Link = PrevLink;
            break;
        }

        PrevLink = &Class->Next;
        Class = Class->Next;
    }

    return Class;
}

BOOL
IntGetAtomFromStringOrAtom(IN PUNICODE_STRING ClassName,
                           OUT RTL_ATOM *Atom)
{
    BOOL Ret = FALSE;

    if (ClassName->Length != 0)
    {
        WCHAR szBuf[65];
        PWSTR AtomName;
        NTSTATUS Status;

        /* NOTE: Caller has to protect the call with SEH! */

        if (ClassName->Length != 0)
        {
            /* FIXME - Don't limit to 64 characters! use SEH when allocating memory! */
            if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / sizeof(szBuf[0]))
            {
                SetLastWin32Error(ERROR_INVALID_PARAMETER);
                return (RTL_ATOM)0;
            }

            /* We need to make a local copy of the class name! The caller could
               modify the buffer and we could overflow in RtlLookupAtomInAtomTable.
               We're protected by SEH, but the ranges that might be accessed were
               not probed... */
            RtlCopyMemory(szBuf,
                          ClassName->Buffer,
                          ClassName->Length);
            szBuf[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
            AtomName = szBuf;
        }
        else
            AtomName = ClassName->Buffer;

        /* lookup the atom */
        Status = RtlLookupAtomInAtomTable(gAtomTable,
                                          AtomName,
                                          Atom);
        if (NT_SUCCESS(Status))
        {
            Ret = TRUE;
        }
        else
        {
            if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
            {
                SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);
            }
            else
            {
                SetLastNtError(Status);
            }
        }
    }
    else
    {
        ASSERT(IS_ATOM(ClassName->Buffer));
        *Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
        Ret = TRUE;
    }

    return Ret;
}

RTL_ATOM
IntGetClassAtom(IN PUNICODE_STRING ClassName,
                IN HINSTANCE hInstance  OPTIONAL,
                IN PW32PROCESSINFO pi  OPTIONAL,
                OUT PWINDOWCLASS *BaseClass  OPTIONAL,
                OUT PWINDOWCLASS **Link  OPTIONAL)
{
    RTL_ATOM Atom = (RTL_ATOM)0;

    if (IntGetAtomFromStringOrAtom(ClassName,
                                   &Atom) &&
        BaseClass != NULL && Atom != (RTL_ATOM)0)
    {
        PWINDOWCLASS Class;

        /* attempt to locate the class object */

        ASSERT(pi != NULL);

        /* Step 1: try to find an exact match of locally registered classes */
        Class = IntFindClass(Atom,
                             hInstance,
                             &pi->LocalClassList,
                             Link);
        if (Class != NULL)
        {
            goto FoundClass;
        }

        /* Step 2: try to find any globally registered class. The hInstance
                   is not relevant for global classes */
        Class = IntFindClass(Atom,
                             NULL,
                             &pi->GlobalClassList,
                             Link);
        if (Class != NULL)
        {
            goto FoundClass;
        }

        /* Step 3: try to find any local class registered by user32 */
        Class = IntFindClass(Atom,
                             pi->hModUser,
                             &pi->LocalClassList,
                             Link);
        if (Class != NULL)
        {
            goto FoundClass;
        }

        /* Step 4: try to find any global class registered by user32 */
        Class = IntFindClass(Atom,
                             pi->hModUser,
                             &pi->GlobalClassList,
                             Link);
        if (Class != NULL)
        {
            goto FoundClass;
        }

        /* Step 5: try to find a system class */
        Class = IntFindClass(Atom,
                             NULL,
                             &pi->SystemClassList,
                             Link);

        if (Class == NULL)
        {
            SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
            return (RTL_ATOM)0;
        }

FoundClass:
        *BaseClass = Class;
    }

    return Atom;
}

RTL_ATOM
UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
                  IN PUNICODE_STRING ClassName,
                  IN PUNICODE_STRING MenuName,
                  IN HANDLE hMenu, /* FIXME */
                  IN WNDPROC wpExtra,
                  IN DWORD dwFlags)
{
    PW32THREADINFO ti;
    PW32PROCESSINFO pi;
    PWINDOWCLASS Class;
    RTL_ATOM ClassAtom;
    RTL_ATOM Ret = (RTL_ATOM)0;

    /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */

    ti = GetW32ThreadInfo();
    if (ti == NULL)
    {
        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
        return (RTL_ATOM)0;
    }

    pi = ti->kpi;

    /* try to find a previously registered class */
    ClassAtom = IntGetClassAtom(ClassName,
                                lpwcx->hInstance,
                                pi,
                                &Class,
                                NULL);
    if (ClassAtom != (RTL_ATOM)0)
    {
        if (lpwcx->style & CS_GLOBALCLASS)
        {
            // global classes shall not have same names as system classes
            if (Class->Global || Class->System)
            {
                DPRINT("Class 0x%p does already exist!\n", ClassAtom);
                SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
                return (RTL_ATOM)0;
            }
        }
        else if ( !Class->Global && !Class->System)
        {
            // local class already exists
            DPRINT("Class 0x%p does already exist!\n", ClassAtom);
            SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
            return (RTL_ATOM)0;
        }
    }

    Class = IntCreateClass(lpwcx,
                           ClassName,
                           MenuName,
                           wpExtra,
                           dwFlags,
                           ti->Desktop,
                           pi);

    if (Class != NULL)
    {
        PWINDOWCLASS *List;

        /* FIXME - pass the PMENU pointer to IntCreateClass instead! */
        Class->hMenu = hMenu;

        /* Register the class */
        if (Class->System)
            List = &pi->SystemClassList;
        else if (Class->Global)
            List = &pi->GlobalClassList;
        else
            List = &pi->LocalClassList;

        Class->Next = *List;
        (void)InterlockedExchangePointer(List,
                                         Class);

        Ret = Class->Atom;
    }

    return Ret;
}

BOOL
UserUnregisterClass(IN PUNICODE_STRING ClassName,
                    IN HINSTANCE hInstance)
{
    PWINDOWCLASS *Link;
    PW32PROCESSINFO pi;
    RTL_ATOM ClassAtom;
    PWINDOWCLASS Class;

    pi = GetW32ProcessInfo();
    if (pi == NULL)
    {
        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
        return FALSE;
    }

    /* NOTE: Accessing the buffer in ClassName may raise an exception! */
    ClassAtom = IntGetClassAtom(ClassName,
                                hInstance,
                                pi,
                                &Class,
                                &Link);
    if (ClassAtom == (RTL_ATOM)0)
    {
        return FALSE;
    }

    ASSERT(Class != NULL);

    if (Class->Windows != 0 ||
        Class->Clone != NULL)
    {
        SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
        return FALSE;
    }

    /* must be a base class! */
    ASSERT(Class->Base == Class);

    /* unlink the class */
    *Link = Class->Next;

    if (NT_SUCCESS(IntDeregisterClassAtom(Class->Atom)))
    {
        /* finally free the resources */
        IntDestroyClass(Class);
        return TRUE;
    }
	return FALSE;
}

INT
UserGetClassName(IN PWINDOWCLASS Class,
                 IN OUT PUNICODE_STRING ClassName,
                 IN BOOL Ansi)
{
    NTSTATUS Status = STATUS_SUCCESS;
    WCHAR szStaticTemp[32];
    PWSTR szTemp = NULL;
    ULONG BufLen = sizeof(szStaticTemp);
    INT Ret = 0;

    /* Note: Accessing the buffer in ClassName may raise an exception! */

    _SEH_TRY
    {
        if (Ansi)
        {
            PANSI_STRING AnsiClassName = (PANSI_STRING)ClassName;
            UNICODE_STRING UnicodeClassName;

            /* limit the size of the static buffer on the stack to the
               size of the buffer provided by the caller */
            if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
            {
                BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
            }

            /* find out how big the buffer needs to be */
            Status = RtlQueryAtomInAtomTable(gAtomTable,
                                             Class->Atom,
                                             NULL,
                                             NULL,
                                             szStaticTemp,
                                             &BufLen);
            if (Status == STATUS_BUFFER_TOO_SMALL)
            {
                if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
                {
                    /* the buffer required exceeds the ansi buffer provided,
                       pretend like we're using the ansi buffer and limit the
                       size to the buffer size provided */
                    BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
                }

                /* allocate a temporary buffer that can hold the unicode class name */
                szTemp = ExAllocatePool(PagedPool,
                                        BufLen);
                if (szTemp == NULL)
                {
                    SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
                    _SEH_LEAVE;

⌨️ 快捷键说明

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