/*********************************************************************** * AddAtomW (KERNEL32.@) * * Unicode version of AddAtomA. */ ATOM WINAPI AddAtomW( LPCWSTR str ) { ATOM atom = 0; RTL_ATOM_TABLE table; if (!check_integral_atom( str, &atom ) && (table = get_local_table( 0 ))) { NTSTATUS status = RtlAddAtomToAtomTable( table, str, &atom ); if (status) { SetLastError( RtlNtStatusToDosError( status ) ); atom = 0; } } return atom; }
RTL_ATOM FASTCALL IntAddGlobalAtom(LPWSTR lpBuffer, BOOL PinAtom) { RTL_ATOM Atom; NTSTATUS Status = STATUS_SUCCESS; Status = RtlAddAtomToAtomTable(gAtomTable, lpBuffer, &Atom); if (!NT_SUCCESS(Status)) { ERR("Error init Global Atom.\n"); return 0; } if ( Atom && PinAtom ) RtlPinAtomInAtomTable(gAtomTable, Atom); return Atom; }
RTL_ATOM FASTCALL IntAddAtom(LPWSTR AtomName) { NTSTATUS Status = STATUS_SUCCESS; PTHREADINFO pti; RTL_ATOM Atom; pti = PsGetCurrentThreadWin32Thread(); if (pti->rpdesk == NULL) { SetLastNtError(Status); return (RTL_ATOM)0; } Status = RtlAddAtomToAtomTable(gAtomTable, AtomName, &Atom); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); return (RTL_ATOM)0; } return Atom; }
/*********************************************************************** * AddAtomA (KERNEL32.@) * * Add a character string to the global atom table and return a unique * value identifying it. * * RETURNS * Success: The atom allocated to str. * Failure: 0. */ ATOM WINAPI AddAtomA( LPCSTR str /* [in] String to add */ ) { ATOM atom = 0; if (!check_integral_atom( str, &atom )) { WCHAR buffer[MAX_ATOM_LEN + 1]; DWORD len; RTL_ATOM_TABLE table; len = MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, MAX_ATOM_LEN + 1 ); if (!len) SetLastError( ERROR_INVALID_PARAMETER ); else if ((table = get_local_table( 0 ))) { NTSTATUS status = RtlAddAtomToAtomTable( table, buffer, &atom ); if (status) { SetLastError( RtlNtStatusToDosError( status ) ); atom = 0; } } } return atom; }
} /* Probe the atom too */ if (Atom) ProbeForWriteUshort(Atom); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Return the exception code */ _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } /* Call the runtime function */ Status = RtlAddAtomToAtomTable(AtomTable, CapturedName, &SafeAtom); if (NT_SUCCESS(Status) && (Atom)) { /* Success and caller wants the atom back.. .enter SEH */ _SEH2_TRY { /* Return the atom */ *Atom = SafeAtom; } _SEH2_EXCEPT(ExSystemExceptionFilter()) { /* Get the exception code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; }
ATOM WINAPI InternalAddAtom(BOOLEAN Local, BOOLEAN Unicode, LPCSTR AtomName) { NTSTATUS Status; ANSI_STRING AnsiString; UNICODE_STRING UnicodeString; PUNICODE_STRING AtomNameString; ATOM Atom = INVALID_ATOM; /* Check if it's an integer atom */ if ((ULONG_PTR)AtomName <= 0xFFFF) { /* Convert the name to an atom */ Atom = (ATOM)PtrToShort((PVOID)AtomName); if (Atom >= MAXINTATOM) { /* Fail, atom number too large */ BaseSetLastNTError(STATUS_INVALID_PARAMETER); return INVALID_ATOM; } /* Return it */ return Atom; } else { /* Check if this is a unicode atom */ if (Unicode) { /* Use a unicode string */ AtomNameString = &UnicodeString; RtlInitUnicodeString(AtomNameString, (LPWSTR)AtomName); Status = STATUS_SUCCESS; } else { /* Use an ansi string */ RtlInitAnsiString(&AnsiString, AtomName ); /* Check if we can abuse the TEB */ if (AnsiString.MaximumLength > 260) { /* We can't, allocate a new string */ AtomNameString = &UnicodeString; Status = RtlAnsiStringToUnicodeString(AtomNameString, &AnsiString, TRUE); } else { /* We can! Get the TEB String */ AtomNameString = &NtCurrentTeb()->StaticUnicodeString; /* Convert it into the TEB */ Status = RtlAnsiStringToUnicodeString(AtomNameString, &AnsiString, FALSE); } } /* Check for failure */ if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return Atom; } } /* Check if we're doing local add */ if (Local) { /* Do a local add */ Status = RtlAddAtomToAtomTable(InternalInitAtomTable(), AtomNameString->Buffer, &Atom); } else { /* Do a global add */ Status = NtAddAtom(AtomNameString->Buffer, AtomNameString->Length, &Atom); } /* Check for failure */ if (!NT_SUCCESS(Status)) BaseSetLastNTError(Status); /* Check if we were non-static ANSI */ if (!(Unicode) && (AtomNameString == &UnicodeString)) { /* Free the allocated buffer */ RtlFreeUnicodeString(AtomNameString); } /* Return the atom */ return Atom; }
/* * @implemented */ BOOL APIENTRY NtUserSetCursorIconData( _In_ HCURSOR Handle, _In_opt_ PUNICODE_STRING pustrModule, _In_opt_ PUNICODE_STRING pustrRsrc, _In_ const CURSORDATA* pCursorData) { PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN Ret = FALSE; BOOLEAN IsShared = FALSE, IsAnim = FALSE; DWORD numFrames; UINT i = 0; TRACE("Enter NtUserSetCursorIconData\n"); UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(Handle))) { UserLeave(); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } _SEH2_TRY { ProbeForRead(pCursorData, sizeof(*pCursorData), 1); if(pCursorData->CURSORF_flags & CURSORF_ACON) { /* This is an animated cursor */ PACON AniCurIcon = (PACON)CurIcon; DWORD numSteps; numFrames = AniCurIcon->cpcur = pCursorData->cpcur; numSteps = AniCurIcon->cicur = pCursorData->cicur; AniCurIcon->iicur = pCursorData->iicur; AniCurIcon->rt = pCursorData->rt; /* Calculate size: one cursor object for each frame, and a frame index and jiffies for each "step" */ AniCurIcon->aspcur = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, /* Let SEH catch allocation failures */ numFrames * sizeof(CURICON_OBJECT*) + numSteps * (sizeof(DWORD) + sizeof(INT)), USERTAG_CURSOR); AniCurIcon->aicur = (DWORD*)(AniCurIcon->aspcur + numFrames); AniCurIcon->ajifRate = (INT*)(AniCurIcon->aicur + numSteps); RtlZeroMemory(AniCurIcon->aspcur, numFrames * sizeof(CURICON_OBJECT*)); ProbeForRead(pCursorData->aicur, numSteps * sizeof(DWORD), 1); RtlCopyMemory(AniCurIcon->aicur, pCursorData->aicur, numSteps * sizeof(DWORD)); ProbeForRead(pCursorData->ajifRate, numSteps * sizeof(INT), 1); RtlCopyMemory(AniCurIcon->ajifRate, pCursorData->ajifRate, numSteps * sizeof(INT)); AniCurIcon->CURSORF_flags = pCursorData->CURSORF_flags; pCursorData = pCursorData->aspcur; IsAnim = TRUE; } else { CurIcon->xHotspot = pCursorData->xHotspot; CurIcon->yHotspot = pCursorData->yHotspot; CurIcon->cx = pCursorData->cx; CurIcon->cy = pCursorData->cy; CurIcon->rt = pCursorData->rt; CurIcon->bpp = pCursorData->bpp; CurIcon->hbmMask = pCursorData->hbmMask; CurIcon->hbmColor = pCursorData->hbmColor; CurIcon->hbmAlpha = pCursorData->hbmAlpha; CurIcon->CURSORF_flags = pCursorData->CURSORF_flags; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto done; } if(IsAnim) { PACON AniCurIcon = (PACON)CurIcon; /* This is an animated cursor. Create a cursor object for each frame and set up the data */ for(i = 0; i < numFrames; i++) { HANDLE hCurFrame = IntCreateCurIconHandle(FALSE); if(!NtUserSetCursorIconData(hCurFrame, NULL, NULL, pCursorData)) goto done; AniCurIcon->aspcur[i] = UserGetCurIconObject(hCurFrame); if(!AniCurIcon->aspcur[i]) goto done; pCursorData++; } } if(CurIcon->CURSORF_flags & CURSORF_LRSHARED) { IsShared = TRUE; if(pustrRsrc && pustrModule) { UNICODE_STRING ustrModuleSafe; /* We use this convenient function, because INTRESOURCEs and ATOMs are the same */ Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->strName, pustrRsrc); if(!NT_SUCCESS(Status)) goto done; Status = ProbeAndCaptureUnicodeString(&ustrModuleSafe, UserMode, pustrModule); if(!NT_SUCCESS(Status)) goto done; Status = RtlAddAtomToAtomTable(gAtomTable, ustrModuleSafe.Buffer, &CurIcon->atomModName); ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode); if(!NT_SUCCESS(Status)) goto done; } } if(!CurIcon->hbmMask) { ERR("NtUserSetCursorIconData was got no hbmMask.\n"); EngSetLastError(ERROR_INVALID_PARAMETER); goto done; } GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmColor) GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmAlpha) GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_PUBLIC); if(IsShared) { /* Update process cache in case of shared cursor */ PPROCESSINFO ppi = CurIcon->head.ppi; UserReferenceObject(CurIcon); CurIcon->pcurNext = ppi->pCursorCache; ppi->pCursorCache = CurIcon; } Ret = TRUE; done: if(!Ret && IsShared) { if(!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); } if(!Ret && IsAnim) { PACON AniCurIcon = (PACON)CurIcon; for(i = 0; i < numFrames; i++) { if(AniCurIcon->aspcur[i]) IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); } AniCurIcon->cicur = 0; AniCurIcon->cpcur = 0; ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); AniCurIcon->aspcur = NULL; AniCurIcon->aicur = NULL; AniCurIcon->ajifRate = NULL; } UserDereferenceObject(CurIcon); TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret); UserLeave(); return Ret; }