Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

364 lines
9.8 KiB

  1. /****************************************************************************
  2. Hidden 32-bit window for
  3. Switch Input Library DLL
  4. Copyright (c) 1992-1997 Bloorview MacMillan Centre
  5. This application performs several helper tasks:
  6. 1) It owns any global resources (hooks, hardware devices) that are
  7. opened on behalf of applications using switch input
  8. 2) It catches timer messages to keep polling the hardware devices
  9. 3) In Windows 95 it receives the 16-bit bios table address information
  10. from the 16-bit hidden application and forwards it into the
  11. 32-bit world of the Switch Input Library
  12. If the window is not hidden on startup, it is in debug mode.
  13. ****************************************************************************/
  14. /**************************************************************** Headers */
  15. #include <windows.h>
  16. #include <tchar.h>
  17. #include "w95trace.c"
  18. #include "msswch.h"
  19. #include "resource.h"
  20. // Types and pointer decls to DLL entry points
  21. typedef BOOL (APIENTRY *LPFNXSWCHREGHELPERWND)( HWND hWnd, PBYTE bda );
  22. typedef void (APIENTRY *LPFNXSWCHPOLLSWITCHES)( HWND hWnd );
  23. typedef void (APIENTRY *LPFNXSWCHTIMERPROC)( HWND hWnd );
  24. typedef LRESULT (APIENTRY *LPFNXSWCHSETSWITCHCONFIG)( WPARAM wParam, PCOPYDATASTRUCT pcd );
  25. typedef BOOL (APIENTRY *LPFNXSWCHENDALL)( void );
  26. LPFNXSWCHREGHELPERWND lpfnXswchRegHelperWnd;
  27. LPFNXSWCHPOLLSWITCHES lpfnXswchPollSwitches;
  28. LPFNXSWCHTIMERPROC lpfnXswchTimerProc;
  29. LPFNXSWCHSETSWITCHCONFIG lpfnXswchSetSwitchConfig;
  30. LPFNXSWCHENDALL lpfnXswchEndAll;
  31. // Helper macro to get pointers to DLL entry points
  32. #define GET_FUNC_PTR(name, ordinal, hlib, type, fUseDLL) \
  33. { \
  34. lpfn ## name = (type)GetProcAddress(hlib, LongToPtr(MAKELONG(ordinal, 0))); \
  35. if (!lpfn ## name) { \
  36. fUseDLL = FALSE; \
  37. ErrMessage(TEXT( #name ), IDS_PROC_NOT_FOUND, 0 ); \
  38. } \
  39. }
  40. static TCHAR x_szSwitchDll[] = TEXT("msswch.dll");
  41. #define MAX_MSGLEN 256
  42. #define SW_APPNAME TEXT("msswchx")
  43. #define SWITCH_TIMER_POLL_INTERVAL 0
  44. #define MAJIC_CMDOPT "SWCH"
  45. // g_bios_data_area[] is a hold-over from Win9x code, unused in NT or W2K
  46. #define BIOS_SIZE 16
  47. BYTE g_bios_data_area[BIOS_SIZE];
  48. INT_PTR APIENTRY SwchWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  49. INT_PTR APIENTRY WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  50. void SwitchOnCreate(HWND hWnd);
  51. BOOL SwitchOnCopyData(WPARAM wParam, LPARAM lParam);
  52. BOOL SwitchOnCopyData(WPARAM wParam, LPARAM lParam);
  53. void SwitchOnTimer(HWND hWnd);
  54. void SwitchOnPoll(HWND hWnd);
  55. void SwitchOnEndSession(HWND hWnd);
  56. void ErrMessage(LPCTSTR szTitle, UINT uMsg, UINT uFlags);
  57. static BOOL AssignDesktop();
  58. static BOOL InitMyProcessDesktopAccess(VOID);
  59. static VOID ExitMyProcessDesktopAccess(VOID);
  60. HINSTANCE g_hInst = NULL;
  61. HANDLE g_hLibrary = 0;
  62. BOOL g_WinlogonDesktop = FALSE;
  63. // IsSystem - Returns TRUE if our process is running as SYSTEM
  64. //
  65. BOOL IsSystem()
  66. {
  67. BOOL fStatus = FALSE;
  68. BOOL fIsLocalSystem = FALSE;
  69. SID_IDENTIFIER_AUTHORITY siaLocalSystem = SECURITY_NT_AUTHORITY;
  70. PSID psidSystem;
  71. if (!AllocateAndInitializeSid(&siaLocalSystem,
  72. 1,
  73. SECURITY_LOCAL_SYSTEM_RID,
  74. 0, 0, 0, 0, 0, 0, 0,
  75. &psidSystem))
  76. {
  77. return FALSE;
  78. }
  79. if (psidSystem)
  80. {
  81. fStatus = CheckTokenMembership(NULL, psidSystem, &fIsLocalSystem);
  82. }
  83. return (fStatus && fIsLocalSystem);
  84. }
  85. /********************************************************\
  86. Windows initialization
  87. \********************************************************/
  88. int PASCAL WinMain(
  89. HINSTANCE hInstance,
  90. HINSTANCE hPrevInstance,
  91. LPSTR lpszCmdLine,
  92. int nCmdShow )
  93. {
  94. HWND hWnd;
  95. MSG msg;
  96. WNDCLASS wndclass;
  97. // Look for magic word
  98. if (strcmp(lpszCmdLine, MAJIC_CMDOPT))
  99. {
  100. TCHAR szErrBuf[MAX_MSGLEN];
  101. if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpszCmdLine, -1, szErrBuf, MAX_MSGLEN))
  102. ErrMessage( szErrBuf, IDS_NOT_USER_PROG, MB_OK | MB_ICONHAND );
  103. return FALSE;
  104. }
  105. //************************************************************************
  106. //
  107. // The following two calls initialize the desktop so that, if we are on
  108. // the Winlogon desktop (secure desktop) our keyboard hook will be
  109. // associated with the correct window station.
  110. //
  111. // Do not cause any windows to be created (eg. CoInitialize) prior to calling
  112. // these functions. Doing so will cause them to fail and the application
  113. // will not appear on the Winlogon desktop.
  114. //
  115. InitMyProcessDesktopAccess();
  116. AssignDesktop();
  117. // the only place it is ok to run as system is on the DESKTOP_WINLOGON desktop. If that is
  118. // not where we are than get out before we cause any security problems
  119. if (!g_WinlogonDesktop && IsSystem())
  120. {
  121. ExitMyProcessDesktopAccess();
  122. return FALSE;
  123. }
  124. //************************************************************************
  125. if(!hPrevInstance)
  126. {
  127. wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  128. wndclass.lpfnWndProc = WndProc;
  129. wndclass.cbClsExtra = 0;
  130. wndclass.cbWndExtra = 0;
  131. wndclass.hInstance = hInstance;
  132. wndclass.hIcon = NULL;
  133. wndclass.hCursor = NULL;
  134. wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
  135. wndclass.lpszMenuName = NULL;
  136. wndclass.lpszClassName = SW_APPNAME;
  137. if(!RegisterClass(&wndclass))
  138. {
  139. ExitMyProcessDesktopAccess();
  140. return FALSE;
  141. }
  142. }
  143. g_hInst=hInstance;
  144. hWnd = CreateWindow(SW_APPNAME, SW_APPNAME,
  145. WS_OVERLAPPEDWINDOW,
  146. 0,0,10,10,
  147. NULL, NULL, hInstance, NULL);
  148. ShowWindow(hWnd, nCmdShow);
  149. UpdateWindow(hWnd);
  150. while(GetMessage(&msg, NULL, 0, 0))
  151. {
  152. TranslateMessage(&msg);
  153. DispatchMessage(&msg);
  154. }
  155. ExitMyProcessDesktopAccess();
  156. return (int)msg.wParam;
  157. }
  158. /********************************************************\
  159. Main window procedure
  160. \********************************************************/
  161. INT_PTR APIENTRY WndProc(
  162. HWND hWnd,
  163. UINT uMsg,
  164. WPARAM wParam,
  165. LPARAM lParam)
  166. {
  167. switch(uMsg)
  168. {
  169. case WM_TIMER:
  170. SwitchOnTimer( hWnd );
  171. break;
  172. case WM_COPYDATA:
  173. return SwitchOnCopyData( wParam, lParam );
  174. break;
  175. case WM_CREATE:
  176. SwitchOnCreate( hWnd );
  177. break;
  178. case WM_CLOSE:
  179. DestroyWindow( hWnd );
  180. break;
  181. case WM_QUERYENDSESSION:
  182. return 1L;
  183. break;
  184. case WM_DESTROY:
  185. PostQuitMessage(0);
  186. // intentional fall-thru to hit clean-up code
  187. case WM_ENDSESSION:
  188. SwitchOnEndSession( hWnd );
  189. break;
  190. default:
  191. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  192. break;
  193. }
  194. return 0L;
  195. }
  196. void SwitchOnCreate(HWND hWnd)
  197. {
  198. SetErrorMode(SEM_FAILCRITICALERRORS); /* Bypass Windows error message */
  199. g_hLibrary = LoadLibrary( x_szSwitchDll );
  200. SetErrorMode(0);
  201. if (g_hLibrary)
  202. {
  203. BOOL fUseDLL = TRUE;
  204. GET_FUNC_PTR(XswchRegHelperWnd, 4, g_hLibrary, LPFNXSWCHREGHELPERWND, fUseDLL)
  205. GET_FUNC_PTR(XswchPollSwitches, 3, g_hLibrary, LPFNXSWCHPOLLSWITCHES, fUseDLL)
  206. GET_FUNC_PTR(XswchTimerProc, 6, g_hLibrary, LPFNXSWCHTIMERPROC, fUseDLL)
  207. GET_FUNC_PTR(XswchSetSwitchConfig, 5, g_hLibrary, LPFNXSWCHSETSWITCHCONFIG, fUseDLL)
  208. GET_FUNC_PTR(XswchEndAll, 2, g_hLibrary, LPFNXSWCHENDALL, fUseDLL)
  209. if (fUseDLL)
  210. {
  211. // register OSK's hWnd as switch resource owner
  212. (*lpfnXswchRegHelperWnd)( hWnd, g_bios_data_area );
  213. // send WM_TIMER messages to poll for switch activity
  214. SetTimer( hWnd, SWITCH_TIMER, SWITCH_TIMER_POLL_INTERVAL, NULL );
  215. }
  216. }
  217. else
  218. {
  219. FreeLibrary( g_hLibrary );
  220. g_hLibrary = 0;
  221. ErrMessage(NULL, IDS_MSSWCH_DLL_NOT_FOUND, 0 );
  222. }
  223. }
  224. void SwitchOnEndSession(HWND hWnd)
  225. {
  226. if (g_hLibrary)
  227. {
  228. KillTimer( hWnd, SWITCH_TIMER );
  229. (*lpfnXswchEndAll)( );
  230. FreeLibrary( g_hLibrary );
  231. g_hLibrary = 0;
  232. }
  233. }
  234. void SwitchOnTimer(HWND hWnd)
  235. {
  236. if (g_hLibrary)
  237. {
  238. (*lpfnXswchTimerProc)( hWnd );
  239. }
  240. }
  241. void SwitchOnPoll(HWND hWnd)
  242. {
  243. if (g_hLibrary)
  244. {
  245. (*lpfnXswchPollSwitches)( hWnd );
  246. }
  247. }
  248. BOOL SwitchOnCopyData(WPARAM wParam, LPARAM lParam)
  249. {
  250. if (g_hLibrary)
  251. {
  252. LRESULT rv = (*lpfnXswchSetSwitchConfig)( wParam, (PCOPYDATASTRUCT)lParam );
  253. return (rv == SWCHERR_NO_ERROR)?TRUE:FALSE;
  254. }
  255. return FALSE;
  256. }
  257. void ErrMessage(LPCTSTR szTitle, UINT uMsg, UINT uFlags)
  258. {
  259. TCHAR szMessage[MAX_MSGLEN];
  260. TCHAR szTitle2[MAX_MSGLEN];
  261. LPCTSTR psz = szTitle;
  262. if (!psz)
  263. psz = x_szSwitchDll;
  264. LoadString(g_hInst, uMsg, szMessage, MAX_MSGLEN);
  265. MessageBox(GetFocus(), szMessage, psz, uFlags);
  266. }
  267. static HWINSTA g_origWinStation = NULL;
  268. static HWINSTA g_userWinStation = NULL;
  269. static BOOL AssignDesktop()
  270. {
  271. HDESK hdesk = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
  272. if (!hdesk)
  273. {
  274. // OpenInputDesktop will mostly fail on "Winlogon" desktop
  275. hdesk = OpenDesktop(__TEXT("Winlogon"),0,FALSE,MAXIMUM_ALLOWED);
  276. if (!hdesk)
  277. return FALSE;
  278. g_WinlogonDesktop = TRUE;
  279. }
  280. CloseDesktop(GetThreadDesktop(GetCurrentThreadId()));
  281. SetThreadDesktop(hdesk);
  282. return TRUE;
  283. }
  284. static BOOL InitMyProcessDesktopAccess(VOID)
  285. {
  286. g_origWinStation = GetProcessWindowStation();
  287. g_userWinStation = OpenWindowStation(__TEXT("WinSta0"), FALSE, MAXIMUM_ALLOWED);
  288. if (!g_userWinStation)
  289. return FALSE;
  290. SetProcessWindowStation(g_userWinStation);
  291. return TRUE;
  292. }
  293. static VOID ExitMyProcessDesktopAccess(VOID)
  294. {
  295. if (g_origWinStation)
  296. SetProcessWindowStation(g_origWinStation);
  297. if (g_userWinStation)
  298. {
  299. CloseWindowStation(g_userWinStation);
  300. g_userWinStation = NULL;
  301. }
  302. }