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.

324 lines
9.7 KiB

  1. #include "basesrv.h"
  2. #include "ahcache.h"
  3. #define SHIM_CACHE_NOT_FOUND 0x00000001
  4. #define SHIM_CACHE_BYPASS 0x00000002 // bypass cache (either removable media or temp dir)
  5. #define SHIM_CACHE_LAYER_ENV 0x00000004 // layer env variable set
  6. #define SHIM_CACHE_MEDIA 0x00000008
  7. #define SHIM_CACHE_TEMP 0x00000010
  8. #define SHIM_CACHE_NOTAVAIL 0x00000020
  9. #define SHIM_CACHE_UPDATE 0x00020000
  10. #define SHIM_CACHE_ACTION 0x00010000
  11. //
  12. // Parameters:
  13. // ExePath
  14. // Environment Block (need __PROCESS_HISTORY and __COMPAT_LAYER)
  15. // File Handle
  16. //
  17. BOOL
  18. BasepSrvShimCacheUpdate(
  19. IN PUNICODE_STRING FileName,
  20. IN HANDLE FileHandle
  21. )
  22. /*++
  23. Return: TRUE if we have a cache hit, FALSE otherwise.
  24. Desc: Search the cache, return TRUE if we have a cache hit
  25. pIndex will receive an index into the rgIndex array that contains
  26. the entry which has been hit
  27. So that if entry 5 contains the hit, and rgIndexes[3] == 5 then
  28. *pIndex == 3
  29. --*/
  30. {
  31. NTSTATUS Status;
  32. AHCACHESERVICEDATA Data;
  33. Data.FileName = *FileName;
  34. Data.FileHandle = FileHandle;
  35. Status = NtApphelpCacheControl(ApphelpCacheServiceUpdate,
  36. &Data);
  37. return NT_SUCCESS(Status);
  38. }
  39. BOOL
  40. BasepSrvShimCacheRemoveEntry(
  41. IN PUNICODE_STRING FileName
  42. )
  43. /*++
  44. Return: TRUE.
  45. Desc: Remove the entry from the cache.
  46. We remove the entry by placing it as the last lru entry
  47. and emptying the path. This routine assumes that the index
  48. passed in is valid.
  49. --*/
  50. {
  51. AHCACHESERVICEDATA Data;
  52. NTSTATUS Status;
  53. Data.FileName = *FileName;
  54. Data.FileHandle = INVALID_HANDLE_VALUE;
  55. Status = NtApphelpCacheControl(ApphelpCacheServiceRemove,
  56. &Data);
  57. return NT_SUCCESS(Status);
  58. }
  59. NTSTATUS
  60. BasepSrvMarshallAppCompatData(
  61. PBASE_CHECK_APPLICATION_COMPATIBILITY_MSG pMsg,
  62. HANDLE ClientProcessHandle,
  63. PVOID pAppCompatData,
  64. SIZE_T cbAppCompatData,
  65. PVOID pSxsData,
  66. SIZE_T cbSxsData,
  67. SIZE_T FusionFlags
  68. )
  69. {
  70. NTSTATUS Status = STATUS_SUCCESS;
  71. SIZE_T cbData;
  72. //
  73. //
  74. //
  75. if (pAppCompatData) {
  76. cbData = cbAppCompatData;
  77. Status = NtAllocateVirtualMemory(ClientProcessHandle,
  78. (PVOID*)&pMsg->pAppCompatData,
  79. 0,
  80. &cbData,
  81. MEM_COMMIT,
  82. PAGE_READWRITE);
  83. if (!NT_SUCCESS(Status)) {
  84. goto Cleanup;
  85. }
  86. // we got the memory allocated, copy our data
  87. Status = NtWriteVirtualMemory(ClientProcessHandle,
  88. pMsg->pAppCompatData,
  89. pAppCompatData,
  90. cbAppCompatData,
  91. NULL);
  92. if (!NT_SUCCESS(Status)) {
  93. goto Cleanup;
  94. }
  95. pMsg->cbAppCompatData = (DWORD)cbAppCompatData;
  96. }
  97. if (pSxsData) {
  98. cbData = cbSxsData;
  99. Status = NtAllocateVirtualMemory(ClientProcessHandle,
  100. (PVOID*)&pMsg->pSxsData,
  101. 0,
  102. &cbData,
  103. MEM_COMMIT,
  104. PAGE_READWRITE);
  105. if (!NT_SUCCESS(Status)) {
  106. goto Cleanup;
  107. }
  108. // we got the memory allocated, copy our data
  109. Status = NtWriteVirtualMemory(ClientProcessHandle,
  110. pMsg->pSxsData,
  111. pSxsData,
  112. cbSxsData,
  113. NULL);
  114. if (!NT_SUCCESS(Status)) {
  115. goto Cleanup;
  116. }
  117. pMsg->cbSxsData = (DWORD)cbSxsData;
  118. }
  119. pMsg->FusionFlags = (DWORD)FusionFlags;
  120. Cleanup:
  121. if (!NT_SUCCESS(Status)) {
  122. if (pMsg->pAppCompatData) {
  123. NtFreeVirtualMemory(ClientProcessHandle,
  124. (PVOID*)&pMsg->pAppCompatData,
  125. &cbAppCompatData,
  126. MEM_RELEASE);
  127. pMsg->pAppCompatData = NULL;
  128. pMsg->cbAppCompatData = 0;
  129. }
  130. if (pMsg->pAppCompatData) {
  131. NtFreeVirtualMemory(ClientProcessHandle,
  132. (PVOID*)&pMsg->pSxsData,
  133. &cbSxsData,
  134. MEM_RELEASE);
  135. pMsg->pSxsData = NULL;
  136. pMsg->cbSxsData = 0;
  137. }
  138. }
  139. if (pAppCompatData) {
  140. RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatData);
  141. }
  142. if (pSxsData) {
  143. RtlFreeHeap(RtlProcessHeap(), 0, pSxsData);
  144. }
  145. return Status;
  146. }
  147. NTSTATUS
  148. BaseSrvCheckApplicationCompatibility(
  149. IN OUT PCSR_API_MSG m,
  150. IN OUT PCSR_REPLY_STATUS ReplyStatus
  151. )
  152. {
  153. PBASE_CHECK_APPLICATION_COMPATIBILITY_MSG pMsg = (PBASE_CHECK_APPLICATION_COMPATIBILITY_MSG)&m->u.ApiMessageData;
  154. NTSTATUS Status;
  155. BOOL bSuccess;
  156. PCSR_THREAD ClientThread;
  157. HANDLE ClientProcessHandle;
  158. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  159. BOOL bRunApp = TRUE;
  160. PVOID pAppCompatData = NULL;
  161. DWORD cbAppCompatData = 0;
  162. PVOID pSxsData = NULL;
  163. DWORD cbSxsData = 0;
  164. DWORD dwFusionFlags = 0;
  165. WCHAR szEmptyEnvironment[] = { L'\0', L'\0' };
  166. //
  167. // first we have to check the message buffer to make sure it is good
  168. //
  169. if (!CsrValidateMessageBuffer(m,
  170. &pMsg->FileName.Buffer,
  171. pMsg->FileName.MaximumLength/sizeof(WCHAR),
  172. sizeof(WCHAR))) {
  173. return STATUS_INVALID_PARAMETER;
  174. }
  175. //
  176. // do more validation here please
  177. //
  178. if (pMsg->pEnvironment != NULL) {
  179. if (!CsrValidateMessageBuffer(m,
  180. &pMsg->pEnvironment,
  181. pMsg->EnvironmentSize/sizeof(WCHAR),
  182. sizeof(WCHAR))) {
  183. return STATUS_INVALID_PARAMETER;
  184. }
  185. // check that the environment ends in two 00
  186. if (pMsg->EnvironmentSize < sizeof(szEmptyEnvironment) ||
  187. *((PWCHAR)pMsg->pEnvironment + (pMsg->EnvironmentSize/sizeof(WCHAR) - 1)) != L'\0' ||
  188. *((PWCHAR)pMsg->pEnvironment + (pMsg->EnvironmentSize/sizeof(WCHAR) - 2)) != L'\0') {
  189. return STATUS_INVALID_PARAMETER;
  190. }
  191. }
  192. Status = BaseSrvDelayLoadApphelp();
  193. if (!NT_SUCCESS(Status)) {
  194. return Status;
  195. }
  196. //
  197. // check environment buffer
  198. //
  199. ClientThread = CSR_SERVER_QUERYCLIENTTHREAD();
  200. ClientProcessHandle = ClientThread->Process->ProcessHandle;
  201. //
  202. // Calling CsrImpersonateClient before NtDuplicateObject to
  203. // make auditing work better.
  204. //
  205. if (!CsrImpersonateClient(NULL)) {
  206. //
  207. // we could not impersonate the caller, fail this alltogether then
  208. //
  209. return STATUS_BAD_IMPERSONATION_LEVEL;
  210. }
  211. if (pMsg->FileHandle != INVALID_HANDLE_VALUE) {
  212. Status = NtDuplicateObject(ClientProcessHandle,
  213. pMsg->FileHandle,
  214. NtCurrentProcess(),
  215. &FileHandle,
  216. 0,
  217. 0,
  218. DUPLICATE_SAME_ACCESS);
  219. if (!NT_SUCCESS(Status)) {
  220. return STATUS_INVALID_PARAMETER;
  221. }
  222. }
  223. //
  224. // next - check application compatibility setting by invoking apphelp.dll
  225. //
  226. bRunApp = pfnCheckRunApp(FileHandle,
  227. pMsg->FileName.Buffer,
  228. pMsg->pEnvironment == NULL ?
  229. (PVOID)szEmptyEnvironment : pMsg->pEnvironment,
  230. pMsg->ExeType,
  231. &pMsg->CacheCookie,
  232. &pAppCompatData,
  233. &cbAppCompatData,
  234. &pSxsData,
  235. &cbSxsData,
  236. &dwFusionFlags);
  237. //
  238. // revert to self
  239. //
  240. CsrRevertToSelf();
  241. //
  242. // if we got compat data back -- marshal the pointers across
  243. //
  244. Status = BasepSrvMarshallAppCompatData(pMsg,
  245. ClientProcessHandle,
  246. pAppCompatData,
  247. cbAppCompatData,
  248. pSxsData,
  249. cbSxsData,
  250. dwFusionFlags);
  251. if (!NT_SUCCESS(Status)) {
  252. goto Cleanup;
  253. }
  254. if (bRunApp && (pMsg->CacheCookie & SHIM_CACHE_ACTION)) {
  255. if (pMsg->CacheCookie & SHIM_CACHE_UPDATE) {
  256. Status = BasepSrvShimCacheUpdate(&pMsg->FileName, FileHandle);
  257. } else {
  258. Status = BasepSrvShimCacheRemoveEntry(&pMsg->FileName);
  259. }
  260. }
  261. Cleanup:
  262. //
  263. // check for the handle please
  264. //
  265. if (FileHandle != INVALID_HANDLE_VALUE) {
  266. NtClose(FileHandle);
  267. }
  268. pMsg->bRunApp = bRunApp;
  269. return STATUS_SUCCESS;
  270. }