But the naive way of doing this also wouldn't really require two passes, right? It would just require more memory because you would first save all file names in an array (stopping at 100), then pick a random one in constant time.
How do you know how big your array has to be in a single pass? I don't think the WinXP source uses vectors or similarly ergonomic auto-growing arrays. You could preallocate an array big enough for 100 paths of length MAX_PATH, but that's a bit wasteful. And it doesn't sound like you'd actually end up with fewer lines of code (in that flavor of C++, in python it would be different)
Practically speaking, I might just allocate an array of 100 pointers. That's only 400 bytes. Then as you encounter each filename, allocate just enough memory for the actual length of the string (plus null terminator) and store the pointer in the array.
Yes, you could allocate it on the stack. I think back then (still?) a filename could be at most 260 characters, each encoded with 16 bits, so about 52k of stack allocation.