fork download
  1. // Copyright 2011 (C) Etienne Dechamps (e-t172) <e-t172@akegroup.org>
  2. /*
  3.  * This program is free software: you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation, either version 3 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program. If not, see <http://w...content-available-to-author-only...u.org/licenses/>.
  15.  */
  16.  
  17. #include <chrono>
  18. #include <cstdlib>
  19. #include <fstream>
  20. #include <iomanip>
  21. #include <memory>
  22. #include <sstream>
  23.  
  24. #include <windows.h>
  25.  
  26. namespace laplock {
  27. namespace {
  28.  
  29. class LogLine {
  30. public:
  31. LogLine() {
  32. if (!logfile) return;
  33. auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
  34. tm localnow;
  35. if (localtime_s(&localnow, &now) == 0) {
  36. *logfile << std::put_time(&localnow, L"%F %T ");
  37. }
  38. }
  39.  
  40. ~LogLine() {
  41. if (!logfile) return;
  42. *logfile << std::endl;
  43. logfile->flush();
  44. }
  45.  
  46. template <typename T> LogLine& operator<<(T value) {
  47. if (!logfile) return *this;
  48. *logfile << value;
  49. return *this;
  50. }
  51.  
  52. static std::unique_ptr<std::wofstream> logfile;
  53. };
  54.  
  55. std::unique_ptr<std::wofstream> LogLine::logfile;
  56.  
  57. std::wostream& operator<<(std::wostream& stream, const GUID& guid) {
  58. wchar_t str[128] = { 0 };
  59. StringFromGUID2(guid, str, sizeof(str));
  60. stream << str;
  61. return stream;
  62. }
  63.  
  64. static void systemError(wchar_t* what)
  65. {
  66. const DWORD error = GetLastError();
  67. LogLine() << "Error " << error << " during: " << what;
  68. static wchar_t buffer[1024];
  69. const wchar_t* errorMessage = buffer;
  70.  
  71. if (!FormatMessage(
  72. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  73. 0,
  74. error,
  75. 0,
  76. buffer,
  77. sizeof(buffer),
  78. 0
  79. ))
  80. errorMessage = L"(cannot format error message)";
  81. else
  82. LogLine() << "System error message: " << errorMessage;
  83.  
  84. std::wstringstream message;
  85. message << L"A system error occured within laplock." << std::endl;
  86. message << L"Operation: " << what << std::endl;
  87. message << L"System message: " << errorMessage;
  88. MessageBox(NULL, message.str().c_str(), L"laplock error", MB_OK | MB_ICONERROR);
  89.  
  90. exit(EXIT_FAILURE);
  91. }
  92.  
  93. static LRESULT CALLBACK windowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  94. {
  95. if (uMsg != WM_POWERBROADCAST || wParam != PBT_POWERSETTINGCHANGE) {
  96. LogLine() << "Window received irrelevant message";
  97. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  98. }
  99.  
  100. if (GetSystemMetrics(SM_REMOTESESSION)) {
  101. LogLine() << "Ignoring window message because session is currently remote";
  102. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  103. }
  104.  
  105. const POWERBROADCAST_SETTING* setting = reinterpret_cast<const POWERBROADCAST_SETTING*>(lParam);
  106. LogLine() << "Received POWERBROADCAST_SETTING " << setting->PowerSetting;
  107. if (setting->PowerSetting != GUID_MONITOR_POWER_ON && setting->PowerSetting != GUID_LIDSWITCH_STATE_CHANGE) {
  108. LogLine() << "Received irrelevant POWERBROADCAST_SETTING";
  109. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  110. }
  111.  
  112. const DWORD* state = reinterpret_cast<const DWORD*>(&setting->Data);
  113. LogLine() << "POWERBROADCAST_SETTING state: " << *state;
  114. if (*state != 0) {
  115. LogLine() << "Irrelevant POWERBROADCAST_SETTING state";
  116. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  117. }
  118.  
  119. LogLine() << "Locking";
  120. if (LockWorkStation() == 0)
  121. systemError(L"locking workstation");
  122. else
  123. LogLine() << "Locked";
  124.  
  125. return 0;
  126. }
  127.  
  128. static void registerWindowClass(HINSTANCE instance)
  129. {
  130. LogLine() << "Registering window class";
  131. WNDCLASSEX windowClass = { 0 };
  132.  
  133. windowClass.cbSize = sizeof(WNDCLASSEX);
  134. windowClass.lpfnWndProc = &windowProcedure;
  135. windowClass.hInstance = instance;
  136. windowClass.lpszClassName = L"laplock";
  137.  
  138. if (RegisterClassEx(&windowClass) == 0)
  139. systemError(L"registering window class");
  140. }
  141.  
  142. static HWND createWindow(HINSTANCE instance)
  143. {
  144. LogLine() << "Creating window";
  145. HWND hWnd = CreateWindow(
  146. L"laplock",
  147. NULL,
  148. 0,
  149. CW_USEDEFAULT,
  150. CW_USEDEFAULT,
  151. CW_USEDEFAULT,
  152. CW_USEDEFAULT,
  153. HWND_MESSAGE,
  154. NULL,
  155. instance,
  156. NULL
  157. );
  158.  
  159. if (hWnd == NULL)
  160. systemError(L"creating window");
  161.  
  162. return hWnd;
  163. }
  164.  
  165. static void registerNotification(HWND window)
  166. {
  167. LogLine() << "Registering GUID_MONITOR_POWER_ON (GUID: " << GUID_MONITOR_POWER_ON << ")";
  168. if (!RegisterPowerSettingNotification(window, &GUID_MONITOR_POWER_ON, DEVICE_NOTIFY_WINDOW_HANDLE))
  169. systemError(L"cannot register GUID_MONITOR_POWER_ON power setting notification");
  170. LogLine() << "Registering GUID_LIDSWITCH_STATE_CHANGE (GUID: " << GUID_LIDSWITCH_STATE_CHANGE << ")";
  171. if (!RegisterPowerSettingNotification(window, &GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE))
  172. systemError(L"cannot register GUID_LIDSWITCH_STATE_CHANGE power setting notification");
  173. LogLine() << "Registering GUID_SYSTEM_AWAYMODE (GUID: " << GUID_SYSTEM_AWAYMODE << ")";
  174. if (!RegisterPowerSettingNotification(window, &GUID_SYSTEM_AWAYMODE, DEVICE_NOTIFY_WINDOW_HANDLE))
  175. systemError(L"cannot register GUID_SYSTEM_AWAYMODE power setting notification");
  176.  
  177. }
  178.  
  179. static WPARAM messageLoop()
  180. {
  181. for (;;)
  182. {
  183. LogLine() << "Awaiting next window message";
  184. MSG message;
  185. BOOL result = GetMessage(&message, NULL, 0, 0);
  186. if (result == -1)
  187. systemError(L"getting window message");
  188. if (result == 0)
  189. return message.wParam;
  190. LogLine() << "Dispatching message";
  191. DispatchMessage(&message);
  192. }
  193. }
  194.  
  195. int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, LPSTR commandLine, int)
  196. {
  197. if (*commandLine != 0)
  198. LogLine::logfile.reset(new std::wofstream(commandLine, std::ios_base::app));
  199. LogLine() << "laplock initializing";
  200.  
  201. registerWindowClass(instance);
  202.  
  203. HWND window = createWindow(instance);
  204.  
  205. registerNotification(window);
  206.  
  207. WPARAM result = messageLoop();
  208. LogLine() << "laplock terminating";
  209. return result;
  210. }
  211.  
  212. }
  213. }
  214.  
  215. int CALLBACK WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR commandLine, int cmdShow)
  216. {
  217. return laplock::WinMain(instance, prevInstance, commandLine, cmdShow);
  218. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:24:21: fatal error: windows.h: No such file or directory
 #include <windows.h>
                     ^
compilation terminated.
stdout
Standard output is empty