Recently I’ve hit a wall during development. I had written a nice workaround for a problem, based on code injection. In fact the code wasn’t injected by loading a DLL but instead by loading relocatable (32bit) code of less than 250 byte size. However, once I started testing it on Vista, the topstack method to retrieve the address of kernel32.dll inside the target process didn’t work anymore, so I had to resort to the PEB method. No big deal.
However, once I got that sorted out, the whole thing worked when run from the same (terminal) session, but failed as soon as the program (in simulation of the later real-world conditions) was started as SYSTEM by the task scheduler (i.e. from the session in which services run). Obviously the task scheduler isn’t all too talkative about the reasons of failure of a scheduled program, so my assumption was, that it must have to do with the stricter session separation on Vista and the documentation of CreateRemoteThread() confirms this:
Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process.