win32.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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 __JWIN32_HPP
  14. #define __JWIN32_HPP
  15. #define _CRT_SECURE_NO_WARNINGS
  16. #define _WIN32_WINNT 0x0500
  17. #include <windows.h>
  18. #include <stdio.h>
  19. #include <stdarg.h>
  20. #include <malloc.h>
  21. #include <tchar.h>
  22. #ifndef arraysize
  23. #define arraysize(T) (sizeof(T)/sizeof(*T))
  24. #endif
  25. namespace win32
  26. {
  27. class Error
  28. {
  29. public:
  30. Error(LPCTSTR msg,...): code(0)
  31. {
  32. memset(buf,0,sizeof(buf));
  33. va_list marker;
  34. va_start(marker,msg);
  35. _vsntprintf(buf,arraysize(buf)-1,msg,marker);
  36. va_end(marker);
  37. }
  38. LPCTSTR GetMessage() const { return buf; }
  39. DWORD GetCode() const { return code; }
  40. static void perror()
  41. {
  42. DWORD code=::GetLastError();
  43. LPVOID msg=0;
  44. if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL) && msg)
  45. {
  46. _tprintf(TEXT("System error %d: %s\n"),code,(const char *)msg);
  47. ::LocalFree(msg);
  48. }
  49. }
  50. protected:
  51. Error(): code(::GetLastError())
  52. {
  53. memset(buf,0,sizeof(buf));
  54. }
  55. DWORD code;
  56. TCHAR buf[256];
  57. };
  58. class SystemError: public Error
  59. {
  60. public:
  61. SystemError(LPCTSTR msg,...)
  62. {
  63. va_list marker;
  64. va_start(marker,msg);
  65. _vsntprintf(buf,arraysize(buf)-1,msg,marker);
  66. va_end(marker);
  67. if(code!=ERROR_SUCCESS)
  68. {
  69. LPVOID msg=0;
  70. if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL) && msg)
  71. {
  72. size_t len=_tcslen(buf);
  73. if(len<arraysize(buf)-1)
  74. _sntprintf(buf+len,arraysize(buf)-1-len,TEXT(" - (%d) %s"),code,(const char *)msg);
  75. ::LocalFree(msg);
  76. }
  77. }
  78. }
  79. };
  80. struct NullHandle
  81. {
  82. operator HANDLE() { return NULL; }
  83. };
  84. struct InvalidHandle
  85. {
  86. operator HANDLE() { return INVALID_HANDLE_VALUE; }
  87. };
  88. template<typename inv> class HandleBase
  89. {
  90. public:
  91. HandleBase(): handle(inv()) {}
  92. HandleBase(HANDLE h, DWORD access, bool inherit=false, DWORD options=0, HANDLE source=GetCurrentProcess()): handle(inv())
  93. {
  94. ::DuplicateHandle(source,h,::GetCurrentProcess(),&handle,access,inherit,options);
  95. }
  96. ~HandleBase() { if(isValid()) Close(); }
  97. operator HANDLE() { return handle; }
  98. bool operator !() { return !isValid(); }
  99. void set(HANDLE h)
  100. {
  101. if(isValid())
  102. Close();
  103. handle=h;
  104. }
  105. HANDLE get()
  106. {
  107. HANDLE temp=handle;
  108. handle=inv();
  109. return temp;
  110. }
  111. void Close()
  112. {
  113. ::CloseHandle(handle);
  114. handle=inv();
  115. }
  116. DWORD Wait(int timeout=INFINITE,bool alertable=false)
  117. {
  118. return ::WaitForSingleObjectEx(*this,timeout,alertable?TRUE:FALSE);
  119. }
  120. bool isSignaled()
  121. {
  122. return Wait(0)==WAIT_OBJECT_0;
  123. }
  124. bool isValid()
  125. {
  126. return handle!=inv();
  127. }
  128. protected:
  129. HANDLE handle;
  130. HandleBase(HANDLE h): handle(h) { }
  131. };
  132. typedef HandleBase<NullHandle> Handle;
  133. class Event: public Handle
  134. {
  135. public:
  136. Event(bool manual, bool state, LPSECURITY_ATTRIBUTES sa=NULL):
  137. Handle(::CreateEvent(sa, manual, state, NULL)) {}
  138. Event(const char* name, bool manual, bool state, LPSECURITY_ATTRIBUTES sa=NULL):
  139. Handle(::CreateEventA(sa, manual, state, name)) {}
  140. Event(const char* name, int access):
  141. Handle(::OpenEventA(access, FALSE, name)) {}
  142. Event(const wchar_t* name, bool manual, bool state, LPSECURITY_ATTRIBUTES sa=NULL):
  143. Handle(::CreateEventW(sa, manual, state, name)) {}
  144. Event(const wchar_t* name, int access):
  145. Handle(::OpenEventW(access, FALSE, name)) {}
  146. bool Set()
  147. {
  148. return ::SetEvent(*this)!=FALSE;
  149. }
  150. bool Reset()
  151. {
  152. return ::ResetEvent(*this)!=FALSE;
  153. }
  154. };
  155. struct Overlapped:public OVERLAPPED
  156. {
  157. Overlapped(LPCTSTR name=NULL)
  158. {
  159. memset((OVERLAPPED*)this,0,sizeof(OVERLAPPED));
  160. hEvent=::CreateEvent(NULL,TRUE,FALSE,name);
  161. }
  162. ~Overlapped()
  163. {
  164. ::CloseHandle(hEvent);
  165. }
  166. operator HANDLE()
  167. {
  168. return hEvent;
  169. }
  170. DWORD Wait(int timeout=INFINITE,bool alertable=false)
  171. {
  172. return ::WaitForSingleObjectEx(*this,timeout,alertable?TRUE:FALSE);
  173. }
  174. bool isSignaled()
  175. {
  176. return Wait(0)==WAIT_OBJECT_0;
  177. }
  178. void Reset()
  179. {
  180. HANDLE evt=hEvent;
  181. ::ResetEvent(evt);
  182. memset((OVERLAPPED*)this,0,sizeof(OVERLAPPED));
  183. hEvent=evt;
  184. }
  185. };
  186. class File: public HandleBase<InvalidHandle>
  187. {
  188. public:
  189. File() {}
  190. File(LPCTSTR name,DWORD access,DWORD share=0,DWORD create=OPEN_EXISTING,DWORD flags=0,LPSECURITY_ATTRIBUTES sa=NULL):
  191. HandleBase<InvalidHandle>(::CreateFile(name,access,share,sa,create,flags,NULL))
  192. {
  193. }
  194. operator bool() { return isValid(); }
  195. bool Open(LPCSTR name,DWORD access,DWORD share=0,DWORD create=OPEN_EXISTING,DWORD flags=0,LPSECURITY_ATTRIBUTES sa=NULL)
  196. {
  197. set(::CreateFileA(name,access,share,sa,create,flags,NULL));
  198. return isValid();
  199. }
  200. bool Open(LPCWSTR name,DWORD access,DWORD share=0,DWORD create=OPEN_EXISTING,DWORD flags=0,LPSECURITY_ATTRIBUTES sa=NULL)
  201. {
  202. set(::CreateFileW(name,access,share,sa,create,flags,NULL));
  203. return isValid();
  204. }
  205. DWORD Read(LPVOID buffer,DWORD count,LPOVERLAPPED ovr=NULL)
  206. {
  207. DWORD temp=0;
  208. ::ReadFile(*this,buffer,count,&temp,ovr);
  209. return temp;
  210. }
  211. DWORD Write(LPCVOID buffer,DWORD count,LPOVERLAPPED ovr=NULL)
  212. {
  213. DWORD temp=0;
  214. ::WriteFile(*this,buffer,count,&temp,ovr);
  215. return temp;
  216. }
  217. DWORD GetResult(LPOVERLAPPED ovr, bool wait=false)
  218. {
  219. DWORD temp=0;
  220. ::GetOverlappedResult(*this,ovr,&temp,wait ? TRUE : FALSE);
  221. return temp;
  222. }
  223. DWORD Transact(LPVOID inBuffer,DWORD inBufferSize,LPVOID outBuffer,DWORD outBufferSize,LPOVERLAPPED lpOverlapped=NULL)
  224. {
  225. DWORD temp=0;
  226. ::TransactNamedPipe(*this,inBuffer,inBufferSize,outBuffer,outBufferSize,&temp,lpOverlapped);
  227. return temp;
  228. }
  229. BOOL SetPipeState(LPDWORD mode,LPDWORD maxCollectionCount=0,LPDWORD collectDataTimeout=0)
  230. {
  231. return ::SetNamedPipeHandleState(*this,mode,maxCollectionCount,collectDataTimeout);
  232. }
  233. BOOL SetPipeMode(DWORD mode)
  234. {
  235. return SetPipeState(&mode);
  236. }
  237. BOOL CancelIO()
  238. {
  239. return ::CancelIo(*this);
  240. }
  241. protected:
  242. File(HANDLE h): HandleBase<InvalidHandle>(h) {}
  243. };
  244. class NamedPipe: public File
  245. {
  246. public:
  247. NamedPipe() {}
  248. NamedPipe(LPCTSTR name,DWORD openMode,DWORD pipeMode=PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT,DWORD maxInstances=PIPE_UNLIMITED_INSTANCES, DWORD outBufferSize=0,DWORD inBufferSize=0,DWORD defaultTimeOut=-1,LPSECURITY_ATTRIBUTES sa=NULL):
  249. File(::CreateNamedPipe(name,openMode,pipeMode,maxInstances,outBufferSize,inBufferSize,defaultTimeOut,sa))
  250. {
  251. }
  252. ~NamedPipe() {}
  253. bool Open(LPCSTR name,DWORD openMode,DWORD pipeMode=PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT,DWORD maxInstances=PIPE_UNLIMITED_INSTANCES, DWORD outBufferSize=0,DWORD inBufferSize=0,DWORD defaultTimeOut=-1,LPSECURITY_ATTRIBUTES sa=NULL)
  254. {
  255. set(::CreateNamedPipeA(name,openMode,pipeMode,maxInstances,outBufferSize,inBufferSize,defaultTimeOut,sa));
  256. return isValid();
  257. }
  258. bool Open(LPCWSTR name,DWORD openMode,DWORD pipeMode=PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT,DWORD maxInstances=PIPE_UNLIMITED_INSTANCES, DWORD outBufferSize=0,DWORD inBufferSize=0,DWORD defaultTimeOut=-1,LPSECURITY_ATTRIBUTES sa=NULL)
  259. {
  260. set(::CreateNamedPipeW(name,openMode,pipeMode,maxInstances,outBufferSize,inBufferSize,defaultTimeOut,sa));
  261. return isValid();
  262. }
  263. bool Connect(LPOVERLAPPED ovr=NULL)
  264. {
  265. return ::ConnectNamedPipe(*this,ovr)==TRUE || GetLastError()==ERROR_PIPE_CONNECTED;
  266. }
  267. bool Disconnect()
  268. {
  269. return ::DisconnectNamedPipe(*this)!=FALSE;
  270. }
  271. bool ImpersonateClient()
  272. {
  273. return ::ImpersonateNamedPipeClient(*this)!=FALSE;
  274. }
  275. };
  276. class Token: public Handle
  277. {
  278. public:
  279. Token() {}
  280. Token(HANDLE existingToken,DWORD access,LPSECURITY_ATTRIBUTES tokenAttributes,SECURITY_IMPERSONATION_LEVEL impersonationLevel,TOKEN_TYPE tokenType)
  281. {
  282. if(!::DuplicateTokenEx(existingToken,access,tokenAttributes,impersonationLevel,tokenType,&handle))
  283. {
  284. }
  285. }
  286. bool AdjustPrivilege(LPCTSTR privname,bool enable)
  287. {
  288. int count=1,
  289. size=sizeof(DWORD)+sizeof(LUID_AND_ATTRIBUTES)*count;
  290. TOKEN_PRIVILEGES* privs=(TOKEN_PRIVILEGES*)_alloca(size);
  291. privs->PrivilegeCount=count;
  292. if(!::LookupPrivilegeValue(NULL,privname,&privs->Privileges[0].Luid))
  293. return false;
  294. if(enable)
  295. privs->Privileges[0].Attributes|=SE_PRIVILEGE_ENABLED;
  296. else
  297. privs->Privileges[0].Attributes=0;
  298. return ::AdjustTokenPrivileges(*this,FALSE,privs,size,NULL,0)!=0 && ::GetLastError()==ERROR_SUCCESS;
  299. }
  300. DWORD GetInfo(TOKEN_INFORMATION_CLASS info,LPVOID buf,DWORD size)
  301. {
  302. DWORD sz=0;
  303. if(!::GetTokenInformation(*this,info,buf,size,&sz))
  304. {
  305. return 0;
  306. }
  307. return sz;
  308. }
  309. DWORD GetInfoSize(TOKEN_INFORMATION_CLASS info)
  310. {
  311. DWORD sz=0;
  312. ::GetTokenInformation(*this,info,0,0,&sz);
  313. return sz;
  314. }
  315. BOOL SetInfo(TOKEN_INFORMATION_CLASS info,LPVOID buf,DWORD size)
  316. {
  317. return ::SetTokenInformation(*this,info,buf,size);
  318. }
  319. protected:
  320. };
  321. class ProcessToken: public Token
  322. {
  323. public:
  324. ProcessToken(int access)
  325. {
  326. ::OpenProcessToken(::GetCurrentProcess(),access,&handle);
  327. }
  328. ProcessToken(HANDLE process,int access)
  329. {
  330. ::OpenProcessToken(process,access,&handle);
  331. }
  332. };
  333. class ThreadToken: public Token
  334. {
  335. public:
  336. ThreadToken(int access,bool self=false)
  337. {
  338. ::OpenThreadToken(::GetCurrentThread(),access,self?TRUE:FALSE,&handle);
  339. }
  340. ThreadToken(HANDLE thread,int access,bool self=false)
  341. {
  342. ::OpenThreadToken(thread,access,self?TRUE:FALSE,&handle);
  343. }
  344. };
  345. class UserToken:public Token
  346. {
  347. public:
  348. UserToken(LPSTR lpszUsername,LPSTR lpszDomain,LPSTR lpszPassword,DWORD dwLogonType,WORD dwLogonProvider=LOGON32_PROVIDER_DEFAULT)
  349. {
  350. if(!LogonUserA(lpszUsername,lpszDomain,lpszPassword,dwLogonType,dwLogonProvider,&handle))
  351. handle=NULL;
  352. }
  353. UserToken(LPWSTR lpszUsername,LPWSTR lpszDomain,LPWSTR lpszPassword,DWORD dwLogonType,WORD dwLogonProvider=LOGON32_PROVIDER_DEFAULT)
  354. {
  355. if(!LogonUserW(lpszUsername,lpszDomain,lpszPassword,dwLogonType,dwLogonProvider,&handle))
  356. handle=NULL;
  357. }
  358. };
  359. }
  360. #endif