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.

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