public IEnumerable <StackEntry> WalkStack() { if (_machine.cs == 0 || _machine.ss == 0) { return(Enumerable.Empty <StackEntry>()); } var list = new List <StackEntry>(); list.Add(new StackEntry() { csip = BitUtils.MakeDWord(_machine.ip, _machine.cs), sp = _machine.sp, name = "cs:ip", }); try { var ss = _machine.ss; var bp = _machine.bp; var cs = _machine.cs; while (true) { var priorBP = _machine.MemoryBus.ReadWord(ss, bp); if (priorBP <= bp) { break; } uint returnAddress; bool farCall; if ((priorBP & 1) != 0) { // far call returnAddress = _machine.MemoryBus.ReadDWord(ss, (ushort)(bp + 2)); priorBP = (ushort)(priorBP & ~1); cs = (ushort)(returnAddress >> 16); farCall = true; } else { // near call returnAddress = (uint)(cs << 16 | _machine.MemoryBus.ReadWord(ss, (ushort)(bp + 2))); farCall = false; } list.Add(new StackEntry() { csip = returnAddress, sp = bp, name = string.Format("0x{0:X4}:{1:X4} {2} call bp = 0x{3:X4}", returnAddress.Hiword(), returnAddress.Loword(), farCall ? "far" : "near", bp), }); bp = priorBP; } return(list.Concat(_transitions).OrderBy(x => x.sp)); } catch { return(list.Concat(_transitions).OrderBy(x => x.sp)); } }
public uint GetString(string str) { if (str == null) { return(0); } // Already allocated? uint ptr; if (_strings.TryGetValue(str, out ptr)) { return(ptr); } // First time? if (_mem == 0) { _mem = _machine.GlobalHeap.Alloc("System String Heap", 0, 0x10000); } // Get the buffer and put the string in it var buf = _machine.GlobalHeap.GetBuffer(_mem, true); int len = buf.WriteString(_ofs, str); // Work out pointer for this string ptr = BitUtils.MakeDWord(_ofs, _mem); _strings.Add(str, ptr); // Update high water _ofs += (ushort)(len + 1); return(ptr); }
public uint SetWindowExt(HDC hDC, short x, short y) { Win32.SIZE size; SetWindowExtEx(hDC, x, y, out size); return(BitUtils.MakeDWord((ushort)(short)size.Width, (ushort)(short)size.Height)); }
public void EnterTransition(string name) { _transitions.Add(new StackEntry() { csip = BitUtils.MakeDWord(_machine.ip, _machine.cs), sp = _machine.sp, name = name, }); }
public uint StackAlloc <T>(T value) { var saveSP = sp; sp -= (ushort)Marshal.SizeOf <T>(); var ptr = BitUtils.MakeDWord(sp, ss); WriteStruct(ptr, ref value); return(ptr); }
public uint GetTextExtent(HDC hDC, uint pszString, short cbString) { var str = _machine.GlobalHeap.ReadCharacters(pszString, cbString); Win32.SIZE size; if (!GetTextExtentPoint(hDC, str, cbString, out size)) { return(0xFFFFFFFF); } return(BitUtils.MakeDWord((ushort)(short)size.Width, (ushort)(short)size.Height)); }
public uint GlobalHandle(ushort selector) { var sel = _machine.GlobalHeap.GetSelector(selector); if (sel == null) { return(0); } System.Diagnostics.Debug.Assert(sel.selector == selector); return(BitUtils.MakeDWord(selector, selector)); }
public uint SysAllocString(string str) { if (str == null) { return(0); } var data = AnsiEncoding.GetBytes(str); var ptr_near = _systemDataHeap.Alloc(Win16.LMEM_FIXED, (ushort)(data.Length + 1)); var ptr_far = BitUtils.MakeDWord(ptr_near, _systemDataHeap.GlobalHandle); this.WriteString(ptr_far, str, (ushort)(data.Length + 1)); return(ptr_far); }
public ushort SetMetaFileBits(ushort handle) { if (handle == 0) { return(0); } // Get size of global allocation uint size = _machine.GlobalHeap.Size(handle); // Get pointer var hp = _machine.GlobalHeap.GetHeapPointer(BitUtils.MakeDWord(0, handle), false); var hEnhMetaFile = SetMetaFileBitsEx(size, hp); return(HENHMETAFILE.To16(hEnhMetaFile)); }
public override void Init(Machine machine) { var autoSeg = DataSegment; if (IsDll) { if (_neFile.Header.EntryPoint != 0) { var saveds = machine.ds; // Call Library entry point machine.di = hModule; machine.ds = autoSeg == null ? (ushort)0 : autoSeg.globalHandle; machine.cx = _neFile.Header.InitHeapSize; // Find entry point var ip = (ushort)(_neFile.Header.EntryPoint & 0xFFFF); var cs = _neFile.Segments[(int)((_neFile.Header.EntryPoint >> 16) - 1)].globalHandle; // Call it machine.CallVM(BitUtils.MakeDWord(ip, cs), "LibMain"); // Restore DS machine.ds = saveds; } } else { // Create the local heap if (autoSeg != null) { var heapBaseAddress = (ushort)(autoSeg.allocationBytes + (IsDll ? 0 : _neFile.Header.InitStackSize)); var heapSize = _neFile.Header.InitHeapSize; machine.GlobalHeap.CreateLocalHeap(autoSeg.globalHandle, heapBaseAddress, heapSize); } } }
public uint ToDWord() { var pt16 = Convert(); return(BitUtils.MakeDWord((ushort)pt16.X, (ushort)pt16.Y)); }
object ReadParamFromStack(Type pt, ParameterInfo pi) { if (pt == null) { pt = pi.ParameterType; } if (pt == typeof(ushort)) { var val = _machine.ReadWord(_machine.ss, _paramPos); _paramPos += 2; return(val); } if (pt == typeof(short)) { var val = unchecked ((short)_machine.ReadWord(_machine.ss, _paramPos)); _paramPos += 2; return(val); } if (pt == typeof(byte)) { var val = _machine.ReadByte(_machine.ss, _paramPos); _paramPos += 2; return(val); } if (pt == typeof(uint)) { var val = _machine.ReadDWord(_machine.ss, _paramPos); _paramPos += 4; return(val); } if (pt == typeof(int)) { var val = unchecked ((int)_machine.ReadDWord(_machine.ss, _paramPos)); _paramPos += 4; return(val); } if (pt == typeof(string)) { var ptrOffset = _machine.ReadWord(_machine.ss, _paramPos); var ptrSeg = _machine.ReadWord(_machine.ss, (ushort)(_paramPos + 2)); var val = _machine.ReadString(ptrSeg, ptrOffset); _paramPos += 4; if (pi != null) { var fna = pi.GetCustomAttribute <FileNameAttribute>(); if (fna != null) { val = _machine.PathMapper.MapGuestToHost(val, fna.ForWrite); } } return(val); } if (pt == typeof(StringOrId)) { var ptrOffset = _machine.ReadWord(_machine.ss, _paramPos); var ptrSeg = _machine.ReadWord(_machine.ss, (ushort)(_paramPos + 2)); var val = new StringOrId(_machine, BitUtils.MakeDWord(ptrOffset, ptrSeg)); _paramPos += 4; return(val); } if (pt == typeof(bool)) { var val = _machine.ReadWord(_machine.ss, _paramPos) != 0; _paramPos += 2; return(val); } if (pt == typeof(StringBuilder)) { // Capture stuff, we'll do it later int paramIndex = _currentParameterIndex; // Get input string pointer var ptrOffset = _machine.ReadWord(_machine.ss, _paramPos); var ptrSeg = _machine.ReadWord(_machine.ss, (ushort)(_paramPos + 2)); _paramPos += 4; int capacity = 0; bool isOut = pi.GetCustomAttribute <OutAttribute>() != null; bool isIn = pi.GetCustomAttribute <InAttribute>() != null; var fna = pi.GetCustomAttribute <FileNameAttribute>(); RegisterPreInvokeCallback(() => { // Work out buffer size capacity var bufsize = pi.GetCustomAttribute <BufSizeAttribute>(); int bufsizeParamIndex = paramIndex + bufsize.ParamDX; var type = _paramValues[bufsizeParamIndex].GetType(); if (type == typeof(int)) { capacity = (int)_paramValues[bufsizeParamIndex]; } else if (type == typeof(ushort)) { capacity = (int)(ushort)_paramValues[bufsizeParamIndex]; } else if (type == typeof(nint)) { capacity = (nint)_paramValues[bufsizeParamIndex]; } else { throw new NotImplementedException(); } // Create string builder var sb = new StringBuilder(fna != null ? 512 : capacity); if (isIn) { var str = _machine.ReadString(ptrSeg, ptrOffset, (ushort)capacity); if (fna != null) { _machine.PathMapper.MapGuestToHost(str, fna.ForWrite); } sb.Append(str); } // Return the string builder _paramValues[paramIndex] = sb; }); if (isOut) { RegisterPostInvokeCallback(() => { var str = _paramValues[paramIndex].ToString(); if (fna != null) { str = _machine.PathMapper.MapHostToGuest(str, fna.ForWrite); } _machine.WriteString(ptrSeg, ptrOffset, str, (ushort)capacity); }); } return(null); // We'll fill it in later } if (pt == typeof(Win32.POINT)) { var x = unchecked ((short)_machine.ReadWord(_machine.ss, _paramPos)); var y = unchecked ((short)_machine.ReadWord(_machine.ss, (ushort)(_paramPos + 2))); _paramPos += 4; return(new Win32.POINT(x, y)); } if (pt == typeof(IntPtr)) { if (pi != null) { if (pi.GetCustomAttribute <MustBeNullAttribute>() == null) { throw new NotImplementedException("IntPtr parameters must have MustBeNull attribute"); } } var ptrOffset = _machine.ReadWord(_machine.ss, _paramPos); var ptrSeg = _machine.ReadWord(_machine.ss, (ushort)(_paramPos + 2)); _paramPos += 4; if (ptrOffset != 0 || ptrSeg != 0) { throw new NotImplementedException("Non-null IntPtr parameter passed"); } return(IntPtr.Zero); } if (MappedTypeAttribute.Is(pt)) { var convertMethod = pt.GetMethod("To32"); // Read the 16-bit value var val16 = ReadParamFromStack(convertMethod.GetParameters()[0].ParameterType, null); // Convert it var val32 = convertMethod.Invoke(null, new object[] { val16 }); if (ShouldDestroy(pi)) { RegisterPostInvokeCallback(() => { var destroyMethod = pt.GetMethod("Destroy"); destroyMethod.Invoke(null, new object[] { val16 }); }); } return(val32); } if (pt.IsByRef) { var underlyingType = pt.GetElementType(); if (underlyingType.IsValueType) { var ptr = _machine.ReadDWord(_machine.ss, _paramPos); object val; if (pi == null || !pi.IsOut) { if (MappedTypeAttribute.Is(underlyingType)) { var convertMethod = underlyingType.GetMethod("To32"); val = _machine.ReadStruct(convertMethod.GetParameters()[0].ParameterType, ptr); val = convertMethod.Invoke(null, new object[] { val }); } else { val = _machine.ReadStruct(underlyingType, ptr); } } else { val = Activator.CreateInstance(underlyingType); } _paramPos += 4; if (pi.GetCustomAttribute <InAttribute>() == null) { int index = _currentParameterIndex; RegisterPostInvokeCallback(() => { val = _paramValues[index]; if (MappedTypeAttribute.Is(underlyingType)) { var convertMethod = underlyingType.GetMethod("To16"); val = convertMethod.Invoke(null, new object[] { val }); } if (ptr != 0) { _machine.WriteStruct(ptr, val); } }); } return(val); } } throw new NotImplementedException(string.Format("Parameter type not supported by thunking layer - {0}", pt)); }
public uint GetFreeSpace() { return(BitUtils.MakeDWord(0, (ushort)_selectorAllocator.FreeSpace)); }
public uint GlobalLock(ushort handle) { return(BitUtils.MakeDWord(0, handle)); }
public uint GetDosEnvironment() { return(BitUtils.MakeDWord(0, _machine.GetDosEnvironmentSegment())); }