Source code of Windows XP (NT5)
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.

486 lines
12 KiB

  1. /*************** ************************************************************/
  2. // tsappcmp.c
  3. //
  4. // Copyright (C) 1997-1999 Microsoft Corp.
  5. /****************************************************************************/
  6. #include "precomp.h"
  7. #pragma hdrstop
  8. extern void InitRegisterSupport();
  9. PWINSTATIONQUERYINFORMATIONW pWinStationQueryInformationW;
  10. extern DWORD gpTermsrvTlsIndex;
  11. BOOL GetDefaultUserProfileName(LPWSTR lpProfileDir, LPDWORD lpcchSize);
  12. extern WCHAR gpwszDefaultUserName[];
  13. extern void FreeLDRTable();
  14. DWORD g_dwFlags=0;
  15. /*
  16. * Read flags, if flags don't exit, then assume default behavior.
  17. * The default behavior is the same as dwFlags = 0x0
  18. * The default behavior will result is the loadlib func calls to be patched by our
  19. * redirected func TLoadLibraryExW().
  20. *
  21. */
  22. void ReadImportTablePatchFLagsAndAppCompatMode( DWORD *pdwFlags, BOOLEAN *pInAppCompatMode )
  23. {
  24. NTSTATUS NtStatus;
  25. UNICODE_STRING KeyName;
  26. OBJECT_ATTRIBUTES ObjectAttributes;
  27. HANDLE KeyHandle;
  28. UCHAR Buffer[100];
  29. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) Buffer;
  30. ULONG KeyValueLength = 100;
  31. ULONG ResultLength;
  32. *pdwFlags=0;
  33. *pInAppCompatMode=FALSE;
  34. RtlInitUnicodeString(
  35. &KeyName,
  36. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Terminal Server"
  37. );
  38. InitializeObjectAttributes(
  39. &ObjectAttributes,
  40. &KeyName,
  41. OBJ_CASE_INSENSITIVE,
  42. 0,
  43. NULL
  44. );
  45. NtStatus = NtOpenKey(
  46. &KeyHandle,
  47. KEY_READ,
  48. &ObjectAttributes
  49. );
  50. if (!NT_SUCCESS(NtStatus)) {
  51. return; // so nothing found, just return since we do have a default behavior.
  52. }
  53. RtlInitUnicodeString(
  54. &KeyName,
  55. REG_TERMSRV_APPCOMPAT
  56. );
  57. NtStatus = NtQueryValueKey(
  58. KeyHandle,
  59. &KeyName,
  60. KeyValuePartialInformation,
  61. KeyValueInformation,
  62. KeyValueLength,
  63. &ResultLength
  64. );
  65. if (NT_SUCCESS(NtStatus))
  66. {
  67. //
  68. // Check that the data is the correct size and type - a DWORD.
  69. //
  70. if ((KeyValueInformation->DataLength >= sizeof(DWORD)) &&
  71. (KeyValueInformation->Type == REG_DWORD))
  72. {
  73. *pInAppCompatMode = * (PBOOLEAN) KeyValueInformation->Data;
  74. }
  75. }
  76. RtlInitUnicodeString(
  77. &KeyName,
  78. TERMSRV_COMPAT_IAT_FLAGS
  79. );
  80. NtStatus = NtQueryValueKey(
  81. KeyHandle,
  82. &KeyName,
  83. KeyValuePartialInformation,
  84. KeyValueInformation,
  85. KeyValueLength,
  86. &ResultLength
  87. );
  88. if (NT_SUCCESS(NtStatus))
  89. {
  90. //
  91. // Check that the data is the correct size and type - a DWORD.
  92. //
  93. if ((KeyValueInformation->DataLength >= sizeof(DWORD)) &&
  94. (KeyValueInformation->Type == REG_DWORD))
  95. {
  96. *pdwFlags = * (PDWORD) KeyValueInformation->Data;
  97. }
  98. }
  99. NtClose(KeyHandle);
  100. }
  101. BOOL WINAPI LibMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  102. {
  103. static ULONG attachCount=0;
  104. static BOOLEAN inAppCompatMode=FALSE;
  105. switch (dwReason)
  106. {
  107. case DLL_PROCESS_ATTACH:
  108. {
  109. PWCHAR pwch, pwchext;
  110. WCHAR pwcAppName[MAX_PATH+1];
  111. PRTL_USER_PROCESS_PARAMETERS pUserParam;
  112. DWORD dwSize;
  113. attachCount++;
  114. ReadImportTablePatchFLagsAndAppCompatMode( &g_dwFlags , &inAppCompatMode ); // this will initialize our global flag for IAT and debug
  115. if ( g_dwFlags & DEBUG_IAT )
  116. {
  117. DbgPrint("tsappcmp: LibMain: DLL_PROCESS_ATTACH called, attach count = %d \n", attachCount );
  118. }
  119. if ( inAppCompatMode )
  120. {
  121. // Get the path of the executable name
  122. pUserParam = NtCurrentPeb()->ProcessParameters;
  123. // Get the executable name, if there's no \ just use the name as it is
  124. pwch = wcsrchr(pUserParam->ImagePathName.Buffer, L'\\');
  125. if (pwch) {
  126. pwch++;
  127. } else {
  128. pwch = pUserParam->ImagePathName.Buffer;
  129. }
  130. wcscpy(pwcAppName, pwch);
  131. pwch = pwcAppName;
  132. #if DBGX
  133. DbgPrint("\nApp-name : %ws\n", pwch );
  134. #endif
  135. // Check if it's a DOS or Win16 app by checking if the app is ntvdm.exe
  136. // Only disable ThreadLibrary calls if not ntvdm.
  137. if (_wcsicmp(pwch, L"ntvdm.exe")) {
  138. DisableThreadLibraryCalls (hInstance);
  139. } else {
  140. gpTermsrvTlsIndex = TlsAlloc();
  141. ASSERT(gpTermsrvTlsIndex != 0xFFFFFFFF);
  142. }
  143. // Init support for the register command
  144. InitRegisterSupport();
  145. dwSize = MAX_PATH;
  146. if (!GetDefaultUserProfileName(gpwszDefaultUserName, &dwSize)) {
  147. gpwszDefaultUserName[0] = L'\0';
  148. }
  149. }
  150. break;
  151. }
  152. case DLL_THREAD_ATTACH:
  153. {
  154. if (inAppCompatMode )
  155. {
  156. TlsSetValue(gpTermsrvTlsIndex,NULL);
  157. }
  158. }
  159. case DLL_PROCESS_DETACH:
  160. {
  161. attachCount--;
  162. if ( g_dwFlags & DEBUG_IAT )
  163. {
  164. DbgPrint("tsappcmp: LibMain: DLL_PROCESS_DETACH called, attach count = %d \n", attachCount );
  165. }
  166. if (inAppCompatMode )
  167. {
  168. if (attachCount==0 )
  169. {
  170. FreeLDRTable();
  171. }
  172. }
  173. }
  174. break;
  175. }
  176. return TRUE;
  177. }
  178. PWCHAR TermsrvFormatObjectName(LPCWSTR OldName)
  179. {
  180. PWCHAR pstrNewObjName = NULL;
  181. #if 0
  182. SIZE_T Size;
  183. Size = ( wcslen(OldName) * sizeof(WCHAR)) + sizeof(L"Local\\") + sizeof(WCHAR);
  184. pstrNewObjName = RtlAllocateHeap(RtlProcessHeap(),
  185. LMEM_FIXED | LMEM_ZEROINIT,
  186. Size);
  187. if (pstrNewObjName) {
  188. swprintf(pstrNewObjName,L"Local\\%ws",OldName);
  189. }
  190. #endif
  191. return pstrNewObjName;
  192. }
  193. DWORD TermsrvGetComputerName( LPWSTR lpBuffer, LPDWORD nSize )
  194. {
  195. ULONG ulCompatFlags=0, ulAppType = 0;
  196. WINSTATIONINFORMATIONW WSInfo;
  197. ULONG ValueLength;
  198. HMODULE hwinsta = NULL;
  199. GetCtxAppCompatFlags(&ulCompatFlags, &ulAppType);
  200. // Return the username instead of the computername?
  201. if ((ulCompatFlags & TERMSRV_COMPAT_USERNAME) &&
  202. (ulCompatFlags & ulAppType)) {
  203. if ( !pWinStationQueryInformationW ) {
  204. /*
  205. * Get handle to winsta.dll
  206. */
  207. if ( (hwinsta = LoadLibraryA( "WINSTA" )) != NULL ) {
  208. pWinStationQueryInformationW = (PWINSTATIONQUERYINFORMATIONW)
  209. GetProcAddress( hwinsta, "WinStationQueryInformationW" );
  210. }
  211. }
  212. // Fetch the WinStation's basic information
  213. if ( pWinStationQueryInformationW ) {
  214. if ( (*pWinStationQueryInformationW)(SERVERNAME_CURRENT,
  215. LOGONID_CURRENT,
  216. WinStationInformation,
  217. &WSInfo,
  218. sizeof(WSInfo),
  219. &ValueLength ) ) {
  220. // Check if username will fit in buffer
  221. if (wcslen(WSInfo.UserName) >= *nSize) {
  222. return ERROR_BUFFER_OVERFLOW;
  223. } else {
  224. wcscpy(lpBuffer, WSInfo.UserName);
  225. return ERROR_SUCCESS;
  226. }
  227. }
  228. }
  229. }
  230. return ERROR_RETRY;
  231. }
  232. void TermsrvAdjustPhyMemLimits (
  233. IN OUT LPDWORD TotalPhys,
  234. IN OUT LPDWORD AvailPhys,
  235. IN DWORD SysPageSize
  236. )
  237. {
  238. ULONG ulAppType = 0;
  239. DWORD PhysicalMemory;
  240. if ( GetCtxPhysMemoryLimits(&ulAppType, &PhysicalMemory) ) {
  241. if (*TotalPhys > PhysicalMemory ) {
  242. *TotalPhys = PhysicalMemory;
  243. }
  244. }
  245. if ( *AvailPhys > *TotalPhys ) {
  246. // Reset the Available Physical Memory to be smaller than the
  247. // Total Physical Memory. It is made smaller to avoid
  248. // possible divide by zero errors when Available and Total are
  249. // equal
  250. *AvailPhys = *TotalPhys - SysPageSize;
  251. }
  252. return;
  253. }
  254. UINT
  255. APIENTRY
  256. TermsrvGetWindowsDirectoryA(
  257. LPSTR lpBuffer,
  258. UINT uSize
  259. )
  260. {
  261. ANSI_STRING AnsiString;
  262. NTSTATUS Status;
  263. ULONG cbAnsiString;
  264. UNICODE_STRING Path;
  265. //
  266. // If in install mode return the system windows dir
  267. //
  268. if (TermsrvAppInstallMode()) {
  269. return 0;
  270. }
  271. if (!TermsrvPerUserWinDirMapping()) {
  272. return 0;
  273. }
  274. // if buffer looks real, then init it to zero
  275. if ( lpBuffer ) {
  276. *lpBuffer = '\0'; // in case we have an error, the shell folks want this to be null
  277. // BUG 453487
  278. }
  279. Path.Length = 0;
  280. Path.MaximumLength = (USHORT)(uSize * sizeof( WCHAR ));
  281. if ( Path.Buffer = LocalAlloc( LPTR, Path.MaximumLength ) ) {
  282. Status = GetPerUserWindowsDirectory( &Path );
  283. if ( NT_SUCCESS(Status) ) {
  284. AnsiString.MaximumLength = (USHORT)(uSize);
  285. AnsiString.Buffer = lpBuffer;
  286. Status = RtlUnicodeStringToAnsiString(
  287. &AnsiString,
  288. &Path,
  289. FALSE
  290. );
  291. } else if ( (Status == STATUS_BUFFER_TOO_SMALL) || (Status == STATUS_BUFFER_OVERFLOW ) ) {
  292. DbgPrint( "KERNEL32: GetWindowsDirectoryA: User buffer too small (%u) need(%u)\n",
  293. uSize, Path.Length >> 1 );
  294. return( Path.Length >> 1 );
  295. }
  296. LocalFree( Path.Buffer );
  297. } else {
  298. Status = STATUS_NO_MEMORY;
  299. DbgPrint( "KERNEL32: GetWindowsDirectoryA: No memory\n" );
  300. }
  301. if ( Status == STATUS_BUFFER_TOO_SMALL ) {
  302. DbgPrint( "KERNEL32: GetWindowsDirectoryA: User buffer too small (%u) need(%u)\n",
  303. uSize, Path.Length >> 1 );
  304. return( Path.Length >> 1 );
  305. } else if ( !NT_SUCCESS(Status) ) {
  306. return 0;
  307. }
  308. return AnsiString.Length;
  309. }
  310. UINT
  311. APIENTRY
  312. TermsrvGetWindowsDirectoryW(
  313. LPWSTR lpBuffer,
  314. UINT uSize
  315. )
  316. {
  317. UNICODE_STRING Path;
  318. NTSTATUS Status;
  319. //
  320. // If in install mode return the system windows dir
  321. //
  322. if (TermsrvAppInstallMode()) {
  323. return 0;
  324. }
  325. if (!TermsrvPerUserWinDirMapping()) {
  326. return 0;
  327. }
  328. // if buffer looks real, then init it to zero
  329. if ( lpBuffer ) {
  330. *lpBuffer = '\0'; // in case we have an error, the shell folks want this to be null
  331. // BUG 453487
  332. }
  333. /*
  334. * If it fails, return 0
  335. * If buffer too small, return len (not includding NULL)
  336. * If buffer ok, return len (not inc. NULL) and fill buffer
  337. * (GetPerUserWindowsDirectory will do all of this for us!)
  338. */
  339. Path.Length = 0;
  340. Path.MaximumLength = (USHORT)(uSize * sizeof( WCHAR ));
  341. Path.Buffer = lpBuffer;
  342. Status = GetPerUserWindowsDirectory( &Path );
  343. if ( Status == STATUS_SUCCESS ) {
  344. /*
  345. * Add a NULL to the end (if it fits!)
  346. */
  347. if ( Path.Length + sizeof( WCHAR ) <= Path.MaximumLength ) {
  348. lpBuffer[(Path.Length>>1)] = UNICODE_NULL;
  349. }
  350. }
  351. return( Path.Length / sizeof(WCHAR) );
  352. }