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.

4001 lines
137 KiB

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;
  3. ;; Copyright (c) 1998-2001 Microsoft Corporation
  4. ;;
  5. ;; Module Name:
  6. ;;
  7. ;; whnt32.tpl
  8. ;;
  9. ;; Abstract:
  10. ;;
  11. ;; This template defines the thunks for the NT api set.
  12. ;;
  13. ;; Author:
  14. ;;
  15. ;; 6-Oct-98 mzoran
  16. ;;
  17. ;; Revision History:
  18. ;; 8-9-99 [askhalid] added call to CpuNotify___ for dll load/unload and call to CpuFlushInstructionCache
  19. ;; for NtAllocateVirtualMemory NtProtectVirtualMemory and NtFlushInstructionCache.
  20. ;;
  21. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  22. [Macros]
  23. MacroName=CallNameFromApiName
  24. NumArgs=1
  25. Begin=
  26. @MArg(1)
  27. End=
  28. [EFunc]
  29. TemplateName=NtAccessCheckByType
  30. NoType=ObjectTypeList
  31. PreCall=
  32. ObjectTypeList = whNT32ShallowThunkAllocObjectTypeList32TO64((NT32OBJECT_TYPE_LIST *)ObjectTypeListHost,ObjectTypeListLength); @NL
  33. End=
  34. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  35. ;;;;;;;;;;;; Thunking Registry APIs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  36. TemplateName=NtCreateKey
  37. Begin=
  38. @GenApiThunk(Wow64@ApiName)
  39. End=
  40. TemplateName=NtDeleteKey
  41. Begin=
  42. @GenApiThunk(Wow64@ApiName)
  43. End=
  44. TemplateName=NtDeleteValueKey
  45. Begin=
  46. @GenApiThunk(Wow64@ApiName)
  47. End=
  48. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  49. ;;
  50. ;; Registry routines
  51. ;; Special handling is needed since they can be asynchronous.
  52. ;;
  53. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  54. ;; The following is the list of structures passed.
  55. ;; None of them are pointer dependent.
  56. ;; List taken from ntos\config\mtapi.c
  57. TemplateName=NtEnumerateKey
  58. Case=(KeyBasicInformation,PKEY_BASIC_INFORMATION)
  59. Case=(KeyNodeInformation,PKEY_NODE_INFORMATION)
  60. Case=(KeyFullInformation,PKEY_FULL_INFORMATION)
  61. Begin=
  62. @GenDebugNonPtrDepCases(Wow64@ApiName,KeyInformationClass)
  63. End=
  64. ;; The following is the list of structures passed.
  65. ;; None of them are pointer dependent.
  66. ;; List taken from ntos\config\mtapi.c
  67. TemplateName=NtEnumerateValueKey
  68. Case=(KeyValueBasicInformation,PKEY_VALUE_BASIC_INFORMATION)
  69. Case=(KeyValueFullInformation,PKEY_VALUE_FULL_INFORMATION)
  70. Case=(KeyValuePartialInformation,PKEY_VALUE_PARTIAL_INFORMATION)
  71. Begin=
  72. @GenDebugNonPtrDepCases(Wow64@ApiName,KeyValueInformationClass)
  73. End=
  74. TemplateName=NtFlushKey
  75. Begin=
  76. @GenApiThunk(Wow64@ApiName)
  77. End=
  78. TemplateName=NtInitializeRegistry
  79. Begin=
  80. @GenApiThunk(Wow64@ApiName)
  81. End=
  82. TemplateName=NtNotifyChangeMultipleKeys
  83. NoType=SlaveObjects
  84. PreCall=
  85. {@Indent(@NL
  86. @NL try { @NL
  87. NT32OBJECT_ATTRIBUTES *Entries32 = (NT32OBJECT_ATTRIBUTES *)SlaveObjectsHost; @NL
  88. ULONG TempEntryCount = Count; @NL
  89. POBJECT_ATTRIBUTES Entries64 = (POBJECT_ATTRIBUTES)Wow64AllocateTemp(sizeof(OBJECT_ATTRIBUTES) * Count); @NL
  90. SlaveObjects = Entries64; @NL
  91. @NL
  92. for(;TempEntryCount > 0; TempEntryCount--, Entries32++, Entries64++) { @NL
  93. Entries64->Length = sizeof (OBJECT_ATTRIBUTES); @NL;
  94. Entries64->ObjectName = Wow64ShallowThunkAllocUnicodeString32TO64(Entries32->ObjectName); @NL
  95. Entries64->SecurityQualityOfService = (PVOID)Entries32->SecurityQualityOfService; @NL
  96. Entries64->SecurityDescriptor = (PVOID)Entries32->SecurityDescriptor; @NL
  97. Entries64->Attributes = (ULONG)Entries32->Attributes; @NL
  98. Entries64->RootDirectory = (HANDLE)Entries32->RootDirectory; @NL
  99. }@NL
  100. } except( NULL, EXCEPTION_EXECUTE_HANDLER){ @NL
  101. return GetExceptionCode (); @NL
  102. } @NL
  103. )}@NL
  104. Wow64WrapApcProc(&ApcRoutine, &ApcContext);
  105. End=
  106. Begin=
  107. @GenApiThunk(Wow64@ApiName)
  108. End=
  109. TemplateName=NtLoadKey
  110. Begin=
  111. @GenApiThunk(Wow64@ApiName)
  112. End=
  113. TemplateName=NtLoadKey2
  114. Begin=
  115. @GenApiThunk(Wow64@ApiName)
  116. End=
  117. TemplateName=NtOpenKey
  118. Begin=
  119. @GenApiThunk(Wow64@ApiName)
  120. End=
  121. TemplateName=NtQueryKey
  122. Begin=
  123. @GenApiThunk(Wow64@ApiName)
  124. End=
  125. TemplateName=NtQueryValueKey
  126. Begin=
  127. @GenApiThunk(Wow64@ApiName)
  128. End=
  129. TemplateName=NtReplaceKey
  130. Begin=
  131. @GenApiThunk(Wow64@ApiName)
  132. End=
  133. TemplateName=NtRestoreKey
  134. Begin=
  135. @GenApiThunk(Wow64@ApiName)
  136. End=
  137. TemplateName=NtSaveKey
  138. Begin=
  139. @GenApiThunk(Wow64@ApiName)
  140. End=
  141. TemplateName=NtSaveMergedKeys
  142. Begin=
  143. @GenApiThunk(Wow64@ApiName)
  144. End=
  145. TemplateName=NtSetValueKey
  146. Begin=
  147. @GenApiThunk(Wow64@ApiName)
  148. End=
  149. TemplateName=NtUnloadKey
  150. Begin=
  151. @GenApiThunk(Wow64@ApiName)
  152. End=
  153. TemplateName=NtQueryOpenSubKeys
  154. Begin=
  155. @GenApiThunk(Wow64@ApiName)
  156. End=
  157. TemplateName=NtClose
  158. Begin=
  159. @GenApiThunk(Wow64@ApiName)
  160. End=
  161. ;; to reflect registrykey security if applicable
  162. TemplateName=NtSetSecurityObject
  163. Begin=
  164. @GenApiThunk(Wow64@ApiName)
  165. End=
  166. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  167. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  168. TemplateName=NtAccessCheckByTypeAndAuditAlarm
  169. NoType=ObjectTypeList
  170. PreCall=
  171. ObjectTypeList = whNT32ShallowThunkAllocObjectTypeList32TO64((NT32OBJECT_TYPE_LIST *)ObjectTypeListHost,ObjectTypeListLength); @NL
  172. End=
  173. TemplateName=NtAccessCheckByTypeResultList
  174. NoType=ObjectTypeList
  175. PreCall=
  176. ObjectTypeList = whNT32ShallowThunkAllocObjectTypeList32TO64((NT32OBJECT_TYPE_LIST *)ObjectTypeListHost,ObjectTypeListLength); @NL
  177. End=
  178. TemplateName=NtAccessCheckByTypeResultListAndAuditAlarm
  179. NoType=ObjectTypeList
  180. PreCall=
  181. ObjectTypeList = whNT32ShallowThunkAllocObjectTypeList32TO64((NT32OBJECT_TYPE_LIST *)ObjectTypeListHost,ObjectTypeListLength); @NL
  182. End=
  183. TemplateName=NtAdjustGroupsToken
  184. NoType=PreviousState
  185. Header=
  186. @NoFormat(
  187. NTSTATUS
  188. whNT32AdjustGroupToken(
  189. IN HANDLE TokenHandle,
  190. IN BOOLEAN ResetToDefault,
  191. IN PTOKEN_GROUPS NewState,
  192. IN ULONG BufferLength,
  193. OUT PVOID PreviousState,
  194. IN PULONG ReturnLength
  195. )
  196. {
  197. NTSTATUS Status;
  198. PTOKEN_GROUPS LocalPreviousState;
  199. if(BufferLength != 0 && PreviousState != NULL) {
  200. LocalPreviousState = Wow64AllocateTemp(BufferLength);
  201. }
  202. else {
  203. LocalPreviousState = (PTOKEN_GROUPS)PreviousState;
  204. }
  205. Status = NtAdjustGroupsToken(TokenHandle,
  206. ResetToDefault,
  207. NewState,
  208. BufferLength,
  209. LocalPreviousState,
  210. ReturnLength
  211. );
  212. if(NT_ERROR(Status) || BufferLength == 0 || PreviousState == NULL) {
  213. return Status;
  214. }
  215. //Thunk the PreviousState
  216. WriteReturnLengthStatus(ReturnLength,
  217. &Status,
  218. whNT32DeepThunkTokenGroups64TO32Length(LocalPreviousState));
  219. whNT32DeepThunkTokenGroups64TO32((NT32TOKEN_GROUPS*)PreviousState, LocalPreviousState);
  220. return Status;
  221. }
  222. )
  223. End=
  224. PreCall=
  225. PreviousState = (PTOKEN_GROUPS)PreviousStateHost; @NL
  226. End=
  227. Begin=
  228. @GenApiThunk(whNT32AdjustGroupToken)
  229. End=
  230. TemplateName=NtFilterToken
  231. NoType=SidsToDisable
  232. NoType=RestrictedSids
  233. PreCall=
  234. SidsToDisable = whNT32ShallowThunkAllocTokenGroups32TO64((NT32TOKEN_GROUPS *)SidsToDisableHost); @NL
  235. RestrictedSids = whNT32ShallowThunkAllocTokenGroups32TO64((NT32TOKEN_GROUPS *)RestrictedSidsHost); @NL
  236. End=
  237. TemplateName=NtQueryInformationAtom
  238. Case=(AtomBasicInformation,PATOM_BASIC_INFORMATION)
  239. Case=(AtomTableInformation,PATOM_TABLE_INFORMATION)
  240. Begin=
  241. @GenDebugNonPtrDepCases(@ApiName,AtomInformationClass)
  242. End=
  243. TemplateName=NtQueryDirectoryObject
  244. Header=
  245. @NoFormat(
  246. NTSTATUS
  247. whNT32QueryDirectoryObject(
  248. IN HANDLE DirectoryHandle,
  249. OUT PVOID Buffer,
  250. IN ULONG Length,
  251. IN BOOLEAN ReturnSingleEntry,
  252. IN BOOLEAN RestartScan,
  253. IN OUT PULONG Context,
  254. OUT PULONG ReturnLength
  255. )
  256. {
  257. NTSTATUS Status;
  258. ULONG TempBufferLength, TempBufferReturnedLength;
  259. PVOID TempBuffer;
  260. ULONG SystemContext;
  261. ULONG GrabbedEntries, TotalSizeNeeded, SizeNeeded, EntriesToReturn, BytesToReturn, c;
  262. POBJECT_DIRECTORY_INFORMATION DirInfo64;
  263. NT32OBJECT_DIRECTORY_INFORMATION *DirInfo32;
  264. WCHAR *Strings;
  265. TempBufferLength = 0x800;
  266. try {
  267. do {
  268. TempBufferLength <<= 1;
  269. TempBuffer = Wow64AllocateTemp(TempBufferLength);
  270. // Grab the entire list of objects starting with the context specified from the app.
  271. // Note that the context is equal to the next entry number.
  272. SystemContext = *Context;
  273. Status = NtQueryDirectoryObject(DirectoryHandle,
  274. TempBuffer,
  275. TempBufferLength,
  276. ReturnSingleEntry,
  277. RestartScan,
  278. &SystemContext,
  279. &TempBufferReturnedLength);
  280. if(NT_ERROR(Status) && Status != STATUS_BUFFER_TOO_SMALL) {
  281. WriteReturnLength(ReturnLength, 0);
  282. return Status;
  283. }
  284. } while(Status != STATUS_NO_MORE_ENTRIES && Status != STATUS_SUCCESS);
  285. if (STATUS_NO_MORE_ENTRIES == Status) {
  286. WOWASSERT(SystemContext == *Context);
  287. WOWASSERT(sizeof(*DirInfo64) == TempBufferReturnedLength)
  288. WriteReturnLength(ReturnLength, 0);
  289. return Status;
  290. }
  291. DirInfo64 = (POBJECT_DIRECTORY_INFORMATION)TempBuffer;
  292. BytesToReturn = TotalSizeNeeded = sizeof(NT32OBJECT_DIRECTORY_INFORMATION);
  293. GrabbedEntries = 0;
  294. EntriesToReturn = 0;
  295. Status = STATUS_NO_MORE_ENTRIES;
  296. while(!(DirInfo64->Name.Buffer == NULL && DirInfo64->TypeName.Buffer == NULL)) {
  297. GrabbedEntries++;
  298. //The kernel will terminate the strings, so that doesn't need to be done here.
  299. SizeNeeded = sizeof(NT32OBJECT_DIRECTORY_INFORMATION) +
  300. DirInfo64->Name.Length + DirInfo64->TypeName.Length +
  301. sizeof(UNICODE_NULL) + sizeof(UNICODE_NULL);
  302. TotalSizeNeeded += SizeNeeded;
  303. if(Length >= TotalSizeNeeded) {
  304. EntriesToReturn++;
  305. BytesToReturn += SizeNeeded;
  306. }
  307. Status = STATUS_SUCCESS;
  308. DirInfo64++;
  309. }
  310. if (Length < BytesToReturn) {
  311. // If only one entry was asked for, fail the API and set the desired return length.
  312. if(ReturnSingleEntry) {
  313. WriteReturnLength(ReturnLength, BytesToReturn);
  314. return STATUS_BUFFER_TOO_SMALL;
  315. }
  316. Status = STATUS_MORE_ENTRIES;
  317. }
  318. //Copy the entries out to the buffer.
  319. DirInfo32 = (NT32OBJECT_DIRECTORY_INFORMATION *)Buffer;
  320. Strings = (WCHAR *)(DirInfo32 + EntriesToReturn + 1);
  321. DirInfo64 = (POBJECT_DIRECTORY_INFORMATION)TempBuffer;
  322. for(c=0; c < EntriesToReturn; c++) {
  323. DirInfo32->Name.Length = DirInfo64->Name.Length;
  324. DirInfo32->Name.MaximumLength = DirInfo64->Name.MaximumLength;
  325. DirInfo32->Name.Buffer = (NT32PWCHAR)PtrToUlong(Strings);
  326. RtlCopyMemory((PVOID)Strings, DirInfo64->Name.Buffer, DirInfo64->Name.Length);
  327. Strings += (DirInfo64->Name.Length / sizeof(WCHAR));
  328. *Strings++ = UNICODE_NULL;
  329. DirInfo32->TypeName.Length = DirInfo64->TypeName.Length;
  330. DirInfo32->TypeName.MaximumLength = DirInfo64->TypeName.MaximumLength;
  331. DirInfo32->TypeName.Buffer = (NT32PWCHAR)PtrToUlong(Strings);
  332. RtlCopyMemory((PVOID)Strings, DirInfo64->TypeName.Buffer, DirInfo64->TypeName.Length);
  333. Strings += (DirInfo64->TypeName.Length / sizeof(WCHAR));
  334. *Strings++ = UNICODE_NULL;
  335. DirInfo32++;
  336. DirInfo64++;
  337. }
  338. // Clear the last entry
  339. RtlZeroMemory(DirInfo32, sizeof(NT32OBJECT_DIRECTORY_INFORMATION));
  340. // Context is actually the number of the next entry to recieve. This needs to be adjusted since
  341. // the entire list may not have been sent to the app.
  342. WOWASSERT(SystemContext >= GrabbedEntries);
  343. *Context = SystemContext - (GrabbedEntries - EntriesToReturn);
  344. WriteReturnLength(ReturnLength, BytesToReturn);
  345. } except (EXCEPTION_EXECUTE_HANDLER) {
  346. Status = GetExceptionCode ();
  347. }
  348. return Status;
  349. }
  350. )
  351. End=
  352. Begin=
  353. #define WriteReturnLength(rl, length) WriteReturnLengthSilent((rl), (length))
  354. @GenApiThunk(whNT32QueryDirectoryObject)
  355. #undef WriteReturnLength
  356. End=
  357. TemplateName=NtQueryEvent
  358. Case=(EventBasicInformation,PEVENT_BASIC_INFORMATION)
  359. Begin=
  360. @GenDebugNonPtrDepCases(@ApiName,EventInformationClass)
  361. End=
  362. TemplateName=NtQueryInformationJobObject
  363. Case=(JobObjectBasicAccountingInformation,PJOBOBJECT_BASIC_ACCOUNTING_INFORMATION)
  364. Case=(JobObjectBasicLimitInformation,PJOBOBJECT_BASIC_LIMIT_INFORMATION)
  365. Case=(JobObjectBasicUIRestrictions,PJOBOBJECT_BASIC_UI_RESTRICTIONS)
  366. Case=(JobObjectBasicProcessIdList)
  367. Case=(JobObjectEndOfJobTimeInformation,PJOBOBJECT_END_OF_JOB_TIME_INFORMATION)
  368. Case=(JobObjectExtendedLimitInformation,PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)
  369. Case=(JobObjectSecurityLimitInformation)
  370. SpecialQueryCase=
  371. case JobObjectSecurityLimitInformation: { @Indent( @NL
  372. // PJOBOBJECT_SECURITY_LIMIT_INFORMATION @NL
  373. PCHAR Buffer; @NL
  374. ULONG BufferSize; @NL
  375. ULONG RequiredLength; @NL
  376. NT32JOBOBJECT_SECURITY_LIMIT_INFORMATION *SecurityLimit32; @NL
  377. PJOBOBJECT_SECURITY_LIMIT_INFORMATION SecurityLimit64; @NL
  378. @NL
  379. @NL
  380. BufferSize = max(JobObjectInformationLength * 2, 0xFFFFFFFF); @NL
  381. Buffer = Wow64AllocateTemp(BufferSize); @NL
  382. RetVal = NtQueryInformationJobObject(JobHandle, JobObjectInformationClass, Buffer, BufferSize, ReturnLength); @NL
  383. if (!NT_ERROR(RetVal)) { @Indent( @NL
  384. SecurityLimit64 = (PJOBOBJECT_SECURITY_LIMIT_INFORMATION)Buffer; @NL
  385. SecurityLimit32 = (NT32JOBOBJECT_SECURITY_LIMIT_INFORMATION *)JobObjectInformation; @NL
  386. RequiredLength = sizeof(NT32JOBOBJECT_SECURITY_LIMIT_INFORMATION); @NL
  387. if (ARGUMENT_PRESENT(SecurityLimit64->SidsToDisable)) { @Indent( @NL
  388. RequiredLength += whNT32DeepThunkTokenGroups64TO32Length(SecurityLimit64->SidsToDisable); @NL
  389. }) @NL
  390. if (ARGUMENT_PRESENT(SecurityLimit64->PrivilegesToDelete)) { @Indent( @NL
  391. RequiredLength += sizeof(ULONG) + (SecurityLimit64->PrivilegesToDelete->PrivilegeCount * sizeof(ULONG));
  392. }) @NL
  393. if (ARGUMENT_PRESENT(SecurityLimit64->RestrictedSids)) { @Indent( @NL
  394. RequiredLength += whNT32DeepThunkTokenGroups64TO32Length(SecurityLimit64->RestrictedSids); @NL
  395. }) @NL
  396. if (RequiredLength > JobObjectInformationLength) { @Indent( @NL
  397. RetVal = STATUS_BUFFER_OVERFLOW; @NL
  398. }) @NL
  399. else { @Indent( @NL
  400. SIZE_T Size = sizeof(NT32JOBOBJECT_SECURITY_LIMIT_INFORMATION); @NL
  401. WriteReturnLength(ReturnLength, RequiredLength); @NL
  402. SecurityLimit32->SecurityLimitFlags = SecurityLimit64->SecurityLimitFlags; @NL
  403. SecurityLimit32->JobToken = (NT32HANDLE)SecurityLimit64->JobToken; @NL
  404. if (ARGUMENT_PRESENT(SecurityLimit64->SidsToDisable)) { @Indent( @NL
  405. PCHAR CopyDest = (PCHAR)SecurityLimit32 + Size; @NL
  406. Size += whNT32DeepThunkTokenGroups64TO32Length(SecurityLimit64->SidsToDisable); @NL
  407. whNT32DeepThunkTokenGroups64TO32((NT32TOKEN_GROUPS *)CopyDest, SecurityLimit64->SidsToDisable); @NL
  408. SecurityLimit32->SidsToDisable = (NT32PTOKEN_GROUPS)CopyDest; @NL
  409. }) @NL
  410. else { @Indent( @NL
  411. SecurityLimit32->SidsToDisable = (NT32PTOKEN_GROUPS)SecurityLimit64->SidsToDisable; @NL
  412. }) @NL
  413. if (ARGUMENT_PRESENT(SecurityLimit64->PrivilegesToDelete)) { @Indent( @NL
  414. PCHAR CopyDest = (PCHAR)SecurityLimit32 + Size; @NL
  415. SIZE_T SizeTokenPrivileges = sizeof(ULONG) + (sizeof(LUID_AND_ATTRIBUTES) * SecurityLimit64->PrivilegesToDelete->PrivilegeCount); @NL
  416. RtlCopyMemory(CopyDest, SecurityLimit64->PrivilegesToDelete, SizeTokenPrivileges); @NL
  417. SecurityLimit32->PrivilegesToDelete = (NT32PTOKEN_PRIVILEGES)CopyDest; @NL
  418. Size += SizeTokenPrivileges; @NL
  419. }) @NL
  420. else { @Indent( @NL
  421. SecurityLimit32->PrivilegesToDelete = (NT32PTOKEN_PRIVILEGES)SecurityLimit64->PrivilegesToDelete; @NL
  422. }) @NL
  423. if (ARGUMENT_PRESENT(SecurityLimit64->RestrictedSids)) { @Indent( @NL
  424. PCHAR CopyDest = (PCHAR)SecurityLimit32 + Size; @NL
  425. Size += whNT32DeepThunkTokenGroups64TO32Length(SecurityLimit64->RestrictedSids); @NL
  426. whNT32DeepThunkTokenGroups64TO32((NT32TOKEN_GROUPS*)CopyDest, SecurityLimit64->RestrictedSids); @NL
  427. SecurityLimit32->RestrictedSids = (NT32PTOKEN_GROUPS)CopyDest; @NL
  428. }) @NL
  429. else { @Indent( @NL
  430. SecurityLimit32->RestrictedSids = (NT32PTOKEN_GROUPS)SecurityLimit64->RestrictedSids; @NL
  431. }) @NL
  432. }) @NL
  433. )} @NL
  434. })@NL
  435. case JobObjectBasicProcessIdList:
  436. @Indent( @NL
  437. {
  438. PJOBOBJECT_BASIC_PROCESS_ID_LIST JobProcessIdList64 = (PJOBOBJECT_BASIC_PROCESS_ID_LIST)JobObjectInformation;
  439. struct NT32_JOBOBJECT_BASIC_PROCESS_ID_LIST *JobProcessIdList32 = (struct NT32_JOBOBJECT_BASIC_PROCESS_ID_LIST *)JobObjectInformation;
  440. ULONG JobObjectInformationLength64 = JobObjectInformationLength;
  441. ULONG ActualReturnLength64;
  442. ULONG i;
  443. if ((ARGUMENT_PRESENT (JobProcessIdList64) != 0) &&
  444. (JobObjectInformationLength64 >= sizeof (struct NT32_JOBOBJECT_BASIC_PROCESS_ID_LIST))) {
  445. ULONG ProcessIds = (((JobObjectInformationLength64 - sizeof (struct NT32_JOBOBJECT_BASIC_PROCESS_ID_LIST)) * sizeof (ULONG_PTR)) / sizeof(ULONG));
  446. JobObjectInformationLength64 = ProcessIds + sizeof (JOBOBJECT_BASIC_PROCESS_ID_LIST);
  447. JobProcessIdList64 = Wow64AllocateTemp (JobObjectInformationLength64);
  448. if (JobProcessIdList64 == NULL) {
  449. return STATUS_NO_MEMORY;
  450. }
  451. }
  452. RetVal = NtQueryInformationJobObject(
  453. JobHandle,
  454. JobObjectInformationClass,
  455. JobProcessIdList64,
  456. JobObjectInformationLength64,
  457. &ActualReturnLength64); @NL
  458. if (NT_SUCCESS (RetVal)) {
  459. JobProcessIdList32->NumberOfAssignedProcesses = JobProcessIdList64->NumberOfAssignedProcesses;
  460. JobProcessIdList32->NumberOfProcessIdsInList = JobProcessIdList64->NumberOfProcessIdsInList;
  461. JobProcessIdList32->ProcessIdList[0] = (ULONG)JobProcessIdList64->ProcessIdList[0];
  462. for (i = 1 ; i < JobProcessIdList64->NumberOfProcessIdsInList ; i++) {
  463. JobProcessIdList32->ProcessIdList[i] = (ULONG)JobProcessIdList64->ProcessIdList[i];
  464. }
  465. if (ARGUMENT_PRESENT(ReturnLength) != 0) {
  466. *ReturnLength = sizeof (struct NT32_JOBOBJECT_BASIC_PROCESS_ID_LIST) + ((JobProcessIdList32->NumberOfProcessIdsInList - 1) * sizeof(ULONG));
  467. }
  468. }
  469. }
  470. break;)@NL
  471. End=
  472. Begin=
  473. #define WriteReturnLength(rl, length) WriteReturnLengthStatus((rl), &RetVal, (length))
  474. @GenQueryThunk(@ApiName,JobObjectInformationClass,JobObjectInformation,JobObjectInformationLength,ReturnLength,ULONG)
  475. #undef WriteReturnLength
  476. End=
  477. ;; None of these structures are pointer dependent.
  478. ;; List taken from ntos\io\complete.c
  479. TemplateName=NtQueryIoCompletion
  480. Case=(IoCompletionBasicInformation,PIO_COMPLETION_BASIC_INFORMATION)
  481. Begin=
  482. @GenDebugNonPtrDepCases(@ApiName,IoCompletionInformationClass)
  483. End=
  484. TemplateName=NtCreateProcess
  485. Also=NtCreateProcessEx
  486. Begin=
  487. @GenApiThunk(@ApiName)
  488. End=
  489. PostCall=
  490. @NoFormat(
  491. if (!NT_ERROR(RetVal) && SectionHandle) {
  492. PEB Peb64;
  493. PEB32 Peb32;
  494. PPEB32 pPeb32;
  495. SIZE_T Size;
  496. HANDLE Process = *ProcessHandle;
  497. ULONG_PTR Wow64Info;
  498. PROCESS_BASIC_INFORMATION pbi;
  499. CHILD_PROCESS_INFO ChildInfo;
  500. // Check the image type to determine if the process is already 32-bit
  501. // or not.
  502. RetVal = NtQueryInformationProcess(Process,
  503. ProcessWow64Information,
  504. &Wow64Info,
  505. sizeof(Wow64Info),
  506. NULL);
  507. if (!NT_SUCCESS(RetVal) || Wow64Info != 0) {
  508. // Either error or the process's image is 32-bit and nothing
  509. // more needs to be done.
  510. goto Done;
  511. }
  512. RetVal = NtQueryInformationProcess(Process,
  513. ProcessBasicInformation,
  514. &pbi,
  515. sizeof(pbi),
  516. NULL);
  517. if (!NT_SUCCESS(RetVal)) {
  518. goto Done;
  519. }
  520. // Read in the process's PEB64
  521. RetVal = NtReadVirtualMemory(Process,
  522. pbi.PebBaseAddress,
  523. &Peb64,
  524. sizeof(Peb64),
  525. NULL);
  526. if (!NT_SUCCESS(RetVal)) {
  527. goto Error;
  528. }
  529. // Thunk the PEB64 to a PEB32
  530. ThunkPeb64ToPeb32(&Peb64, &Peb32);
  531. // Allocate space for a PEB32 in the low 2gb of the process
  532. pPeb32 = NULL;
  533. Size = PAGE_SIZE;
  534. RetVal = NtAllocateVirtualMemory(Process,
  535. &pPeb32,
  536. 0x7fffffff, // ZeroBits
  537. &Size,
  538. MEM_RESERVE|MEM_COMMIT,
  539. PAGE_EXECUTE_READWRITE);
  540. if (!NT_SUCCESS(RetVal)) {
  541. goto Error;
  542. }
  543. // Write the PEB32 into the process
  544. RetVal = NtWriteVirtualMemory(Process,
  545. pPeb32,
  546. &Peb32,
  547. sizeof(Peb32),
  548. NULL);
  549. if (!NT_SUCCESS(RetVal)) {
  550. goto Error;
  551. }
  552. //
  553. // Gather up some data that will be needed for the NtCreateThread
  554. // call which creates the initial thread.
  555. //
  556. ChildInfo.Signature = CHILD_PROCESS_SIGNATURE;
  557. ChildInfo.TailSignature = CHILD_PROCESS_SIGNATURE;
  558. ChildInfo.pPeb32 = pPeb32;
  559. RetVal = NtQuerySection(SectionHandle,
  560. SectionImageInformation,
  561. &ChildInfo.ImageInformation,
  562. sizeof(ChildInfo.ImageInformation),
  563. NULL);
  564. if (!NT_SUCCESS(RetVal)) {
  565. goto Error;
  566. }
  567. //
  568. // Stuff the information into the child process, immediately after
  569. // the PEB64 in memory
  570. //
  571. NtWriteVirtualMemory(Process,
  572. ((BYTE*)pbi.PebBaseAddress) + PAGE_SIZE - sizeof(ChildInfo),
  573. &ChildInfo,
  574. sizeof(ChildInfo),
  575. NULL);
  576. if (!NT_SUCCESS(RetVal)) {
  577. goto Error;
  578. }
  579. LOGPRINT((TRACELOG, "@ApiName: Peb32 at %p ChildInfo at %p\n",
  580. ChildInfo.pPeb32, ((BYTE*)pbi.PebBaseAddress) + PAGE_SIZE - sizeof(ChildInfo)));
  581. goto Done;
  582. Error:
  583. NtTerminateProcess(Process, RetVal);
  584. Done:;
  585. }
  586. )
  587. End=
  588. TemplateName=NtTerminateProcess
  589. PreCall=
  590. // Handle the special case of NtTerminateProcess() getting called@NL
  591. // to terminate all threads but the current one@NL
  592. if (!ProcessHandle) {@NL
  593. CpuProcessTerm(ProcessHandle);@NL
  594. }@NL
  595. // KERNEL32 call this function with NtCurrentProcess when exiting. @NL
  596. // This is as good as any place to put shutdown code. @NL
  597. if (NtCurrentProcess() == ProcessHandle) {@Indent(@NL
  598. Wow64Shutdown(ProcessHandle); @NL
  599. )}@NL
  600. End=
  601. ; The input and output types are aways the same with this function.
  602. TemplateName=NtPowerInformation
  603. Case=(SystemPowerPolicyAc,PSYSTEM_POWER_POLICY)
  604. Case=(SystemPowerPolicyDc,PSYSTEM_POWER_POLICY)
  605. Case=(AdministratorPowerPolicy,PADMINISTRATOR_POWER_POLICY)
  606. Case=(VerifySystemPolicyAc,PSYSTEM_POWER_POLICY)
  607. Case=(VerifySystemPolicyDc,PSYSTEM_POWER_POLICY)
  608. Case=(SystemPowerPolicyCurrent,PSYSTEM_POWER_POLICY)
  609. Case=(SystemPowerCapabilities,PSYSTEM_POWER_CAPABILITIES)
  610. Case=(SystemBatteryState,PSYSTEM_BATTERY_STATE)
  611. Case=(SystemPowerStateHandler,PVOID)
  612. Case=(ProcessorStateHandler,PVOID)
  613. Case=(SystemReserveHiberFile,PBOOLEAN)
  614. Case=(SystemPowerInformation,PSYSTEM_POWER_INFORMATION)
  615. Case=(ProcessorInformation,PPROCESSOR_POWER_INFORMATION)
  616. Begin=
  617. // ProcessorInformation is dependent on the number of processors, but no good method exists
  618. // to emulate this since it returns a record for each bit that is set in the active processor mask.
  619. // Since the 32bit mask returned to the app is bogus, this API is difficult to emulate.
  620. // Fortunately, the only code that uses these APIs are control panel applications and they are going
  621. // to be 64bit.
  622. @GenDebugNonPtrDepCases(@ApiName,InformationLevel)
  623. End=
  624. TemplateName=NtQueryInformationProcess
  625. Case=(ProcessBasicInformation)
  626. Case=(ProcessQuotaLimits,PQUOTA_LIMITS)
  627. Case=(ProcessIoCounters,PULONG)
  628. Case=(ProcessVmCounters)
  629. Case=(ProcessTimes,PKERNEL_USER_TIMES)
  630. Case=(ProcessBasePriority,KPRIORITY*)
  631. Case=(ProcessRaisePriority,PULONG)
  632. Case=(ProcessDebugPort,PHANDLE)
  633. Case=(ProcessExceptionPort,PHANDLE)
  634. Case=(ProcessAccessToken,PPROCESS_ACCESS_TOKEN)
  635. Case=(ProcessLdtInformation,PULONG) ; this is really PROCESS_LDT_INFORMATION but that isn't defined on Alpha
  636. Case=(ProcessLdtSize,PULONG) ; this is really PROCESS_LDT_SIZE but that isn't defined on alpha
  637. Case=(ProcessDefaultHardErrorMode,PULONG)
  638. Case=(ProcessPooledUsageAndLimits,PPOOLED_USAGE_AND_LIMITS)
  639. Case=(ProcessWorkingSetWatch)
  640. Case=(ProcessEnableAlignmentFaultFixup,BOOLEAN *)
  641. Case=(ProcessPriorityClass,PPROCESS_PRIORITY_CLASS)
  642. Case=(ProcessWx86Information,PHANDLE)
  643. Case=(ProcessHandleCount,PULONG)
  644. Case=(ProcessAffinityMask)
  645. Case=(ProcessPriorityBoost,PULONG)
  646. Case=(ProcessDeviceMap,PPROCESS_DEVICEMAP_INFORMATION)
  647. Case=(ProcessSessionInformation,PPROCESS_SESSION_INFORMATION)
  648. Case=(ProcessForegroundInformation,PPROCESS_FOREGROUND_BACKGROUND)
  649. Case=(ProcessWow64Information,PULONG_PTR)
  650. Case=(ProcessLUIDDeviceMapsEnabled,PULONG)
  651. Case=(ProcessDebugFlags)
  652. Case=(ProcessImageFileName)
  653. Case=(ProcessHandleTracing)
  654. SpecialQueryCase=
  655. @NoFormat(
  656. case ProcessBasicInformation:
  657. {
  658. PROCESS_BASIC_INFORMATION pbi;
  659. if (ProcessInformationLengthHost != sizeof(NT32PROCESS_BASIC_INFORMATION)) {
  660. RetVal = STATUS_INFO_LENGTH_MISMATCH;
  661. break;
  662. }
  663. RetVal = NtQueryInformationProcess(ProcessHandle,
  664. ProcessBasicInformation,
  665. &pbi,
  666. sizeof(pbi),
  667. (PULONG)ReturnLengthHost);
  668. if (!NT_ERROR(RetVal)) {
  669. NT32PROCESS_BASIC_INFORMATION *pbi32 = (NT32PROCESS_BASIC_INFORMATION*)ProcessInformationHost;
  670. NTSTATUS st;
  671. ULONG_PTR Wow64Info;
  672. // Copy back the "easy" fields
  673. pbi32->ExitStatus = pbi.ExitStatus;
  674. pbi32->AffinityMask = Wow64ThunkAffinityMask64TO32(pbi.AffinityMask);
  675. pbi32->UniqueProcessId = (NT32ULONG_PTR)pbi.UniqueProcessId;
  676. pbi32->InheritedFromUniqueProcessId = (NT32ULONG_PTR)pbi.InheritedFromUniqueProcessId;
  677. // PebBaseAddress is special. If the process is 32-bit then
  678. // return the PEB32 pointer. If the process is 64-bit but has no
  679. // threads, create a PEB32 and return a pointer to it. Lastly,
  680. // if the process is 64-bit and has threads, return a bad pointer
  681. // so 32-bit apps don't get all confused. Most nicely check the
  682. // return value from NtReadVirtualMemory() and gracefully fail if
  683. // the read fails.
  684. st = NtQueryInformationProcess(ProcessHandle,
  685. ProcessWow64Information,
  686. &Wow64Info,
  687. sizeof(Wow64Info),
  688. NULL);
  689. if (NT_ERROR(st)) {
  690. //
  691. // Query failed for some reason. Return a bad pointer but don't
  692. // fail the API call.
  693. //
  694. LOGPRINT((TRACELOG, "whNtQueryInformationProcess: ProcessWow64Information failed status %X, return 0 for PEB\n", st));
  695. pbi32->PebBaseAddress = 0;
  696. break;
  697. } else if (Wow64Info) {
  698. //
  699. // Process is 32-bit. The PEB32 pointer is Wow64Info
  700. //
  701. LOGPRINT((TRACELOG, "whNtQueryInformationProcess: Process is 32bit returning %x as PEB32\n", (ULONG)Wow64Info));
  702. pbi32->PebBaseAddress = (ULONG)Wow64Info;
  703. } else {
  704. //
  705. // Process is 64-bit. If the process has no threads, then
  706. // we're in the middle of a 32-bit CreateProcess() and it's OK to
  707. // temporarily create a PEB32 in the process.
  708. //
  709. CHILD_PROCESS_INFO ChildInfo;
  710. PEB32 ChildPeb32;
  711. SIZE_T BytesRead;
  712. //
  713. // Assume failure, that we don't want to report back a PEB32 address
  714. //
  715. pbi32->PebBaseAddress = 0;
  716. // Read in the process's PEB64
  717. st = NtReadVirtualMemory(ProcessHandle,
  718. ((BYTE*)pbi.PebBaseAddress) + PAGE_SIZE - sizeof(ChildInfo),
  719. &ChildInfo,
  720. sizeof(ChildInfo),
  721. NULL);
  722. if (!NT_SUCCESS(st)) {
  723. LOGPRINT((TRACELOG, "whNtQueryInformationProcess: could not read the child info, status %X.\n", st));
  724. st = STATUS_SUCCESS;
  725. break;
  726. }
  727. //
  728. // Verify the signatures at the head and tail of the ChildInfo
  729. // structure are correct. The memory the ChildInfo struct is
  730. // stored in is "borrowed". It may be reused by the process to
  731. // store process handles. We validate that the structure appears
  732. // to atleast look correct before dereferencing it.
  733. //
  734. if ((ChildInfo.Signature != CHILD_PROCESS_SIGNATURE) ||
  735. (ChildInfo.TailSignature != CHILD_PROCESS_SIGNATURE)) {
  736. LOGPRINT((TRACELOG, "whNtQueryInformationProcess: ChildInfo signatures don't match\n"));
  737. st = STATUS_SUCCESS;
  738. break;
  739. }
  740. //
  741. // Now try and read the PEB32, again this is to verify the
  742. // PEB32 pointer looks good.
  743. //
  744. st = NtReadVirtualMemory(
  745. ProcessHandle,
  746. ChildInfo.pPeb32,
  747. &ChildPeb32,
  748. sizeof(ChildPeb32),
  749. &BytesRead);
  750. if (!NT_SUCCESS(st))
  751. {
  752. LOGPRINT((TRACELOG, "whNtQueryInformationProcess: Couldn't validate 32bit PEB\n"));
  753. LOGPRINT((TRACELOG, "whNtQueryInformationProcess: Returned %p bytes of %p requested\n",
  754. BytesRead, sizeof(ChildPeb32)));
  755. st = STATUS_SUCCESS;
  756. break;
  757. }
  758. // Tell the caller where the PEB32 is
  759. LOGPRINT((TRACELOG, "whNtQueryInformationProcess: process is 64bit and has a fake 32bit peb at %p.\n", ChildInfo.pPeb32));
  760. pbi32->PebBaseAddress = (NT32PPEB)ChildInfo.pPeb32;
  761. }
  762. }
  763. break;
  764. }
  765. case ProcessHandleTracing: @NL
  766. {
  767. PPROCESS_HANDLE_TRACING_QUERY Pht64;
  768. NT32PROCESS_HANDLE_TRACING_QUERY *Pht32 = (NT32PROCESS_HANDLE_TRACING_QUERY *)ProcessInformation;
  769. ULONG StacksLeft;
  770. NT32PROCESS_HANDLE_TRACING_ENTRY *NextTrace32;
  771. PPROCESS_HANDLE_TRACING_ENTRY NextTrace64;
  772. ULONG Length64;
  773. ULONG ReturnLength64;
  774. ULONG Count;
  775. if (ProcessInformationLength < FIELD_OFFSET (NT32PROCESS_HANDLE_TRACING_QUERY, HandleTrace)) {
  776. return STATUS_INFO_LENGTH_MISMATCH;
  777. }
  778. StacksLeft = ((ProcessInformationLength - FIELD_OFFSET (NT32PROCESS_HANDLE_TRACING_QUERY, HandleTrace)) / sizeof (Pht32->HandleTrace[0]));
  779. //
  780. // Allocate as much as we need here
  781. //
  782. try {
  783. Length64 = (StacksLeft * sizeof (Pht64->HandleTrace[0])) + (FIELD_OFFSET (PROCESS_HANDLE_TRACING_QUERY, HandleTrace));
  784. Pht64 = Wow64AllocateTemp (Length64);
  785. Pht64->Handle = (HANDLE) LongToPtr (Pht32->Handle);
  786. RetVal = NtQueryInformationProcess (ProcessHandle,
  787. ProcessInformationClass,
  788. Pht64,
  789. Length64,
  790. &ReturnLength64);
  791. //
  792. // If all is well
  793. //
  794. if (NT_SUCCESS (RetVal)) {
  795. Pht32->TotalTraces = Pht64->TotalTraces;
  796. NextTrace32 = (NT32PROCESS_HANDLE_TRACING_ENTRY *)&Pht32->HandleTrace[0];
  797. NextTrace64 = &Pht64->HandleTrace[0];
  798. for (Count = 0 ; Count < Pht64->TotalTraces ; Count++) {
  799. NextTrace32->Handle = PtrToLong (NextTrace64->Handle);
  800. @ForceType(PostCall,((PCLIENT_ID)&NextTrace64->ClientId),((NT32CLIENT_ID *)&NextTrace32->ClientId),PCLIENT_ID,OUT) @NL
  801. NextTrace32->Type = NextTrace64->Type;
  802. for (StacksLeft = 0 ; StacksLeft < (sizeof (NextTrace64->Stacks) / sizeof (NextTrace64->Stacks[0])) ; StacksLeft++) {
  803. NextTrace32->Stacks[StacksLeft] = PtrToUlong (NextTrace64->Stacks[StacksLeft]);
  804. }
  805. NextTrace32++;
  806. NextTrace64++;
  807. }
  808. //
  809. // Update the return length
  810. //
  811. if (ARGUMENT_PRESENT (ReturnLengthHost)) {
  812. *ReturnLength = ((PCHAR)NextTrace32 - (PCHAR)Pht32);
  813. }
  814. } else {
  815. //
  816. // We may have returned the actual length
  817. //
  818. Pht32->TotalTraces = Pht64->TotalTraces;
  819. if (ARGUMENT_PRESENT (ReturnLengthHost)) {
  820. *ReturnLength = ((Pht64->TotalTraces * sizeof (Pht32->HandleTrace[0])) + FIELD_OFFSET (NT32PROCESS_HANDLE_TRACING_QUERY, HandleTrace));
  821. }
  822. }
  823. } except (EXCEPTION_EXECUTE_HANDLER) {
  824. RetVal = GetExceptionCode ();
  825. }
  826. break;
  827. }
  828. case ProcessWorkingSetWatch: @NL
  829. @Indent(
  830. WOWASSERT(TRUE); @NL
  831. return STATUS_NOT_IMPLEMENTED; @NL
  832. ) @NL
  833. case ProcessAffinityMask: @NL
  834. {
  835. ULONG_PTR Affinity64;
  836. if (ProcessInformationLength != sizeof(ULONG)) {
  837. RetVal = STATUS_INFO_LENGTH_MISMATCH;
  838. break;
  839. }
  840. RetVal = NtQueryInformationProcess(ProcessHandle,
  841. ProcessAffinityMask,
  842. &Affinity64,
  843. sizeof(Affinity64),
  844. NULL);
  845. *(PULONG)ProcessInformation = Wow64ThunkAffinityMask64TO32(Affinity64);
  846. }
  847. case ProcessImageFileName:
  848. {
  849. ULONG ReturnLengthLocal;
  850. PUNICODE_STRING32 ProcessInformation32 = (PUNICODE_STRING32)ProcessInformation;
  851. PUNICODE_STRING ProcessInformation64 = (PUNICODE_STRING)ProcessInformation32;
  852. if (ProcessInformationLength > 0) {
  853. ProcessInformationLength += (sizeof (UNICODE_STRING) - sizeof (UNICODE_STRING32));
  854. ProcessInformation64 = Wow64AllocateTemp (ProcessInformationLength);
  855. }
  856. RetVal = NtQueryInformationProcess(ProcessHandle,
  857. ProcessInformationClass,
  858. ProcessInformation64,
  859. ProcessInformationLength,
  860. ReturnLength
  861. );
  862. if (NT_SUCCESS (RetVal)) {
  863. if (ProcessInformation32 != NULL) {
  864. @ForceType(PostCall,ProcessInformation64,ProcessInformation32,PUNICODE_STRING,OUT) @NL
  865. try {
  866. RtlCopyMemory (ProcessInformation32+1,
  867. ProcessInformation64+1,
  868. ProcessInformation64->MaximumLength);
  869. ProcessInformation32->Buffer = (PWCHAR)(ProcessInformation32+1);
  870. } except (EXCEPTION_EXECUTE_HANDLER) {
  871. RetVal = GetExceptionCode ();
  872. }
  873. }
  874. }
  875. }
  876. break;
  877. case ProcessDebugFlags:
  878. {
  879. PVOID Peb32;
  880. RetVal = NtQueryInformationProcess(ProcessHandle,
  881. ProcessWow64Information,
  882. &Peb32, sizeof(Peb32),
  883. NULL);
  884. if (NT_SUCCESS(RetVal) && Peb32) {
  885. RetVal = NtQueryInformationProcess(ProcessHandle,
  886. ProcessInformationClass,
  887. ProcessInformation,
  888. ProcessInformationLength,
  889. ReturnLength);
  890. }
  891. else {
  892. RetVal = STATUS_INVALID_INFO_CLASS;
  893. }
  894. break;
  895. }
  896. case ProcessVmCounters: @NL @Indent(
  897. {
  898. VM_COUNTERS_EX VmCountersEx64;
  899. if (ProcessInformationLength == sizeof (NT32VM_COUNTERS)) {
  900. ProcessInformationLength = sizeof (VM_COUNTERS);
  901. RetVal = STATUS_SUCCESS;
  902. } else if (ProcessInformationLength == sizeof (NT32VM_COUNTERS_EX)) {
  903. ProcessInformationLength = sizeof (VM_COUNTERS_EX);
  904. RetVal = STATUS_SUCCESS;
  905. } else {
  906. RetVal = STATUS_INFO_LENGTH_MISMATCH;
  907. }
  908. if (NT_SUCCESS (RetVal)) {
  909. RetVal = NtQueryInformationProcess (ProcessHandle,
  910. ProcessInformationClass,
  911. &VmCountersEx64,
  912. ProcessInformationLength,
  913. ReturnLength
  914. );
  915. if (NT_SUCCESS (RetVal)) {
  916. //
  917. // Thunk the return length
  918. //
  919. if (ARGUMENT_PRESENT(ReturnLengthHost)) {
  920. if (*ReturnLength == sizeof (VM_COUNTERS_EX)) {
  921. *ReturnLength = sizeof (NT32VM_COUNTERS_EX);
  922. } else if (*ReturnLength == sizeof (VM_COUNTERS)) {
  923. *ReturnLength = sizeof (NT32VM_COUNTERS);
  924. } else {
  925. //
  926. // Invalid case
  927. //
  928. WOWASSERT (FALSE);
  929. }
  930. }
  931. if (ProcessInformationLength == sizeof (VM_COUNTERS_EX)) {
  932. @ForceType(PostCall,((PVM_COUNTERS_EX)(&VmCountersEx64)),(NT32VM_COUNTERS_EX *)ProcessInformation,PVM_COUNTERS_EX,OUT) @NL
  933. } else if (ProcessInformationLength == sizeof (VM_COUNTERS)) {
  934. @ForceType(PostCall,((PVM_COUNTERS_EX)(&VmCountersEx64)),(NT32VM_COUNTERS *)ProcessInformation,PVM_COUNTERS,OUT) @NL
  935. } else {
  936. //
  937. // Invalid case
  938. //
  939. WOWASSERT (FALSE);
  940. }
  941. }
  942. }
  943. break;
  944. }
  945. )
  946. End=
  947. Begin=
  948. #define WriteReturnLength(rl, length) WriteReturnLengthStatus((rl), &RetVal, (length))
  949. @GenQueryThunk(@ApiName,ProcessInformationClass,ProcessInformation,ProcessInformationLength,ReturnLength,ULONG)
  950. #undef WriteReturnLength
  951. End=
  952. TemplateName=NtQueryInformationThread
  953. Case=(ThreadTimes,PKERNEL_USER_TIMES)
  954. Case=(ThreadQuerySetWin32StartAddress,PULONG)
  955. Case=(ThreadPerformanceCount,PLARGE_INTEGER)
  956. Case=(ThreadAmILastThread,PULONG)
  957. Case=(ThreadPriorityBoost,PULONG)
  958. Case=(ThreadIsIoPending,PULONG)
  959. Case=(ThreadDescriptorTableEntry)
  960. Case=(ThreadBasicInformation)
  961. SpecialQueryCase=
  962. case ThreadDescriptorTableEntry: @NL
  963. @Indent(
  964. return Wow64GetThreadSelectorEntry(ThreadHandle,
  965. ThreadInformation,
  966. ThreadInformationLength,
  967. ReturnLength); @NL
  968. break; @NL
  969. )@NL
  970. case ThreadBasicInformation: @Indent( @NL
  971. return @CallApi(whNtQueryInformationThreadBasicInformation,RetVal)
  972. break; @NL
  973. )@NL
  974. End=
  975. Header=
  976. NTSTATUS @NL
  977. whNtQueryInformationThreadBasicInformation(IN HANDLE ThreadHandle,
  978. IN THREADINFOCLASS ThreadInformationClass,
  979. OUT PVOID ThreadInformationHost,
  980. IN ULONG ThreadInformationLength,
  981. OUT PULONG ReturnLength OPTIONAL
  982. ) @NL
  983. { @Indent( @NL
  984. NTSTATUS Status; @NL
  985. PTHREAD_BASIC_INFORMATION ThreadInformation; @NL
  986. @Types(Locals,ThreadInformation,PTHREAD_BASIC_INFORMATION)
  987. if (ThreadInformationHost == NULL) { @Indent( @NL
  988. WriteReturnLength(ReturnLength, sizeof(NT32THREAD_BASIC_INFORMATION)); @NL
  989. return STATUS_INVALID_PARAMETER; @NL
  990. }) @NL
  991. if (ThreadInformationLength != sizeof(NT32THREAD_BASIC_INFORMATION)) { @Indent( @NL
  992. WriteReturnLength(ReturnLength, sizeof(NT32THREAD_BASIC_INFORMATION)); @NL
  993. return STATUS_INFO_LENGTH_MISMATCH; @NL
  994. }) @NL
  995. @Types(PreCall,ThreadInformation,PTHREAD_BASIC_INFORMATION)
  996. Status = Wow64QueryBasicInformationThread(ThreadHandle,(PTHREAD_BASIC_INFORMATION)ThreadInformation); @NL
  997. @Types(PostCall,ThreadInformation,PTHREAD_BASIC_INFORMATION)
  998. if (ReturnLength) { @Indent( @NL
  999. WriteReturnLength(ReturnLength, sizeof(NT32THREAD_BASIC_INFORMATION)); @NL
  1000. }) @NL
  1001. return Status; @NL
  1002. }) @NL
  1003. End=
  1004. Begin=
  1005. #define WriteReturnLength(rl, length) WriteReturnLengthSilent((rl), (length))
  1006. @GenQueryThunk(NtQueryInformationThread,ThreadInformationClass,ThreadInformation,ThreadInformationLength,ReturnLength,ULONG)
  1007. #undef WriteReturnLength
  1008. End=
  1009. TemplateName=NtQueryInformationToken
  1010. Case=(TokenUser,PTOKEN_USER)
  1011. Case=(TokenGroups,PTOKEN_GROUPS)
  1012. Case=(TokenPrivileges,PTOKEN_PRIVILEGES)
  1013. Case=(TokenOwner,PTOKEN_OWNER)
  1014. Case=(TokenPrimaryGroup,PTOKEN_PRIMARY_GROUP)
  1015. Case=(TokenDefaultDacl,PTOKEN_DEFAULT_DACL)
  1016. Case=(TokenSource,PTOKEN_SOURCE)
  1017. Case=(TokenType,PTOKEN_TYPE)
  1018. Case=(TokenImpersonationLevel,PSECURITY_IMPERSONATION_LEVEL)
  1019. Case=(TokenStatistics,PTOKEN_STATISTICS)
  1020. Case=(TokenRestrictedSids,PTOKEN_GROUPS)
  1021. Case=(TokenSessionId,PULONG)
  1022. Case=(TokenSandBoxInert,PULONG)
  1023. Case=(TokenGroupsAndPrivileges)
  1024. SpecialQueryCase=
  1025. @Indent( @NL
  1026. case TokenGroupsAndPrivileges:
  1027. {
  1028. PTOKEN_GROUPS_AND_PRIVILEGES TokenInformation64;
  1029. struct NT32_TOKEN_GROUPS_AND_PRIVILEGES *TokenInformation32 = (struct NT32_TOKEN_GROUPS_AND_PRIVILEGES *)TokenInformation;
  1030. struct NT32_SID_AND_ATTRIBUTES *Sids;
  1031. PCHAR Sid, Start;
  1032. NTSTATUS NtStatus;
  1033. INT AllocSize = 0, SidLength;
  1034. ULONG i, RetInfoLen;
  1035. ULONG ReturnLength64;
  1036. AllocSize += LENGTH + sizeof(struct _TOKEN_GROUPS_AND_PRIVILEGES) - sizeof(struct NT32_TOKEN_GROUPS_AND_PRIVILEGES);
  1037. TokenInformation64 = Wow64AllocateTemp(AllocSize);
  1038. if (TokenInformation64 == NULL) {
  1039. RtlRaiseStatus (STATUS_NO_MEMORY);
  1040. }
  1041. NtStatus = NtQueryInformationToken (TokenHandle,
  1042. TokenInformationClass,
  1043. TokenInformation64,
  1044. AllocSize,
  1045. &ReturnLength64);
  1046. if (NT_ERROR (NtStatus)) {
  1047. WriteReturnLength (ReturnLength, ReturnLength64);
  1048. return NtStatus;
  1049. }
  1050. if (WOW64_ISPTR (TokenInformation32)) {
  1051. if (ReturnLength64 > TokenInformationLength) {
  1052. return STATUS_INFO_LENGTH_MISMATCH;
  1053. }
  1054. TokenInformation32->SidCount = TokenInformation64->SidCount;
  1055. TokenInformation32->Sids = (struct NT32SID_AND_ATTRIBUTES *)((PCHAR)(TokenInformation32) + sizeof(struct NT32_TOKEN_GROUPS_AND_PRIVILEGES));
  1056. Sids = TokenInformation32->Sids;
  1057. Sid = (PCHAR) (Sids + (TokenInformation32->SidCount));
  1058. Start = (PCHAR)Sids;
  1059. for (i=0 ; i<TokenInformation64->SidCount ; i++) {
  1060. Sids[i].Sid = Sid;
  1061. Sids[i].Attributes = TokenInformation64->Sids[i].Attributes;
  1062. SidLength = RtlLengthSid(TokenInformation64->Sids[i].Sid);
  1063. RtlCopyMemory(Sid, TokenInformation64->Sids[i].Sid, SidLength);
  1064. Sid += SidLength;
  1065. }
  1066. TokenInformation32->SidLength = ((PCHAR)Sid - (PCHAR)Sids);
  1067. if (TokenInformation32->SidLength == 0) {
  1068. TokenInformation32->Sids = 0;
  1069. }
  1070. TokenInformation32->RestrictedSidCount = TokenInformation64->RestrictedSidCount;
  1071. TokenInformation32->RestrictedSids = (struct NT32_SID_AND_ATTRIBUTES *)Sid;
  1072. Sids = (struct NT32_SID_AND_ATTRIBUTES *)Sid;
  1073. Start = (PCHAR)Sids;
  1074. Sid = (PCHAR) (Sids + (TokenInformation32->RestrictedSidCount));
  1075. for (i=0 ; i<TokenInformation64->RestrictedSidCount ; i++) {
  1076. Sids[i].Sid = Sid;
  1077. Sids[i].Attributes = TokenInformation64->RestrictedSids[i].Attributes;
  1078. SidLength = RtlLengthSid(TokenInformation64->RestrictedSids[i].Sid);
  1079. RtlCopyMemory(Sid, TokenInformation64->RestrictedSids[i].Sid, SidLength);
  1080. Sid += SidLength;
  1081. }
  1082. TokenInformation32->RestrictedSidLength = ((PCHAR)Sid - Start);
  1083. if (TokenInformation32->RestrictedSidLength == 0) {
  1084. TokenInformation32->RestrictedSids = 0;
  1085. }
  1086. TokenInformation32->PrivilegeCount = TokenInformation64->PrivilegeCount;
  1087. TokenInformation32->PrivilegeLength = TokenInformation64->PrivilegeLength;
  1088. if (TokenInformation32->PrivilegeCount > 0) {
  1089. TokenInformation32->Privileges = (struct NT32LUID_AND_ATTRIBUTES *)Sid;
  1090. RtlCopyMemory (Sid, TokenInformation64->Privileges, TokenInformation32->PrivilegeCount * sizeof(NT32LUID_AND_ATTRIBUTES));
  1091. Sid += TokenInformation32->PrivilegeCount;
  1092. }
  1093. else
  1094. {
  1095. TokenInformation32->Privileges = 0;
  1096. }
  1097. RtlCopyMemory (&TokenInformation32->AuthenticationId,
  1098. &TokenInformation64->AuthenticationId,
  1099. sizeof (TokenInformation64->AuthenticationId));
  1100. RetInfoLen = (Sid - (PCHAR)TokenInformation32);
  1101. } else {
  1102. RetInfoLen = ReturnLength64;
  1103. }
  1104. //
  1105. // update the return length
  1106. //
  1107. WriteReturnLength (ReturnLength, RetInfoLen);
  1108. RetVal = NtStatus;
  1109. }
  1110. break;
  1111. ) @NL
  1112. Begin=
  1113. #define WriteReturnLength(rl, length) WriteReturnLengthStatus((rl), &RetVal, (length))
  1114. @GenQueryThunk(@ApiName,TokenInformationClass,TokenInformation,TokenInformationLength,ReturnLength,ULONG)
  1115. #undef WriteReturnLength
  1116. End=
  1117. TemplateName=NtQueryMutant
  1118. Case=(MutantBasicInformation,PMUTANT_BASIC_INFORMATION)
  1119. Begin=
  1120. @GenDebugNonPtrDepCases(@ApiName,MutantInformationClass)
  1121. End=
  1122. TemplateName=NtQueryObject
  1123. Case=(ObjectBasicInformation,POBJECT_BASIC_INFORMATION)
  1124. Case=(ObjectNameInformation)
  1125. Case=(ObjectTypeInformation)
  1126. Case=(ObjectTypesInformation)
  1127. Case=(ObjectHandleFlagInformation,POBJECT_HANDLE_FLAG_INFORMATION)
  1128. SpecialQueryCase=
  1129. @NoFormat(
  1130. case ObjectNameInformation: @NL
  1131. @Indent({
  1132. SIZE_T AllocSize = 0;
  1133. POBJECT_NAME_INFORMATION NameInformation;
  1134. struct NT32_OBJECT_NAME_INFORMATION *Name32 = (struct NT32_OBJECT_NAME_INFORMATION *)ObjectInformation;
  1135. AllocSize += LENGTH + sizeof(OBJECT_NAME_INFORMATION) - sizeof(struct NT32_OBJECT_NAME_INFORMATION);
  1136. NameInformation = Wow64AllocateTemp(AllocSize);
  1137. RetVal=NtQueryObject(Handle,
  1138. ObjectNameInformation,
  1139. NameInformation,
  1140. AllocSize,
  1141. ReturnLength
  1142. );
  1143. if (!NT_ERROR(RetVal)) {
  1144. // Thunk the Name (a UNICODE_STRING) by hand... the Buffer
  1145. // pointer actually points to the first byte past the end of
  1146. // the OBJECT_TYPE_INFORMATION struct.
  1147. try {
  1148. Name32->Name.Length = NameInformation->Name.Length;
  1149. Name32->Name.MaximumLength = NameInformation->Name.MaximumLength;
  1150. Name32->Name.Buffer = PtrToUlong(Name32+1);
  1151. RtlCopyMemory((PVOID)Name32->Name.Buffer, NameInformation->Name.Buffer, NameInformation->Name.Length);
  1152. ((PWSTR)Name32->Name.Buffer)[ (NameInformation->Name.Length/sizeof(WCHAR)) ] = UNICODE_NULL;
  1153. WriteReturnLength(ReturnLength, sizeof(struct NT32_OBJECT_NAME_INFORMATION) + Name32->Name.MaximumLength);
  1154. } except (EXCEPTION_EXECUTE_HANDLER) {
  1155. RetVal = GetExceptionCode ();
  1156. }
  1157. }
  1158. }
  1159. break;)
  1160. case ObjectTypeInformation: @NL
  1161. @Indent({
  1162. SIZE_T AllocSize = 0;
  1163. POBJECT_TYPE_INFORMATION TypeInformation;
  1164. struct NT32_OBJECT_TYPE_INFORMATION *Type32 = (struct NT32_OBJECT_TYPE_INFORMATION *)ObjectInformation;
  1165. AllocSize += LENGTH + sizeof(OBJECT_TYPE_INFORMATION) - sizeof(struct NT32_OBJECT_TYPE_INFORMATION);
  1166. TypeInformation = Wow64AllocateTemp(AllocSize);
  1167. LENGTH = (NT32SIZE_T)AllocSize;
  1168. RetVal=NtQueryObject(Handle,
  1169. ObjectTypeInformation,
  1170. TypeInformation,
  1171. Length,
  1172. ReturnLength
  1173. );
  1174. if (!NT_ERROR(RetVal)) {
  1175. // Thunk the TypeName (a UNICODE_STRING) by hand... the Buffer
  1176. // pointer actually points to the first byte past the end of
  1177. // the OBJECT_TYPE_INFORMATION struct.
  1178. try {
  1179. Type32->TypeName.Length = TypeInformation->TypeName.Length;
  1180. Type32->TypeName.MaximumLength = TypeInformation->TypeName.MaximumLength;
  1181. Type32->TypeName.Buffer = PtrToUlong(Type32+1);
  1182. RtlCopyMemory((PVOID)Type32->TypeName.Buffer, TypeInformation->TypeName.Buffer, TypeInformation->TypeName.Length);
  1183. // NULL out the UNICODE string
  1184. ((PWSTR)(Type32->TypeName.Buffer))[ Type32->TypeName.Length/sizeof(WCHAR) ] = UNICODE_NULL;
  1185. // Thunk the other fields in the OBJECT_TYPE_INFORMATION by a simple
  1186. // copy
  1187. RtlCopyMemory(&Type32->TotalNumberOfObjects,
  1188. &TypeInformation->TotalNumberOfObjects,
  1189. sizeof(NT32OBJECT_TYPE_INFORMATION)-FIELD_OFFSET(struct NT32_OBJECT_TYPE_INFORMATION, TotalNumberOfObjects));
  1190. WriteReturnLength(ReturnLength, sizeof(struct NT32_OBJECT_TYPE_INFORMATION) + Type32->TypeName.MaximumLength);
  1191. } except (EXCEPTION_EXECUTE_HANDLER) {
  1192. RetVal = GetExceptionCode ();
  1193. }
  1194. }
  1195. }
  1196. break;)
  1197. case ObjectTypesInformation: @NL
  1198. @Indent({
  1199. SIZE_T AllocSize = 0;
  1200. SIZE_T OldLength = 0;
  1201. PULONG TypesInformation;
  1202. ULONG n;
  1203. // figure out how many OBJECT_TYPE_INFORMATIONs the caller had space for, and
  1204. // grow the 64-bit temp size to handle 'n' 64-bit OBJECT_TYPE_INFORMATIONs.
  1205. n = (LENGTH-sizeof(ULONG)) / sizeof(struct NT32_OBJECT_TYPE_INFORMATION);
  1206. AllocSize += LENGTH + n*(sizeof(OBJECT_TYPE_INFORMATION) - sizeof(struct NT32_OBJECT_TYPE_INFORMATION));
  1207. TypesInformation = Wow64AllocateTemp(AllocSize);
  1208. OldLength = LENGTH;
  1209. LENGTH = (NT32SIZE_T)AllocSize;
  1210. RetVal=NtQueryObject(Handle,
  1211. ObjectTypesInformation,
  1212. TypesInformation,
  1213. Length,
  1214. ReturnLength
  1215. );
  1216. // Note: if this fails with STATUS_INFO_LENGTH_MISMATCH, it will return
  1217. // back the 64-bit ReturnLength value. That should be OK for a 32-bit
  1218. // app to use if it needs to allocate a bigger buffer for a second call.
  1219. if (!NT_ERROR(RetVal)) {
  1220. POBJECT_TYPE_INFORMATION Type64;
  1221. struct NT32_OBJECT_TYPE_INFORMATION *Type32;
  1222. try {
  1223. // Copy over the count of objects
  1224. *(PULONG)ObjectInformation = *TypesInformation;
  1225. Type64 = (POBJECT_TYPE_INFORMATION) (ALIGN_UP(((ULONG)(TypesInformation+1)), PVOID));
  1226. Type32 = (struct NT32_OBJECT_TYPE_INFORMATION*)( ((PULONG)ObjectInformation)+1 );
  1227. for (n = 0; n<*TypesInformation; n++) {
  1228. // Thunk the TypeName (a UNICODE_STRING) by hand... the Buffer
  1229. // pointer actually points to the first byte past the end of
  1230. // the OBJECT_TYPE_INFORMATION struct.
  1231. Type32->TypeName.Length = Type64->TypeName.Length;
  1232. Type32->TypeName.MaximumLength = Type64->TypeName.MaximumLength;
  1233. Type32->TypeName.Buffer = PtrToUlong((Type32+1));
  1234. RtlCopyMemory((PVOID)Type32->TypeName.Buffer, Type64->TypeName.Buffer, Type64->TypeName.Length);
  1235. ((PWSTR)(Type32->TypeName.Buffer))[ Type64->TypeName.Length/sizeof(WCHAR) ] = UNICODE_NULL;
  1236. // Thunk the other fields in the OBJECT_TYPE_INFORMATION by a simple
  1237. // copy
  1238. RtlCopyMemory(&Type32->TotalNumberOfObjects,
  1239. &Type64->TotalNumberOfObjects,
  1240. sizeof(struct NT32_OBJECT_TYPE_INFORMATION)-FIELD_OFFSET(struct NT32_OBJECT_TYPE_INFORMATION, TotalNumberOfObjects));
  1241. // Move the pointers forward
  1242. Type64 = (POBJECT_TYPE_INFORMATION)(
  1243. (PCHAR)(Type64+1) + ALIGN_UP(Type64->TypeName.MaximumLength, PVOID));
  1244. Type32 = (struct NT32_OBJECT_TYPE_INFORMATION *)(
  1245. (PCHAR)(Type32+1) + ALIGN_UP(Type32->TypeName.MaximumLength, ULONG));
  1246. }
  1247. WriteReturnLength(ReturnLength, (ULONG)( (PBYTE)Type32 - (PBYTE)ObjectInformation ));
  1248. } except (EXCEPTION_EXECUTE_HANDLER) {
  1249. RetVal = GetExceptionCode ();
  1250. }
  1251. }
  1252. }
  1253. break;)
  1254. )
  1255. Begin=
  1256. #define WriteReturnLength(rl, length) WriteReturnLengthSilent((rl), (length))
  1257. @GenQueryThunk(@ApiName,ObjectInformationClass,ObjectInformation,Length,ReturnLength,ULONG)
  1258. #undef WriteReturnLength
  1259. End=
  1260. TemplateName=NtQuerySection
  1261. Case=(SectionBasicInformation,PSECTION_BASIC_INFORMATION)
  1262. Case=(SectionImageInformation,PSECTION_IMAGE_INFORMATION)
  1263. Header=
  1264. End=
  1265. Begin=
  1266. #define WriteReturnLength(rl, length) WriteReturnLengthSilent((PULONG)(rl), (ULONG)(length))
  1267. @GenQueryThunk(@ApiName,SectionInformationClass,SectionInformation,SectionInformationLength,ReturnLength,SIZE_T)
  1268. #undef WriteReturnLength
  1269. End=
  1270. PostCall=
  1271. @NoFormat(
  1272. if (!NT_ERROR(RetVal) && SectionInformationClass == SectionImageInformation) {
  1273. struct NT32_SECTION_IMAGE_INFORMATION *pSecInfo32 = (struct NT32_SECTION_IMAGE_INFORMATION *)SectionInformation;
  1274. #if defined(_AMD64_)
  1275. if (pSecInfo32->Machine == IMAGE_FILE_MACHINE_AMD64)
  1276. #elif defined(_IA64_)
  1277. if (pSecInfo32->Machine == IMAGE_FILE_MACHINE_IA64)
  1278. #else
  1279. #error "No Target Architecture"
  1280. #endif
  1281. {
  1282. // Image section is 64-bit. Lie about a number of the fields
  1283. // so RtlCreateUserProcess and CreateProcessW are happy.
  1284. pSecInfo32->TransferAddress = 0x81231234; // bogus nonzero value
  1285. pSecInfo32->MaximumStackSize = 1024*1024; // max stack size = 1meg
  1286. pSecInfo32->CommittedStackSize = 64*1024; // 64k commit
  1287. }
  1288. }
  1289. )
  1290. End=
  1291. TemplateName=NtQuerySecurityObject
  1292. NoType=SecurityDescriptor
  1293. Header=
  1294. @NoFormat(
  1295. NTSTATUS
  1296. whNT32QuerySecurityObject(
  1297. IN HANDLE Handle,
  1298. IN SECURITY_INFORMATION SecurityInformation,
  1299. OUT PVOID SecurityDescriptor,
  1300. IN ULONG Length,
  1301. OUT PULONG LengthNeeded
  1302. )
  1303. {
  1304. NTSTATUS Status;
  1305. SECURITY_DESCRIPTOR *Descriptor64;
  1306. NT32SECURITY_DESCRIPTOR *Descriptor32;
  1307. Status = NtQuerySecurityObject(Handle,
  1308. SecurityInformation,
  1309. (PSECURITY_DESCRIPTOR)SecurityDescriptor,
  1310. Length,
  1311. LengthNeeded
  1312. );
  1313. if (NT_ERROR(Status) || !SecurityDescriptor) {
  1314. return Status;
  1315. }
  1316. Descriptor64 = (SECURITY_DESCRIPTOR *)SecurityDescriptor;
  1317. try {
  1318. if (Descriptor64->Control & SE_SELF_RELATIVE) {
  1319. //Descriptor is self-relative, no thunking needed.
  1320. return Status;
  1321. }
  1322. Descriptor32 = (NT32SECURITY_DESCRIPTOR *)SecurityDescriptor;
  1323. //Copy up the lower fields.
  1324. //Note that the destination structure is small.
  1325. Descriptor32->Owner = (NT32PSID)Descriptor64->Owner;
  1326. Descriptor32->Group = (NT32PSID)Descriptor64->Group;
  1327. Descriptor32->Sacl = (NT32PSID)Descriptor64->Sacl;
  1328. Descriptor32->Dacl = (NT32PSID)Descriptor64->Dacl;
  1329. } except (EXCEPTION_EXECUTE_HANDLER) {
  1330. Status = GetExceptionCode ();
  1331. }
  1332. return Status;
  1333. }
  1334. )
  1335. End=
  1336. PreCall=
  1337. SecurityDescriptor = (PSECURITY_DESCRIPTOR)SecurityDescriptorHost; @NL
  1338. Begin=
  1339. @GenApiThunk(whNT32QuerySecurityObject)
  1340. End=
  1341. TemplateName=NtQuerySystemInformation
  1342. Case=(SystemBasicInformation,PSYSTEM_BASIC_INFORMATION)
  1343. Case=(SystemProcessorInformation,PSYSTEM_PROCESSOR_INFORMATION)
  1344. Case=(SystemEmulationBasicInformation,PSYSTEM_BASIC_INFORMATION)
  1345. Case=(SystemEmulationProcessorInformation,PSYSTEM_PROCESSOR_INFORMATION)
  1346. Case=(SystemPerformanceInformation,PSYSTEM_PERFORMANCE_INFORMATION)
  1347. Case=(SystemTimeOfDayInformation,PSYSTEM_TIMEOFDAY_INFORMATION)
  1348. Case=(SystemCallCountInformation,PSYSTEM_CALL_COUNT_INFORMATION)
  1349. Case=(SystemDeviceInformation,PSYSTEM_DEVICE_INFORMATION)
  1350. Case=(SystemProcessorPerformanceInformation)
  1351. Case=(SystemFlagsInformation,PSYSTEM_FLAGS_INFORMATION)
  1352. Case=(SystemModuleInformation,PRTL_PROCESS_MODULES)
  1353. Case=(SystemLocksInformation,PRTL_PROCESS_LOCKS)
  1354. Case=(SystemStackTraceInformation,PRTL_PROCESS_BACKTRACES)
  1355. Case=(SystemPagedPoolInformation,PSYSTEM_POOL_INFORMATION)
  1356. Case=(SystemNonPagedPoolInformation,PSYSTEM_POOL_INFORMATION)
  1357. Case=(SystemHandleInformation,PSYSTEM_HANDLE_INFORMATION)
  1358. Case=(SystemObjectInformation,PSYSTEM_OBJECTTYPE_INFORMATION)
  1359. Case=(SystemPageFileInformation,PSYSTEM_PAGEFILE_INFORMATION)
  1360. Case=(SystemFileCacheInformation,PSYSTEM_FILECACHE_INFORMATION)
  1361. Case=(SystemPoolTagInformation,PSYSTEM_POOLTAG_INFORMATION)
  1362. Case=(SystemInterruptInformation,PSYSTEM_INTERRUPT_INFORMATION)
  1363. Case=(SystemDpcBehaviorInformation,PSYSTEM_DPC_BEHAVIOR_INFORMATION)
  1364. Case=(SystemFullMemoryInformation,PSYSTEM_MEMORY_INFORMATION)
  1365. Case=(SystemTimeAdjustmentInformation,PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)
  1366. Case=(SystemSummaryMemoryInformation,PSYSTEM_MEMORY_INFORMATION)
  1367. Case=(SystemExceptionInformation,PSYSTEM_EXCEPTION_INFORMATION)
  1368. Case=(SystemKernelDebuggerInformation,PSYSTEM_KERNEL_DEBUGGER_INFORMATION)
  1369. Case=(SystemContextSwitchInformation,PSYSTEM_CONTEXT_SWITCH_INFORMATION)
  1370. Case=(SystemRegistryQuotaInformation,PSYSTEM_REGISTRY_QUOTA_INFORMATION)
  1371. Case=(SystemCurrentTimeZoneInformation,PRTL_TIME_ZONE_INFORMATION)
  1372. Case=(SystemLookasideInformation,PSYSTEM_LOOKASIDE_INFORMATION)
  1373. Case=(SystemProcessorIdleInformation,PSYSTEM_PROCESSOR_IDLE_INFORMATION)
  1374. Case=(SystemLostDelayedWriteInformation,PULONG)
  1375. Case=(SystemRangeStartInformation,ULONG_PTR*)
  1376. Case=(SystemComPlusPackage,PULONG)
  1377. Case=(SystemPerformanceTraceInformation)
  1378. Case=(SystemCallTimeInformation)
  1379. Case=(SystemPathInformation)
  1380. Case=(SystemVdmInstemulInformation)
  1381. Case=(SystemVdmBopInformation)
  1382. Case=(SystemProcessInformation)
  1383. Case=(SystemExtendedProcessInformation)
  1384. Header=
  1385. @NoFormat(
  1386. NTSTATUS
  1387. whNT32ThunkProcessInformationEx (
  1388. IN PSYSTEM_PROCESS_INFORMATION ProcessInformation,
  1389. IN BOOLEAN ExtendedProcessInformation,
  1390. IN OUT NT32SYSTEM_PROCESS_INFORMATION **ProcessInformation32,
  1391. OUT PULONG SystemInformationLength32
  1392. ) @NL
  1393. {
  1394. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  1395. PSYSTEM_EXTENDED_THREAD_INFORMATION ThreadInfoEx;
  1396. NT32SYSTEM_PROCESS_INFORMATION *ProcessInfo32 = *ProcessInformation32;
  1397. NT32SYSTEM_THREAD_INFORMATION *ThreadInfo32;
  1398. NT32SYSTEM_EXTENDED_THREAD_INFORMATION *ThreadInfoEx32;
  1399. PVOID pvLast;
  1400. ULONG NumberOfThreads;
  1401. ULONG BufferLength = *SystemInformationLength32;
  1402. //
  1403. // Check if the user has enough space
  1404. //
  1405. if (BufferLength < sizeof (NT32SYSTEM_PROCESS_INFORMATION)) {
  1406. return STATUS_INFO_LENGTH_MISMATCH;
  1407. }
  1408. BufferLength = BufferLength - sizeof (NT32SYSTEM_PROCESS_INFORMATION);
  1409. @ForceType(PostCall,ProcessInformation,ProcessInfo32,SYSTEM_PROCESS_INFORMATION*,OUT)
  1410. NumberOfThreads = ProcessInformation->NumberOfThreads;
  1411. ThreadInfo = (PSYSTEM_THREAD_INFORMATION) (ProcessInformation + 1);
  1412. ThreadInfoEx = (PSYSTEM_EXTENDED_THREAD_INFORMATION) (ProcessInformation + 1);
  1413. ThreadInfo32 = (NT32SYSTEM_THREAD_INFORMATION *) (ProcessInfo32 + 1);
  1414. ThreadInfoEx32 = (NT32SYSTEM_EXTENDED_THREAD_INFORMATION *) (ProcessInfo32 + 1);
  1415. pvLast = (ProcessInfo32 + 1);
  1416. if (ExtendedProcessInformation) {
  1417. if (BufferLength < (sizeof (PSYSTEM_EXTENDED_THREAD_INFORMATION) * NumberOfThreads)) {
  1418. return STATUS_INFO_LENGTH_MISMATCH;
  1419. }
  1420. BufferLength = BufferLength - (sizeof (PSYSTEM_EXTENDED_THREAD_INFORMATION) * NumberOfThreads);
  1421. } else {
  1422. if (BufferLength < (sizeof (PSYSTEM_THREAD_INFORMATION) * NumberOfThreads)) {
  1423. return STATUS_INFO_LENGTH_MISMATCH;
  1424. }
  1425. BufferLength = BufferLength - (sizeof (PSYSTEM_THREAD_INFORMATION) * NumberOfThreads);
  1426. }
  1427. while (NumberOfThreads > 0) {
  1428. if (ExtendedProcessInformation) {
  1429. @ForceType(PostCall,ThreadInfoEx,ThreadInfoEx32,PSYSTEM_EXTENDED_THREAD_INFORMATION,OUT)
  1430. ThreadInfoEx = ThreadInfoEx + 1;
  1431. ThreadInfoEx32 = ThreadInfoEx32 + 1;
  1432. pvLast = ThreadInfoEx32;
  1433. } else {
  1434. @ForceType(PostCall,ThreadInfo,ThreadInfo32,PSYSTEM_THREAD_INFORMATION,OUT)
  1435. ThreadInfo = ThreadInfo + 1;
  1436. ThreadInfo32 = ThreadInfo32 + 1;
  1437. pvLast = ThreadInfo32;
  1438. }
  1439. NumberOfThreads--;
  1440. }
  1441. if (ProcessInformation->ImageName.Buffer != NULL) {
  1442. if (BufferLength < ProcessInformation->ImageName.MaximumLength) {
  1443. return STATUS_INFO_LENGTH_MISMATCH;
  1444. }
  1445. BufferLength = BufferLength - ProcessInformation->ImageName.MaximumLength;
  1446. RtlCopyMemory (pvLast,
  1447. ProcessInformation->ImageName.Buffer,
  1448. ProcessInformation->ImageName.MaximumLength
  1449. );
  1450. ProcessInfo32->ImageName.Buffer = pvLast;
  1451. pvLast = (PCHAR)pvLast + ProcessInformation->ImageName.MaximumLength;
  1452. } else {
  1453. ProcessInfo32->ImageName.Buffer = NULL;
  1454. }
  1455. pvLast = ROUND_UP ((ULONG_PTR)pvLast, sizeof(ULONGLONG));
  1456. if (ProcessInformation->NextEntryOffset == 0)
  1457. ProcessInfo32->NextEntryOffset = 0;
  1458. else
  1459. ProcessInfo32->NextEntryOffset = (ULONG) ((PCHAR)pvLast - (PCHAR)ProcessInfo32);
  1460. *ProcessInformation32 = pvLast;
  1461. *SystemInformationLength32 = BufferLength;
  1462. return STATUS_SUCCESS;
  1463. }
  1464. NTSTATUS
  1465. whNT32QuerySystemProcessInformationEx (
  1466. IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  1467. OUT PVOID SystemInformation32,
  1468. IN ULONG SystemInformationLength32,
  1469. OUT PULONG ReturnLength32 OPTIONAL
  1470. ) @NL
  1471. {
  1472. NTSTATUS NtStatus;
  1473. ULONG SystemInformationLength;
  1474. ULONG ReturnLength;
  1475. BOOLEAN ExtendedProcessInformation;
  1476. PCHAR SystemInformationHost = (PCHAR)SystemInformation32;
  1477. PSYSTEM_PROCESS_INFORMATION SystemInformation;
  1478. //
  1479. // Allocate enough input buffer
  1480. //
  1481. SystemInformationLength = (SystemInformationLength32 + 0x400);
  1482. SystemInformation = Wow64AllocateTemp (SystemInformationLength);
  1483. if (SystemInformation == NULL) {
  1484. return STATUS_NO_MEMORY;
  1485. }
  1486. NtStatus = NtQuerySystemInformation (
  1487. SystemInformationClass,
  1488. SystemInformation,
  1489. SystemInformationLength,
  1490. &ReturnLength
  1491. );
  1492. if (NT_SUCCESS (NtStatus)) {
  1493. if (SystemInformationClass == SystemExtendedProcessInformation) {
  1494. ExtendedProcessInformation = TRUE;
  1495. } else {
  1496. ExtendedProcessInformation = FALSE;
  1497. }
  1498. //
  1499. // Thunk back the output to the caller.
  1500. //
  1501. try {
  1502. while (TRUE) {
  1503. NtStatus = whNT32ThunkProcessInformationEx (
  1504. SystemInformation,
  1505. ExtendedProcessInformation,
  1506. (NT32SYSTEM_PROCESS_INFORMATION **)&SystemInformation32,
  1507. &SystemInformationLength32
  1508. );
  1509. if (NT_SUCCESS (NtStatus)) {
  1510. if (SystemInformation->NextEntryOffset == 0) {
  1511. break;
  1512. }
  1513. SystemInformation = (PSYSTEM_PROCESS_INFORMATION) ((PCHAR)SystemInformation + SystemInformation->NextEntryOffset);
  1514. } else {
  1515. break;
  1516. }
  1517. }
  1518. //
  1519. // If all is good, let's update the output if present
  1520. //
  1521. if (NT_SUCCESS (NtStatus)) {
  1522. if (ARGUMENT_PRESENT (ReturnLength32)) {
  1523. *ReturnLength32 = ((PCHAR)SystemInformation32 - (PCHAR)SystemInformationHost);
  1524. }
  1525. }
  1526. } except (EXCEPTION_EXECUTE_HANDLER) {
  1527. NtStatus = GetExceptionCode ();
  1528. }
  1529. }
  1530. return NtStatus;
  1531. }
  1532. // SystemProcessorPerformanceInformation will return information about the processors in the system.
  1533. // On NT64, the maximum number of processors has increased to 64 instead of 32. Fortunately,
  1534. // the system will stop returning information when the client buffer is filled up. So a 32bit
  1535. // app will request preformance information on 32 processors, and the system will give them
  1536. // back information on 32 processors as expected.
  1537. NTSTATUS
  1538. whNT32QuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  1539. OUT PVOID SystemInformation,
  1540. IN ULONG SystemInformationLength,
  1541. OUT PULONG ReturnLength OPTIONAL
  1542. )
  1543. {
  1544. PWOW64_SYSTEM_INFORMATION EmulatedSysInfo;
  1545. NTSTATUS RetVal = STATUS_SUCCESS;
  1546. EmulatedSysInfo = Wow64GetEmulatedSystemInformation();
  1547. switch(SystemInformationClass) {
  1548. case SystemBasicInformation:
  1549. if (SystemInformationLength != sizeof(SYSTEM_BASIC_INFORMATION)) {
  1550. return STATUS_INFO_LENGTH_MISMATCH;
  1551. }
  1552. if (SystemInformation == NULL) {
  1553. return STATUS_INVALID_PARAMETER;
  1554. }
  1555. RtlCopyMemory(SystemInformation,
  1556. &EmulatedSysInfo->BasicInfo,
  1557. sizeof(SYSTEM_BASIC_INFORMATION));
  1558. WriteReturnLength(ReturnLength, sizeof(SYSTEM_BASIC_INFORMATION));
  1559. return RetVal;
  1560. break;
  1561. case SystemProcessorInformation:
  1562. if (SystemInformationLength != sizeof(SYSTEM_PROCESSOR_INFORMATION)) {
  1563. return STATUS_INFO_LENGTH_MISMATCH;
  1564. }
  1565. if (SystemInformation == NULL) {
  1566. return STATUS_INVALID_PARAMETER;
  1567. }
  1568. RtlCopyMemory(SystemInformation,
  1569. &EmulatedSysInfo->ProcessorInfo,
  1570. sizeof(SYSTEM_PROCESSOR_INFORMATION)
  1571. );
  1572. WriteReturnLength(ReturnLength, sizeof(SYSTEM_PROCESSOR_INFORMATION));
  1573. return RetVal;
  1574. break;
  1575. case SystemRangeStartInformation:
  1576. if (SystemInformationLength != sizeof(ULONG_PTR)) {
  1577. return STATUS_INFO_LENGTH_MISMATCH;
  1578. }
  1579. if (SystemInformation == NULL) {
  1580. return STATUS_INVALID_PARAMETER;
  1581. }
  1582. RtlCopyMemory(SystemInformation,
  1583. &EmulatedSysInfo->RangeInfo,
  1584. sizeof(ULONG_PTR));
  1585. // WriteReturnLength(ReturnLength, sizeof(ULONG_PTR));
  1586. WriteReturnLength(ReturnLength, sizeof(ULONG));
  1587. return RetVal;
  1588. default:
  1589. return NtQuerySystemInformation(SystemInformationClass,
  1590. SystemInformation,
  1591. SystemInformationLength,
  1592. ReturnLength
  1593. );
  1594. }
  1595. }
  1596. )
  1597. End=
  1598. SpecialQueryCase=
  1599. case SystemPerformanceTraceInformation: @NL
  1600. case SystemCallTimeInformation: @NL
  1601. case SystemPathInformation: @NL @Indent(
  1602. // Note: Not implemented in the kernel. @NL
  1603. return STATUS_NOT_IMPLEMENTED; @NL
  1604. )
  1605. case SystemVdmInstemulInformation: @NL
  1606. case SystemVdmBopInformation: @NL @Indent(
  1607. // Note: not supported since VDM is not supported. @NL
  1608. return STATUS_NOT_IMPLEMENTED; @NL
  1609. )
  1610. case SystemProcessorPerformanceInformation:
  1611. {
  1612. NTSTATUS NtStatus;
  1613. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorPerformanceInformation64;
  1614. NT32SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *ProcessorPerformanceInformation32;
  1615. ULONG EntriesCount;
  1616. ULONG ReturnLength64;
  1617. ProcessorPerformanceInformation32 = (NT32SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *)SystemInformation;
  1618. if (SystemInformationLength < sizeof (NT32SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) {
  1619. return STATUS_INFO_LENGTH_MISMATCH;
  1620. }
  1621. EntriesCount = SystemInformationLength / sizeof (NT32SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
  1622. if (ARGUMENT_PRESENT (ProcessorPerformanceInformation32)) {
  1623. ProcessorPerformanceInformation64 = Wow64AllocateTemp (EntriesCount * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
  1624. if (ProcessorPerformanceInformation64 == NULL) {
  1625. return STATUS_NO_MEMORY;
  1626. }
  1627. } else {
  1628. ProcessorPerformanceInformation64 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)ProcessorPerformanceInformation32;
  1629. }
  1630. NtStatus = whNT32QuerySystemInformation (
  1631. SystemInformationClass,
  1632. ProcessorPerformanceInformation64,
  1633. EntriesCount * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
  1634. &ReturnLength64
  1635. );
  1636. if (NT_SUCCESS (NtStatus)) {
  1637. ASSERT ((ReturnLength64 / sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) <= EntriesCount);
  1638. ReturnLength64 = ReturnLength64 / sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
  1639. try {
  1640. EntriesCount = ReturnLength64;
  1641. while (ReturnLength64 > 0) {
  1642. @ForceType(PostCall,ProcessorPerformanceInformation64,ProcessorPerformanceInformation32,PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION,OUT); @NL
  1643. ProcessorPerformanceInformation64++;
  1644. ProcessorPerformanceInformation32++;
  1645. ReturnLength64--;
  1646. }
  1647. if (ARGUMENT_PRESENT (ReturnLength)) {
  1648. *ReturnLength = EntriesCount * sizeof (NT32SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
  1649. }
  1650. } except (EXCEPTION_EXECUTE_HANDLER) {
  1651. NtStatus = GetExceptionCode ();
  1652. }
  1653. }
  1654. return NtStatus;
  1655. }
  1656. break;
  1657. case SystemProcessInformation:
  1658. case SystemExtendedProcessInformation:
  1659. return whNT32QuerySystemProcessInformationEx (
  1660. SystemInformationClass,
  1661. SystemInformation,
  1662. SystemInformationLength,
  1663. ReturnLength
  1664. );
  1665. break;
  1666. End=
  1667. Begin=
  1668. #define WriteReturnLength(rl, length) WriteReturnLengthStatus((rl), &RetVal, (length))
  1669. @GenQueryThunk(whNT32QuerySystemInformation,SystemInformationClass,SystemInformation,SystemInformationLength,ReturnLength,ULONG)
  1670. #undef WriteReturnLength
  1671. End=
  1672. TemplateName=NtWow64GetNativeSystemInformation
  1673. Case=(SystemBasicInformation,PSYSTEM_BASIC_INFORMATION)
  1674. Case=(SystemProcessorInformation,PSYSTEM_PROCESSOR_INFORMATION)
  1675. Case=(SystemEmulationBasicInformation,PSYSTEM_BASIC_INFORMATION)
  1676. Case=(SystemEmulationProcessorInformation,PSYSTEM_PROCESSOR_INFORMATION)
  1677. Begin=
  1678. #define WriteReturnLength(rl, length) WriteReturnLengthStatus((rl), &RetVal, (length))
  1679. @GenQueryThunk(NtQuerySystemInformation,SystemInformationClass,NativeSystemInformation,InformationLength,ReturnLength,ULONG)
  1680. #undef WriteReturnLength
  1681. End=
  1682. TemplateName=NtQuerySemaphore
  1683. Case=(SemaphoreBasicInformation,PSEMAPHORE_BASIC_INFORMATION)
  1684. Begin=
  1685. @GenDebugNonPtrDepCases(@ApiName,SemaphoreInformationClass)
  1686. End=
  1687. TemplateName=NtQueryVirtualMemory
  1688. Case=(MemoryBasicInformation,PMEMORY_BASIC_INFORMATION)
  1689. Case=(MemoryWorkingSetInformation,PMEMORY_WORKING_SET_INFORMATION)
  1690. Case=(MemoryMappedFilenameInformation,POBJECT_NAME_INFORMATION)
  1691. Begin=
  1692. #define WriteReturnLength(rl, length) WriteReturnLengthSilent((PULONG)(rl), (ULONG)(length))
  1693. @GenQueryThunk(@ApiName,MemoryInformationClass,MemoryInformation,MemoryInformationLength,ReturnLength,SIZE_T)
  1694. #undef WriteReturnLength
  1695. End=
  1696. TemplateName=NtQueryVirtualMemory64
  1697. Case=(MemoryBasicInformation,PUCHAR)
  1698. Case=(MemoryWorkingSetInformation,PMEMORY_WORKING_SET_INFORMATION)
  1699. Case=(MemoryMappedFilenameInformation,POBJECT_NAME_INFORMATION)
  1700. Begin=
  1701. #define WriteReturnLength(rl, length) WriteReturnLengthSilent((rl), (length))
  1702. @GenQueryThunk(@ApiName,MemoryInformationClass,MemoryInformation,MemoryInformationLength,ReturnLength,SIZE_T)
  1703. #undef WriteReturnLength
  1704. End=
  1705. TemplateName=NtQueryVolumeInformationFile
  1706. Case=(FileFsVolumeInformation,PFILE_FS_VOLUME_INFORMATION)
  1707. Case=(FileFsLabelInformation,PFILE_FS_LABEL_INFORMATION)
  1708. Case=(FileFsSizeInformation,PFILE_FS_SIZE_INFORMATION)
  1709. Case=(FileFsDeviceInformation,PFILE_FS_DEVICE_INFORMATION)
  1710. Case=(FileFsAttributeInformation,PFILE_FS_ATTRIBUTE_INFORMATION)
  1711. Case=(FileFsControlInformation,PFILE_FS_CONTROL_INFORMATION)
  1712. Case=(FileFsFullSizeInformation,PFILE_FS_FULL_SIZE_INFORMATION)
  1713. Case=(FileFsObjectIdInformation,PFILE_FS_OBJECTID_INFORMATION)
  1714. Case=(FileFsDriverPathInformation,PFILE_FS_DRIVER_PATH_INFORMATION)
  1715. Begin=
  1716. @GenDebugNonPtrDepCases(@ApiName,FsInformationClass)
  1717. End=
  1718. TemplateName=NtRaiseHardError
  1719. NoType=Parameters
  1720. Header=
  1721. @NoFormat(
  1722. NTSTATUS
  1723. whNT32RaiseHardError(
  1724. IN NTSTATUS ErrorStatus,
  1725. IN ULONG NumberOfParameters,
  1726. IN ULONG UnicodeStringParameterMask,
  1727. IN PVOID Parameters, //these parameters are not thunked yet(PULONG).
  1728. IN ULONG ValidResponseOptions,
  1729. OUT PULONG Response
  1730. )
  1731. {
  1732. ULONG ParameterCount;
  1733. PULONG Parameters32;
  1734. PULONG_PTR Parameters64;
  1735. Parameters32 = (PULONG)Parameters;
  1736. Parameters64 = Wow64AllocateTemp(NumberOfParameters * sizeof(ULONG_PTR));
  1737. for(ParameterCount=0; ParameterCount < NumberOfParameters; ParameterCount++) {
  1738. if (UnicodeStringParameterMask & (1<<ParameterCount)) {
  1739. //Parameter is a UNICODE_STRING
  1740. Parameters64[ParameterCount] = (ULONG_PTR)Wow64ShallowThunkAllocUnicodeString32TO64(Parameters32[ParameterCount]);
  1741. }
  1742. else {
  1743. Parameters64[ParameterCount] = (ULONG_PTR)Parameters32[ParameterCount];
  1744. }
  1745. }
  1746. return NtRaiseHardError(ErrorStatus,
  1747. NumberOfParameters,
  1748. UnicodeStringParameterMask,
  1749. Parameters64,
  1750. ValidResponseOptions,
  1751. Response
  1752. );
  1753. }
  1754. )
  1755. End=
  1756. PreCall=
  1757. Parameters = (PULONG_PTR)ParametersHost; @NL
  1758. Begin=
  1759. @GenApiThunk(whNT32RaiseHardError)
  1760. End=
  1761. TemplateName=NtSetInformationJobObject
  1762. Case=(JobObjectBasicLimitInformation,PJOBOBJECT_BASIC_LIMIT_INFORMATION)
  1763. Case=(JobObjectExtendedLimitInformation,PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)
  1764. Case=(JobObjectBasicUIRestrictions,PJOBOBJECT_BASIC_UI_RESTRICTIONS)
  1765. Case=(JobObjectEndOfJobTimeInformation,PJOBOBJECT_END_OF_JOB_TIME_INFORMATION)
  1766. Case=(JobObjectAssociateCompletionPortInformation,PJOBOBJECT_ASSOCIATE_COMPLETION_PORT)
  1767. Case=(JobObjectSecurityLimitInformation,PJOBOBJECT_SECURITY_LIMIT_INFORMATION)
  1768. Begin=
  1769. @GenSetThunk(@ApiName,JobObjectInformationClass,JobObjectInformation,JobObjectInformationLength)
  1770. End=
  1771. TemplateName=NtCreateJobSet
  1772. NoType=UserJobSet
  1773. Locals=
  1774. UserJobSet = (PJOB_SET_ARRAY)UlongToPtr(UserJobSetHost);
  1775. End=
  1776. PreCall=
  1777. if ((NumJob > 0) &&
  1778. (ARGUMENT_PRESENT (UserJobSet) != 0)) {
  1779. ULONG JobIndex;
  1780. NT32JOB_SET_ARRAY *UserJobSet32 = (NT32JOB_SET_ARRAY *)UlongToPtr(UserJobSetHost);
  1781. UserJobSet = Wow64AllocateTemp (NumJob * sizeof (JOB_SET_ARRAY));
  1782. if (UserJobSet == NULL) {
  1783. return STATUS_NO_MEMORY;
  1784. }
  1785. try {
  1786. for (JobIndex = 0 ; JobIndex < NumJob ; JobIndex++) {
  1787. UserJobSet[JobIndex].Flags = UserJobSet32[JobIndex].Flags;
  1788. UserJobSet[JobIndex].MemberLevel = UserJobSet32[JobIndex].MemberLevel;
  1789. UserJobSet[JobIndex].JobHandle = LongToPtr(UserJobSet32[JobIndex].JobHandle);
  1790. }
  1791. } except (EXCEPTION_EXECUTE_HANDLER) {
  1792. return GetExceptionCode ();
  1793. }
  1794. }
  1795. End=
  1796. Begin=
  1797. @GenApiThunk(@ApiName)
  1798. End=
  1799. TemplateName=NtSetInformationObject
  1800. Case=(ObjectHandleFlagInformation,POBJECT_HANDLE_FLAG_INFORMATION)
  1801. Begin=
  1802. @GenDebugNonPtrDepCases(@ApiName,ObjectInformationClass)
  1803. End=
  1804. TemplateName=NtSetInformationProcess
  1805. Header=
  1806. @NoFormat(
  1807. NTSTATUS
  1808. whNtSetInformationProcessEnableAlignmentFaultFixup(IN HANDLE ProcessHandle,
  1809. IN PROCESSINFOCLASS ProcessInformationClass,
  1810. IN PVOID ProcessInformationHost,
  1811. IN ULONG ProcessInformationLength
  1812. )
  1813. { @Indent( @NL
  1814. // Force enabling of alignment fixup since 32bit NT silently ignored this setting and always
  1815. // fixed up alignment faults.
  1816. BOOLEAN b = TRUE;
  1817. if (!ProcessInformationHost) {
  1818. return STATUS_INVALID_PARAMETER;
  1819. }
  1820. if (sizeof(BOOLEAN) != ProcessInformationLength) {
  1821. return STATUS_INFO_LENGTH_MISMATCH;
  1822. }
  1823. return NtSetInformationProcess(ProcessHandle,
  1824. ProcessInformationClass,
  1825. &b,
  1826. sizeof(BOOLEAN));
  1827. }
  1828. NTSTATUS
  1829. whNtSetInformationProcessDefaultHardErrorMode(IN HANDLE ProcessHandle,
  1830. IN PROCESSINFOCLASS ProcessInformationClass,
  1831. IN PVOID ProcessInformationHost,
  1832. IN ULONG ProcessInformationLength
  1833. )
  1834. { @Indent( @NL
  1835. // Force enabling of alignment fixup since 32bit NT silently ignored this setting and always
  1836. // fixed up alignment faults.
  1837. ULONG ul;
  1838. if (!ProcessInformationHost) {
  1839. return STATUS_INVALID_PARAMETER;
  1840. }
  1841. if (sizeof(ULONG) != ProcessInformationLength) {
  1842. return STATUS_INFO_LENGTH_MISMATCH;
  1843. }
  1844. ul = *(ULONG *)ProcessInformationHost | PROCESS_HARDERROR_ALIGNMENT_BIT;
  1845. return NtSetInformationProcess(ProcessHandle,
  1846. ProcessInformationClass,
  1847. &ul,
  1848. sizeof(ULONG));
  1849. }
  1850. NTSTATUS
  1851. whNtSetInformationProcessAffinityMask(
  1852. IN HANDLE ProcessHandle,
  1853. IN PROCESSINFOCLASS ProcessInformationClass,
  1854. IN PVOID ProcessInformation,
  1855. IN ULONG ProcessInformationLength
  1856. )
  1857. {
  1858. ULONG_PTR AffinityMask;
  1859. if ((NULL == ProcessInformation) || (ProcessInformationLength != sizeof(ULONG))) {
  1860. // Let the NT Api fail this call with the correct return code.
  1861. return NtSetInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength);
  1862. }
  1863. AffinityMask = Wow64ThunkAffinityMask32TO64(*(PULONG)ProcessInformation);
  1864. return NtSetInformationProcess(ProcessHandle, ProcessInformationClass, &AffinityMask, sizeof(AffinityMask));
  1865. }
  1866. )
  1867. End=
  1868. Case=(ProcessBasicInformation)
  1869. Case=(ProcessWorkingSetWatch)
  1870. Case=(ProcessEnableAlignmentFaultFixup)
  1871. Case=(ProcessAffinityMask)
  1872. Case=(ProcessDefaultHardErrorMode)
  1873. Case=(ProcessQuotaLimits,PQUOTA_LIMITS)
  1874. Case=(ProcessIoCounters,PULONG)
  1875. Case=(ProcessVmCounters,PVM_COUNTERS)
  1876. Case=(ProcessTimes,PKERNEL_USER_TIMES)
  1877. Case=(ProcessBasePriority,KPRIORITY*)
  1878. Case=(ProcessRaisePriority,PULONG)
  1879. Case=(ProcessDebugPort,PHANDLE)
  1880. Case=(ProcessExceptionPort,PHANDLE)
  1881. Case=(ProcessAccessToken,PPROCESS_ACCESS_TOKEN)
  1882. Case=(ProcessLdtInformation)
  1883. Case=(ProcessLdtSize)
  1884. Case=(ProcessPooledUsageAndLimits,PPOOLED_USAGE_AND_LIMITS)
  1885. Case=(ProcessUserModeIOPL)
  1886. Case=(ProcessPriorityClass,PPROCESS_PRIORITY_CLASS)
  1887. Case=(ProcessWx86Information,PHANDLE)
  1888. Case=(ProcessHandleCount,PULONG)
  1889. Case=(ProcessPriorityBoost,PULONG)
  1890. Case=(ProcessDeviceMap,PPROCESS_DEVICEMAP_INFORMATION)
  1891. Case=(ProcessSessionInformation,PPROCESS_SESSION_INFORMATION)
  1892. Case=(ProcessForegroundInformation,PPROCESS_FOREGROUND_BACKGROUND)
  1893. Case=(ProcessHandleTracing,PPROCESS_HANDLE_TRACING_ENABLE)
  1894. Case=(ProcessWow64Information,PULONG_PTR)
  1895. SpecialSetCase=
  1896. case ProcessWorkingSetWatch: @NL @Indent(
  1897. WOWASSERT(TRUE);
  1898. return STATUS_NOT_IMPLEMENTED;
  1899. )
  1900. case ProcessEnableAlignmentFaultFixup: @NL @Indent(
  1901. @CallApi(whNtSetInformationProcessEnableAlignmentFaultFixup,RetVal)
  1902. break;
  1903. )
  1904. case ProcessAffinityMask: @NL @Indent(
  1905. @CallApi(whNtSetInformationProcessAffinityMask,RetVal)
  1906. break;
  1907. )
  1908. case ProcessDefaultHardErrorMode: @NL @Indent(
  1909. @CallApi(whNtSetInformationProcessDefaultHardErrorMode,RetVal)
  1910. break;
  1911. )
  1912. Begin=
  1913. @GenSetThunk(@ApiName,ProcessInformationClass,ProcessInformation,ProcessInformationLength)
  1914. End=
  1915. TemplateName=NtSetInformationThread
  1916. Header=
  1917. @NoFormat(
  1918. NTSTATUS
  1919. whNtSetInformationThreadAffinityMask(
  1920. IN HANDLE ThreadHandle,
  1921. IN THREADINFOCLASS ThreadInformationClass,
  1922. IN PVOID ThreadInformation,
  1923. IN ULONG ThreadInformationLength
  1924. )
  1925. {
  1926. ULONG Affinity32;
  1927. ULONG_PTR Affinity64;
  1928. NTSTATUS StatusApi, StTemp;
  1929. HANDLE ProcessHandle;
  1930. THREAD_BASIC_INFORMATION ThreadInfo;
  1931. PROCESS_BASIC_INFORMATION ProcessInfo;
  1932. OBJECT_ATTRIBUTES ObjectAttributes;
  1933. if (NULL == ThreadInformation) {
  1934. return STATUS_INVALID_PARAMETER;
  1935. }
  1936. if (sizeof(ULONG) != ThreadInformationLength) {
  1937. return STATUS_INFO_LENGTH_MISMATCH;
  1938. }
  1939. Affinity32 = *(PULONG)ThreadInformation;
  1940. Affinity64 = Wow64ThunkAffinityMask32TO64(Affinity32);
  1941. StatusApi = NtSetInformationThread(ThreadHandle,
  1942. ThreadInformationClass,
  1943. &Affinity64,
  1944. sizeof(Affinity64));
  1945. if (StatusApi != STATUS_INVALID_PARAMETER) {
  1946. return StatusApi;
  1947. }
  1948. //Attempt to bash the thread affinity into being a subset of the process affinity.
  1949. //This should only happen if process the process affinty or thread affinity
  1950. //had some of the upper bits set set by some external entity and the app is trying
  1951. //to compute the thread affinity by subtracting bits from the process affinity.
  1952. //So query the process affinity, and try to mask off the bits. If we don't have
  1953. //permission to query the process affinity, fail the API.
  1954. StTemp = NtQueryInformationThread(ThreadHandle,
  1955. ThreadBasicInformation,
  1956. &ThreadInfo,
  1957. sizeof(ThreadInfo),
  1958. NULL);
  1959. if (!NT_SUCCESS(StTemp)) {
  1960. return StatusApi;
  1961. }
  1962. InitializeObjectAttributes(&ObjectAttributes,
  1963. NULL,
  1964. 0,
  1965. NULL,
  1966. NULL
  1967. );
  1968. StTemp = NtOpenProcess(&ProcessHandle,
  1969. PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
  1970. &ObjectAttributes, //ObjectAttributes
  1971. &(ThreadInfo.ClientId)
  1972. );
  1973. if (!NT_SUCCESS(StTemp)) {
  1974. return StatusApi;
  1975. }
  1976. StTemp = NtQueryInformationProcess(ProcessHandle,
  1977. ProcessBasicInformation,
  1978. &ProcessInfo,
  1979. sizeof(ProcessInfo),
  1980. NULL);
  1981. if (!NT_SUCCESS(StTemp)) {
  1982. goto done;
  1983. }
  1984. // Try to set the Affinity mask again after anding it with the process affinity.
  1985. // If this also fails, nothing more can be done. Just exit.
  1986. Affinity64 &= ProcessInfo.AffinityMask;
  1987. StatusApi = NtSetInformationThread(ThreadHandle,
  1988. ThreadInformationClass,
  1989. &Affinity64,
  1990. sizeof(Affinity64));
  1991. done:
  1992. NtClose(ProcessHandle);
  1993. return StatusApi;
  1994. }
  1995. End=
  1996. Case=(ThreadPriority,KPRIORITY*)
  1997. Case=(ThreadBasePriority,PLONG)
  1998. Case=(ThreadEnableAlignmentFaultFixup,PBOOLEAN)
  1999. Case=(ThreadImpersonationToken,PHANDLE)
  2000. Case=(ThreadQuerySetWin32StartAddress,PULONG_PTR)
  2001. Case=(ThreadIdealProcessor,PULONG)
  2002. Case=(ThreadPriorityBoost,PULONG)
  2003. Case=(ThreadZeroTlsCell,PULONG)
  2004. Case=(ThreadSetTlsArrayAddress,PVOID*)
  2005. Case=(ThreadHideFromDebugger)
  2006. Case=(ThreadAffinityMask)
  2007. SpecialSetCase=
  2008. case ThreadAffinityMask: @Indent( @NL
  2009. @CallApi(whNtSetInformationThreadAffinityMask,RetVal)
  2010. break; @NL
  2011. )@NL
  2012. case ThreadHideFromDebugger: @Indent( @NL
  2013. @CallApi(@ApiName,RetVal);
  2014. break; @NL
  2015. )@NL
  2016. End=
  2017. Begin=
  2018. @GenSetThunk(@ApiName,ThreadInformationClass,ThreadInformation,ThreadInformationLength)
  2019. End=
  2020. TemplateName=NtSetInformationToken
  2021. Case=(TokenOwner,PTOKEN_OWNER)
  2022. Case=(TokenPrimaryGroup,PTOKEN_PRIMARY_GROUP)
  2023. Case=(TokenDefaultDacl,PTOKEN_DEFAULT_DACL)
  2024. Case=(TokenSessionId,PULONG)
  2025. Case=(TokenSessionReference,PULONG)
  2026. Begin=
  2027. @GenSetThunk(@ApiName,TokenInformationClass,TokenInformation,TokenInformationLength)
  2028. End=
  2029. TemplateName=NtSetSystemInformation
  2030. Case=(SystemFlagsInformation,PSYSTEM_FLAGS_INFORMATION)
  2031. Case=(SystemTimeAdjustmentInformation,PSYSTEM_SET_TIME_ADJUST_INFORMATION)
  2032. Case=(SystemTimeSlipNotification,PHANDLE)
  2033. Case=(SystemRegistryQuotaInformation,PSYSTEM_REGISTRY_QUOTA_INFORMATION)
  2034. Case=(SystemPrioritySeperation,PULONG)
  2035. Case=(SystemExtendServiceTableInformation,PUNICODE_STRING)
  2036. Case=(SystemFileCacheInformation,PSYSTEM_FILECACHE_INFORMATION)
  2037. Case=(SystemDpcBehaviorInformation,PSYSTEM_DPC_BEHAVIOR_INFORMATION)
  2038. Case=(SystemSessionCreate,PULONG)
  2039. Case=(SystemSessionDetach,PULONG)
  2040. Case=(SystemComPlusPackage,PULONG)
  2041. Case=(SystemUnloadGdiDriverInformation)
  2042. Case=(SystemLoadGdiDriverInformation)
  2043. SpecialSetCase=
  2044. //Only valid from kmode. @NL
  2045. case SystemUnloadGdiDriverInformation: @NL
  2046. case SystemLoadGdiDriverInformation: @NL
  2047. return STATUS_PRIVILEGE_NOT_HELD; @NL
  2048. End=
  2049. Begin=
  2050. @GenSetThunk(@ApiName,SystemInformationClass,SystemInformation,SystemInformationLength)
  2051. End=
  2052. TemplateName=NtWaitForMultipleObjects
  2053. NoType=Handles
  2054. Locals=
  2055. HANDLE *TempHandles; @NL
  2056. NT32HANDLE *TempHandlesHost; @NL
  2057. UINT TempIndex; @NL
  2058. End=
  2059. PreCall=
  2060. TempHandlesHost = (NT32HANDLE *)HandlesHost; @NL
  2061. TempHandles = Wow64AllocateTemp(sizeof(HANDLE) * Count); @NL
  2062. try { @NL
  2063. for(TempIndex = 0; TempIndex < Count; TempIndex++) { @NL
  2064. @Indent(
  2065. TempHandles[TempIndex] = (HANDLE)TempHandlesHost[TempIndex]; @NL
  2066. )
  2067. } @NL
  2068. } except (EXCEPTION_EXECUTE_HANDLER) { @NL
  2069. return GetExceptionCode (); @NL
  2070. } @NL
  2071. Handles = (HANDLE *)TempHandles; @NL
  2072. End=
  2073. PostCall=
  2074. End=
  2075. TemplateName=NtCompactKeys
  2076. NoType=KeyArray
  2077. Locals=
  2078. HANDLE *TempHandles; @NL
  2079. NT32HANDLE *TempHandlesHost; @NL
  2080. UINT TempIndex; @NL
  2081. End=
  2082. PreCall=
  2083. TempHandlesHost = (NT32HANDLE *)KeyArrayHost; @NL
  2084. TempHandles = Wow64AllocateTemp(sizeof(HANDLE) * Count); @NL
  2085. try { @NL
  2086. for(TempIndex = 0; TempIndex < Count; TempIndex++) { @NL
  2087. @Indent(
  2088. TempHandles[TempIndex] = (HANDLE)TempHandlesHost[TempIndex]; @NL
  2089. )
  2090. } @NL
  2091. } except (EXCEPTION_EXECUTE_HANDLER) { @NL
  2092. return GetExceptionCode (); @NL
  2093. } @NL
  2094. KeyArray = (HANDLE *)TempHandles; @NL
  2095. End=
  2096. PostCall=
  2097. End=
  2098. ;; These APIs take an APC routine.
  2099. TemplateName=NtQueueApcThread
  2100. PreCall=
  2101. Wow64WrapApcProc(&ApcRoutine, &ApcArgument1);
  2102. End=
  2103. TemplateName=NtSetTimer
  2104. PreCall=
  2105. Wow64WrapApcProc(&TimerApcRoutine, &TimerContext);
  2106. End=
  2107. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2108. ;;
  2109. ;; IO Routines
  2110. ;; Special handling is needed since they can be asynchronous.
  2111. ;;
  2112. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2113. [Macros]
  2114. MacroName=AsynchronousIoPrecall
  2115. NumArgs=0
  2116. Begin=
  2117. Wow64WrapApcProc(&ApcRoutine, &ApcContext); @NL
  2118. { @Indent( @NL
  2119. NTSTATUS Status; @NL
  2120. IO_STATUS_BLOCK IosbTemp; @NL
  2121. FILE_MODE_INFORMATION ModeInfo; @NL
  2122. @NL
  2123. // Determine if the file is opened for asynchronous access. @NL
  2124. Status = NtQueryInformationFile(FileHandle, &IosbTemp, &ModeInfo, sizeof(ModeInfo), FileModeInformation); @NL
  2125. // This API will only return STATUS_SUCCESS on success; @NL
  2126. if (STATUS_SUCCESS != Status) { @Indent( @NL
  2127. RtlRaiseStatus(Status); @NL
  2128. )} @NL
  2129. if (!((ModeInfo.Mode & FILE_SYNCHRONOUS_IO_ALERT) || (ModeInfo.Mode & FILE_SYNCHRONOUS_IO_NONALERT))) { @Indent( @NL
  2130. // In this case, the operation will be asynchronous and a 32bit IO_STATUS_BLOCK will be passed. @NL
  2131. // Signal the kernel that a 32bit Iosb is being passed in. @NL
  2132. ApcRoutine = (PIO_APC_ROUTINE)((LONG_PTR)ApcRoutine | 1); @NL
  2133. // Signal the thunk that a 32bit Iosb is being passed in. @NL
  2134. IoStatusBlock = (PIO_STATUS_BLOCK)IoStatusBlockHost; @NL
  2135. AsynchronousIo = TRUE; @NL
  2136. )} @NL
  2137. if (ModeInfo.Mode & FILE_SYNCHRONOUS_IO_ALERT) {
  2138. AlertableIo = TRUE;
  2139. }
  2140. )} @NL
  2141. End=
  2142. [EFunc]
  2143. TemplateName=NtLockFile
  2144. Also=NtReadFile
  2145. Also=NtWriteFile
  2146. Also=NtNotifyChangeDirectoryFile
  2147. Locals=
  2148. BOOLEAN AsynchronousIo = FALSE;
  2149. BOOLEAN AlertableIo = FALSE;
  2150. End=
  2151. PreCall=
  2152. @AsynchronousIoPrecall
  2153. End=
  2154. TemplateName=NtFsControlFile
  2155. Also=NtDeviceIoControlFile
  2156. Locals=
  2157. BOOLEAN AsynchronousIo = FALSE;
  2158. BOOLEAN AlertableIo = FALSE;
  2159. BOOLEAN BuffersRealigned = FALSE;
  2160. PVOID OriginalInputBuffer;
  2161. PVOID OriginalOutputBuffer;
  2162. ULONG Ioctl = pBaseArgs[5];
  2163. HANDLE OriginalEvent;
  2164. End=
  2165. PreCall=
  2166. @AsynchronousIoPrecall
  2167. {@Indent( @NL
  2168. OriginalInputBuffer = InputBuffer;
  2169. OriginalOutputBuffer = OutputBuffer;
  2170. if (IS_IOCTL_REALIGNMENT_REQUIRED (Ioctl)) {
  2171. if ((InputBuffer != NULL) && (InputBufferLength > 0)) {
  2172. if (((ULONG_PTR)InputBuffer & ((MAX_NATURAL_ALIGNMENT) - 1)) != 0) {
  2173. InputBuffer = Wow64AllocateTemp (InputBufferLength);
  2174. if (InputBuffer == NULL) {
  2175. RtlRaiseStatus (STATUS_NO_MEMORY);
  2176. }
  2177. RetVal = STATUS_SUCCESS;
  2178. try {
  2179. RtlCopyMemory (InputBuffer,
  2180. OriginalInputBuffer,
  2181. InputBufferLength
  2182. );
  2183. }
  2184. except (EXCEPTION_EXECUTE_HANDLER) {
  2185. RetVal = GetExceptionCode ();
  2186. }
  2187. if (!NT_SUCCESS (RetVal)) {
  2188. return RetVal;
  2189. }
  2190. BuffersRealigned = TRUE;
  2191. }
  2192. }
  2193. if ((OutputBuffer != NULL) && (OutputBufferLength > 0)) {
  2194. if (((ULONG_PTR)OutputBuffer & ((MAX_NATURAL_ALIGNMENT) - 1)) != 0) {
  2195. OutputBuffer = Wow64AllocateTemp (OutputBufferLength);
  2196. if (OutputBuffer == NULL) {
  2197. RtlRaiseStatus (STATUS_NO_MEMORY);
  2198. }
  2199. BuffersRealigned = TRUE;
  2200. }
  2201. }
  2202. if ((BuffersRealigned == TRUE) && (AsynchronousIo == TRUE)) {
  2203. OriginalEvent = Event;
  2204. RetVal = NtCreateEvent (&Event,
  2205. EVENT_ALL_ACCESS,
  2206. NULL,
  2207. SynchronizationEvent,
  2208. FALSE
  2209. );
  2210. if (!NT_SUCCESS (RetVal)) {
  2211. RtlRaiseStatus (RetVal);
  2212. }
  2213. }
  2214. }
  2215. )} @NL
  2216. End=
  2217. PostCall=
  2218. {@Indent( @NL
  2219. if (BuffersRealigned == TRUE) {
  2220. if (NT_SUCCESS (RetVal)) {
  2221. if (RetVal == STATUS_PENDING) {
  2222. if (AsynchronousIo == TRUE) {
  2223. RetVal = NtWaitForSingleObject (Event,
  2224. AlertableIo,
  2225. NULL);
  2226. }
  2227. if (NT_SUCCESS (RetVal)) {
  2228. if (OutputBuffer != OriginalOutputBuffer) {
  2229. try {
  2230. RtlCopyMemory (OriginalOutputBuffer,
  2231. OutputBuffer,
  2232. OutputBufferLength
  2233. );
  2234. } except (EXCEPTION_EXECUTE_HANDLER) {
  2235. RetVal = GetExceptionCode ();
  2236. }
  2237. if (!NT_SUCCESS (RetVal)) {
  2238. RtlRaiseStatus (RetVal);
  2239. }
  2240. }
  2241. if (OriginalEvent != NULL ) {
  2242. NtSetEvent (OriginalEvent,
  2243. NULL
  2244. );
  2245. }
  2246. }
  2247. }
  2248. }
  2249. if (AsynchronousIo == TRUE) {
  2250. NtClose (Event);
  2251. }
  2252. }
  2253. )} @NL
  2254. End=
  2255. TemplateName=NtReadFileScatter
  2256. Also=NtWriteFileGather
  2257. Begin=
  2258. @GenUnsupportedNtApiThunk
  2259. End=
  2260. ;; The following is the list of structures passed.
  2261. ;; None of them are pointer dependent.
  2262. ;; List taken from ntos\io\dir.c
  2263. TemplateName=NtQueryDirectoryFile
  2264. Case=(FileDirectoryInformation,PFILE_DIRECTORY_INFORMATION)
  2265. Case=(FileFullDirectoryInformation,PFILE_FULL_DIR_INFORMATION)
  2266. Case=(FileBothDirectoryInformation,PFILE_BOTH_DIR_INFORMATION)
  2267. Case=(FileNamesInformation,PFILE_NAMES_INFORMATION)
  2268. Case=(FileObjectIdInformation,PFILE_OBJECT_INFORMATION)
  2269. Case=(FileQuotaInformation,PFILE_QUOTA_INFORMATION)
  2270. Case=(FileReparsePointInformation,FILE_REPARSE_POINT_INFORMATION)
  2271. Case=(FileIdBothDirectoryInformation,PFILE_ID_BOTH_DIR_INFORMATION)
  2272. Case=(FileIdFullDirectoryInformation,PFILE_ID_FULL_DIRECTORY_INFORMATION)
  2273. Case=(FileValidDataLengthInformation,PFILE_VALID_DATA_LENGTH_INFORMATION)
  2274. Locals=
  2275. BOOL bRealigned=FALSE;
  2276. PVOID *pTempFileInfo;
  2277. BOOLEAN AsynchronousIo = FALSE;
  2278. BOOLEAN AlertableIo = FALSE;
  2279. End=
  2280. PreCall=
  2281. @AsynchronousIoPrecall
  2282. //[LARGE_INTEGER ALIGNMENT FIXEX]
  2283. if ( (SIZE_T)(FileInformation) & (0x07) ) {
  2284. // allocate a buffer with correct alignment, to pass to the Win64 API
  2285. pTempFileInfo = FileInformation;
  2286. FileInformation = Wow64AllocateTemp(Length);
  2287. try {
  2288. RtlCopyMemory(FileInformation, pTempFileInfo, Length);
  2289. } except (EXCEPTION_EXECUTE_HANDLER) {
  2290. return GetExceptionCode ();
  2291. }
  2292. bRealigned = TRUE;
  2293. }
  2294. End=
  2295. Begin=
  2296. @GenDebugNonPtrDepCases(@ApiName,FileInformationClass)
  2297. End=
  2298. PostCall=
  2299. if (!NT_ERROR(RetVal) && bRealigned) {
  2300. RtlCopyMemory((PVOID)pTempFileInfo, FileInformation, Length);
  2301. }
  2302. End=
  2303. ;; The following is the list of structures passed.
  2304. ;; None of them are pointer dependent.
  2305. ;; List taken from ntos\io\iodata.c
  2306. TemplateName=NtQueryInformationFile
  2307. Case=(FileBasicInformation,PFILE_BASIC_INFORMATION)
  2308. Case=(FileStandardInformation,PFILE_STANDARD_INFORMATION)
  2309. Case=(FileInternalInformation,PFILE_INTERNAL_INFORMATION)
  2310. Case=(FileEaInformation,PFILE_EA_INFORMATION)
  2311. Case=(FileAccessInformation,PFILE_ACCESS_INFORMATION)
  2312. Case=(FileNameInformation,PFILE_NAME_INFORMATION)
  2313. Case=(FilePositionInformation,PFILE_POSITON_INFORMATION)
  2314. Case=(FileModeInformation,PFILE_MODE_INFORMATION)
  2315. Case=(FileAlignmentInformation,PFILE_ALIGNMENT_INFORMATION)
  2316. Case=(FileAllInformation,PFILE_ALL_INFORMATION)
  2317. Case=(FileAlternateNameInformation,PFILE_NAME_INFORMATION)
  2318. Case=(FileStreamInformation,PFILE_STREAM_INFORMATION)
  2319. Case=(FilePipeInformation,PFILE_PIPE_INFORMATION)
  2320. Case=(FilePipeLocalInformation,PFILE_PIPE_LOCAL_INFORMATION)
  2321. Case=(FilePipeRemoteInformation,PFILE_PIPE_REMOTE_INFORMATION)
  2322. Case=(FileMailslotQueryInformation,PFILE_MAILSLOT_QUERY_INFORMATION)
  2323. Case=(FileCompressionInformation,PFILE_COMPRESSION_INFORMATION)
  2324. Case=(FileObjectIdInformation,PFILE_OBJECTID_INFORMATION)
  2325. Case=(FileQuotaInformation,PFILE_QUOTA_INFORMATION)
  2326. Case=(FileReparsePointInformation,PFILE_REPARSE_POINT_INFORMATION)
  2327. Case=(FileNetworkOpenInformation,PFILE_NETWORK_OPEN_INFORMATION)
  2328. Case=(FileAttributeTagInformation,PFILE_ATTRIBUTE_TAB_INFORMATION)
  2329. Locals=
  2330. BOOL bRealigned=FALSE;
  2331. PVOID *pTempFileInfo;
  2332. End=
  2333. PreCall=
  2334. //[LARGE_INTEGER ALIGNMENT FIXEX]
  2335. if ( (SIZE_T)(FileInformation) & (0x07) ) {
  2336. // allocate a buffer with correct alignment, to pass to the Win64 API
  2337. pTempFileInfo = FileInformation;
  2338. FileInformation = Wow64AllocateTemp(Length);
  2339. try {
  2340. RtlCopyMemory(FileInformation, pTempFileInfo, Length);
  2341. } except (EXCEPTION_EXECUTE_HANDLER) {
  2342. return GetExceptionCode ();
  2343. }
  2344. bRealigned = TRUE;
  2345. }
  2346. End=
  2347. Begin=
  2348. @GenDebugNonPtrDepCases(@ApiName,FileInformationClass)
  2349. End=
  2350. PostCall=
  2351. if (!NT_ERROR(RetVal) && bRealigned) {
  2352. RtlCopyMemory((PVOID)pTempFileInfo, FileInformation, Length);
  2353. }
  2354. End=
  2355. TemplateName=NtSetInformationFile
  2356. Case=(FileBasicInformation,PFILE_BASIC_INFORMATION)
  2357. Case=(FileRenameInformation,PFILE_RENAME_INFORMATION)
  2358. Case=(FileLinkInformation,PFILE_LINK_INFORMATION)
  2359. Case=(FileDispositionInformation,PFILE_DISPOSITION_INFORMATION)
  2360. Case=(FilePositionInformation,PFILE_POSITION_INFORMATION)
  2361. Case=(FileModeInformation,PFILE_MODE_INFORMATION)
  2362. Case=(FileAllocationInformation,PFILE_ALLOCATION_INFORMATION)
  2363. Case=(FileEndOfFileInformation,PFILE_END_OF_FILE_INFORMATION)
  2364. Case=(FilePipeInformation,PFILE_PIPE_INFORMATION)
  2365. Case=(FilePipeRemoteInformation,PFILE_PIPE_REMOTE_INFORMATION)
  2366. Case=(FileMailslotSetInformation,PFILE_MAILSLOT_SET_INFORMATION)
  2367. Case=(FileObjectIdInformation,PFILE_OBJECTID_INFORMATION)
  2368. Case=(FileCompletionInformation,PFILE_COMPLETION_INFORMATION)
  2369. Case=(FileMoveClusterInformation,PFILE_MOVE_CLUSTER_INFORMATION)
  2370. Case=(FileQuotaInformation,PFILE_QUOTA_INFORMATION)
  2371. Case=(FileTrackingInformation,PFILE_TRACKING_INFORMATION)
  2372. Case=(FileValidDataLengthInformation,PFILE_VALID_DATA_LENGTH_INFORMATION)
  2373. Case=(FileShortNameInformation,PFILE_NAME_INFORMATION)
  2374. Locals=
  2375. BOOL bRealigned=FALSE;
  2376. PVOID *pTempFileInfo;
  2377. End=
  2378. PreCall=
  2379. //[LARGE_INTEGER ALIGNMENT FIXEX]
  2380. if ( (SIZE_T)(FileInformation) & (0x07) ) {
  2381. // allocate a buffer with correct alignment, to pass to the Win64 API
  2382. pTempFileInfo = FileInformation;
  2383. FileInformation = Wow64AllocateTemp(Length);
  2384. try {
  2385. RtlCopyMemory(FileInformation, pTempFileInfo, Length);
  2386. } except (EXCEPTION_EXECUTE_HANDLER) {
  2387. return GetExceptionCode ();
  2388. }
  2389. bRealigned = TRUE;
  2390. }
  2391. End=
  2392. Begin=
  2393. @GenSetThunk(@ApiName,FileInformationClass,FileInformation,Length)
  2394. End=
  2395. PostCall=
  2396. if (!NT_ERROR(RetVal) && bRealigned) {
  2397. RtlCopyMemory((PVOID)pTempFileInfo, FileInformation, Length);
  2398. }
  2399. End=
  2400. TemplateName=NtSetVolumeInformationFile
  2401. Case=(FileFsVolumeInformation,PFILE_FS_VOLUME_INFORMATION)
  2402. Case=(FileFsLabelInformation,PFILE_FS_LABEL_INFORMATION)
  2403. Case=(FileFsSizeInformation,PFILE_FS_SIZE_INFORMATION)
  2404. Case=(FileFsDeviceInformation,PFILE_FS_DEVICE_INFORMATION)
  2405. Case=(FileFsAttributeInformation,PFILE_FS_ATTRIBUTE_INFORMATION)
  2406. Case=(FileFsControlInformation,PFILE_FS_CONTROL_INFORMATION)
  2407. Case=(FileFsFullSizeInformation,PFILE_FS_FULL_SIZE_INFORMATION)
  2408. Case=(FileFsObjectIdInformation,PFILE_FS_OBJECTID_INFORMATION)
  2409. Begin=
  2410. @GenDebugNonPtrDepCases(@ApiName,FsInformationClass)
  2411. End=
  2412. TemplateName=NtQueryMultipleValueKey
  2413. NoType=ValueEntries
  2414. PreCall=
  2415. {@Indent(@NL
  2416. @NL try { @NL
  2417. NT32KEY_VALUE_ENTRY *Entries32 = (NT32KEY_VALUE_ENTRY *)ValueEntriesHost; @NL
  2418. ULONG TempEntryCount = EntryCount; @NL
  2419. PKEY_VALUE_ENTRY Entries64 = (PKEY_VALUE_ENTRY)Wow64AllocateTemp(sizeof(KEY_VALUE_ENTRY) * EntryCount); @NL
  2420. ValueEntries = Entries64; @NL
  2421. @NL
  2422. for(;TempEntryCount > 0; TempEntryCount--, Entries32++, Entries64++) { @NL
  2423. Entries64->ValueName = Wow64ShallowThunkAllocUnicodeString32TO64(Entries32->ValueName); @NL
  2424. Entries64->DataLength = (ULONG)Entries32->DataLength; @NL
  2425. Entries64->DataOffset = (ULONG)Entries32->DataOffset; @NL
  2426. Entries64->Type = (ULONG)Entries32->Type; @NL
  2427. }@NL
  2428. } except( NULL, EXCEPTION_EXECUTE_HANDLER){ @NL
  2429. return GetExceptionCode (); @NL
  2430. } @NL
  2431. )}@NL
  2432. End=
  2433. Begin=
  2434. @GenApiThunk(Wow64@ApiName)
  2435. End=
  2436. PostCall=
  2437. {@Indent(@NL
  2438. @NL try { @NL
  2439. NT32KEY_VALUE_ENTRY *Entries32 = (NT32KEY_VALUE_ENTRY *)ValueEntriesHost; @NL
  2440. ULONG TempEntryCount = EntryCount; @NL
  2441. PKEY_VALUE_ENTRY Entries64 = ValueEntries;@NL
  2442. @NL
  2443. for(;TempEntryCount > 0; TempEntryCount--, Entries32++, Entries64++) { @NL
  2444. (ULONG)Entries32->DataLength = Entries64->DataLength; @NL
  2445. (ULONG)Entries32->DataOffset = Entries64->DataOffset; @NL
  2446. (ULONG)Entries32->Type = Entries64->Type; @NL
  2447. }@NL
  2448. } except( NULL, EXCEPTION_EXECUTE_HANDLER){ @NL
  2449. return GetExceptionCode (); @NL
  2450. } @NL
  2451. )}@NL
  2452. End=
  2453. ;;All of the data passed is non pointer dependent.
  2454. ;;list taken from ntos\config\ntapi.c
  2455. TemplateName=NtSetInformationKey
  2456. Case=(KeyWriteTimeInformation,PLARGE_INTEGER)
  2457. Begin=
  2458. @GenDebugNonPtrDepCases(Wow64@ApiName,KeySetInformationClass)
  2459. End=
  2460. ;;These functions are asynchronous, but fortunately the Buffer is not used.
  2461. ;;The IO_STATUS_BLOCK will be thunked in the kernel.
  2462. TemplateName=NtNotifyChangeKey
  2463. NoType=IoStatusBlock
  2464. PreCall=
  2465. IoStatusBlock = (PIO_STATUS_BLOCK)IoStatusBlockHost; @NL
  2466. Wow64WrapApcProc(&ApcRoutine, &ApcContext);
  2467. End=
  2468. Begin=
  2469. @GenApiThunk(Wow64@ApiName)
  2470. End=
  2471. TemplateName=NtNotifyChangeKeys
  2472. NoType=IoStatusBlock
  2473. NoType=SlaveObjects
  2474. PreCall=
  2475. IoStatusBlock = (PIO_STATUS_BLOCK)IoStatusBlockHost; @NL
  2476. if (0 == Count) { @Indent( @NL
  2477. SlaveObjects = (POBJECT_ATTRIBUTES)SlaveObjectsHost; @NL
  2478. )} @NL
  2479. else { @Indent( @NL
  2480. if (Count > 1) { @Indent( @NL
  2481. // The kernel does not support a count > 1 @NL
  2482. RtlRaiseStatus(STATUS_INVALID_PARAMTER); @NL
  2483. )} @NL
  2484. // Count must be 1 @NL
  2485. SlaveObjects = (POBJECT_ATTRIBUTES)Wow64ShallowThunkAllocObjectAttributes32TO64(SlaveObjectsHost); @NL
  2486. )} @NL
  2487. End=
  2488. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2489. ;;
  2490. ;; Many of the thread control functions are implemented in Wow64.
  2491. ;;
  2492. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2493. TemplateName=NtContinue
  2494. Begin=
  2495. @GenApiThunk(Wow64@ApiName)
  2496. End=
  2497. TemplateName=NtSuspendThread
  2498. Begin=
  2499. @GenApiThunk(Wow64SuspendThread)
  2500. End=
  2501. TemplateName=NtGetContextThread
  2502. Begin=
  2503. @GenApiThunk(Wow64GetContextThread)
  2504. End=
  2505. TemplateName=NtSetContextThread
  2506. Begin=
  2507. @GenApiThunk(Wow64SetContextThread)
  2508. End=
  2509. TemplateName=NtCreateThread
  2510. Begin=
  2511. @GenApiThunk(Wow64@ApiName)
  2512. End=
  2513. TemplateName=NtTerminateThread
  2514. Begin=
  2515. @GenApiThunk(Wow64@ApiName)
  2516. End=
  2517. TemplateName=NtRaiseException
  2518. NoType=ExceptionRecord
  2519. NoType=ContextRecord
  2520. PreCall=
  2521. ExceptionRecord = (PEXCEPTION_RECORD)ExceptionRecordHost; @NL
  2522. ContextRecord = (PCONTEXT)ContextRecordHost; @NL
  2523. End=
  2524. Begin=
  2525. @GenApiThunk(Wow64KiRaiseException)
  2526. End=
  2527. TemplateName=NtCallbackReturn
  2528. Begin=
  2529. @GenApiThunk(Wow64@ApiName)
  2530. End=
  2531. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2532. ;;
  2533. ;; Memory-Management
  2534. ;;
  2535. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2536. TemplateName=NtProtectVirtualMemory
  2537. PreCall=
  2538. if ( WOW64IsCurrentProcess ( ProcessHandle ) && @NL
  2539. ( NewProtect & ( PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY ) ) ) { @NL
  2540. try { @NL
  2541. CpuFlushInstructionCache ( *BaseAddress, *(ULONG *) RegionSize ); @NL
  2542. } except (EXCEPTION_EXECUTE_HANDLER) { @NL
  2543. return GetExceptionCode (); @NL
  2544. } @NL
  2545. } @NL
  2546. End=
  2547. TemplateName=NtAllocateVirtualMemory
  2548. PreCall=
  2549. if (AllocationType & MEM_WRITE_WATCH) {
  2550. // WOW64 does not suport WriteWatch. See the NtGetWriteWatch thunk.
  2551. return STATUS_NOT_SUPPORTED;
  2552. }
  2553. if (NULL == *BaseAddress && 0 == ZeroBits) { @NL
  2554. // Force the address to be below 2gb, in case the target process @NL
  2555. // is 64-bit. @NL
  2556. ZeroBits = 0x7fffffff; @NL
  2557. } @NL
  2558. End=
  2559. PostCall=
  2560. if ( ( !NT_ERROR(RetVal) ) && WOW64IsCurrentProcess ( ProcessHandle ) && ( Protect & ( PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY ) ) ) { @NL
  2561. try { @NL
  2562. CpuFlushInstructionCache ( *BaseAddress, *(ULONG *) RegionSize ); @NL
  2563. } except (EXCEPTION_EXECUTE_HANDLER) { @NL
  2564. return GetExceptionCode (); @NL
  2565. } @NL
  2566. } @NL
  2567. End=
  2568. TemplateName=NtMapViewOfSection
  2569. Locals=
  2570. PVOID ArbitraryUserPointer; @NL
  2571. PTEB Teb = NtCurrentTeb(); @NL
  2572. PTEB32 Teb32 = NtCurrentTeb32(); @NL
  2573. SECTION_IMAGE_INFORMATION Info; @NL
  2574. WCHAR* DllName;
  2575. UNICODE_STRING NtNameStr = {0, 0, NULL};
  2576. RTL_UNICODE_STRING_BUFFER DosNameStrBuf;
  2577. End=
  2578. PreCall=
  2579. // Copy the 32-bit ArbitraryUserPointer into the 64-bit Teb. It @NL
  2580. // contains a pointer to the unicode filename of the image being @NL
  2581. // mapped. @NL
  2582. ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer; @NL
  2583. //
  2584. // Find real (redirected) image name
  2585. //
  2586. RtlInitUnicodeStringBuffer(&DosNameStrBuf, 0, 0);
  2587. DllName = (PVOID)Teb32->NtTib.ArbitraryUserPointer;
  2588. __try {
  2589. if (RtlDosPathNameToNtPathName_U(DllName, &NtNameStr, NULL, NULL)) {
  2590. ULONG Len = NtNameStr.Length;
  2591. Wow64RedirectFileName(NtNameStr.Buffer, &Len);
  2592. NtNameStr.Length = Len;
  2593. if ( NT_SUCCESS(RtlAssignUnicodeStringBuffer(&DosNameStrBuf, &NtNameStr)) &&
  2594. NT_SUCCESS(RtlNtPathNameToDosPathName(0, &DosNameStrBuf, NULL, NULL))) {
  2595. DllName = DosNameStrBuf.String.Buffer;
  2596. }
  2597. }
  2598. }
  2599. __except (EXCEPTION_EXECUTE_HANDLER) {
  2600. // Suppress all exceptions here
  2601. }
  2602. Teb->NtTib.ArbitraryUserPointer = DllName;
  2603. if (NULL == *BaseAddress && 0 == ZeroBits) { @NL
  2604. // Force the address to be below 2gb, in case the target process @NL
  2605. // is 64-bit. @NL
  2606. ZeroBits = 0x7fffffff; @NL
  2607. } @NL
  2608. // 32-bit NT has a bug where the alignment check for *SectionOffset @NL
  2609. // is only 32-bit even though it is a LARGE_INTEGER. 64-bit NT @NL
  2610. // does a more aggressive check, so double-buffer here. @NL
  2611. End=
  2612. PostCall=
  2613. Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer; @NL
  2614. if (!NT_ERROR(RetVal)) { @NL
  2615. if (WOW64IsCurrentProcess(ProcessHandle)) { @NL
  2616. CpuNotifyDllLoad ( DllName, *BaseAddress, *(ULONG *) ViewSize ); @NL
  2617. } @NL
  2618. // For non-x86 images, be sure to return a mismatch warning @NL
  2619. if (!Wow64IsModule32bitHelper(NtCurrentProcess(), @NL
  2620. (ULONG64)(*BaseAddress))) { @NL
  2621. RetVal = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; @NL
  2622. } @NL
  2623. } @NL
  2624. if (NtNameStr.Buffer) RtlFreeHeap(RtlProcessHeap(), 0, NtNameStr.Buffer);
  2625. RtlFreeUnicodeStringBuffer(&DosNameStrBuf);
  2626. End=
  2627. TemplateName=NtUnmapViewOfSection
  2628. PostCall=
  2629. if ( ( !NT_ERROR(RetVal) ) && WOW64IsCurrentProcess ( ProcessHandle ) ) @NL
  2630. CpuNotifyDllUnload ( BaseAddress );
  2631. End=
  2632. TemplateName=NtFlushInstructionCache
  2633. PostCall=
  2634. if ( ( !NT_ERROR(RetVal) ) && WOW64IsCurrentProcess ( ProcessHandle ) ) @NL
  2635. CpuFlushInstructionCache ( BaseAddress, Length );
  2636. End=
  2637. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2638. ;;
  2639. ;; NT debugger UI APIs
  2640. ;;
  2641. ;;
  2642. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2643. TemplateName=NtWow64DebuggerCall
  2644. Begin=
  2645. @ApiProlog
  2646. @NoFormat(
  2647. NTSTATUS RetVal = STATUS_SUCCESS;
  2648. // Don't log this one, as our logging competes with the BREAKPOINT_PRINT logging
  2649. //LOGPRINT((TRACELOG, "wh@ApiName(@ApiNum) api thunk: @IfArgs(@ArgList(@ArgName: %x@ArgMore(,)))\n"@IfArgs(, @ArgList((@ArgHostName)@ArgMore(,))))); @NL
  2650. switch (ServiceClassHost) {
  2651. case 0: // BREAKPOINT_BREAK from sdk\inc\nti386.h
  2652. WOWASSERT(FALSE); // This should never be hit from usermode
  2653. break;
  2654. case 1: // BREAKPOINT_PRINT:
  2655. // Arg2Host, Output->Length, is ignored
  2656. DbgPrintEx(Arg3Host, // ComponentId
  2657. Arg4Host, // Level
  2658. "%s",
  2659. (PCHAR)Arg1Host);// String to print
  2660. break;
  2661. case 2: // BREAKPOINT_PROMPT:
  2662. // Arg2Host, Output->Length, is ignored
  2663. RetVal = DbgPrompt((PCHAR)Arg1Host, // Output->Buffer
  2664. (PCHAR)Arg3Host, // Input->Buffer
  2665. Arg4Host); // Input->MaximumLength
  2666. break;
  2667. case 3: // BREAKPOINT_LOAD_SYMBOLS
  2668. case 4: // BREAKPOINT_UNLOAD_SYMBOLS
  2669. WOWASSERT(FALSE); // This should never be hit from usermode
  2670. break;
  2671. default:
  2672. WOWASSERT(FALSE);
  2673. break;
  2674. }
  2675. return RetVal;
  2676. }
  2677. End=
  2678. TemplateName=NtWaitForDebugEvent
  2679. NoType=WaitStateChange
  2680. Locals=
  2681. DBGUI_WAIT_STATE_CHANGE WaitStateChangeCopy; @NL
  2682. NT32DBGUI_WAIT_STATE_CHANGE *WaitStateChangeDest; @NL
  2683. End=
  2684. PreCall=
  2685. if (ARGUMENT_PRESENT(WaitStateChangeHost)) { @Indent( @NL
  2686. WaitStateChange = &WaitStateChangeCopy; @NL
  2687. WaitStateChangeDest = (NT32DBGUI_WAIT_STATE_CHANGE *)WaitStateChangeHost; @NL
  2688. )} @NL
  2689. else { @Indent( @NL
  2690. WaitStateChange = (DBGUI_WAIT_STATE_CHANGE *)WaitStateChangeHost; @NL
  2691. )} @NL
  2692. wait_again: @NL
  2693. End=
  2694. PostCall=
  2695. if (!NT_ERROR(RetVal) && ARGUMENT_PRESENT(WaitStateChange) && RetVal != STATUS_TIMEOUT && RetVal != STATUS_USER_APC && RetVal != STATUS_ALERTED && RetVal != DBG_NO_STATE_CHANGE) { @Indent( @NL
  2696. WaitStateChangeDest->NewState = WaitStateChange->NewState; @NL
  2697. @ForceType(PostCall,(&WaitStateChange->AppClientId),(&WaitStateChangeDest->AppClientId),PCLIENT_ID,OUT) @NL
  2698. switch(WaitStateChange->NewState) { @Indent( @NL
  2699. case DbgIdle: @NL
  2700. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgIdle\n"));@NL
  2701. goto do_nothing; @NL
  2702. case DbgReplyPending: @NL @Indent(
  2703. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgReplyPending\n")); @NL
  2704. do_nothing:
  2705. // Nothing else to do in this case. @NL
  2706. break; @NL
  2707. ) @NL
  2708. case DbgCreateThreadStateChange: @NL @Indent(
  2709. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgCreateThreadWaitStateChange\n"));@NL
  2710. @ForceType(PostCall,(&WaitStateChange->StateInfo.CreateThread),(&WaitStateChangeDest->StateInfo.CreateThread),PDBGUI_CREATE_THREAD,OUT) @NL
  2711. break; @NL
  2712. ) @NL
  2713. case DbgCreateProcessStateChange: @NL @Indent(
  2714. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgCreateProcessWaitStateChange\n"));@NL
  2715. @ForceType(PostCall,(&WaitStateChange->StateInfo.CreateProcessInfo),(&WaitStateChangeDest->StateInfo.CreateProcessInfo),PDBGUI_CREATE_PROCESS,OUT) @NL
  2716. break; @NL
  2717. ) @NL
  2718. case DbgExitThreadStateChange: @NL @Indent(
  2719. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgExitThreadWaitStateChange\n"));@NL
  2720. WOWASSERT(sizeof(NT32DBGKM_EXIT_THREAD) == sizeof(DBGKM_EXIT_THREAD)); @NL
  2721. RtlCopyMemory(&WaitStateChangeDest->StateInfo.ExitThread, &WaitStateChange->StateInfo.ExitThread, sizeof(DBGKM_EXIT_THREAD)); @NL
  2722. break; @NL
  2723. ) @NL
  2724. case DbgExitProcessStateChange: @NL @Indent(
  2725. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgExitProcessWaitStateChange\n")); @NL
  2726. WOWASSERT(sizeof(NT32DBGKM_EXIT_PROCESS) == sizeof(DBGKM_EXIT_PROCESS)); @NL
  2727. RtlCopyMemory(&WaitStateChangeDest->StateInfo.ExitProcess, &WaitStateChange->StateInfo.ExitProcess,sizeof(DBGKM_EXIT_PROCESS)); @NL
  2728. break; @NL
  2729. ) @NL
  2730. case DbgExceptionStateChange: @NL
  2731. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgBreakpointWaitStateChange\n")); @NL
  2732. goto do_exception; @NL
  2733. case DbgBreakpointStateChange: @NL
  2734. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgBreakpointWaitStateChange\n")); @NL
  2735. //
  2736. // 32-bit x86 debuggers shouldn't expect to receive
  2737. // native hard coded break points, so bypass them
  2738. //
  2739. if ((NT_SUCCESS(Wow64SkipOverBreakPoint(&WaitStateChange->AppClientId,
  2740. &WaitStateChange->StateInfo.Exception.ExceptionRecord))) &&
  2741. (NT_SUCCESS(NtDebugContinue(DebugObjectHandle,
  2742. &WaitStateChange->AppClientId,
  2743. DBG_CONTINUE))))
  2744. {
  2745. LOGPRINT((TRACELOG, "Bypassing native breakpoint at %lx\n",
  2746. WaitStateChange->StateInfo.Exception.ExceptionRecord.ExceptionAddress));
  2747. goto wait_again;
  2748. }
  2749. LOGPRINT((ERRORLOG, "32-bit Debugger couldn't skip native breakpoint at %lx\n",
  2750. WaitStateChange->StateInfo.Exception.ExceptionRecord.ExceptionAddress));
  2751. goto do_exception; @NL
  2752. case DbgSingleStepStateChange: @NL @Indent(
  2753. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgSingleStepWaitStateChange\n")); @NL
  2754. do_exception:
  2755. WaitStateChangeDest->StateInfo.Exception.FirstChance = WaitStateChange->StateInfo.Exception.FirstChance; @NL
  2756. ThunkExceptionRecord64To32((&WaitStateChange->StateInfo.Exception.ExceptionRecord),((PEXCEPTION_RECORD32)(&WaitStateChangeDest->StateInfo.Exception.ExceptionRecord)));@NL
  2757. // BUG, BUG. Do not thunk the entire exception chain at this point. @NL
  2758. // It appears that NTSD does not use the entire chain, so a hack to get it @NL
  2759. // is not worth the risk of bugs that it might introduce. Leave it alone for now. @NL
  2760. break; @NL
  2761. ) @NL
  2762. case DbgLoadDllStateChange: @NL @Indent(
  2763. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgLoadDllWaitStateChange\n")); @NL
  2764. if (!Wow64IsModule32bit(&WaitStateChange->AppClientId,
  2765. (ULONG64)WaitStateChange->StateInfo.LoadDll.BaseOfDll) &&
  2766. (NT_SUCCESS(NtDebugContinue(DebugObjectHandle,
  2767. &WaitStateChange->AppClientId,
  2768. DBG_CONTINUE))))
  2769. {
  2770. LOGPRINT((TRACELOG, "Bypassing 64-bit load Dll messege. \n"));
  2771. goto wait_again;
  2772. }
  2773. @ForceType(PostCall,(&WaitStateChange->StateInfo.LoadDll),(&WaitStateChangeDest->StateInfo.LoadDll),PDBGKM_LOAD_DLL,OUT) @NL
  2774. break; @NL
  2775. ) @NL
  2776. case DbgUnloadDllStateChange: @NL @Indent(
  2777. LOGPRINT((TRACELOG, "DbgUiWaitWaitStateChange: DbgUnloadDllWaitStateChange\n")); @NL
  2778. @ForceType(PostCall,(&WaitStateChange->StateInfo.UnloadDll),(&WaitStateChangeDest->StateInfo.UnloadDll),PDBGKM_UNLOAD_DLL,OUT) @NL
  2779. break; @NL
  2780. ) @NL
  2781. default: @NL @Indent(
  2782. LOGPRINT((ERRORLOG, "Unknown DBGUI_WAIT_STATE_CHANGE of %x\n", WaitStateChange->NewState));
  2783. WOWASSERT(FALSE); @NL
  2784. ) @NL
  2785. )} @NL
  2786. )} @NL
  2787. End=
  2788. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2789. ;;
  2790. ;; A few CSR thunks that are in NTDLL
  2791. ;; Most are placeholders and will be going away very soon
  2792. ;;
  2793. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2794. TemplateName=NtWow64CsrClientConnectToServer
  2795. Locals=
  2796. End=
  2797. PostCall=
  2798. {@NL
  2799. // Copy setting from 64Bit PEB to the 32Bit PEB @NL
  2800. PPEB32 peb32;
  2801. peb32 = (PPEB32)(NtCurrentTeb32()->ProcessEnvironmentBlock); @NL
  2802. peb32->ReadOnlySharedMemoryBase = PtrToUlong(NtCurrentPeb()->ReadOnlySharedMemoryBase); @NL
  2803. peb32->ReadOnlySharedMemoryHeap = PtrToUlong(NtCurrentPeb()->ReadOnlySharedMemoryHeap); @NL
  2804. peb32->ReadOnlyStaticServerData = PtrToUlong(NtCurrentPeb()->ReadOnlyStaticServerData); @NL
  2805. }@NL
  2806. End=
  2807. Begin=
  2808. @GenApiThunk(CsrClientConnectToServer)
  2809. End=
  2810. TemplateName=NtWow64CsrNewThread
  2811. Begin=
  2812. @GenApiThunk(CsrNewThread)
  2813. End=
  2814. TemplateName=NtWow64CsrIdentifyAlertableThread
  2815. Begin=
  2816. @GenApiThunk(CsrNewThread)
  2817. End=
  2818. TemplateName=NtWow64CsrClientCallServer
  2819. Begin=
  2820. @GenPlaceHolderThunk(CsrClientCallServer)
  2821. End=
  2822. TemplateName=NtWow64CsrAllocateCaptureBuffer
  2823. Begin=
  2824. @GenPlaceHolderThunk(CsrAllocateCaptureBuffer)
  2825. End=
  2826. TemplateName=NtWow64CsrFreeCaptureBuffer
  2827. Begin=
  2828. @GenPlaceHolderThunk(CsrFreeCaptureBuffer)
  2829. End=
  2830. TemplateName=NtWow64CsrAllocateMessagePointer
  2831. Begin=
  2832. @GenPlaceHolderThunk(CsrAllocateMessagePointer)
  2833. End=
  2834. TemplateName=NtWow64CsrCaptureMessageBuffer
  2835. Begin=
  2836. @GenPlaceHolderThunk(CsrCaptureMessageBuffer)
  2837. End=
  2838. TemplateName=NtWow64CsrCaptureMessageString
  2839. Begin=
  2840. @GenPlaceHolderThunk(CsrCaptureMessageString)
  2841. End=
  2842. TemplateName=NtWow64CsrSetPriorityClass
  2843. Begin=
  2844. @GenApiThunk(CsrSetPriorityClass)
  2845. End=
  2846. TemplateName=NtWow64CsrAllocateCapturePointer
  2847. Begin=
  2848. @GenPlaceHolderThunk(CsrAllocateCapturePointer)
  2849. End=
  2850. TemplateName=NtWow64CsrGetProcessId
  2851. Begin=
  2852. @GenPlaceHolderThunk(CsrGetProcessId)
  2853. End=
  2854. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2855. ;;
  2856. ;; These APIs are only called by the user mode PNP manager
  2857. ;; which will be in 64bit code in NT64. Since no user apps call
  2858. ;; them and the structures passed across are rather nasty they will
  2859. ;; not be supported here.
  2860. ;;
  2861. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2862. TemplateName=NtGetPlugPlayEvent
  2863. Begin=
  2864. @GenUnsupportedNtApiThunk
  2865. End=
  2866. ; case PlugPlayControlEnumerateDevice:
  2867. ; case PlugPlayControlRegisterNewDevice:
  2868. ; case PlugPlayControlDeregisterDevice:
  2869. ; case PlugPlayControlInitializeDevice:
  2870. ; case PlugPlayControlStartDevice:
  2871. ; case PlugPlayControlEjectDevice:
  2872. ; case PlugPlayControlUnlockDevice: PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA
  2873. ; case PlugPlayControlQueryAndRemoveDevice: PPLUGPLAY_CONTROL_QUERY_AND_REMOVE_DATA
  2874. ; case PlugPlayControlUserResponse: PPLUGPLAY_CONTROL_USER_RESPONSE_DATA
  2875. ; case PlugPlayControlGenerateLegacyDevice PPLUGPLAY_CONTROL_LEGACY_DEVGEN_DATA
  2876. ; case PlugPlayControlDetectResourceConflict PPLUGPLAY_CONTROL_DEVICE_RESOURCE_DATA
  2877. ; case PlugPlayControlQueryConflictList PPLUGPLAY_CONTROL_CONFLICT_DATA
  2878. ; case PlugPlayControlGetInterfaceDeviceList PPLUGPLAY_CONTROL_INTERFACE_LIST_DATA
  2879. ; case PlugPlayControlProperty PPLUGPLAY_CONTROL_PROPERTY_DATA
  2880. ; case PlugPlayControlDeviceClassAssociation PPLUGPLAY_CONTROL_CLASS_ASSOCIATION_DATA
  2881. ; case PlugPlayControlGetRelatedDevice PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA
  2882. ; case PlugPlayControlGetInterfaceDeviceAlias PPLUGPLAY_CONTROL_INTERFACE_ALIAS_DATA
  2883. ; case PlugPlayControlDeviceStatus PPLUGPLAY_CONTROL_STATUS_DATA
  2884. ; case PlugPlayControlGetDeviceDepth PPLUGPLAY_CONTROL_DEPTH_DATA
  2885. ; case PlugPlayControlQueryDeviceRelations PPLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA
  2886. ; case PlugPlayControlTargetDeviceRelation PPLUGPLAY_CONTROL_TARGET_RELATION_DATA
  2887. ; case PlugPlayControlRequestEject PLUGPLAY_CONTROL_REQUEST_EJECT
  2888. TemplateName=NtPlugPlayControl
  2889. Begin=
  2890. @GenUnsupportedNtApiThunk
  2891. End=
  2892. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2893. ;;
  2894. ;; All channel APIs currently return STATUS_NOT_IMPLEMENTED
  2895. ;; They will not be supported here either.
  2896. ;;
  2897. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2898. TemplateName=NtCreateChannel
  2899. Also=NtOpenChannel
  2900. Also=NtListenChannel
  2901. Also=NtSendWaitReplyChannel
  2902. Also=NtReplyWaitSendChannel
  2903. Also=NtSetContextChannel
  2904. Begin=
  2905. @GenUnsupportedNtApiThunk
  2906. End=
  2907. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2908. ;;
  2909. ;; LPC functions are supported, but the caller must be aware
  2910. ;; that the header has changed. See ntlpcapi.h for more info.
  2911. ;;
  2912. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2913. ;;These APIs are nothing special.
  2914. TemplateName=NtCreatePort
  2915. Also=NtCreateWaitablePort
  2916. Also=NtSecureConnectPort
  2917. Begin=
  2918. @GenApiThunk(@ApiName)
  2919. End=
  2920. ; These APIs take messages.
  2921. TemplateName=NtListenPort
  2922. Also=NtAcceptConnectPort
  2923. Also=NtCompleteConnectPort
  2924. Also=NtRequestPort
  2925. Also=NtReplyPort
  2926. Also=NtReplyWaitReplyPort
  2927. Also=NtReplyWaitReceivePort
  2928. Also=NtReplyWaitReceivePortEx
  2929. Also=NtImpersonateClientOfPort
  2930. Also=NtReadRequestData
  2931. Also=NtWriteRequestData
  2932. Begin=
  2933. @GenApiThunk(@ApiName)
  2934. End=
  2935. TemplateName=NtRequestWaitReplyPort
  2936. Locals=
  2937. PPORT_MESSAGE OriginalRequestMessage;
  2938. PPORT_MESSAGE OriginalReplyMessage;
  2939. UNALIGNED PORT_MESSAGE *UnalignedMessage;
  2940. ULONG RequestTotalLength, ReplyTotalLength;
  2941. End=
  2942. PreCall=
  2943. OriginalRequestMessage = RequestMessage;
  2944. OriginalReplyMessage = ReplyMessage;
  2945. if ((RequestMessage != NULL) &&
  2946. (((ULONG_PTR)RequestMessage & ((MAX_NATURAL_ALIGNMENT) - 1)) != 0)) {
  2947. UnalignedMessage = RequestMessage;
  2948. RequestTotalLength = UnalignedMessage->u1.s1.TotalLength;
  2949. RequestMessage = Wow64AllocateTemp (RequestTotalLength);
  2950. if (RequestMessage == NULL) {
  2951. RtlRaiseStatus (STATUS_NO_MEMORY);
  2952. }
  2953. RtlCopyMemory (RequestMessage, OriginalRequestMessage, RequestTotalLength);
  2954. }
  2955. if ((ReplyMessage != NULL) &&
  2956. (((ULONG_PTR)ReplyMessage & ((MAX_NATURAL_ALIGNMENT) - 1)) != 0)) {
  2957. if (OriginalReplyMessage == OriginalRequestMessage) {
  2958. ReplyMessage = RequestMessage;
  2959. ReplyTotalLength = RequestTotalLength;
  2960. } else {
  2961. UnalignedMessage = ReplyMessage;
  2962. ReplyTotalLength = sizeof (PORT_MESSAGE) + PORT_MAXIMUM_MESSAGE_LENGTH + sizeof(ULONGLONG);
  2963. ReplyMessage = Wow64AllocateTemp (ReplyTotalLength);
  2964. if (ReplyMessage == NULL) {
  2965. RtlRaiseStatus (STATUS_NO_MEMORY);
  2966. }
  2967. ReplyMessage->u1.s1.TotalLength = UnalignedMessage->u1.s1.TotalLength;
  2968. }
  2969. }
  2970. End=
  2971. Begin=
  2972. @GenApiThunk(@ApiName)
  2973. End=
  2974. PostCall=
  2975. if (OriginalRequestMessage != RequestMessage) {
  2976. RtlCopyMemory (OriginalRequestMessage, RequestMessage, RequestTotalLength);
  2977. }
  2978. if ((OriginalReplyMessage != ReplyMessage) &&
  2979. (ReplyMessage != RequestMessage)) {
  2980. UnalignedMessage = ReplyMessage;
  2981. RtlCopyMemory (OriginalReplyMessage, ReplyMessage, UnalignedMessage->u1.s1.TotalLength);
  2982. }
  2983. End=
  2984. ;; This API doesn't have any query fields defined.
  2985. TemplateName=NtQueryInformationPort
  2986. Begin=
  2987. @GenApiThunk(@ApiName)
  2988. End=
  2989. ;; This API has more restrictive alignment checking on Win64 than it
  2990. ;; did on Win32.
  2991. TemplateName=NtQueryFullAttributesFile
  2992. Locals=
  2993. FILE_NETWORK_OPEN_INFORMATION FileInformationLocal;
  2994. End=
  2995. PreCall=
  2996. FileInformation = &FileInformationLocal;
  2997. End=
  2998. PostCall=
  2999. try {
  3000. RtlCopyMemory((PVOID)FileInformationHost, &FileInformationLocal, sizeof(FileInformationLocal));
  3001. } except (EXCEPTION_EXECUTE_HANDLER) {
  3002. return GetExceptionCode ();
  3003. }
  3004. End=
  3005. TemplateName=NtWriteVirtualMemory
  3006. PreCall=
  3007. if (BaseAddress == Buffer && !WOW64IsCurrentProcess(ProcessHandle)) {
  3008. MEMORY_BASIC_INFORMATION mbi;
  3009. MEMORY_BASIC_INFORMATION mbiChild;
  3010. PROCESS_BASIC_INFORMATION pbi;
  3011. PVOID pLdr;
  3012. NTSTATUS st;
  3013. PIMAGE_NT_HEADERS32 NtHeaders;
  3014. PIMAGE_SECTION_HEADER SectionTable, LastSection, FirstSection, Section;
  3015. ULONG_PTR SrcVirtualAddress, DestVirtualAddress;
  3016. ULONG SubSectionSize;
  3017. // From mi\mi.h:
  3018. #define MI_ROUND_TO_SIZE(LENGTH,ALIGNMENT) \
  3019. (((LENGTH) + ((ALIGNMENT) - 1)) & ~((ALIGNMENT) - 1))
  3020. #define PAGE_SIZE_X86 (0x1000)
  3021. // Attempt to write to some child process, but the address in
  3022. // this process matches the address in the child. If the address
  3023. // is within the exe, then this is probably Cygnus. It creates
  3024. // the child suspended, writes a global var into the child exe,
  3025. // then resumes the child. Unfortunately, Wx86/WOW64 haven't
  3026. // reformatted the image yet, so the write goes to the wrong place.
  3027. st = NtQueryVirtualMemory(NtCurrentProcess(),
  3028. BaseAddress,
  3029. MemoryBasicInformation,
  3030. &mbi,
  3031. sizeof(mbi),
  3032. NULL);
  3033. if (!NT_SUCCESS(st)) {
  3034. // looks bad, the API call is probably going to fail
  3035. goto SkipHack;
  3036. }
  3037. if (mbi.Type != SEC_IMAGE || mbi.AllocationBase != NtCurrentPeb()->ImageBaseAddress) {
  3038. // Address isn't within the exe
  3039. goto SkipHack;
  3040. }
  3041. st = NtQueryVirtualMemory(ProcessHandle,
  3042. BaseAddress,
  3043. MemoryBasicInformation,
  3044. &mbiChild,
  3045. sizeof(mbiChild),
  3046. NULL);
  3047. if (!NT_SUCCESS(st)) {
  3048. goto SkipHack;
  3049. }
  3050. if (mbi.AllocationBase != mbiChild.AllocationBase ||
  3051. mbi.RegionSize != mbiChild.RegionSize ||
  3052. mbi.Type != mbiChild.Type) {
  3053. // Possibly different exes in parent and child
  3054. goto SkipHack;
  3055. }
  3056. st = NtQueryInformationProcess(ProcessHandle,
  3057. ProcessBasicInformation,
  3058. &pbi,
  3059. sizeof(pbi),
  3060. NULL);
  3061. if (!NT_SUCCESS(st)) {
  3062. goto SkipHack;
  3063. }
  3064. st = NtReadVirtualMemory(ProcessHandle,
  3065. (PVOID)((ULONG_PTR)pbi.PebBaseAddress+FIELD_OFFSET(PEB, Ldr)),
  3066. &pLdr,
  3067. sizeof(pLdr),
  3068. NULL);
  3069. if (!NT_SUCCESS(st)) {
  3070. goto SkipHack;
  3071. }
  3072. if (pLdr) {
  3073. // The child process' 64-bit loader sn't initialized.
  3074. // Assume the parent has already resumed it and knows
  3075. // what is going on.
  3076. goto SkipHack;
  3077. }
  3078. // Now... figure out where the write really needs to go
  3079. NtHeaders = (PIMAGE_NT_HEADERS32)RtlImageNtHeader(mbi.AllocationBase);
  3080. SectionTable = IMAGE_FIRST_SECTION(NtHeaders);
  3081. LastSection = SectionTable + NtHeaders->FileHeader.NumberOfSections;
  3082. if (SectionTable->PointerToRawData == SectionTable->VirtualAddress) {
  3083. // If the first section does not need to be moved then we exclude it
  3084. // from condideration in passes 1 and 2
  3085. FirstSection = SectionTable + 1;
  3086. } else {
  3087. FirstSection = SectionTable;
  3088. }
  3089. for (Section = FirstSection; Section < LastSection; Section++) {
  3090. SrcVirtualAddress = (ULONG_PTR)mbi.AllocationBase + Section->PointerToRawData;
  3091. DestVirtualAddress = (ULONG_PTR)mbi.AllocationBase + (ULONG_PTR)Section->VirtualAddress;
  3092. // Compute the subsection size
  3093. SubSectionSize = Section->SizeOfRawData;
  3094. if (Section->Misc.VirtualSize &&
  3095. SubSectionSize > MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86)) {
  3096. SubSectionSize = MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86);
  3097. }
  3098. if (SubSectionSize != 0 && Section->PointerToRawData != 0) {
  3099. // subsection has some meaning
  3100. if ((ULONG_PTR)BaseAddress >= DestVirtualAddress &&
  3101. (ULONG_PTR)BaseAddress < DestVirtualAddress+SubSectionSize) {
  3102. // the pointer points to within this Destination
  3103. // range for this subsection. Adjust it to point
  3104. // into the source range.
  3105. BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - DestVirtualAddress + SrcVirtualAddress);
  3106. LOGPRINT((TRACELOG, "whNtWriteVirtualMemory: Adjusted BaseAddress is %p\n", BaseAddress));
  3107. break;
  3108. }
  3109. }
  3110. }
  3111. SkipHack:;
  3112. }
  3113. End=
  3114. ;; per LandyW and Patrick Dussud (owner of the call to this API in msjava),
  3115. ;; wow64 will not support this. The problem is that the mm uses native
  3116. ;; page granularity, and we don't have a good way to convert the dirty
  3117. ;; bits to 4k granularity. The only way to make this API work is to
  3118. ;; have mm maintain 4k granularity itself.
  3119. TemplateName=NtGetWriteWatch
  3120. Begin=
  3121. @GenUnsupportedNtApiThunk
  3122. End=
  3123. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3124. ;;
  3125. ;; VDM is not supported on NT64
  3126. ;;
  3127. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3128. TemplateName=NtVdmControl
  3129. Begin=
  3130. @GenUnsupportedNtApiThunk
  3131. End=
  3132. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3133. ;;
  3134. ;; Debugging the kernel from a 32bit app is unsupported.
  3135. ;;
  3136. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3137. TemplateName=NtSystemDebugControl
  3138. Begin=
  3139. @GenUnsupportedNtApiThunk
  3140. End=
  3141. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3142. ;;
  3143. ;; AWE functions are not supported on wow64 since
  3144. ;; they are strongly page size dependent. They will
  3145. ;; mostly be called from large scale database servers which
  3146. ;; would benefit from porting.
  3147. ;;
  3148. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3149. TemplateName=NtMapUserPhysicalPages
  3150. Also=NtAllocateUserPhysicalPages
  3151. Also=NtFreeUserPhysicalPages
  3152. Also=NtMapUserPhysicalPagesScatter
  3153. Begin=
  3154. @GenUnsupportedNtApiThunk
  3155. End=
  3156. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3157. ;;
  3158. ;; File header
  3159. ;;
  3160. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3161. [Code]
  3162. TemplateName=whnt32
  3163. CGenBegin=
  3164. @NoFormat(
  3165. /*
  3166. * genthunk generated code: Do Not Modify
  3167. * PlaceHolderThunk for kernel transitions from ntdll.dll
  3168. *
  3169. */
  3170. #define _WOW64DLLAPI_
  3171. #define SECURITY_USERMODE // needed when including spmlpc.h
  3172. // For alpha 64 we emulate 4k pages for compatibility w/ intel
  3173. #define _WHNT32_C_
  3174. #include "nt32.h"
  3175. #include "cgenhdr.h"
  3176. #include <stdio.h>
  3177. #include <stdlib.h>
  3178. #include <malloc.h>
  3179. #include <windef.h>
  3180. #include <ntosdef.h>
  3181. #include <procpowr.h>
  3182. #if defined(_X86_)
  3183. #include <v86emul.h>
  3184. #include <i386.h>
  3185. #elif defined(_AMD64_)
  3186. #include <amd64.h>
  3187. #elif defined(_IA64_)
  3188. #include <v86emul.h>
  3189. #include <ia64.h>
  3190. #else
  3191. #error "No Target Architecture"
  3192. #endif
  3193. #include <arc.h>
  3194. #include <ke.h>
  3195. #include "wow64.h"
  3196. #include "wow64cpu.h"
  3197. #include "thnkhlpr.h"
  3198. #include "wow64warn.h"
  3199. #include "va.h"
  3200. ASSERTNAME;
  3201. #if defined(WOW64DOPROFILE)
  3202. #define APIPROFILE(apinum) (ptewhnt32[(apinum)].HitCount++)
  3203. #else
  3204. #define APIPROFILE(apinum)
  3205. #endif
  3206. #define _NTBASE_API_ 1 // Return NTSTATUS exception codes for the NtBase APIs
  3207. #define ROUND_UP(n,size) (((ULONG)(n) + (size - 1)) & ~(size - 1))
  3208. #pragma warning(disable : 4311) //Disable 'type cast' pointer truncation warning
  3209. #pragma warning(disable : 4244)
  3210. #pragma warning(disable : 4242)
  3211. #pragma warning(disable : 4047)
  3212. #if defined(WOW64DOPROFILE)
  3213. WOW64SERVICE_PROFILE_TABLE_ELEMENT ptewhnt32[];
  3214. #endif
  3215. )
  3216. #if defined(WOW64DOPROFILE) @NL
  3217. @ApiList(#define @ApiName_PROFILE_SUBLIST NULL @NL)
  3218. #endif @NL
  3219. #define IS_IOCTL_REALIGNMENT_REQUIRED(Ioctl) ((DEVICE_TYPE_FROM_CTL_CODE(Ioctl) == FILE_DEVICE_FILE_SYSTEM) && ((Ioctl & 3) == METHOD_NEITHER)) @NL
  3220. @NoFormat(
  3221. ULONG
  3222. whNT32DeepThunkSidAndAttributesArray64TO32Length(
  3223. IN ULONG ArrayLength,
  3224. IN PSID_AND_ATTRIBUTES Source
  3225. )
  3226. {
  3227. ULONG RequiredLength = 0;
  3228. if (!ArrayLength) return RequiredLength;
  3229. while(ArrayLength-- > 0) {
  3230. RequiredLength += sizeof(NT32SID_AND_ATTRIBUTES);
  3231. RequiredLength += RtlLengthSid(Source->Sid);
  3232. Source++;
  3233. }
  3234. return RequiredLength;
  3235. }
  3236. ULONG
  3237. whNT32DeepThunkSidAndAttributesArray32TO64Length(
  3238. IN ULONG ArrayLength,
  3239. IN NT32SID_AND_ATTRIBUTES *Source
  3240. )
  3241. {
  3242. ULONG RequiredLength = 0;
  3243. if (!ArrayLength) return RequiredLength;
  3244. while(ArrayLength-- > 0) {
  3245. RequiredLength += sizeof(SID_AND_ATTRIBUTES);
  3246. RequiredLength += RtlLengthSid((PSID)Source->Sid);
  3247. Source++;
  3248. }
  3249. return RequiredLength;
  3250. }
  3251. NT32SID_AND_ATTRIBUTES *
  3252. whNT32DeepThunkSidAndAttributesArray64TO32(
  3253. IN ULONG ArrayLength,
  3254. OUT NT32SID_AND_ATTRIBUTES *Dest,
  3255. IN PSID_AND_ATTRIBUTES Source
  3256. )
  3257. {
  3258. PSID SidDest;
  3259. NT32SID_AND_ATTRIBUTES *OriginalDest = Dest;
  3260. if (!ArrayLength) return (NT32SID_AND_ATTRIBUTES *)NULL;
  3261. SidDest = (PSID)(Dest + ArrayLength);
  3262. while(ArrayLength-- > 0) {
  3263. ULONG SidLength;
  3264. SidLength = RtlLengthSid(Source->Sid);
  3265. RtlCopySid(SidLength,
  3266. SidDest,
  3267. Source->Sid);
  3268. Dest->Sid = (NT32PSID)SidDest;
  3269. Dest->Attributes = Source->Attributes;
  3270. Dest++;
  3271. Source++;
  3272. SidDest = (PSID)((PBYTE)SidDest + SidLength);
  3273. }
  3274. return OriginalDest;
  3275. }
  3276. PSID_AND_ATTRIBUTES
  3277. whNT32DeepThunkSidAndAttributesArray32TO64(
  3278. IN ULONG ArrayLength,
  3279. OUT PSID_AND_ATTRIBUTES Dest,
  3280. IN NT32SID_AND_ATTRIBUTES *Source
  3281. )
  3282. {
  3283. PSID SidDest;
  3284. PSID_AND_ATTRIBUTES OriginalDest = Dest;
  3285. if (!ArrayLength) return NULL;
  3286. SidDest = (PSID)(Dest + ArrayLength);
  3287. while(ArrayLength-- > 0) {
  3288. ULONG SidLength;
  3289. SidLength = RtlLengthSid((PSID)Source->Sid);
  3290. RtlCopySid(SidLength,
  3291. SidDest,
  3292. (PSID)Source->Sid);
  3293. Dest->Sid = (PSID)SidDest;
  3294. Dest->Attributes = Source->Attributes;
  3295. Dest++;
  3296. Source++;
  3297. SidDest = (PSID)((PBYTE)SidDest + SidLength);
  3298. }
  3299. return OriginalDest;
  3300. }
  3301. ULONG
  3302. whNT32DeepThunkTokenGroups64TO32Length(
  3303. IN PTOKEN_GROUPS Src
  3304. )
  3305. {
  3306. if (!Src) return 0;
  3307. return sizeof(ULONG) +
  3308. whNT32DeepThunkSidAndAttributesArray64TO32Length(Src->GroupCount, Src->Groups);
  3309. }
  3310. ULONG
  3311. whNT32DeepThunkTokenGroups32TO64Length(
  3312. IN NT32TOKEN_GROUPS *Src
  3313. )
  3314. {
  3315. if (!Src) return 0;
  3316. return sizeof(ULONG) +
  3317. whNT32DeepThunkSidAndAttributesArray32TO64Length(Src->GroupCount, (NT32SID_AND_ATTRIBUTES*)Src->Groups);
  3318. }
  3319. NT32TOKEN_GROUPS *
  3320. whNT32DeepThunkTokenGroups64TO32(
  3321. OUT NT32TOKEN_GROUPS *Dst,
  3322. IN PTOKEN_GROUPS Src
  3323. )
  3324. {
  3325. if (!Src) return (NT32TOKEN_GROUPS *)Src;
  3326. Dst->GroupCount = Src->GroupCount;
  3327. whNT32DeepThunkSidAndAttributesArray64TO32(Src->GroupCount, (NT32SID_AND_ATTRIBUTES*)Dst->Groups, Src->Groups);
  3328. return Dst;
  3329. }
  3330. PTOKEN_GROUPS
  3331. whNT32DeepThunkTokenGroups32TO64(
  3332. OUT PTOKEN_GROUPS Dst,
  3333. IN NT32TOKEN_GROUPS *Src
  3334. )
  3335. {
  3336. if (!Src) return (PTOKEN_GROUPS)Src;
  3337. Dst->GroupCount = Src->GroupCount;
  3338. whNT32DeepThunkSidAndAttributesArray32TO64(Src->GroupCount, Dst->Groups, (NT32SID_AND_ATTRIBUTES*)Src->Groups);
  3339. return Dst;
  3340. }
  3341. PTOKEN_GROUPS
  3342. whNT32ShallowThunkAllocTokenGroups32TO64(
  3343. IN NT32TOKEN_GROUPS *Src
  3344. )
  3345. {
  3346. PTOKEN_GROUPS Dest;
  3347. ULONG GroupCount;
  3348. UINT c;
  3349. if(!Src) {
  3350. return (PTOKEN_GROUPS)Src;
  3351. }
  3352. GroupCount = Src->GroupCount;
  3353. Dest = Wow64AllocateTemp(sizeof(ULONG) + sizeof(SID_AND_ATTRIBUTES) * GroupCount);
  3354. Dest->GroupCount = GroupCount;
  3355. for(c=0; c<GroupCount; c++) {
  3356. Dest->Groups[c].Sid = (PSID)Src->Groups[c].Sid;
  3357. Dest->Groups[c].Attributes = Src->Groups[c].Attributes;
  3358. }
  3359. return Dest;
  3360. }
  3361. POBJECT_TYPE_LIST
  3362. whNT32ShallowThunkAllocObjectTypeList32TO64(
  3363. IN NT32OBJECT_TYPE_LIST *Src,
  3364. ULONG Elements
  3365. )
  3366. {
  3367. POBJECT_TYPE_LIST Dest;
  3368. SIZE_T c;
  3369. if (0 == Elements || !Src) {
  3370. return NULL;
  3371. }
  3372. Dest = Wow64AllocateTemp(sizeof(OBJECT_TYPE_LIST)*Elements);
  3373. for(c=0;c<Elements; c++) {
  3374. Dest[c].Level = Src[c].Level;
  3375. Dest[c].Sbz = Src[c].Sbz;
  3376. Dest[c].ObjectType = (GUID *)Src[c].ObjectType;
  3377. }
  3378. return Dest;
  3379. }
  3380. RTL_CRITICAL_SECTION HandleDataCriticalSection;
  3381. @Template(Thunks)
  3382. @NL
  3383. // All of the native NT APIs return an error code as the return parameter. @NL
  3384. // Thus, all that is needed is to return the exception code in the return value. @NL
  3385. @NL
  3386. // Exception code in return value. @NL
  3387. #define WOW64_DEFAULT_ERROR_ACTION ApiErrorNTSTATUS @NL
  3388. @NL
  3389. // This parameter is unused. @NL
  3390. #define WOW64_DEFAULT_ERROR_PARAM 0 @NL
  3391. @NL
  3392. // A case list is not needed for these APIs. @NL
  3393. #define WOW64_API_ERROR_CASES NULL @NL
  3394. @NL
  3395. @GenDispatchTable(sdwhnt32)
  3396. @NL
  3397. #if defined(WOW64DOPROFILE) @NL
  3398. @NL
  3399. WOW64SERVICE_PROFILE_TABLE_ELEMENT ptewhnt32[] = { @Indent( @NL
  3400. @ApiList({L"@ApiName", 0, @ApiName_PROFILE_SUBLIST, TRUE}, @NL)
  3401. {NULL, 0, NULL, TRUE} //For debugging @NL
  3402. )};@NL
  3403. @NL
  3404. @NL
  3405. WOW64SERVICE_PROFILE_TABLE ptwhnt32 = {L"WHNT32", L"NT Executive Thunks", ptewhnt32,
  3406. (sizeof(ptewhnt32)/sizeof(WOW64SERVICE_PROFILE_TABLE_ELEMENT))-1}; @NL
  3407. @NL
  3408. #endif @NL
  3409. CGenEnd=