A process id is a DWORD (unsigned 32-bit value). The maximum value of a DWORD is 0xFFFFFFFF (or -1 as a signed 32 bit value). However, as Raymond Chen discusses in his blog at Invalid thread and process IDs, the AllowSetForegroundWindow function documentation indicates that 0xFFFFFFFF is not a valid process id since it is used by the ASFW_ANY parameter. Therefore, the theoretical maximum value for a valid process id would be 0xFFFFFFFE.
Maximum value of process ID
What is the maximum process ID for each OS?
- Windows XP Pro (32bit)
- Windows7 Pro (32bit)
- Windows 10 IoT Enterprise 2016 LTSB(64bit)
Developer technologies | Visual Studio | Other
1 additional answer
Sort by: Most helpful
-
Xitalogy 1 Reputation point
2021-04-17T08:58:13.9+00:00 Unfortunately, the accepted answer appears to be incorrect
EDIT: Apr 18 2021 - xitalogy - the OP on the accepted answer put a comment on it and edited it to correct it. It was a simple typo. I will leave this answer here, though, because I feel anyone who wants to go through the (rather lengthy and technical) answer here could benefit from some of the additional information.
Click this link, then scroll down to DWORD:
https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
It says the following (copied/pasted):
DWORD A 32-bit unsigned integer. The range is 0 through 4294967295 decimal.
This type is declared in IntSafe.h as follows:
typedef unsigned long DWORD;I verified the typedef in IntSafe.h in the Windows 10 SDK
NOTE: 0x is the C/C++ prefix to indicate hexadecimal notation
32 bits / 8 bits per byte == 4 bytes: 0xFF == 255 (one byte) 4 bytes would be 0xFFFFFFFF == 4294967295 (4 FFs put together, not 3 as in your answer, which would be 24 bits, not 32 bits) for a DWORD (unsigned long)
Copied directly from WinUser.h in the Windows 10 SDK:
#define ASFW_ANY ((DWORD)-1)
This gives 4294967295 (decimal) for a DWORD (unsigned long) or -1 (decimal) for a long (signed). Both would show 0xFFFFFFFF when displayed in hexadecimal (see test results below).
Testing
Here are the results of some test code I wrote in Visual Studio 2019 Preview (C++) with identical results for 64 bit and 32 bit targets (numbers should be identical in Windows XP Pro and Windows 7 Pro):
DWORD DWORD_var (hex)................: 0xFFFFFFFF (dec): 4294967295 DWORD DWORD_var (AFSW_ANY - hex).....: 0xFFFFFFFF (dec): 4294967295 unsigned long unsigned_long_var (hex): 0xFFFFFFFF (dec): 4294967295 long long_var (hex)..................: 0xFFFFFFFF (dec): -1 long long_var (hex)..................: 0xFFFFFFFE (dec): -2 long long_var (hex)..................: 0x80000000 (dec): -2147483648 long long_var (hex)..................: 0x7FFFFFFF (dec): 2147483647 long long_var (hex)..................: 0x7FFFFFFE (dec): 2147483646 long long_var (hex)..................: 0xFFFFFF (dec): 16777215 long long_var (hex)..................: 0xFFFFFE (dec): 16777214
Here is that code (C++):
DWORD DWORD_var = 0xFFFFFFFF; unsigned long unsigned_long_var = 0xFFFFFFFF; long long_var = 0xFFFFFFFF; std::wostringstream wostringstream; wostringstream << std::endl << "DWORD DWORD_var (hex)................: 0x" << std::hex << std::uppercase << DWORD_var << " (dec): " << std::dec << DWORD_var; DWORD_var = ASFW_ANY; // From WinUser.h: #define ASFW_ANY ((DWORD)-1) wostringstream << std::endl << "DWORD DWORD_var (AFSW_ANY - hex).....: 0x" << std::hex << std::uppercase << DWORD_var << " (dec): " << std::dec << DWORD_var; wostringstream << std::endl << "unsigned long unsigned_long_var (hex): 0x" << std::hex << std::uppercase << unsigned_long_var << " (dec): " << std::dec << unsigned_long_var; wostringstream << std::endl << "long long_var (hex)..................: 0x" << std::hex << std::uppercase << long_var << " (dec): " << std::dec << long_var; long_var = 0xFFFFFFFE; wostringstream << std::endl << "long long_var (hex)..................: 0x" << std::hex << std::uppercase << long_var << " (dec): " << std::dec << long_var; long_var = 0x80000000; wostringstream << std::endl << "long long_var (hex)..................: 0x" << std::hex << std::uppercase << long_var << " (dec): " << std::dec << long_var; long_var = 0x7FFFFFFF; wostringstream << std::endl << "long long_var (hex)..................: 0x" << std::hex << std::uppercase << long_var << " (dec): " << std::dec << long_var; long_var = 0x7FFFFFFE; wostringstream << std::endl << "long long_var (hex)..................: 0x" << std::hex << std::uppercase << long_var << " (dec): " << std::dec << long_var; long_var = 0xFFFFFF; wostringstream << std::endl << "long long_var (hex)..................: 0x" << std::hex << std::uppercase << long_var << " (dec): " << std::dec << long_var; long_var = 0xFFFFFE; wostringstream << std::endl << "long long_var (hex)..................: 0x" << std::hex << std::uppercase << long_var << " (dec): " << std::dec << long_var; OutputDebugString(wostringstream.str().c_str());
Final Note on Process/Thread ID Limits
Mark Russinovich wrote the following in a 2009 blog post. My guess is it is still accurate in Windows 10 today.:
Unlike some UNIX variants, most resources in Windows have no fixed upper bound compiled into the operating system, but rather derive their limits based on basic operating system resources that I’ve already covered. Process and threads, for example, require physical memory, virtual memory, and pool memory, so the number of processes or threads that can be created on a given Windows system is ultimately determined by one of these resources, depending on the way that the processes or threads are created and which constraint is hit first.
Link to that post:
Obviously, though practically speaking unreachable, the upper limit of a DWORD would be a hard constraint, however, and since -1 is not a valid value, I kind of wonder if any number resulting in a negative if signed might be invalid, which would give a hard (but again, practically speaking unreachable) upper limit of 2147483647. That is just speculation, though