@@ -26,17 +26,86 @@ public sealed class NtAtom
2626 {
2727 #region Constructors
2828
29- internal NtAtom ( ushort atom )
29+ internal NtAtom ( ushort atom , bool global )
3030 {
3131 Atom = atom ;
32+ Global = global ;
33+ }
34+
35+ #endregion
36+
37+ #region Private Members
38+ private static IEnumerable < NtAtom > GetGlobalAtoms ( )
39+ {
40+ int size = 1024 ;
41+ while ( size < 5 * 1024 * 1024 )
42+ {
43+ using ( var buffer = new SafeStructureInOutBuffer < AtomTableInformation > ( size , true ) )
44+ {
45+ NtStatus status = NtSystemCalls . NtQueryInformationAtom ( 0 ,
46+ AtomInformationClass . AtomTableInformation , buffer , buffer . Length , out int return_length ) ;
47+ if ( status . IsSuccess ( ) )
48+ {
49+ AtomTableInformation table = buffer . Result ;
50+ IntPtr data = buffer . Data . DangerousGetHandle ( ) ;
51+ ushort [ ] atoms = new ushort [ table . NumberOfAtoms ] ;
52+ buffer . Data . ReadArray ( 0 , atoms , 0 , atoms . Length ) ;
53+ return atoms . Select ( a => new NtAtom ( a , true ) ) . ToArray ( ) ;
54+ }
55+ else if ( status != NtStatus . STATUS_INFO_LENGTH_MISMATCH )
56+ {
57+ throw new NtException ( status ) ;
58+ }
59+ size *= 2 ;
60+ }
61+ }
62+ return new NtAtom [ 0 ] ;
63+ }
64+
65+ private static IEnumerable < NtAtom > GetUserAtoms ( )
66+ {
67+ List < NtAtom > atoms = new List < NtAtom > ( ) ;
68+ for ( int atom = 0xC000 ; atom < 0x10000 ; ++ atom )
69+ {
70+ var next_atom = new NtAtom ( ( ushort ) atom , false ) ;
71+ if ( next_atom . GetName ( false ) . IsSuccess )
72+ {
73+ atoms . Add ( next_atom ) ;
74+ }
75+ }
76+ return atoms . AsReadOnly ( ) ;
77+ }
78+
79+ private NtResult < string > GetGlobalName ( bool throw_on_error )
80+ {
81+ using ( var buffer = new SafeStructureInOutBuffer < AtomBasicInformation > ( 2048 , false ) )
82+ {
83+ return NtSystemCalls . NtQueryInformationAtom ( Atom , AtomInformationClass . AtomBasicInformation ,
84+ buffer , buffer . Length , out int return_length )
85+ . CreateResult ( throw_on_error , ( ) => buffer . Data . ReadUnicodeString ( buffer . Result . NameLength / 2 ) ) ;
86+ }
87+ }
88+
89+ private NtResult < string > GetUserName ( bool throw_on_error )
90+ {
91+ using ( UnicodeStringAllocated str = new UnicodeStringAllocated ( 2048 ) )
92+ {
93+ int length = NtSystemCalls . NtUserGetAtomName ( Atom , str ) ;
94+ if ( length == 0 )
95+ {
96+ return NtStatus . STATUS_OBJECT_NAME_NOT_FOUND . CreateResultFromError < string > ( throw_on_error ) ;
97+ }
98+ str . String . Length = ( ushort ) ( length * 2 ) ;
99+ return str . ToString ( ) . CreateResult ( ) ;
100+ }
32101 }
33102
34103 #endregion
35104
36105 #region Static Methods
37106
38107 /// <summary>
39- /// Add an atom name
108+ /// Add a global atom name
40109 /// </summary>
41110 /// <param name="name">The name to add</param>
42111 /// <param name="flags">Flags for the add.</param>
@@ -47,17 +116,17 @@ public static NtResult<NtAtom> Add(string name, AddAtomFlags flags, bool throw_o
47116 if ( flags == AddAtomFlags . None )
48117 {
49118 return NtSystemCalls . NtAddAtom ( name + "\0 " , ( name . Length + 1 ) * 2 ,
50- out ushort atom ) . CreateResult ( throw_on_error , ( ) => new NtAtom ( atom ) ) ;
119+ out ushort atom ) . CreateResult ( throw_on_error , ( ) => new NtAtom ( atom , true ) ) ;
51120 }
52121 else
53122 {
54123 return NtSystemCalls . NtAddAtomEx ( name + "\0 " , ( name . Length + 1 ) * 2 ,
55- out ushort atom , flags ) . CreateResult ( throw_on_error , ( ) => new NtAtom ( atom ) ) ;
124+ out ushort atom , flags ) . CreateResult ( throw_on_error , ( ) => new NtAtom ( atom , true ) ) ;
56125 }
57126 }
58127
59128 /// <summary>
60- /// Add an atom name
129+ /// Add a global atom name
61130 /// </summary>
62131 /// <param name="name">The name to add</param>
63132 /// <param name="flags">Flags for the add.</param>
@@ -68,7 +137,7 @@ public static NtAtom Add(string name, AddAtomFlags flags)
68137 }
69138
70139 /// <summary>
71- /// Add an atom name
140+ /// Add a global atom name
72141 /// </summary>
73142 /// <param name="name">The name to add</param>
74143 /// <param name="throw_on_error">True to throw on error.</param>
@@ -79,7 +148,7 @@ public static NtResult<NtAtom> Add(string name, bool throw_on_error)
79148 }
80149
81150 /// <summary>
82- /// Add an atom name
151+ /// Add a global atom name
83152 /// </summary>
84153 /// <param name="name">The name to add</param>
85154 /// <returns>A reference to the atom</returns>
@@ -89,19 +158,19 @@ public static NtAtom Add(string name)
89158 }
90159
91160 /// <summary>
92- /// Find an atom by name.
161+ /// Find a global atom by name.
93162 /// </summary>
94163 /// <param name="name">The name of the atom.</param>
95164 /// <param name="throw_on_error">True to throw on error.</param>
96165 /// <returns>The found atom.</returns>
97166 public static NtResult < NtAtom > Find ( string name , bool throw_on_error )
98167 {
99168 return NtSystemCalls . NtFindAtom ( name + "\0 " , ( name . Length + 1 ) * 2 ,
100- out ushort atom ) . CreateResult ( throw_on_error , ( ) => new NtAtom ( atom ) ) ;
169+ out ushort atom ) . CreateResult ( throw_on_error , ( ) => new NtAtom ( atom , true ) ) ;
101170 }
102171
103172 /// <summary>
104- /// Find an atom by name.
173+ /// Find a global atom by name.
105174 /// </summary>
106175 /// <param name="name">The name of the atom.</param>
107176 /// <returns>The found atom.</returns>
@@ -111,25 +180,37 @@ public static NtAtom Find(string name)
111180 }
112181
113182 /// <summary>
114- /// Query if the atom exists.
183+ /// Query if a global atom exists.
115184 /// </summary>
116185 /// <param name="atom">The atom to check.</param>
117186 /// <returns>True if the atom exists.</returns>
118187 public static bool Exists ( ushort atom )
119188 {
120- return new NtAtom ( atom ) . GetName ( false ) . IsSuccess ;
189+ return Exists ( atom , true ) ;
121190 }
122191
123192 /// <summary>
124- /// Open an atom by number.
193+ /// Query if the atom exists.
194+ /// </summary>
195+ /// <param name="atom">The atom to check.</param>
196+ /// <param name="global">Specify true to check for a global atom, otherwise gets a user atom.</param>
197+ /// <returns>True if the atom exists.</returns>
198+ public static bool Exists ( ushort atom , bool global )
199+ {
200+ return new NtAtom ( atom , global ) . GetName ( false ) . IsSuccess ;
201+ }
202+
203+ /// <summary>
204+ /// Open a global atom by number.
125205 /// </summary>
126206 /// <param name="atom">The atom to open.</param>
127207 /// <param name="check_exists">True to check atom exists.</param>
208+ /// <param name="global">True to open a global atom, otherwise a user atom.</param>
128209 /// <param name="throw_on_error">True to throw on error.</param>
129210 /// <returns>The atom object.</returns>
130- public static NtResult < NtAtom > Open ( ushort atom , bool check_exists , bool throw_on_error )
211+ public static NtResult < NtAtom > Open ( ushort atom , bool check_exists , bool global , bool throw_on_error )
131212 {
132- NtAtom ret = new NtAtom ( atom ) ;
213+ NtAtom ret = new NtAtom ( atom , global ) ;
133214 if ( check_exists )
134215 {
135216 return ret . GetName ( false ) . Status . CreateResult ( throw_on_error , ( ) => ret ) ;
@@ -138,7 +219,19 @@ public static NtResult<NtAtom> Open(ushort atom, bool check_exists, bool throw_o
138219 }
139220
140221 /// <summary>
141- /// Open an atom by number.
222+ /// Open a global atom by number.
223+ /// </summary>
224+ /// <param name="atom">The atom to open.</param>
225+ /// <param name="check_exists">True to check atom exists.</param>
226+ /// <param name="throw_on_error">True to throw on error.</param>
227+ /// <returns>The atom object.</returns>
228+ public static NtResult < NtAtom > Open ( ushort atom , bool check_exists , bool throw_on_error )
229+ {
230+ return Open ( atom , check_exists , true , throw_on_error ) ;
231+ }
232+
233+ /// <summary>
234+ /// Open a global atom by number.
142235 /// </summary>
143236 /// <param name="atom">The atom to open.</param>
144237 /// <param name="check_exists">True to check atom exists.</param>
@@ -149,7 +242,7 @@ public static NtAtom Open(ushort atom, bool check_exists)
149242 }
150243
151244 /// <summary>
152- /// Open an atom by number.
245+ /// Open a global atom by number.
153246 /// </summary>
154247 /// <param name="atom">The atom to open.</param>
155248 /// <returns>The atom object.</returns>
@@ -162,37 +255,24 @@ public static NtAtom Open(ushort atom)
162255 /// Enumerate all atoms.
163256 /// </summary>
164257 /// <returns>An enumeration of all atoms on the system.</returns>
258+ public static IEnumerable < NtAtom > GetAtoms ( bool global )
259+ {
260+ return global ? GetGlobalAtoms ( ) : GetUserAtoms ( ) ;
261+ }
262+
263+ /// <summary>
264+ /// Enumerate all global atoms.
265+ /// </summary>
266+ /// <returns>An enumeration of all atoms on the system.</returns>
165267 public static IEnumerable < NtAtom > GetAtoms ( )
166268 {
167- int size = 1024 ;
168- while ( size < 5 * 1024 * 1024 )
169- {
170- using ( var buffer = new SafeStructureInOutBuffer < AtomTableInformation > ( size , true ) )
171- {
172- NtStatus status = NtSystemCalls . NtQueryInformationAtom ( 0 ,
173- AtomInformationClass . AtomTableInformation , buffer , buffer . Length , out int return_length ) ;
174- if ( status . IsSuccess ( ) )
175- {
176- AtomTableInformation table = buffer . Result ;
177- IntPtr data = buffer . Data . DangerousGetHandle ( ) ;
178- ushort [ ] atoms = new ushort [ table . NumberOfAtoms ] ;
179- buffer . Data . ReadArray ( 0 , atoms , 0 , atoms . Length ) ;
180- return atoms . Select ( a => new NtAtom ( a ) ) ;
181- }
182- else if ( status != NtStatus . STATUS_INFO_LENGTH_MISMATCH )
183- {
184- throw new NtException ( status ) ;
185- }
186- size *= 2 ;
187- }
188- }
189- return new NtAtom [ 0 ] ;
269+ return GetAtoms ( true ) ;
190270 }
191271 #endregion
192272
193273 #region Public Methods
194274 /// <summary>
195- /// Delete an atom.
275+ /// Delete a global atom.
196276 /// </summary>
197277 /// <param name="throw_on_error">True to throw on error.</param>
198278 /// <returns>The NT status code.</returns>
@@ -202,7 +282,7 @@ public NtStatus Delete(bool throw_on_error)
202282 }
203283
204284 /// <summary>
205- /// Delete an atom.
285+ /// Delete a global atom.
206286 /// </summary>
207287 public void Delete ( )
208288 {
@@ -216,12 +296,7 @@ public void Delete()
216296 /// <returns>The name of the atom.</returns>
217297 public NtResult < string > GetName ( bool throw_on_error )
218298 {
219- using ( var buffer = new SafeStructureInOutBuffer < AtomBasicInformation > ( 2048 , false ) )
220- {
221- return NtSystemCalls . NtQueryInformationAtom ( Atom , AtomInformationClass . AtomBasicInformation ,
222- buffer , buffer . Length , out int return_length )
223- . CreateResult ( throw_on_error , ( ) => buffer . Data . ReadUnicodeString ( buffer . Result . NameLength / 2 ) ) ;
224- }
299+ return Global ? GetGlobalName ( throw_on_error ) : GetUserName ( throw_on_error ) ;
225300 }
226301
227302 #endregion
@@ -239,6 +314,11 @@ public NtResult<string> GetName(bool throw_on_error)
239314 /// <returns>The name of the atom</returns>
240315 public string Name => GetName ( true ) . Result ;
241316
317+ /// <summary>
318+ /// If true indicates this is a global atom, otherwise it's a user atom.
319+ /// </summary>
320+ public bool Global { get ; }
321+
242322 #endregion
243323 }
244324}
0 commit comments