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.

363 lines
8.8 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <vdm.h>
  6. #include "insignia.h"
  7. #include "host_def.h"
  8. #include <stdlib.h>
  9. #include "xt.h"
  10. #include "error.h"
  11. #include "host_rrr.h"
  12. #include "host_nls.h"
  13. #include "nt_timer.h"
  14. void CpuEnvInit(void);
  15. typedef struct _CpuEnvironmentVariable {
  16. struct _CpuEnvironmentVariable *Next;
  17. char *Data;
  18. char Name[1];
  19. } CPUENVVAR, *PCPUENVVAR;
  20. PCPUENVVAR CpuEnvVarListHead=NULL;
  21. #if DBG
  22. BOOLEAN verboseGetenv;
  23. #endif
  24. INT host_main(INT argc, CHAR **argv); // located in base\support\main.c
  25. __cdecl main(int argc, CHAR ** argv)
  26. {
  27. int ret=-1;
  28. /*
  29. * Intialize synchronization events for the timer\heartbeat
  30. * so that we can always suspend the heartbeat when an exception
  31. * occurs.
  32. */
  33. TimerInit();
  34. try {
  35. CpuEnvInit();
  36. /*
  37. * Load in the default system error message, since a resource load
  38. * will fail when we are out of memory, if this fails we must exit
  39. * to avoid confusion.
  40. */
  41. nls_init();
  42. ret = host_main(argc, argv);
  43. }
  44. except(VdmUnhandledExceptionFilter(GetExceptionInformation())) {
  45. ; // we shouldn't arrive here
  46. }
  47. return ret;
  48. }
  49. //
  50. // The following function is placed here, so build will resolve references to
  51. // DbgBreakPoint here, instead of NTDLL.
  52. //
  53. VOID
  54. DbgBreakPoint(
  55. VOID
  56. )
  57. /*++
  58. Routine Description:
  59. This routine is a substitute for the NT DbgBreakPoint routine.
  60. If a user mode debugger is atached we invoke the real DbgBreakPoint()
  61. thru the win32 api DebugBreak.
  62. If no usermode debugger is attached:
  63. - free build no effect
  64. - checked build raise an acces violation to invoke the system
  65. hard error popup which will give user a chance to invoke
  66. ntsd.
  67. Arguments:
  68. None.
  69. Return Value:
  70. None.
  71. --*/
  72. {
  73. HANDLE MyDebugPort;
  74. DWORD dw;
  75. // are we being debugged ??
  76. dw = NtQueryInformationProcess(
  77. NtCurrentProcess(),
  78. ProcessDebugPort,
  79. &MyDebugPort,
  80. sizeof(MyDebugPort),
  81. NULL );
  82. if (!NT_SUCCESS(dw) || MyDebugPort == NULL) {
  83. #ifndef PROD
  84. RaiseException(STATUS_ACCESS_VIOLATION, 0L, 0L, NULL);
  85. #endif
  86. return;
  87. }
  88. DebugBreak();
  89. }
  90. /*
  91. * Softpc env variables are mapped to the registry
  92. *
  93. * "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\WOW\CpuEnv"
  94. *
  95. * The string values for the CpuEnv key are read at initialization
  96. * into the CpuEnv linked list. The Environment variables are defined
  97. * as string key values, where the name of the value is equivalent to
  98. * the Cpu Environment Variable name, and the string value is equivalent
  99. * to the value of the environment variable value. This allows the
  100. * emulator defaults to be overridden, by adding the appropriate value
  101. * to CpuEnv subkey. Under standard retail setup there won't normally
  102. * be a CpuEnv subkey, and NO cpu env variables defined to minimize
  103. * code\data on a standard retail system.
  104. *
  105. */
  106. /*
  107. * Adds a CpuEnv KEY_VALUE_FULL_INFORMATION to the CpuEnvList
  108. */
  109. BOOLEAN
  110. AddToCpuEnvList(
  111. PKEY_VALUE_FULL_INFORMATION KeyValueInfo
  112. )
  113. {
  114. NTSTATUS Status;
  115. ULONG BufferSize;
  116. PCPUENVVAR CpuEnvVar;
  117. UNICODE_STRING UnicodeString;
  118. ANSI_STRING ValueName;
  119. ANSI_STRING ValueData;
  120. char NameBuffer[MAX_PATH+sizeof(WCHAR)];
  121. char DataBuffer[MAX_PATH+sizeof(WCHAR)];
  122. /*
  123. * Convert Value Name and Data strings from unicode to ansi
  124. */
  125. ValueName.Buffer = NameBuffer;
  126. ValueName.MaximumLength = sizeof(NameBuffer) - sizeof(WCHAR);
  127. ValueName.Length = 0;
  128. UnicodeString.Buffer = (PWSTR)KeyValueInfo->Name;
  129. UnicodeString.MaximumLength =
  130. UnicodeString.Length = (USHORT)KeyValueInfo->NameLength;
  131. Status = RtlUnicodeStringToAnsiString(&ValueName, &UnicodeString,FALSE);
  132. if (!NT_SUCCESS(Status)) {
  133. return FALSE;
  134. }
  135. ValueData.Buffer = DataBuffer;
  136. ValueData.MaximumLength = sizeof(DataBuffer) - sizeof(WCHAR);
  137. ValueData.Length = 0;
  138. UnicodeString.Buffer = (PWSTR)((PBYTE)KeyValueInfo + KeyValueInfo->DataOffset);
  139. UnicodeString.MaximumLength =
  140. UnicodeString.Length = (USHORT)KeyValueInfo->DataLength;
  141. Status = RtlUnicodeStringToAnsiString(&ValueData, &UnicodeString, FALSE);
  142. if (!NT_SUCCESS(Status)) {
  143. return FALSE;
  144. }
  145. /*
  146. * Allocate CPUENVLIST structure, with space for the ansi strings
  147. */
  148. CpuEnvVar = malloc(sizeof(CPUENVVAR)+ // list structure size
  149. ValueName.Length + // strlen Name
  150. ValueData.Length + // strlen Data
  151. 1 // Null for Data
  152. );
  153. if (!CpuEnvVar) {
  154. return FALSE;
  155. }
  156. /*
  157. * Copy in the ansi strings, and link it into CpuEnvVar List
  158. */
  159. memcpy(CpuEnvVar->Name, ValueName.Buffer, ValueName.Length);
  160. *(CpuEnvVar->Name + ValueName.Length) = '\0';
  161. CpuEnvVar->Data = CpuEnvVar->Name + ValueName.Length + 1;
  162. memcpy(CpuEnvVar->Data, ValueData.Buffer, ValueData.Length);
  163. *(CpuEnvVar->Data + ValueData.Length) = '\0';
  164. CpuEnvVar->Next = CpuEnvVarListHead;
  165. CpuEnvVarListHead = CpuEnvVar;
  166. return TRUE;
  167. }
  168. /*
  169. * Reads the CpuEnv values from the registry, into CpuEnvList
  170. */
  171. void
  172. CpuEnvInit(
  173. void
  174. )
  175. {
  176. int Index;
  177. NTSTATUS Status;
  178. HANDLE CpuEnvKey = NULL;
  179. ULONG ResultLength;
  180. UNICODE_STRING UnicodeString;
  181. OBJECT_ATTRIBUTES ObjectAttributes;
  182. PKEY_VALUE_FULL_INFORMATION KeyValueInfo;
  183. BYTE NameDataBuffer[sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_PATH*2*sizeof(WCHAR)];
  184. //
  185. // Initialize TEB->Vdm to current version number
  186. //
  187. Index = (GetTickCount() << 16) | 0x80000000;
  188. Index |= sizeof(VDM_TIB) + sizeof(VDMVIRTUALICA) + sizeof(VDMICAUSERDATA);
  189. NtCurrentTeb()->Vdm = (PVOID)Index;
  190. KeyValueInfo = (PKEY_VALUE_FULL_INFORMATION) NameDataBuffer;
  191. #ifndef MONITOR
  192. /*
  193. * BUGBUG temp hack code to add two env var, which aren't properly
  194. * defaulted to in the risc cpu emulator
  195. *
  196. * THIS is to be removed before SUR ship 19-Dec-1995 Jonle
  197. */
  198. {
  199. PWCHAR Data;
  200. wcscpy(KeyValueInfo->Name, L"Soft486Buffers");
  201. KeyValueInfo->NameLength = wcslen(KeyValueInfo->Name) * sizeof(WCHAR);
  202. Data = (PWCH)((PBYTE)KeyValueInfo->Name + KeyValueInfo->NameLength + sizeof(WCHAR));
  203. wcscpy(Data, L"511");
  204. KeyValueInfo->DataLength = wcslen(Data) * sizeof(WCHAR);
  205. KeyValueInfo->DataOffset = (PBYTE)Data - (PBYTE)KeyValueInfo;
  206. AddToCpuEnvList(KeyValueInfo);
  207. wcscpy(KeyValueInfo->Name, L"LCIF_FILENAME");
  208. KeyValueInfo->NameLength = wcslen(KeyValueInfo->Name) * sizeof(WCHAR);
  209. Data = (PWCH)((PBYTE)KeyValueInfo->Name + KeyValueInfo->NameLength + sizeof(WCHAR));
  210. wcscpy(Data, L"R lcif");
  211. KeyValueInfo->DataLength = wcslen(Data) * sizeof(WCHAR);
  212. KeyValueInfo->DataOffset = (PBYTE)Data - (PBYTE)KeyValueInfo;
  213. AddToCpuEnvList(KeyValueInfo);
  214. }
  215. #endif
  216. RtlInitUnicodeString(
  217. &UnicodeString,
  218. L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Wow\\CpuEnv"
  219. );
  220. InitializeObjectAttributes(&ObjectAttributes,
  221. &UnicodeString,
  222. OBJ_CASE_INSENSITIVE,
  223. (HANDLE)NULL,
  224. NULL
  225. );
  226. Status = NtOpenKey(&CpuEnvKey,
  227. KEY_READ,
  228. &ObjectAttributes
  229. );
  230. //
  231. // If there is no CpuEnv key, CpuEnvList is empty.
  232. //
  233. if (!NT_SUCCESS(Status)) {
  234. return;
  235. }
  236. Index = 0;
  237. while (TRUE) {
  238. Status = NtEnumerateValueKey(CpuEnvKey,
  239. Index,
  240. KeyValueFullInformation,
  241. KeyValueInfo,
  242. sizeof(NameDataBuffer),
  243. &ResultLength
  244. );
  245. if (!NT_SUCCESS(Status) || !AddToCpuEnvList(KeyValueInfo)) {
  246. break;
  247. }
  248. Index++;
  249. };
  250. NtClose(CpuEnvKey);
  251. #if DBG
  252. {
  253. char *pEnvStr;
  254. pEnvStr = getenv("VERBOSE_GETENV");
  255. verboseGetenv = pEnvStr && !_stricmp(pEnvStr, "TRUE");
  256. }
  257. #endif
  258. }
  259. /*
  260. * In order to catch all references, we define our own
  261. * version of the CRT getenv, which does the mapping.
  262. */
  263. char * __cdecl getenv(const char *Name)
  264. {
  265. PCPUENVVAR CpuEnvVar;
  266. char *Value = NULL;
  267. CpuEnvVar = CpuEnvVarListHead;
  268. while (CpuEnvVar) {
  269. if (!_stricmp(CpuEnvVar->Name, Name)) {
  270. Value = CpuEnvVar->Data;
  271. break;
  272. }
  273. CpuEnvVar = CpuEnvVar->Next;
  274. }
  275. #if DBG
  276. if (verboseGetenv) {
  277. DbgPrint("getenv %s:<%s>\n", Name, Value);
  278. }
  279. #endif
  280. return Value;
  281. }