{
	"id": "0453e2bd-99c9-4187-a7de-58374dbfa0cb",
	"created_at": "2026-04-06T00:16:51.39652Z",
	"updated_at": "2026-04-10T03:22:13.035091Z",
	"deleted_at": null,
	"sha1_hash": "b031560fad36ef7e7384bd7e7c44352c86215bb7",
	"title": "About Atom Tables - Win32 apps",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 72020,
	"plain_text": "About Atom Tables - Win32 apps\r\nBy jwmsft\r\nArchived: 2026-04-05 22:49:41 UTC\r\nAn atom table is a system-defined table that stores strings and corresponding identifiers. An application places a\r\nstring in an atom table and receives a 16-bit integer, called an atom, that can be used to access the string. A string\r\nthat has been placed in an atom table is called an atom name.\r\nThe system provides a number of atom tables. Each atom table serves a different purpose. For example, Dynamic\r\nData Exchange (DDE) applications use the global atom table to share item-name and topic-name strings with\r\nother applications. Rather than passing actual strings, a DDE application passes global atoms to its partner\r\napplication. The partner uses the atoms to obtain the strings from the atom table.\r\nApplications can use local atom tables to store their own item-name associations.\r\nThe system uses atom tables that are not directly accessible to applications. However, the application uses these\r\natoms when calling a variety of functions. For example, registered clipboard formats are stored in an internal atom\r\ntable used by the system. An application adds atoms to this atom table using the RegisterClipboardFormat\r\nfunction. Also, registered classes are stored in an internal atom table used by the system. An application adds\r\natoms to this atom table using the RegisterClass or RegisterClassEx function.\r\nThe following topics are discussed in this section.\r\nGlobal Atom Table\r\nUser Atom Table\r\nLocal Atom Tables\r\nAtom Types\r\nString Atoms\r\nInteger Atoms\r\nAtom Creation and Usage Count\r\nAtom-Table Queries\r\nAtom String Formats\r\nThe global atom table is available to all applications. When an application places a string in the global atom table,\r\nthe system generates an atom that is unique throughout the system. Any application that has the atom can obtain\r\nthe string it identifies by querying the global atom table.\r\nAn application that defines a private DDE-data format for sharing data with other applications should place the\r\nformat name in the global atom table. This technique prevents conflicts with the names of formats defined by the\r\nsystem or by other applications, and makes the identifiers (atoms) for the messages or formats available to the\r\nother applications.\r\nhttps://msdn.microsoft.com/library/windows/desktop/ms649053.aspx\r\nPage 1 of 4\n\nIn addition to the global atom table, the user atom table is another system atom table that is also shared across all\r\nprocesses. The user atom table is used for a small number of scenarios internal to win32k; for example, windows\r\nmodule names, well known strings in win32k, OLE formats, etc. Although applications do not interact with the\r\nuser atom table directly, they call several APIs—such as RegisterClass, RegisterWindowMessage, and\r\nRegisterClipboardFormat—that add entries to the user atom table. The entries added by RegisterClass can be\r\ndeleted by UnregisterClass . However, the entries added by RegisterWindowMessage and\r\nRegisterClipboardFormat do not get deleted until the session ends. If the user atom table has no more space and\r\nthe string being passed in is not already in the table, the call will fail.\r\nMany critical APIs, including CreateWindow, rely on user atoms. Therefore, space exhaustion in the user atom\r\ntable will result in serious issues; for example, all applications may fail to launch. Here are some\r\nrecommendations to ensure your application utilizes atom tables efficiently and preserves the reliability and\r\nperformance of the application and system:\r\n1. You should limit your app's usage of the user atom table. Storing unique strings using APIs like\r\nRegisterClass , RegisterWindowMessage , or RegisterClipboardFormat takes space in the user atom\r\ntable, which is used globally by other apps to register window classes using strings. If at all possible, you\r\nshould use AddAtom/DeleteAtom to store strings in a local atom table, or\r\nGlobalAddAtom/GlobalDeleteAtom if the atoms are needed cross-process.\r\n2. If there is concern about the application causing user atom table issues, you can investigate the root cause\r\nby connecting the kernel debugger and breaking into the process on calls to UserAddAtomEx ( bae1\r\nwin32kbase!UserAddAtomEx /p \u003ceprocess\u003e \"kc10;g\" ). Look for user32! on the callstack to see which\r\nAPI is being called. The methodology is similar to the global atom table issue detection explained in\r\nIdentifying Global Atom Table Leaks. Another way to dump the contents of the user atom table is by\r\ncalling GetClipboardFormatName over the range of possible atoms from 0xC000 to 0xFFFF. If the total\r\natom count steadily goes up while the application is running or does not return to baseline when the app is\r\nclosed, there is a problem.\r\nAn application can use a local atom table to efficiently manage a large number of strings used only within the\r\napplication. These strings, and the associated atoms, are available only to the application that created the table.\r\nAn application requiring the same string in a number of structures can reduce memory usage by using a local atom\r\ntable. Rather than copying the string into each structure, the application can place the string in the atom table and\r\ninclude the resulting atom in the structures. In this way, a string appears only once in memory but can be used\r\nmany times in the application.\r\nApplications can also use local atom tables to save time when searching for a particular string. To perform a\r\nsearch, an application need only place the search string in the atom table and compare the resulting atom with the\r\natoms in the relevant structures. Comparing atoms is typically faster than comparing strings.\r\nAtom tables are implemented as hash tables. By default, a local atom table uses 37 buckets for its hash table.\r\nHowever, you can change the number of buckets used by calling the InitAtomTable function. If the application\r\ncalls InitAtomTable, however, it must do so before calling any other atom-management functions.\r\nhttps://msdn.microsoft.com/library/windows/desktop/ms649053.aspx\r\nPage 2 of 4\n\nApplications can create two types of atoms: string atoms and integer atoms. The values of integer atoms and string\r\natoms do not overlap, so both types of atoms can be used in the same block of code.\r\nSeveral functions accept either strings or atoms as parameters. When passing an atom to these functions, an\r\napplication can use the MAKEINTATOM macro to convert the atom into a form that can be used by the function.\r\nThe following sections describe atom types.\r\nString Atoms\r\nInteger Atoms\r\nWhen applications pass null-terminated strings to the GlobalAddAtom, AddAtom, GlobalFindAtom, and\r\nFindAtom functions, they receive string atoms (16-bit integers) in return. String atoms have the following\r\nproperties:\r\nThe values of string atoms are in the range 0xC000 (MAXINTATOM) through 0xFFFF.\r\nCase is not significant in searches for an atom name in an atom table. Also, the entire string must match in\r\na search operation; no substring matching is performed.\r\nThe string associated with a string atom can be no more than 255 bytes in size. This limitation applies to all\r\natom functions.\r\nA reference count is associated with each atom name. The count is incremented each time the atom name is\r\nadded to the table and decremented each time the atom name is deleted from it. This prevents different\r\nusers of the same string atom from destroying each other's atom names. When the reference count for an\r\natom name equals zero, the system removes the atom and the atom name from the table.\r\nInteger atoms differ from string atoms in the following ways:\r\nThe values of integer atoms are in the range 0x0001 through 0xBFFF (MAXINTATOM– 1).\r\nThe string representation of an integer atom is #dddd, where the values represented by dddd are decimal\r\ndigits. Leading zeros are ignored.\r\nThere is no reference count or storage overhead associated with an integer atom.\r\nAn application creates a local atom by calling the AddAtom function; it creates a global atom by calling the\r\nGlobalAddAtom function. Both functions require a pointer to a string. The system searches the appropriate atom\r\ntable for the string and returns the corresponding atom to the application. In the case of a string atom, if the string\r\nalready resides in the atom table, the system increments the reference count for the string during this process.\r\nRepeated calls to add the same atom name return the same atom. If the atom name does not exist in the table when\r\nAddAtom is called, the atom name is added to the table and a new atom is returned. If it is a string atom, its\r\nreference count is also set to one.\r\nAn application should call the DeleteAtom function when it no longer needs to use a local atom; it should call the\r\nGlobalDeleteAtom function when it no longer needs a global atom. In the case of a string atom, either of these\r\nfunctions reduces the reference count of the corresponding atom by one. When the reference count reaches zero,\r\nthe system deletes the atom name from the table.\r\nhttps://msdn.microsoft.com/library/windows/desktop/ms649053.aspx\r\nPage 3 of 4\n\nThe atom name of a string atom remains in the global atom table as long as its reference count is greater than zero,\r\neven after the application that placed it in the table terminates. A local atom table is destroyed when the associated\r\napplication terminates, regardless of the reference counts of the atoms in the table.\r\nAn application can determine whether a particular string is already in an atom table by using the FindAtom or\r\nGlobalFindAtom function. These functions search an atom table for the specified string and, if the string is there,\r\nreturn the corresponding atom.\r\nAn application can use the GetAtomName or GlobalGetAtomName function to retrieve an atom-name string\r\nfrom an atom table, provided the application has the atom corresponding to the string being sought. Both functions\r\ncopy the atom-name string of the specified atom to a buffer and return the length of the string that was copied.\r\nGetAtomName retrieves an atom-name string from a local atom table, and GlobalGetAtomName retrieves an\r\natom-name string from the global atom table.\r\nThe AddAtom, GlobalAddAtom, FindAtom, and GlobalFindAtom functions take a pointer to a null-terminated\r\nstring. An application can specify this pointer in one of the following ways.\r\nString format Description\r\n#dddd An integer specified as a decimal string. Used to create or find an integer atom.\r\nstring atom\r\nname\r\nA string atom name. Used to add a string atom name to an atom table and receive an atom\r\nin return.\r\nSource: https://msdn.microsoft.com/library/windows/desktop/ms649053.aspx\r\nhttps://msdn.microsoft.com/library/windows/desktop/ms649053.aspx\r\nPage 4 of 4",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://msdn.microsoft.com/library/windows/desktop/ms649053.aspx"
	],
	"report_names": [
		"ms649053.aspx"
	],
	"threat_actors": [],
	"ts_created_at": 1775434611,
	"ts_updated_at": 1775791333,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/b031560fad36ef7e7384bd7e7c44352c86215bb7.pdf",
		"text": "https://archive.orkl.eu/b031560fad36ef7e7384bd7e7c44352c86215bb7.txt",
		"img": "https://archive.orkl.eu/b031560fad36ef7e7384bd7e7c44352c86215bb7.jpg"
	}
}