The mistake that cloudy did and probably you too was that you can't use global variables inside the injected function.
Code:
system("c:/windows/notepad.exe");
This string IS a global variable. One way to do it might be something like this:
Code:
char localvar[24]={'c',':','/','w','i','n','d','o','w','s','/','n',
'o','t','e','p','a','d','.','e','x','e',0};
The second mistake was to call a function inside injected function. You can't call functions directly because the import section of each process is different. (The normal calls inside processes first call the import section equivalent which redirects it to the real function).
The only way to get something done is to also inject a structure with the real addresses (the addresses of basic DLL's functions are the same in every process) of the functions you want to use (I recommend only to send the addys of GetProcAddress and GetModuleHandle) into the target process and pass the pointer to that structure as an argument to your remote thread. You can get the real address of a function by using for example
Code:
fnGetProcAddress=GetProcAddress(GetModuleHandle("kernel32"),"GetProcAddressA");
You can only pass the functions of the modules of the basic Windows DLL's such as kernel32, user32 and a few more. So if you want to get the addys of more functions inside that process you have to send it the addys of GetProcAddress and GetModuleHandle so it could indepently get the addys of more functions.
Cloudy also just used a guessed size of the injected function, which is very bad too. There isn't a standard way to get the size of a function, but there is one hackish way to do it. You can add an empty function after the injected function and subtract the address of the injected function from the function after it. Notice that this may or may not work depending on your compiler. For example in MSVC++ if you make two injected functions and add an empty function after them, it merges the empty functions, so you've got to make those functions do different meaningless things.
One more thing - you've got to turn off ANY exception handling routines which the compiler adds, because it adds these routines to your injected function too.
If you didn't understand any of this, you should start by learning the structure of an executable, a little assembly and reverse engineering.