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.

442 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. sclgntfy.cxx
  5. Abstract:
  6. Notification dll for secondary logon service
  7. Author:
  8. Praerit Garg (Praeritg)
  9. Revision History:
  10. --*/
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #endif
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #ifdef __cplusplus
  18. }
  19. #endif
  20. #include <windows.h>
  21. #include <winwlx.h>
  22. #include <strsafe.h>
  23. #include "seclogon.h"
  24. #include <stdio.h>
  25. #include "sclgntfy.hxx"
  26. //
  27. // Some helpful tips about winlogon's notify events
  28. //
  29. // 1) The logoff and shutdown notifications are always done
  30. // synchronously regardless of the Asynchronous registry entry.
  31. //
  32. // 2) If you need to spawn child processes, you have to use
  33. // CreateProcessAsUser() otherwise the process will start
  34. // on winlogon's desktop (not the user's)
  35. //
  36. // 3) The logon notification comes before the user's network
  37. // connections are restored. If you need the user's persisted
  38. // net connections, use the StartShell event.
  39. //
  40. // 4) Don't put any UI up during either screen saver event.
  41. // These events are intended for background processing only.
  42. //
  43. HINSTANCE g_hDllInstance=NULL;
  44. #define NOTIFY_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify\\sclgntfy")
  45. BOOL
  46. SlpCreateProcessWithLogon(
  47. ULONG LogonIdLowPart,
  48. LONG LogonIdHighPart
  49. );
  50. extern "C" void *__cdecl _alloca(size_t);
  51. DWORD SetupLocalRPCSecurity(handle_t hRPCBinding)
  52. {
  53. CHAR szDomainName[128];
  54. CHAR szName[128];
  55. DWORD cbDomainName;
  56. DWORD cbName;
  57. DWORD dwResult;
  58. PSID pSid = NULL;
  59. RPC_SECURITY_QOS SecurityQOS;
  60. SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
  61. SID_NAME_USE SidNameUse;
  62. // We're doing LRPC -- we need to get the account name of the service to do mutual auth
  63. if (!AllocateAndInitializeSid(&SidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSid)) {
  64. dwResult = GetLastError();
  65. goto error;
  66. }
  67. cbName = sizeof(szName);
  68. cbDomainName = sizeof(szDomainName);
  69. if (!LookupAccountSidA(NULL, pSid, szName, &cbName, szDomainName, &cbDomainName, &SidNameUse)) {
  70. dwResult = GetLastError();
  71. goto error;
  72. }
  73. // Specify quality of service parameters.
  74. SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; // the server will need to impersonate us
  75. SecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION;
  76. SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH; // we need mutual auth
  77. SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; // calls go to the server under the identity that created the binding handle
  78. dwResult = RpcBindingSetAuthInfoExA(hRPCBinding, (unsigned char *)szName, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_WINNT, NULL, 0, &SecurityQOS);
  79. if (RPC_S_OK != dwResult)
  80. goto error;
  81. dwResult = ERROR_SUCCESS;
  82. error:
  83. if (NULL != pSid) {
  84. FreeSid(pSid);
  85. }
  86. return dwResult;
  87. }
  88. BOOL
  89. SlpCreateProcessWithLogon(
  90. ULONG LogonIdLowPart,
  91. LONG LogonIdHighPart
  92. )
  93. /*++
  94. Routine Description:
  95. Arguments:
  96. Return Value:
  97. --*/
  98. {
  99. BOOL fOk = FALSE;
  100. DWORD dwResult;
  101. LPWSTR pwszBinding = NULL;
  102. RPC_BINDING_HANDLE hRPCBinding = NULL;
  103. SECL_BLOB sbNULL = { 0, NULL };
  104. SECL_SLI sli;
  105. SECL_SLRI slri;
  106. SECL_STRING ssNULL = { 0, 0, NULL };
  107. ZeroMemory(&sli, sizeof(sli));
  108. ZeroMemory(&slri, sizeof(slri));
  109. __try {
  110. sli.ulLogonIdLowPart = LogonIdLowPart;
  111. sli.lLogonIdHighPart = LogonIdHighPart;
  112. sli.ulProcessId = GetCurrentProcessId();
  113. sli.ssUsername = ssNULL;
  114. sli.ssDomain = ssNULL;
  115. sli.ssPassword = ssNULL;
  116. sli.ssApplicationName = ssNULL;
  117. sli.ssCommandLine = ssNULL;
  118. sli.ulCreationFlags = 0;
  119. sli.sbEnvironment = sbNULL;
  120. sli.ssCurrentDirectory = ssNULL;
  121. sli.ssTitle = ssNULL;
  122. sli.ssDesktop = ssNULL;
  123. // Make the RPC call:
  124. //
  125. dwResult = RpcStringBindingCompose
  126. (NULL,
  127. (unsigned short *)L"ncalrpc",
  128. NULL,
  129. (unsigned short *)wszSeclogonSharedProcEndpointName,
  130. NULL,
  131. (unsigned short **)&pwszBinding);
  132. if (RPC_S_OK != dwResult) { __leave; }
  133. dwResult = RpcBindingFromStringBinding((unsigned short *)pwszBinding, &hRPCBinding);
  134. if (0 != dwResult) { __leave; }
  135. dwResult = SetupLocalRPCSecurity(hRPCBinding);
  136. if (ERROR_SUCCESS != dwResult) { __leave; }
  137. __try {
  138. SeclCreateProcessWithLogonW
  139. (hRPCBinding,
  140. &sli,
  141. &slri);
  142. }
  143. __except(EXCEPTION_EXECUTE_HANDLER) {
  144. dwResult = RpcExceptionCode();
  145. }
  146. if (0 != dwResult) { __leave; }
  147. fOk = (slri.ulErrorCode == NO_ERROR); // This function succeeds if the server's function succeeds
  148. if (!fOk) {
  149. //
  150. // If the server function failed, set the server's
  151. // returned eror code as this thread's error code
  152. //
  153. SetLastError(slri.ulErrorCode);
  154. }
  155. }
  156. __finally {
  157. if (NULL != pwszBinding) { RpcStringFree((unsigned short **)&pwszBinding); }
  158. if (NULL != hRPCBinding) { RpcBindingFree(&hRPCBinding); }
  159. }
  160. return(fOk);
  161. }
  162. //////////////////////////////// End Of File /////////////////////////////////
  163. BOOL WINAPI DllMain(HANDLE hInstance, ULONG dwReason, LPVOID lpReserved)
  164. //BOOL WINAPI LibMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  165. {
  166. switch (dwReason)
  167. {
  168. case DLL_PROCESS_ATTACH:
  169. {
  170. // DisableThreadLibraryCalls (hInstance);
  171. g_hDllInstance = (HINSTANCE)hInstance;
  172. }
  173. break;
  174. }
  175. return TRUE;
  176. UNREFERENCED_PARAMETER(lpReserved);
  177. }
  178. //
  179. // WLEventLogon moved to recovery.cpp
  180. //
  181. VOID WLEventLogoff (PWLX_NOTIFICATION_INFO pInfo)
  182. {
  183. TOKEN_STATISTICS TokenStats;
  184. DWORD ReturnLength;
  185. LUID LogonId;
  186. // OutputDebugString (TEXT("NOTIFY: Entering WLEventLogff.\r\n"));
  187. //
  188. // We are interested in this event.
  189. //
  190. //
  191. // We will basically call CreateProcessWithLogon
  192. // in a specially formed message such that secondary logon
  193. // service can cleanup processes associated with this
  194. // logon id.
  195. //
  196. if(GetTokenInformation(pInfo->hToken, TokenStatistics,
  197. (PVOID *)&TokenStats,
  198. sizeof(TOKEN_STATISTICS),
  199. &ReturnLength))
  200. {
  201. LogonId.HighPart = TokenStats.AuthenticationId.HighPart;
  202. LogonId.LowPart = TokenStats.AuthenticationId.LowPart;
  203. SlpCreateProcessWithLogon(
  204. LogonId.LowPart,
  205. LogonId.HighPart
  206. );
  207. }
  208. }
  209. VOID WLEventStartup (PWLX_NOTIFICATION_INFO pInfo)
  210. {
  211. // OutputDebugString (TEXT("NOTIFY: Entering WLEventStartup.\r\n"));
  212. UNREFERENCED_PARAMETER(pInfo);
  213. }
  214. VOID WLEventShutdown (PWLX_NOTIFICATION_INFO pInfo)
  215. {
  216. // OutputDebugString (TEXT("NOTIFY: Entering WLEventShutdown.\r\n"));
  217. UNREFERENCED_PARAMETER(pInfo);
  218. }
  219. VOID WLEventStartScreenSaver (PWLX_NOTIFICATION_INFO pInfo)
  220. {
  221. // OutputDebugString (TEXT("NOTIFY: Entering WLEventStartScreenSaver.\r\n"));
  222. UNREFERENCED_PARAMETER(pInfo);
  223. }
  224. VOID WLEventStopScreenSaver (PWLX_NOTIFICATION_INFO pInfo)
  225. {
  226. // OutputDebugString (TEXT("NOTIFY: Entering WLEventStopScreenSaver.\r\n"));
  227. UNREFERENCED_PARAMETER(pInfo);
  228. }
  229. VOID WLEventLock (PWLX_NOTIFICATION_INFO pInfo)
  230. {
  231. // OutputDebugString (TEXT("NOTIFY: Entering WLEventLock.\r\n"));
  232. UNREFERENCED_PARAMETER(pInfo);
  233. }
  234. VOID WLEventUnlock (PWLX_NOTIFICATION_INFO pInfo)
  235. {
  236. // OutputDebugString (TEXT("NOTIFY: Entering WLEventUnlock.\r\n"));
  237. UNREFERENCED_PARAMETER(pInfo);
  238. }
  239. VOID WLEventStartShell (PWLX_NOTIFICATION_INFO pInfo)
  240. {
  241. // OutputDebugString (TEXT("NOTIFY: Entering WLEventStartShell.\r\n"));
  242. UNREFERENCED_PARAMETER(pInfo);
  243. }
  244. /////////////////////////////////////////////////////////////////////////////
  245. // DllRegisterServer - Adds entries to the system registry
  246. STDAPI DllRegisterServer(void)
  247. {
  248. HKEY hKey;
  249. LONG lResult;
  250. DWORD dwDisp, dwTemp;
  251. lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, NOTIFY_PATH, 0, NULL,
  252. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
  253. &hKey, &dwDisp);
  254. if (lResult != ERROR_SUCCESS)
  255. {
  256. return lResult;
  257. }
  258. //
  259. // save the return code for EFS registration
  260. //
  261. LONG lEfsResult = DllRegisterServerEFS();
  262. lResult = RegSetValueEx (hKey, TEXT("Logoff"), 0, REG_SZ, (LPBYTE)TEXT("WLEventLogoff"),
  263. (lstrlen(TEXT("WLEventLogoff")) + 1) * sizeof(TCHAR));
  264. if (lResult == ERROR_SUCCESS) {
  265. #if 0
  266. RegSetValueEx (hKey, TEXT("Logon"), 0, REG_SZ, (LPBYTE)TEXT("WLEventLogon"),
  267. (lstrlen(TEXT("WLEventLogon")) + 1) * sizeof(TCHAR));
  268. RegSetValueEx (hKey, TEXT("Startup"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStartup"),
  269. (lstrlen(TEXT("WLEventStartup")) + 1) * sizeof(TCHAR));
  270. RegSetValueEx (hKey, TEXT("Shutdown"), 0, REG_SZ, (LPBYTE)TEXT("WLEventShutdown"),
  271. (lstrlen(TEXT("WLEventShutdown")) + 1) * sizeof(TCHAR));
  272. RegSetValueEx (hKey, TEXT("StartScreenSaver"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStartScreenSaver"),
  273. (lstrlen(TEXT("WLEventStartScreenSaver")) + 1) * sizeof(TCHAR));
  274. RegSetValueEx (hKey, TEXT("StopScreenSaver"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStopScreenSaver"),
  275. (lstrlen(TEXT("WLEventStopScreenSaver")) + 1) * sizeof(TCHAR));
  276. RegSetValueEx (hKey, TEXT("Lock"), 0, REG_SZ, (LPBYTE)TEXT("WLEventLock"),
  277. (lstrlen(TEXT("WLEventLock")) + 1) * sizeof(TCHAR));
  278. RegSetValueEx (hKey, TEXT("Unlock"), 0, REG_SZ, (LPBYTE)TEXT("WLEventUnlock"),
  279. (lstrlen(TEXT("WLEventUnlock")) + 1) * sizeof(TCHAR));
  280. RegSetValueEx (hKey, TEXT("StartShell"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStartShell"),
  281. (lstrlen(TEXT("WLEventStartShell")) + 1) * sizeof(TCHAR));
  282. #endif
  283. dwTemp = 0;
  284. lResult = RegSetValueEx (hKey, TEXT("Impersonate"), 0, REG_DWORD, (LPBYTE)&dwTemp, sizeof(dwTemp));
  285. if (lResult == ERROR_SUCCESS) {
  286. dwTemp = 1;
  287. lResult = RegSetValueEx (hKey, TEXT("Asynchronous"), 0, REG_DWORD, (LPBYTE)&dwTemp, sizeof(dwTemp));
  288. if (lResult == ERROR_SUCCESS) {
  289. lResult = RegSetValueEx (hKey, TEXT("DllName"), 0, REG_EXPAND_SZ, (LPBYTE)TEXT("sclgntfy.dll"),
  290. (lstrlen(TEXT("sclgntfy.dll")) + 1) * sizeof(TCHAR));
  291. }
  292. }
  293. }
  294. RegCloseKey (hKey);
  295. //
  296. // return failure if either seclogon or EFS registration fails.
  297. //
  298. if ( lResult == ERROR_SUCCESS ) {
  299. lResult = lEfsResult;
  300. }
  301. return lResult;
  302. }
  303. /////////////////////////////////////////////////////////////////////////////
  304. // DllUnregisterServer - Removes entries from the system registry
  305. STDAPI DllUnregisterServer(void)
  306. {
  307. RegDeleteKey (HKEY_LOCAL_MACHINE, NOTIFY_PATH);
  308. return S_OK;
  309. }
  310. BOOL
  311. pLoadResourceString(
  312. IN UINT idMsg,
  313. OUT LPTSTR lpBuffer,
  314. IN int nBufferMax,
  315. IN LPTSTR lpDefault
  316. )
  317. {
  318. HRESULT hr;
  319. if ( lpBuffer == NULL || lpDefault == NULL ) {
  320. SetLastError(ERROR_INVALID_PARAMETER);
  321. return FALSE;
  322. }
  323. if ( g_hDllInstance == NULL ||
  324. !LoadString (g_hDllInstance,
  325. idMsg,
  326. lpBuffer,
  327. nBufferMax)) {
  328. hr = StringCchCopy(lpBuffer, nBufferMax, lpDefault);
  329. if (FAILED(hr)) {
  330. SetLastError(hr);
  331. return FALSE;
  332. }
  333. lpBuffer[nBufferMax-1] = L'\0';
  334. }
  335. return TRUE;
  336. }