Claro que va a fallar. Tenes que usar GetModuleFileNameEx, no GetModuleFileName. De hecho ni siquiera son los mismos parámetros, lee la documentación de la MSDN.
DWORD WINAPI GetModuleFileNameEx(
__in HANDLE hProcess,
__in_opt HMODULE hModule,
__out LPTSTR lpFilename,
__in DWORD nSize
);
To locate the file for a module that was loaded by another process, use the GetModuleFileNameEx function.
hModule [in, optional]
A handle to the module. If this parameter is NULL, GetModuleFileNameEx returns the path of the executable file of the process specified in hProcess.
Igualmente de esta manera hay que hacer un openproces con lo que no podre abrir cualquier proceso, por ejemplo el lsa.exe y no podre obtener su ruta.
En el ejemplo yo puse PROCESS_ALL_ACCESS para escribir menos pero lo correcto es utilizar solo lo necesario, lo cual en el caso de GetModuleFileNameEx es PROCESS_QUERY_INFORMATION y PROCESS_VM_READ por lo que no debería haber demasiado problema con la mayoría de los procesos y en caso de haberlo te basta con ajustar los privilegios correctamente.
Por otro lado, obviamente existe una limitación al querer hacerlo desde modo usuario, pero eso es un tema aparte. La limitación la instalas vos desde un principio al querer hacerlo desde modo usuario.
Saludos