1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: User Atom helper routines 5 * FILE: win32ss/user/ntuser/useratom.c 6 * PROGRAMER: Filip Navara <xnavara@volny.cz> 7 */ 8 9 #include <win32k.h> 10 DBG_DEFAULT_CHANNEL(UserMisc); 11 12 RTL_ATOM FASTCALL 13 IntAddAtom(LPWSTR AtomName) 14 { 15 NTSTATUS Status = STATUS_SUCCESS; 16 PTHREADINFO pti; 17 RTL_ATOM Atom; 18 19 pti = PsGetCurrentThreadWin32Thread(); 20 if (pti->rpdesk == NULL) 21 { 22 SetLastNtError(Status); 23 return (RTL_ATOM)0; 24 } 25 26 Status = RtlAddAtomToAtomTable(gAtomTable, AtomName, &Atom); 27 28 if (!NT_SUCCESS(Status)) 29 { 30 SetLastNtError(Status); 31 return (RTL_ATOM)0; 32 } 33 return Atom; 34 } 35 36 ULONG FASTCALL 37 IntGetAtomName(RTL_ATOM nAtom, LPWSTR lpBuffer, ULONG cjBufSize) 38 { 39 NTSTATUS Status = STATUS_SUCCESS; 40 PTHREADINFO pti; 41 ULONG Size = cjBufSize; 42 43 pti = PsGetCurrentThreadWin32Thread(); 44 if (pti->rpdesk == NULL) 45 { 46 SetLastNtError(Status); 47 return 0; 48 } 49 50 Status = RtlQueryAtomInAtomTable(gAtomTable, nAtom, NULL, NULL, lpBuffer, &Size); 51 52 if (!NT_SUCCESS(Status)) 53 { 54 SetLastNtError(Status); 55 return 0; 56 } 57 58 return Size; 59 } 60 61 RTL_ATOM FASTCALL 62 IntAddGlobalAtom(LPWSTR lpBuffer, BOOL PinAtom) 63 { 64 RTL_ATOM Atom; 65 NTSTATUS Status = STATUS_SUCCESS; 66 67 Status = RtlAddAtomToAtomTable(gAtomTable, lpBuffer, &Atom); 68 69 if (!NT_SUCCESS(Status)) 70 { 71 ERR("Error init Global Atom.\n"); 72 return 0; 73 } 74 75 if (Atom && PinAtom) 76 RtlPinAtomInAtomTable(gAtomTable, Atom); 77 78 return Atom; 79 } 80 81 /*! 82 * \brief Returns the name of an atom. 83 * 84 * \param atom - The atom to be queried. 85 * \param pustrName - Pointer to an initialized UNICODE_STRING that receives 86 * the name of the atom. The function does not update the 87 Length member. The string is always NULL-terminated. 88 * 89 * \return The length of the name in characters, or 0 if the function fails. 90 * 91 * \note The function does not aquire any global lock, since synchronisation is 92 * handled by the RtlAtom function. 93 */ 94 _Success_(return != 0) 95 _At_(pustrName->Buffer, _Out_z_bytecap_post_bytecount_(pustrName->MaximumLength, return * 2 + 2)) 96 ULONG 97 APIENTRY 98 NtUserGetAtomName( 99 _In_ ATOM atom, 100 _Inout_ PUNICODE_STRING pustrName) 101 { 102 WCHAR awcBuffer[256]; 103 ULONG cjLength; 104 105 /* Retrieve the atom name into a local buffer (max length is 255 chars) */ 106 cjLength = IntGetAtomName((RTL_ATOM)atom, awcBuffer, sizeof(awcBuffer)); 107 if (cjLength != 0) 108 { 109 _SEH2_TRY 110 { 111 /* Probe the unicode string and the buffer */ 112 ProbeForRead(pustrName, sizeof(*pustrName), 1); 113 ProbeForWrite(pustrName->Buffer, pustrName->MaximumLength, 1); 114 115 /* Check if we have enough space to write the NULL termination */ 116 if (pustrName->MaximumLength >= sizeof(UNICODE_NULL)) 117 { 118 /* Limit the length to the buffer size */ 119 cjLength = min(pustrName->MaximumLength - sizeof(UNICODE_NULL), 120 cjLength); 121 122 /* Copy the string and NULL terminate it */ 123 RtlCopyMemory(pustrName->Buffer, awcBuffer, cjLength); 124 pustrName->Buffer[cjLength / sizeof(WCHAR)] = L'\0'; 125 } 126 else 127 { 128 cjLength = 0; 129 } 130 } 131 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 132 { 133 /* On exception, set last error and fail */ 134 SetLastNtError(_SEH2_GetExceptionCode()); 135 cjLength = 0; 136 } 137 _SEH2_END 138 } 139 140 /* Return the length in characters */ 141 return cjLength / sizeof(WCHAR); 142 } 143 144 /* EOF */ 145