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.

448 lines
13 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include "tsappcmp.h"
  6. #include <regapi.h>
  7. PTERMSRVCREATEREGENTRY gpfnTermsrvCreateRegEntry;
  8. PTERMSRVOPENREGENTRY gpfnTermsrvOpenRegEntry;
  9. PTERMSRVSETVALUEKEY gpfnTermsrvSetValueKey;
  10. PTERMSRVDELETEKEY gpfnTermsrvDeleteKey;
  11. PTERMSRVDELETEVALUE gpfnTermsrvDeleteValue;
  12. PTERMSRVRESTOREKEY gpfnTermsrvRestoreKey;
  13. PTERMSRVSETKEYSECURITY gpfnTermsrvSetKeySecurity;
  14. PTERMSRVOPENUSERCLASSES gpfnTermsrvOpenUserClasses;
  15. PTERMSRVGETPRESETVALUE gpfnTermsrvGetPreSetValue;
  16. DWORD gdwRegistryExtensionFlags=0;
  17. BOOL IsTerminalServerCompatible(VOID)
  18. {
  19. PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader( NtCurrentPeb()->ImageBaseAddress );
  20. if ((NtHeader) && (NtHeader->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)) {
  21. return TRUE;
  22. } else {
  23. return FALSE;
  24. }
  25. }
  26. BOOL IsSystemLUID(VOID)
  27. {
  28. HANDLE TokenHandle;
  29. UCHAR TokenInformation[ sizeof( TOKEN_STATISTICS ) ];
  30. ULONG ReturnLength;
  31. LUID CurrentLUID = { 0, 0 };
  32. LUID SystemLUID = SYSTEM_LUID;
  33. NTSTATUS Status;
  34. if ( CurrentLUID.LowPart == 0 && CurrentLUID.HighPart == 0 ) {
  35. Status = NtOpenProcessToken( NtCurrentProcess(),
  36. TOKEN_QUERY,
  37. &TokenHandle );
  38. if ( !NT_SUCCESS( Status ) )
  39. return(TRUE);
  40. NtQueryInformationToken( TokenHandle, TokenStatistics, &TokenInformation,
  41. sizeof(TokenInformation), &ReturnLength );
  42. NtClose( TokenHandle );
  43. RtlCopyLuid(&CurrentLUID,
  44. &(((PTOKEN_STATISTICS)TokenInformation)->AuthenticationId));
  45. }
  46. if (RtlEqualLuid(&CurrentLUID, &SystemLUID)) {
  47. return(TRUE);
  48. } else {
  49. return(FALSE );
  50. }
  51. }
  52. /**
  53. Params:
  54. [out] Boolean *RelaxedSecurityMode
  55. If TRUE, then we are running app server in relaxed security mode
  56. which means that the TsUserSID will be present in user's token, allowing
  57. user more access to various reg and file system components.
  58. Retrun:
  59. TRUE means app server is enabled, and it is in app-compat mode ( the default)
  60. FALSE means this is not an app server
  61. **/
  62. BOOL IsTSAppCompatEnabled( BOOLEAN *RelaxedSecurityMode )
  63. {
  64. NTSTATUS NtStatus;
  65. OBJECT_ATTRIBUTES ObjectAttributes;
  66. UNICODE_STRING UniString;
  67. HKEY hKey = 0;
  68. ULONG ul, ulcbuf;
  69. PKEY_VALUE_PARTIAL_INFORMATION pKeyValInfo = NULL;
  70. BOOL retval = TRUE;
  71. RtlInitUnicodeString(&UniString,REG_NTAPI_CONTROL_TSERVER);
  72. // Determine the value info buffer size
  73. ulcbuf = sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_PATH*sizeof(WCHAR) +
  74. sizeof(ULONG);
  75. pKeyValInfo = RtlAllocateHeap(RtlProcessHeap(),
  76. 0,
  77. ulcbuf);
  78. // Did everything initialize OK?
  79. if (UniString.Buffer && pKeyValInfo) {
  80. InitializeObjectAttributes(&ObjectAttributes,
  81. &UniString,
  82. OBJ_CASE_INSENSITIVE,
  83. NULL,
  84. NULL
  85. );
  86. NtStatus = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
  87. if (NT_SUCCESS(NtStatus)) {
  88. RtlInitUnicodeString(&UniString,
  89. L"TSAppCompat");
  90. NtStatus = NtQueryValueKey(hKey,
  91. &UniString,
  92. KeyValuePartialInformation,
  93. pKeyValInfo,
  94. ulcbuf,
  95. &ul);
  96. if (NT_SUCCESS(NtStatus) && (REG_DWORD == pKeyValInfo->Type)) {
  97. if ((*(PULONG)pKeyValInfo->Data) == 0) {
  98. retval = FALSE;
  99. }
  100. }
  101. RtlInitUnicodeString(&UniString,
  102. L"TSUserEnabled");
  103. NtStatus = NtQueryValueKey(hKey,
  104. &UniString,
  105. KeyValuePartialInformation,
  106. pKeyValInfo,
  107. ulcbuf,
  108. &ul);
  109. if (NT_SUCCESS(NtStatus) && (REG_DWORD == pKeyValInfo->Type) )
  110. {
  111. *RelaxedSecurityMode = (BOOLEAN ) (*(PULONG)pKeyValInfo->Data);
  112. }
  113. else // in case of any problems, assume standard security mode
  114. {
  115. *RelaxedSecurityMode = FALSE;
  116. }
  117. NtClose(hKey);
  118. }
  119. }
  120. // Free up the buffers we allocated
  121. // Need to zero out the buffers, because some apps (MS Internet Assistant)
  122. // won't install if the heap is not zero filled.
  123. if (pKeyValInfo) {
  124. memset(pKeyValInfo, 0, ulcbuf);
  125. RtlFreeHeap( RtlProcessHeap(), 0, pKeyValInfo );
  126. }
  127. return(retval);
  128. }
  129. ULONG GetCompatFlags()
  130. {
  131. ULONG ulAppFlags = 0;
  132. PRTL_USER_PROCESS_PARAMETERS pUserParam;
  133. PWCHAR pwch, pwchext;
  134. WCHAR pwcAppName[MAX_PATH+1];
  135. NTSTATUS NtStatus;
  136. OBJECT_ATTRIBUTES ObjectAttributes;
  137. UNICODE_STRING UniString;
  138. HKEY hKey = 0;
  139. ULONG ul, ulcbuf;
  140. PKEY_VALUE_PARTIAL_INFORMATION pKeyValInfo = NULL;
  141. LPWSTR UniBuff = NULL;
  142. ULONG dwCompatFlags = 0;
  143. UniString.Buffer = NULL;
  144. // Get the path of the executable name
  145. pUserParam = NtCurrentPeb()->ProcessParameters;
  146. // Get the executable name, if there's no \ just use the name as it is
  147. pwch = wcsrchr(pUserParam->ImagePathName.Buffer, L'\\');
  148. if (pwch) {
  149. pwch++;
  150. } else {
  151. pwch = pUserParam->ImagePathName.Buffer;
  152. }
  153. wcscpy(pwcAppName, pwch);
  154. pwch = pwcAppName;
  155. // Remove the extension
  156. if (pwchext = wcsrchr(pwch, L'.')) {
  157. *pwchext = '\0';
  158. }
  159. UniString.Buffer = NULL;
  160. ul = sizeof(TERMSRV_COMPAT_APP) + (wcslen(pwch) + 1)*sizeof(WCHAR);
  161. UniBuff = RtlAllocateHeap(RtlProcessHeap(),
  162. 0,
  163. ul);
  164. if (UniBuff) {
  165. wcscpy(UniBuff, TERMSRV_COMPAT_APP);
  166. wcscat(UniBuff, pwch);
  167. RtlInitUnicodeString(&UniString, UniBuff);
  168. }
  169. // Determine the value info buffer size
  170. ulcbuf = sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_PATH*sizeof(WCHAR) +
  171. sizeof(ULONG);
  172. pKeyValInfo = RtlAllocateHeap(RtlProcessHeap(),
  173. 0,
  174. ulcbuf);
  175. // Did everything initialize OK?
  176. if (UniString.Buffer && pKeyValInfo) {
  177. InitializeObjectAttributes(&ObjectAttributes,
  178. &UniString,
  179. OBJ_CASE_INSENSITIVE,
  180. NULL,
  181. NULL
  182. );
  183. NtStatus = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
  184. if (NT_SUCCESS(NtStatus)) {
  185. RtlInitUnicodeString(&UniString,
  186. COMPAT_FLAGS);
  187. NtStatus = NtQueryValueKey(hKey,
  188. &UniString,
  189. KeyValuePartialInformation,
  190. pKeyValInfo,
  191. ulcbuf,
  192. &ul);
  193. if (NT_SUCCESS(NtStatus) && (REG_DWORD == pKeyValInfo->Type)) {
  194. dwCompatFlags = *(PULONG)pKeyValInfo->Data;
  195. }
  196. NtClose(hKey);
  197. }
  198. }
  199. // Free up the buffers we allocated
  200. // Need to zero out the buffers, because some apps (MS Internet Assistant)
  201. // won't install if the heap is not zero filled.
  202. if (UniBuff) {
  203. memset(UniBuff, 0, UniString.MaximumLength);
  204. RtlFreeHeap( RtlProcessHeap(), 0, UniBuff );
  205. }
  206. if (pKeyValInfo) {
  207. memset(pKeyValInfo, 0, ulcbuf);
  208. RtlFreeHeap( RtlProcessHeap(), 0, pKeyValInfo );
  209. }
  210. return(dwCompatFlags);
  211. }
  212. /**
  213. Return code :
  214. TRUE means app compat is enabled for this app
  215. FALSE means app compat is not enabled for this app
  216. **/
  217. BOOLEAN AdvApi_InitializeTermsrvFpns( BOOLEAN *pIsInRelaxedSecurityMode , DWORD *pdwCompatFlags )
  218. {
  219. HANDLE dllHandle;
  220. ULONG dwCompatFlags;
  221. BOOLEAN rc=FALSE;
  222. if (IsTerminalServerCompatible() || (!IsTSAppCompatEnabled( pIsInRelaxedSecurityMode ))) {
  223. return rc;
  224. }
  225. *pdwCompatFlags = dwCompatFlags = GetCompatFlags();
  226. //Don't load app compatibility dll for system components
  227. if (IsSystemLUID()) {
  228. if ( (dwCompatFlags & (TERMSRV_COMPAT_SYSREGMAP | TERMSRV_COMPAT_WIN32))
  229. != (TERMSRV_COMPAT_SYSREGMAP | TERMSRV_COMPAT_WIN32) ) {
  230. //
  231. // Process is running as SYSTEM and we don't have an app
  232. // compatibility flag telling us to do the regmap stuff.
  233. //
  234. return rc;
  235. }
  236. } else if ( (dwCompatFlags & (TERMSRV_COMPAT_NOREGMAP | TERMSRV_COMPAT_WIN32))
  237. == (TERMSRV_COMPAT_NOREGMAP | TERMSRV_COMPAT_WIN32) ) {
  238. //
  239. // We don't want to do registry mapping for this user process
  240. //
  241. return rc;
  242. }
  243. //
  244. // Load Terminal Server application compatibility dll
  245. //
  246. dllHandle = LoadLibrary("tsappcmp.dll");
  247. if (dllHandle) {
  248. gpfnTermsrvCreateRegEntry =
  249. (PTERMSRVCREATEREGENTRY)GetProcAddress(dllHandle,"TermsrvCreateRegEntry");
  250. gpfnTermsrvOpenRegEntry =
  251. (PTERMSRVOPENREGENTRY)GetProcAddress(dllHandle,"TermsrvOpenRegEntry");
  252. gpfnTermsrvSetValueKey =
  253. (PTERMSRVSETVALUEKEY)GetProcAddress(dllHandle,"TermsrvSetValueKey");
  254. gpfnTermsrvDeleteKey =
  255. (PTERMSRVDELETEKEY)GetProcAddress(dllHandle,"TermsrvDeleteKey");
  256. gpfnTermsrvDeleteValue =
  257. (PTERMSRVDELETEVALUE)GetProcAddress(dllHandle,"TermsrvDeleteValue");
  258. gpfnTermsrvRestoreKey =
  259. (PTERMSRVRESTOREKEY)GetProcAddress(dllHandle,"TermsrvRestoreKey");
  260. gpfnTermsrvSetKeySecurity =
  261. (PTERMSRVSETKEYSECURITY)GetProcAddress(dllHandle,"TermsrvSetKeySecurity");
  262. gpfnTermsrvOpenUserClasses =
  263. (PTERMSRVOPENUSERCLASSES)GetProcAddress(dllHandle,"TermsrvOpenUserClasses");
  264. gpfnTermsrvGetPreSetValue =
  265. (PTERMSRVGETPRESETVALUE)GetProcAddress(dllHandle,"TermsrvGetPreSetValue");
  266. rc = TRUE;
  267. }
  268. return rc;
  269. }
  270. void
  271. GetRegistryExtensionFlags( DWORD dwCompatFlags )
  272. /*++
  273. GetRegistryExtensionFlags
  274. Routine Description:
  275. Reads DWORD value of
  276. Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\RegistryExtensionFlags
  277. Arguments:
  278. none
  279. Return Value:
  280. none
  281. --*/
  282. {
  283. DWORD dwResult=0;
  284. NTSTATUS Status;
  285. HANDLE hKey;
  286. UNICODE_STRING KeyName;
  287. PCWSTR wszKeyName=TERMSRV_BASE;
  288. OBJECT_ATTRIBUTES ObjAttr;
  289. RtlInitUnicodeString(&KeyName,wszKeyName );
  290. InitializeObjectAttributes(&ObjAttr,&KeyName,OBJ_CASE_INSENSITIVE,NULL,NULL);
  291. Status = NtOpenKey(&hKey,KEY_QUERY_VALUE,&ObjAttr);
  292. if(NT_SUCCESS(Status)){
  293. UNICODE_STRING ValueName;
  294. PKEY_VALUE_PARTIAL_INFORMATION pKeyValInfo = NULL;
  295. ULONG ulSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(DWORD);
  296. pKeyValInfo = RtlAllocateHeap(RtlProcessHeap(), 0, ulSize);
  297. if(pKeyValInfo){
  298. PCWSTR wszValueName=L"RegistryExtensionFlags";
  299. RtlInitUnicodeString(&ValueName,wszValueName );
  300. Status=NtQueryValueKey(hKey,&ValueName,KeyValuePartialInformation,
  301. (PVOID)pKeyValInfo,ulSize,&ulSize);
  302. if(NT_SUCCESS(Status)){
  303. gdwRegistryExtensionFlags=*((LPDWORD)(pKeyValInfo->Data));
  304. }
  305. RtlFreeHeap( RtlProcessHeap(), 0, pKeyValInfo );
  306. // the global advapi extension flags might be turned off for this app, so check.
  307. if ( dwCompatFlags & TERMSRV_COMPAT_NO_PER_USER_CLASSES_REDIRECTION )
  308. {
  309. gdwRegistryExtensionFlags &= ~ TERMSRV_ENABLE_PER_USER_CLASSES_REDIRECTION;
  310. }
  311. if ( dwCompatFlags & TERMSRV_COMPAT_NO_ENABLE_ACCESS_FLAG_MODIFICATION )
  312. {
  313. gdwRegistryExtensionFlags &= ~TERMSRV_ENABLE_ACCESS_FLAG_MODIFICATION;
  314. }
  315. }
  316. NtClose(hKey);
  317. }
  318. }