winprocess.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef __WINPROCESS
  14. #define __WINPROCESS
  15. #include "win32.hpp"
  16. #include "winternl.h"
  17. #include "psapi.h"
  18. #include <vector>
  19. #include <list>
  20. #define MAX_COMMAND 1024
  21. // another kludge to build Win2K programs with NT 4 build environment
  22. extern "C" WINBASEAPI BOOL WINAPI ProcessIdToSessionId(DWORD dwProcessId,DWORD *pSessionId);
  23. namespace win32
  24. {
  25. typedef std::vector<wchar_t> wstring;
  26. class Process: public Handle
  27. {
  28. public:
  29. Process()
  30. {}
  31. Process(int _pid, int access): Handle(::OpenProcess(access, FALSE, _pid))
  32. {}
  33. Process(HANDLE h, int access): Handle(h,access)
  34. {}
  35. //needs SDK
  36. #ifdef _PSAPI_H_
  37. TCHAR* GetImageName(TCHAR* buf,size_t size)
  38. {
  39. DWORD res=0;
  40. TCHAR temp[MAX_PATH];
  41. if(::GetModuleFileNameEx(*this,NULL,temp,arraysize(temp)))
  42. {
  43. if(!::GetLongPathName(temp,buf,size))
  44. {
  45. _tcsncpy(buf,temp,size);
  46. }
  47. return buf;
  48. }
  49. return 0;
  50. }
  51. #endif
  52. bool Terminate(int code=-1)
  53. {
  54. return ::TerminateProcess(*this,code)!=FALSE;
  55. }
  56. };
  57. class RemoteMemoryAsync
  58. {
  59. public:
  60. RemoteMemoryAsync(HANDLE proc,void* data,size_t size,DWORD access)
  61. {
  62. buf=::VirtualAllocEx(proc,NULL,size,MEM_COMMIT,access);
  63. if(buf)
  64. ::WriteProcessMemory(proc,buf,data,size,0);
  65. }
  66. operator void*() { return buf; }
  67. protected:
  68. void* buf;
  69. };
  70. class RemoteMemory: public RemoteMemoryAsync
  71. {
  72. public:
  73. RemoteMemory(HANDLE _proc,void* data,size_t size,DWORD access):
  74. RemoteMemoryAsync(_proc,data,size,access), proc(_proc) {}
  75. ~RemoteMemory()
  76. {
  77. if(buf)
  78. ::VirtualFreeEx(proc,buf,0,MEM_RELEASE);
  79. }
  80. protected:
  81. HANDLE proc;
  82. };
  83. class RemoteThread: public Handle
  84. {
  85. public:
  86. RemoteThread(HANDLE process, LPTHREAD_START_ROUTINE func, LPVOID param, DWORD flags, DWORD stack=0):
  87. Handle(::CreateRemoteThread(process,NULL,stack,func,param,flags,&id))
  88. {
  89. }
  90. protected:
  91. DWORD id;
  92. };
  93. class ProcessPipe
  94. {
  95. public:
  96. ProcessPipe(const TCHAR* progname, const char * envp=NULL)
  97. {
  98. HANDLE pipeRead, pipeWrite;
  99. // Create a pipe to read output from the child program
  100. if(!::CreatePipe(&pipeRead, &pipeWrite, NULL, 0))
  101. {
  102. return;
  103. }
  104. read.set(pipeRead);
  105. Handle hstdout(pipeWrite,0,true,DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE);
  106. // Create a pipe to supply data to the child program
  107. if(!::CreatePipe(&pipeRead, &pipeWrite, NULL, 0))
  108. {
  109. return;
  110. }
  111. write.set(pipeWrite);
  112. Handle hstdin(pipeRead,0,true,DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE);
  113. // Prep the child program
  114. STARTUPINFO StartupInfo;
  115. memset(&StartupInfo,0,sizeof(StartupInfo));
  116. StartupInfo.cb = sizeof(StartupInfo);
  117. StartupInfo.wShowWindow = SW_HIDE;
  118. StartupInfo.hStdOutput = hstdout;
  119. StartupInfo.hStdInput = hstdin;
  120. StartupInfo.hStdError = 0;
  121. StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
  122. PROCESS_INFORMATION pi;
  123. // Launch it..
  124. if (!CreateProcess(NULL, // lpApplicationName
  125. (TCHAR *) progname, // lpCommandLine
  126. NULL, // lpProcessAttributes
  127. NULL, // lpThreadAttributes
  128. TRUE, // bInheritHandles
  129. CREATE_NO_WINDOW, // dwCreationFlags
  130. (void *)envp, // lpEnvironment
  131. NULL, // lpCurrentDirectory
  132. &StartupInfo, // lpStartupInfo
  133. &pi)) // lpProcessInformation
  134. {
  135. return;
  136. }
  137. CloseHandle(pi.hProcess);
  138. CloseHandle(pi.hThread);
  139. }
  140. size_t Write(const char *input, size_t inputLen)
  141. {
  142. DWORD wrote;
  143. if(!::WriteFile(write, input, inputLen, &wrote, NULL))
  144. {
  145. }
  146. return wrote;
  147. }
  148. void CloseRead()
  149. {
  150. read.Close();
  151. }
  152. void CloseWrite()
  153. {
  154. write.Close();
  155. }
  156. size_t Read(char *output, size_t outputLen)
  157. {
  158. DWORD bread=0;
  159. if(::ReadFile(read, output, outputLen, &bread, NULL))
  160. {
  161. return bread;
  162. }
  163. return bread;
  164. }
  165. protected:
  166. Handle read, write;
  167. };
  168. struct ProcessPid: public Process
  169. {
  170. ProcessPid(): pid(0) {}
  171. ProcessPid(int _pid,DWORD _access): Process(_pid,PROCESS_DUP_HANDLE|_access), pid(_pid) {}
  172. int GetPid() { return pid; }
  173. int GetSession()
  174. {
  175. DWORD session=-1;
  176. if(::ProcessIdToSessionId(pid,&session))
  177. return session;
  178. return -1;
  179. }
  180. int pid;
  181. };
  182. class ProcessList: public std::list<ProcessPid>
  183. {
  184. public:
  185. ProcessList(DWORD _access=SYNCHRONIZE): access(_access)
  186. {
  187. }
  188. void add(int pid)
  189. {
  190. ProcessPid p(pid,access);
  191. if(p)
  192. {
  193. #if _MSC_VER >= 1300
  194. push_back(p);
  195. #else
  196. iterator it=insert(end());
  197. std::swap(*it,p);
  198. #endif
  199. }
  200. }
  201. void add(const TCHAR* image)
  202. {
  203. TCHAR imagepath[MAX_PATH];
  204. if(image && !::SearchPath(NULL,image,TEXT(".exe"),arraysize(imagepath),imagepath,NULL))
  205. {
  206. return;
  207. }
  208. size_t len=imagepath ? _tcslen(imagepath) : 0;
  209. for(DWORD buflen=1024*sizeof(DWORD);;buflen*=2)
  210. {
  211. DWORD* processes=(DWORD*)_alloca(buflen), size=0;
  212. if (::EnumProcesses(processes, buflen, &size))
  213. {
  214. if(buflen<=size && buflen<1000*1000)
  215. continue;
  216. for (unsigned i=1;i<size/sizeof(DWORD);i++)
  217. {
  218. TCHAR path[MAX_PATH]={0};
  219. Process proc(processes[i], PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_DUP_HANDLE|access);
  220. if(proc && proc.GetImageName(path, arraysize(path)))
  221. {
  222. if(!image || _tcsnicmp(imagepath,path,len)==0 &&
  223. (path[len]==0 || // Filename matches
  224. _tcsrchr(path+len,'\\')==path+len)) // Directories match
  225. {
  226. add(processes[i]);
  227. }
  228. }
  229. }
  230. break;
  231. }
  232. else
  233. throw Error(TEXT("Could not enum processes"));
  234. }
  235. }
  236. DWORD access;
  237. };
  238. }
  239. #endif