From 686119c7dd4f6f6341bdcbfa0eda1ce20a9ee9e4 Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Sat, 28 Oct 2023 05:04:41 -0700 Subject: [PATCH] organize and cleanup a ton of win32 imports, do cleanup elsewhere with that --- .../KeyInput/RawKeyInput.cs | 6 +- .../SDL2/SDL2InputAdapter.cs | 6 +- src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs | 409 +++++++++--------- .../CustomControls/FolderBrowserDialogEx.cs | 70 ++- .../CustomControls/InputWidget.cs | 11 +- .../Extensions/ControlExtensions.cs | 43 +- .../tools/SNES/SNESGraphicsDebugger.cs | 4 +- .../Extensions/PathExtensions.cs | 2 +- .../MemoryBlock/MemoryBlockWindowsPal.cs | 2 +- src/BizHawk.Common/Win32/AVIWriterImports.cs | 13 +- src/BizHawk.Common/Win32/CWDHacks.cs | 68 ++- src/BizHawk.Common/Win32/CommctrlImports.cs | 57 +++ src/BizHawk.Common/Win32/HeapApiImports.cs | 22 + ...Kernel32Imports.cs => MemoryApiImports.cs} | 3 +- src/BizHawk.Common/Win32/MotWHack.cs | 3 +- src/BizHawk.Common/Win32/ShellLinkImports.cs | 20 +- src/BizHawk.Common/Win32/ShlobjImports.cs | 93 ++++ src/BizHawk.Common/Win32/ThreadHacks.cs | 26 +- src/BizHawk.Common/Win32/Win32Imports.cs | 208 +-------- .../Win32/Win32ShellContextMenu.cs | 5 + src/BizHawk.Common/Win32/WmImports.cs | 90 ++++ .../N64/NativeApi/mupen64plusCoreApi.cs | 10 +- 22 files changed, 654 insertions(+), 517 deletions(-) create mode 100644 src/BizHawk.Common/Win32/CommctrlImports.cs create mode 100644 src/BizHawk.Common/Win32/HeapApiImports.cs rename src/BizHawk.Common/Win32/{Kernel32Imports.cs => MemoryApiImports.cs} (91%) create mode 100644 src/BizHawk.Common/Win32/ShlobjImports.cs create mode 100644 src/BizHawk.Common/Win32/WmImports.cs diff --git a/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs b/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs index adcf38a00a..6e8e543e4d 100644 --- a/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs +++ b/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs @@ -9,7 +9,7 @@ using BizHawk.Common; using BizHawk.Common.CollectionExtensions; using static BizHawk.Common.RawInputImports; -using static BizHawk.Common.Win32Imports; +using static BizHawk.Common.WmImports; using RawKey = Vortice.DirectInput.Key; @@ -35,7 +35,7 @@ namespace BizHawk.Bizware.Input { var wc = default(WNDCLASS); wc.lpfnWndProc = _wndProc; - wc.hInstance = GetModuleHandle(null); + wc.hInstance = Win32Imports.GetModuleHandle(null); wc.lpszClassName = "RawKeyInputClass"; var atom = RegisterClass(ref wc); @@ -125,7 +125,7 @@ namespace BizHawk.Bizware.Input nHeight: 1, hWndParent: HWND_MESSAGE, hMenu: IntPtr.Zero, - hInstance: GetModuleHandle(null), + hInstance: Win32Imports.GetModuleHandle(null), lpParam: IntPtr.Zero); if (window == IntPtr.Zero) diff --git a/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs b/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs index bad8f912eb..dcdb9dbae2 100644 --- a/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs +++ b/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs @@ -46,10 +46,10 @@ namespace BizHawk.Bizware.Input // similar code shouldn't be needed on other platforms (which have global message queues and not thread local message queues) if (!OSTailoredCode.IsUnixHost) { - while (Win32Imports.PeekMessage(out var msg, IntPtr.Zero, 0, 0, Win32Imports.PM_REMOVE)) + while (WmImports.PeekMessage(out var msg, IntPtr.Zero, 0, 0, WmImports.PM_REMOVE)) { - Win32Imports.TranslateMessage(ref msg); - Win32Imports.DispatchMessage(ref msg); + WmImports.TranslateMessage(ref msg); + WmImports.DispatchMessage(ref msg); } } diff --git a/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs index 326d52405d..fec7b679ae 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs @@ -12,6 +12,8 @@ using BizHawk.Common; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.Common; +using static BizHawk.Common.HeapApiImports; + // some helpful p/invoke from http://www.codeproject.com/KB/audio-video/Motion_Detection.aspx?msg=1142967 namespace BizHawk.Client.EmuHawk { @@ -19,7 +21,7 @@ namespace BizHawk.Client.EmuHawk "Uses the Microsoft AVIFIL32 system to write .avi files. Audio is uncompressed; Video can be compressed with any installed VCM codec. Splits on 2G and resolution change.")] internal class AviWriter : IVideoWriter { - private CodecToken _currVideoCodecToken = null; + private CodecToken _currVideoCodecToken; private AviWriterSegment _currSegment; private readonly IDialogParent _dialogParent; @@ -35,9 +37,7 @@ namespace BizHawk.Client.EmuHawk private bool IsOpen => _nameProvider != null; public void Dispose() - { - _currSegment?.Dispose(); - } + => _currSegment?.Dispose(); /// sets the codec token to be used for video compression /// does not inherit @@ -57,12 +57,16 @@ namespace BizHawk.Client.EmuHawk { var (dir, baseName, ext) = template.SplitPathToDirFileAndExt(); yield return template; - int counter = 1; - for (;;) + var counter = 1; + while (counter < int.MaxValue) { yield return Path.Combine(dir, $"{baseName}_{counter}{ext}"); counter++; } + + yield return Path.Combine(dir, $"{baseName}_{counter}{ext}"); + + throw new InvalidOperationException("Reached maximum names"); } /// @@ -70,9 +74,7 @@ namespace BizHawk.Client.EmuHawk /// set a video codec token first. /// public void OpenFile(string baseName) - { - OpenFile(CreateBasicNameProvider(baseName)); - } + => OpenFile(CreateBasicNameProvider(baseName)); // thread communication // synchronized queue with custom messages @@ -86,19 +88,18 @@ namespace BizHawk.Client.EmuHawk { while (true) { - object o = _threadQ.Take(); - if (o is IVideoProvider provider) + var o = _threadQ.Take(); + switch (o) { - AddFrameEx(provider); - } - else if (o is short[] arr) - { - AddSamplesEx(arr); - } - else - { - // anything else is assumed to be quit time - return; + case IVideoProvider provider: + AddFrameEx(provider); + break; + case short[] arr: + AddSamplesEx(arr); + break; + default: + // anything else is assumed to be quit time + return; } } } @@ -121,6 +122,7 @@ namespace BizHawk.Client.EmuHawk public int BackgroundColor { get; } public int VsyncNumerator { get; } public int VsyncDenominator { get; } + public VideoCopy(IVideoProvider c) { _vb = (int[])c.GetVideoBuffer().Clone(); @@ -134,9 +136,7 @@ namespace BizHawk.Client.EmuHawk } public int[] GetVideoBuffer() - { - return _vb; - } + => _vb; } /// opens an avi file for recording, with being used to name files @@ -149,14 +149,14 @@ namespace BizHawk.Client.EmuHawk throw new InvalidOperationException("Tried to start recording an AVI with no video codec token set"); } - _threadQ = new System.Collections.Concurrent.BlockingCollection(30); - _workerT = new System.Threading.Thread(new System.Threading.ThreadStart(ThreadProc)); + _threadQ = new(30); + _workerT = new(ThreadProc) { IsBackground = true }; _workerT.Start(); } public void CloseFile() { - _threadQ.Add(new object()); // acts as stop message + _threadQ.Add(new()); // acts as stop message _workerT.Join(); _currSegment?.Dispose(); _currSegment = null; @@ -169,7 +169,7 @@ namespace BizHawk.Client.EmuHawk { if (!_workerT.IsAlive) { - throw new Exception("AVI Worker thread died!"); + throw new("AVI Worker thread died!"); } } } @@ -183,7 +183,7 @@ namespace BizHawk.Client.EmuHawk Segment(); } - _currSegment.AddFrame(source); + _currSegment!.AddFrame(source); } /// worker thrread died @@ -195,7 +195,7 @@ namespace BizHawk.Client.EmuHawk { if (!_workerT.IsAlive) { - throw new Exception("AVI Worker thread died!"); + throw new("AVI Worker thread died!"); } } } @@ -208,7 +208,7 @@ namespace BizHawk.Client.EmuHawk Segment(); } - _currSegment.AddSamples(samples); + _currSegment!.AddSamples(samples); } private void ConsiderLengthSegment() @@ -218,7 +218,7 @@ namespace BizHawk.Client.EmuHawk return; } - long len = _currSegment.GetLengthApproximation(); + var len = _currSegment.GetLengthApproximation(); const long segment_length_limit = 2 * 1000 * 1000 * 1000; // 2GB // const long segment_length_limit = 10 * 1000 * 1000; //for testing @@ -228,11 +228,6 @@ namespace BizHawk.Client.EmuHawk } } - private void StartRecording() - { - // i guess theres nothing to do here - } - private void Segment() { if (!IsOpen) @@ -240,18 +235,12 @@ namespace BizHawk.Client.EmuHawk return; } - if (_currSegment == null) - { - StartRecording(); - } - else - { - _currSegment.Dispose(); - } + _currSegment?.Dispose(); + _currSegment = new(); - _currSegment = new AviWriterSegment(); _nameProvider.MoveNext(); _currSegment.OpenFile(_nameProvider.Current, _parameters, _currVideoCodecToken); + try { _currSegment.OpenStreams(); @@ -278,17 +267,25 @@ namespace BizHawk.Client.EmuHawk a_samplerate = 44100, a_channels = 2 }; - var temp = new AviWriterSegment(); - string tempfile = Path.GetTempFileName(); - File.Delete(tempfile); - tempfile = Path.ChangeExtension(tempfile, "avi"); - temp.OpenFile(tempfile, tempParams, null); - var ret = temp.AcquireVideoCodecToken(_dialogParent.AsWinFormsHandle().Handle, _currVideoCodecToken); - CodecToken token = (CodecToken)ret; - config.AviCodecToken = token?.Serialize(); - temp.CloseFile(); - File.Delete(tempfile); - return token; + + var tempSegment = new AviWriterSegment(); + var tempFile = Path.GetTempFileName(); + File.Delete(tempFile); + tempFile = Path.ChangeExtension(tempFile, "avi"); + tempSegment.OpenFile(tempFile, tempParams, null); + + try + { + var ret = tempSegment.AcquireVideoCodecToken(_dialogParent.AsWinFormsHandle().Handle, _currVideoCodecToken); + var token = (CodecToken)ret; + config.AviCodecToken = token?.Serialize(); + return token; + } + finally + { + tempSegment.CloseFile(); + File.Delete(tempFile); + } } private class Parameters @@ -329,11 +326,18 @@ namespace BizHawk.Client.EmuHawk public void PopulateWAVEFORMATEX(ref AVIWriterImports.WAVEFORMATEX wfex) { const int WAVE_FORMAT_PCM = 1; - int bytes = 0; - if (a_bits == 16) bytes = 2; - else if (a_bits == 8) bytes = 1; - else throw new InvalidOperationException($"only 8/16 bits audio are supported by {nameof(AviWriter)} and you chose: {a_bits}"); - if (a_channels is not (1 or 2)) throw new InvalidOperationException($"only 1/2 channels audio are supported by {nameof(AviWriter)} and you chose: {a_channels}"); + var bytes = a_bits switch + { + 16 => 2, + 8 => 1, + _ => throw new InvalidOperationException($"only 8/16 bits audio are supported by {nameof(AviWriter)} and you chose: {a_bits}") + }; + + if (a_channels is not (1 or 2)) + { + throw new InvalidOperationException($"only 1/2 channels audio are supported by {nameof(AviWriter)} and you chose: {a_channels}"); + } + wfex.Init(); wfex.nBlockAlign = (ushort)(bytes * a_channels); wfex.nChannels = (ushort)a_channels; @@ -373,12 +377,10 @@ namespace BizHawk.Client.EmuHawk /// public void SetVideoParameters(int width, int height) { - bool change = false; + var change = _parameters.width != width || + _parameters.height != height; - change |= _parameters.width != width; _parameters.width = width; - - change |= _parameters.height != height; _parameters.height = height; if (change) @@ -392,18 +394,14 @@ namespace BizHawk.Client.EmuHawk /// public void SetAudioParameters(int sampleRate, int channels, int bits) { - bool change = false; + var change = _parameters.a_samplerate != sampleRate || + _parameters.a_channels != channels || + _parameters.a_bits != bits || + _parameters.has_audio != true; - change |= _parameters.a_samplerate != sampleRate; _parameters.a_samplerate = sampleRate; - - change |= _parameters.a_channels != channels; _parameters.a_channels = channels; - - change |= _parameters.a_bits != bits; _parameters.a_bits = bits; - - change |= _parameters.has_audio != true; _parameters.has_audio = true; if (change) @@ -414,24 +412,31 @@ namespace BizHawk.Client.EmuHawk public class CodecToken : IDisposable { - public void Dispose() { } - private CodecToken() { } + public void Dispose() + { + } + + private CodecToken() + { + } + private AVIWriterImports.AVICOMPRESSOPTIONS _comprOptions; public string codec; public byte[] Format = Array.Empty(); public byte[] Parms = Array.Empty(); - private static string Decode_mmioFOURCC(int code) + private static unsafe string Decode_mmioFOURCC(int code) { - char[] chs = new char[4]; + var chs = stackalloc char[4]; - for (int i = 0; i < 4; i++) + for (var i = 0; i < 4; i++) { chs[i] = (char)(byte)((code >> (i << 3)) & 0xFF); if (!char.IsLetterOrDigit(chs[i])) chs[i] = ' '; } - return new string(chs); + + return new(chs, 0, 4); } public static CodecToken CreateFromAVICOMPRESSOPTIONS(ref AVIWriterImports.AVICOMPRESSOPTIONS opts) @@ -461,27 +466,36 @@ namespace BizHawk.Client.EmuHawk { #endif #if false // test: increase stability by never freeing anything, ever - if (opts.lpParms != IntPtr.Zero) Win32Imports.HeapFree(Win32Imports.GetProcessHeap(), 0, opts.lpParms); - if (opts.lpFormat != IntPtr.Zero) Win32Imports.HeapFree(Win32Imports.GetProcessHeap(), 0, opts.lpFormat); + if (opts.lpParms != IntPtr.Zero) + { + HeapFree(GetProcessHeap(), 0, opts.lpParms); + } + + if (opts.lpFormat != IntPtr.Zero) + { + HeapFree(GetProcessHeap(), 0, opts.lpFormat); + } #endif #if AVI_SUPPORT opts.lpParms = IntPtr.Zero; opts.lpFormat = IntPtr.Zero; } - public void AllocateToAVICOMPRESSOPTIONS(ref AVIWriterImports.AVICOMPRESSOPTIONS opts) + public void AllocateToAVICOMPRESSOPTIONS(out AVIWriterImports.AVICOMPRESSOPTIONS opts) { + if (_comprOptions.cbParms != 0) + { + _comprOptions.lpParms = HeapAlloc(GetProcessHeap(), 0, _comprOptions.cbParms); + Marshal.Copy(Parms, 0, _comprOptions.lpParms, _comprOptions.cbParms); + } + + if (_comprOptions.cbFormat != 0) + { + _comprOptions.lpFormat = HeapAlloc(GetProcessHeap(), 0, _comprOptions.cbFormat); + Marshal.Copy(Format, 0, _comprOptions.lpFormat, _comprOptions.cbFormat); + } + opts = _comprOptions; - if (opts.cbParms != 0) - { - opts.lpParms = Win32Imports.HeapAlloc(Win32Imports.GetProcessHeap(), 0, opts.cbParms); - Marshal.Copy(Parms, 0, opts.lpParms, opts.cbParms); - } - if (opts.cbFormat != 0) - { - opts.lpFormat = Win32Imports.HeapAlloc(Win32Imports.GetProcessHeap(), 0, opts.cbFormat); - Marshal.Copy(Format, 0, opts.lpFormat, opts.cbFormat); - } } private byte[] SerializeToByteArray() @@ -511,7 +525,7 @@ namespace BizHawk.Client.EmuHawk var m = new MemoryStream(data, false); var b = new BinaryReader(m); - AVIWriterImports.AVICOMPRESSOPTIONS comprOptions = new AVIWriterImports.AVICOMPRESSOPTIONS(); + var comprOptions = default(AVIWriterImports.AVICOMPRESSOPTIONS); byte[] format; byte[] parms; @@ -544,25 +558,20 @@ namespace BizHawk.Client.EmuHawk b.Close(); } - var ret = new CodecToken + return new() { _comprOptions = comprOptions, Format = format, Parms = parms, codec = Decode_mmioFOURCC(comprOptions.fccHandler) }; - return ret; } public string Serialize() - { - return Convert.ToBase64String(SerializeToByteArray()); - } + => Convert.ToBase64String(SerializeToByteArray()); public static CodecToken DeSerialize(string s) - { - return DeSerializeFromByteArray(Convert.FromBase64String(s)); - } + => DeSerializeFromByteArray(Convert.FromBase64String(s)); } /// @@ -573,21 +582,15 @@ namespace BizHawk.Client.EmuHawk { } - private unsafe class AviWriterSegment : IDisposable + private class AviWriterSegment : IDisposable { static AviWriterSegment() { AVIWriterImports.AVIFileInit(); } - public AviWriterSegment() - { - } - public void Dispose() - { - CloseFile(); - } + => CloseFile(); private CodecToken _currVideoCodecToken; private bool _isOpen; @@ -631,19 +634,15 @@ namespace BizHawk.Client.EmuHawk private OutputStatus _outStatus; public long GetLengthApproximation() - { - return _outStatus.video_bytes + _outStatus.audio_bytes; - } + => _outStatus.video_bytes + _outStatus.audio_bytes; - private static bool FAILED(int hr) => hr < 0; - - private static int AVISaveOptions(IntPtr stream, ref AVIWriterImports.AVICOMPRESSOPTIONS opts, IntPtr owner) + private static unsafe int AVISaveOptions(IntPtr stream, ref AVIWriterImports.AVICOMPRESSOPTIONS opts, IntPtr owner) { fixed (AVIWriterImports.AVICOMPRESSOPTIONS* _popts = &opts) { - IntPtr* pStream = &stream; - AVIWriterImports.AVICOMPRESSOPTIONS* popts = _popts; - AVIWriterImports.AVICOMPRESSOPTIONS** ppopts = &popts; + var pStream = &stream; + var popts = _popts; + var ppopts = &popts; return AVIWriterImports.AVISaveOptions(owner, 0, 1, pStream, ppopts); } } @@ -654,10 +653,10 @@ namespace BizHawk.Client.EmuHawk public void OpenFile(string destPath, Parameters parameters, CodecToken videoCodecToken) { static int mmioFOURCC(string str) => ( - (byte)(str[0]) - | ((byte)(str[1]) << 8) - | ((byte)(str[2]) << 16) - | ((byte)(str[3]) << 24) + (byte)str[0] | + ((byte)str[1] << 8) | + ((byte)str[2] << 16) | + ((byte)str[3] << 24) ); this._parameters = parameters; @@ -671,28 +670,34 @@ namespace BizHawk.Client.EmuHawk File.Delete(destPath); } - if (FAILED(AVIWriterImports.AVIFileOpenW(ref _pAviFile, destPath, AVIWriterImports.OpenFileStyle.OF_CREATE | AVIWriterImports.OpenFileStyle.OF_WRITE, 0))) + var hr = AVIWriterImports.AVIFileOpenW(ref _pAviFile, destPath, + AVIWriterImports.OpenFileStyle.OF_CREATE | AVIWriterImports.OpenFileStyle.OF_WRITE, 0); + var hrEx = Marshal.GetExceptionForHR(hr); + if (hrEx != null) { - throw new InvalidOperationException($"Couldnt open dest path for avi file: {destPath}"); + throw new InvalidOperationException($"Couldnt open dest path for avi file: {destPath}", hrEx); } // initialize the video stream - AVIWriterImports.AVISTREAMINFOW vidstream_header = new AVIWriterImports.AVISTREAMINFOW(); - AVIWriterImports.BITMAPINFOHEADER bmih = new AVIWriterImports.BITMAPINFOHEADER(); + var vidstream_header = default(AVIWriterImports.AVISTREAMINFOW); + var bmih = default(AVIWriterImports.BITMAPINFOHEADER); parameters.PopulateBITMAPINFOHEADER24(ref bmih); vidstream_header.fccType = mmioFOURCC("vids"); vidstream_header.dwRate = parameters.fps; vidstream_header.dwScale = parameters.fps_scale; vidstream_header.dwSuggestedBufferSize = (int)bmih.biSizeImage; - if (FAILED(AVIWriterImports.AVIFileCreateStreamW(_pAviFile, out _pAviRawVideoStream, ref vidstream_header))) + + hr = AVIWriterImports.AVIFileCreateStreamW(_pAviFile, out _pAviRawVideoStream, ref vidstream_header); + hrEx = Marshal.GetExceptionForHR(hr); + if (hrEx != null) { CloseFile(); - throw new InvalidOperationException("Failed opening raw video stream. Not sure how this could happen"); + throw new InvalidOperationException("Failed opening raw video stream. Not sure how this could happen", hrEx); } // initialize audio stream - AVIWriterImports.AVISTREAMINFOW audstream_header = new AVIWriterImports.AVISTREAMINFOW(); - AVIWriterImports.WAVEFORMATEX wfex = new AVIWriterImports.WAVEFORMATEX(); + var audstream_header = default(AVIWriterImports.AVISTREAMINFOW); + var wfex = default(AVIWriterImports.WAVEFORMATEX); parameters.PopulateWAVEFORMATEX(ref wfex); audstream_header.fccType = mmioFOURCC("auds"); audstream_header.dwQuality = -1; @@ -700,13 +705,16 @@ namespace BizHawk.Client.EmuHawk audstream_header.dwRate = (int)wfex.nAvgBytesPerSec; audstream_header.dwSampleSize = wfex.nBlockAlign; audstream_header.dwInitialFrames = 1; // ??? optimal value? - if (FAILED(AVIWriterImports.AVIFileCreateStreamW(_pAviFile, out _pAviRawAudioStream, ref audstream_header))) + + hr = AVIWriterImports.AVIFileCreateStreamW(_pAviFile, out _pAviRawAudioStream, ref audstream_header); + hrEx = Marshal.GetExceptionForHR(hr); + if (hrEx != null) { CloseFile(); - throw new InvalidOperationException("Failed opening raw audio stream. Not sure how this could happen"); + throw new InvalidOperationException("Failed opening raw audio stream. Not sure how this could happen", hrEx); } - _outStatus = new OutputStatus(); + _outStatus = new(); _isOpen = true; } @@ -726,11 +734,11 @@ namespace BizHawk.Client.EmuHawk } // encoder params - AVIWriterImports.AVICOMPRESSOPTIONS comprOptions = new AVIWriterImports.AVICOMPRESSOPTIONS(); - _currVideoCodecToken?.AllocateToAVICOMPRESSOPTIONS(ref comprOptions); + var comprOptions = default(AVIWriterImports.AVICOMPRESSOPTIONS); + _currVideoCodecToken?.AllocateToAVICOMPRESSOPTIONS(out comprOptions); - bool result = AVISaveOptions(_pAviRawVideoStream, ref comprOptions, hwnd) != 0; - CodecToken ret = CodecToken.CreateFromAVICOMPRESSOPTIONS(ref comprOptions); + var result = AVISaveOptions(_pAviRawVideoStream, ref comprOptions, hwnd) != 0; + var ret = CodecToken.CreateFromAVICOMPRESSOPTIONS(ref comprOptions); // so, AVISaveOptions may have changed some of the pointers // if it changed the pointers, did it it free the old ones? we don't know @@ -741,12 +749,7 @@ namespace BizHawk.Client.EmuHawk // guess what? doesn't matter. We'll free them all ourselves. CodecToken.DeallocateAVICOMPRESSOPTIONS(ref comprOptions); - if (result) - { - return ret; - } - - return null; + return result ? ret : null; } /// begin recording @@ -759,19 +762,19 @@ namespace BizHawk.Client.EmuHawk } // open compressed video stream - AVIWriterImports.AVICOMPRESSOPTIONS opts = new AVIWriterImports.AVICOMPRESSOPTIONS(); - _currVideoCodecToken.AllocateToAVICOMPRESSOPTIONS(ref opts); - bool failed = FAILED(AVIWriterImports.AVIMakeCompressedStream(out _pAviCompressedVideoStream, _pAviRawVideoStream, ref opts, IntPtr.Zero)); + _currVideoCodecToken.AllocateToAVICOMPRESSOPTIONS(out var opts); + + var hr = AVIWriterImports.AVIMakeCompressedStream(out _pAviCompressedVideoStream, _pAviRawVideoStream, ref opts, IntPtr.Zero); + var hrEx = Marshal.GetExceptionForHR(hr); CodecToken.DeallocateAVICOMPRESSOPTIONS(ref opts); - - if (failed) + if (hrEx != null) { CloseStreams(); - throw new InvalidOperationException("Failed making compressed video stream"); + throw new InvalidOperationException("Failed making compressed video stream", hrEx); } // set the compressed video stream input format - AVIWriterImports.BITMAPINFOHEADER bmih = new AVIWriterImports.BITMAPINFOHEADER(); + var bmih = default(AVIWriterImports.BITMAPINFOHEADER); if (_bit32) { _parameters.PopulateBITMAPINFOHEADER32(ref bmih); @@ -781,17 +784,22 @@ namespace BizHawk.Client.EmuHawk _parameters.PopulateBITMAPINFOHEADER24(ref bmih); } - if (FAILED(AVIWriterImports.AVIStreamSetFormat(_pAviCompressedVideoStream, 0, ref bmih, Marshal.SizeOf(bmih)))) + hr = AVIWriterImports.AVIStreamSetFormat(_pAviCompressedVideoStream, 0, ref bmih, Marshal.SizeOf(bmih)); + hrEx = Marshal.GetExceptionForHR(hr); + if (hrEx != null) { _bit32 = true; // we'll try again CloseStreams(); - throw new InvalidOperationException("Failed setting compressed video stream input format"); + throw new InvalidOperationException("Failed setting compressed video stream input format", hrEx); } // set audio stream input format - AVIWriterImports.WAVEFORMATEX wfex = new AVIWriterImports.WAVEFORMATEX(); + var wfex = default(AVIWriterImports.WAVEFORMATEX); _parameters.PopulateWAVEFORMATEX(ref wfex); - if (FAILED(AVIWriterImports.AVIStreamSetFormat(_pAviRawAudioStream, 0, ref wfex, Marshal.SizeOf(wfex)))) + + hr = AVIWriterImports.AVIStreamSetFormat(_pAviRawAudioStream, 0, ref wfex, Marshal.SizeOf(wfex)); + hrEx = Marshal.GetExceptionForHR(hr); + if (hrEx != null) { CloseStreams(); throw new InvalidOperationException("Failed setting raw audio stream input format"); @@ -833,7 +841,7 @@ namespace BizHawk.Client.EmuHawk /// /// end recording /// - public void CloseStreams() + private void CloseStreams() { if (_pAviRawAudioStream != IntPtr.Zero) { @@ -848,18 +856,20 @@ namespace BizHawk.Client.EmuHawk } // todo - why couldnt this take an ISoundProvider? it could do the timekeeping as well.. hmm - public void AddSamples(short[] samples) + public void AddSamples(IReadOnlyList samples) { - int todo = samples.Length; - int idx = 0; + var todo = samples.Count; + var idx = 0; while (todo > 0) { - int remain = OutputStatus.AUDIO_SEGMENT_SIZE - _outStatus.audio_buffered_shorts; - int chunk = Math.Min(remain, todo); - for (int i = 0; i < chunk; i++) + var remain = OutputStatus.AUDIO_SEGMENT_SIZE - _outStatus.audio_buffered_shorts; + var chunk = Math.Min(remain, todo); + + for (var i = 0; i < chunk; i++) { _outStatus.BufferedShorts[_outStatus.audio_buffered_shorts++] = samples[idx++]; } + todo -= chunk; if (_outStatus.audio_buffered_shorts == OutputStatus.AUDIO_SEGMENT_SIZE) @@ -869,27 +879,28 @@ namespace BizHawk.Client.EmuHawk } } - private void FlushBufferedAudio() + private unsafe void FlushBufferedAudio() { - int todo = _outStatus.audio_buffered_shorts; - int todo_realsamples = todo / 2; - IntPtr buf = GetStaticGlobalBuf(todo * 2); + var todo = _outStatus.audio_buffered_shorts; + var todo_realsamples = todo / 2; + var buf = GetStaticGlobalBuf(todo * 2); - short* sptr = (short*)buf.ToPointer(); - for (int i = 0; i < todo; i++) + var sptr = (short*)buf.ToPointer(); + for (var i = 0; i < todo; i++) { sptr[i] = _outStatus.BufferedShorts[i]; } // (TODO - inefficient- build directly in a buffer) - _ = AVIWriterImports.AVIStreamWrite(_pAviRawAudioStream, _outStatus.audio_samples, todo_realsamples, buf, todo_realsamples * 4, 0, IntPtr.Zero, out var bytes_written); + _ = AVIWriterImports.AVIStreamWrite(_pAviRawAudioStream, _outStatus.audio_samples, + todo_realsamples, buf, todo_realsamples * 4, 0, IntPtr.Zero, out var bytes_written); _outStatus.audio_samples += todo_realsamples; _outStatus.audio_bytes += bytes_written; _outStatus.audio_buffered_shorts = 0; } /// attempted frame resize during encoding - public void AddFrame(IVideoProvider source) + public unsafe void AddFrame(IVideoProvider source) { const int AVIIF_KEYFRAME = 0x00000010; @@ -897,40 +908,42 @@ namespace BizHawk.Client.EmuHawk || _parameters.height != source.BufferHeight) throw new InvalidOperationException("video buffer changed between start and now"); - int pitch_add = _parameters.pitch_add; + var pitch_add = _parameters.pitch_add; - int todo = _parameters.pitch * _parameters.height; - int w = source.BufferWidth; - int h = source.BufferHeight; + var todo = _parameters.pitch * _parameters.height; + var w = source.BufferWidth; + var h = source.BufferHeight; if (!_bit32) { - IntPtr buf = GetStaticGlobalBuf(todo); + var buf = GetStaticGlobalBuf(todo); // TODO - would using a byte* be faster? - int[] buffer = source.GetVideoBuffer(); - fixed (int* buffer_ptr = &buffer[0]) + var buffer = source.GetVideoBuffer(); + fixed (int* buffer_ptr = buffer) { - byte* bytes_ptr = (byte*)buf.ToPointer(); + var bytes_ptr = (byte*)buf.ToPointer(); { - byte* bp = bytes_ptr; + var bp = bytes_ptr; for (int idx = w * h - w, y = 0; y < h; y++) { - for (int x = 0; x < w; x++, idx++) + for (var x = 0; x < w; x++, idx++) { - int r = (buffer[idx] >> 0) & 0xFF; - int g = (buffer[idx] >> 8) & 0xFF; - int b = (buffer[idx] >> 16) & 0xFF; + var r = (buffer_ptr[idx] >> 0) & 0xFF; + var g = (buffer_ptr[idx] >> 8) & 0xFF; + var b = (buffer_ptr[idx] >> 16) & 0xFF; *bp++ = (byte)r; *bp++ = (byte)g; *bp++ = (byte)b; } + idx -= w * 2; bp += pitch_add; } - int ret = AVIWriterImports.AVIStreamWrite(_pAviCompressedVideoStream, _outStatus.video_frames, 1, new IntPtr(bytes_ptr), todo, AVIIF_KEYFRAME, IntPtr.Zero, out var bytes_written); + _ = AVIWriterImports.AVIStreamWrite(_pAviCompressedVideoStream, _outStatus.video_frames, + 1, new(bytes_ptr), todo, AVIIF_KEYFRAME, IntPtr.Zero, out var bytes_written); _outStatus.video_bytes += bytes_written; _outStatus.video_frames++; } @@ -938,30 +951,32 @@ namespace BizHawk.Client.EmuHawk } else // 32 bit { - IntPtr buf = GetStaticGlobalBuf(todo * 4); - int[] buffer = source.GetVideoBuffer(); - fixed (int* buffer_ptr = &buffer[0]) + var buf = GetStaticGlobalBuf(todo * 4); + var buffer = source.GetVideoBuffer(); + fixed (int* buffer_ptr = buffer) { - byte* bytes_ptr = (byte*)buf.ToPointer(); + var bytes_ptr = (byte*)buf.ToPointer(); { - byte* bp = bytes_ptr; + var bp = bytes_ptr; for (int idx = w * h - w, y = 0; y < h; y++) { - for (int x = 0; x < w; x++, idx++) + for (var x = 0; x < w; x++, idx++) { - int r = (buffer[idx] >> 0) & 0xFF; - int g = (buffer[idx] >> 8) & 0xFF; - int b = (buffer[idx] >> 16) & 0xFF; + var r = (buffer_ptr[idx] >> 0) & 0xFF; + var g = (buffer_ptr[idx] >> 8) & 0xFF; + var b = (buffer_ptr[idx] >> 16) & 0xFF; *bp++ = (byte)r; *bp++ = (byte)g; *bp++ = (byte)b; *bp++ = 0; } + idx -= w * 2; } - int ret = AVIWriterImports.AVIStreamWrite(_pAviCompressedVideoStream, _outStatus.video_frames, 1, new IntPtr(bytes_ptr), todo * 3, AVIIF_KEYFRAME, IntPtr.Zero, out var bytes_written); + _ = AVIWriterImports.AVIStreamWrite(_pAviCompressedVideoStream, _outStatus.video_frames, + 1, new(bytes_ptr), todo * 3, AVIIF_KEYFRAME, IntPtr.Zero, out var bytes_written); _outStatus.video_bytes += bytes_written; _outStatus.video_frames++; } @@ -974,13 +989,11 @@ namespace BizHawk.Client.EmuHawk public void SetDefaultVideoCodecToken(Config config) { var ct = CodecToken.DeSerialize(config.AviCodecToken); - _currVideoCodecToken = ct ?? throw new Exception($"No default {nameof(config.AviCodecToken)} in config!"); + _currVideoCodecToken = ct ?? throw new($"No default {nameof(config.AviCodecToken)} in config!"); } public string DesiredExtension() - { - return "avi"; - } + => "avi"; public bool UsesAudio => _parameters.has_audio; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs b/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs index 9c1f3d45ea..d1fff6bf24 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs @@ -7,6 +7,8 @@ using System.Windows.Forms; using BizHawk.Common; +using static BizHawk.Common.ShlobjImports; + namespace BizHawk.Client.EmuHawk { /// @@ -21,8 +23,8 @@ namespace BizHawk.Client.EmuHawk /// public sealed class FolderBrowserEx : Component { - /// is this supposed to be public? we're obviously not using it at callsites at the moment --yoshi - private readonly Win32Imports.BROWSEINFO.FLAGS publicOptions = Win32Imports.BROWSEINFO.FLAGS.RestrictToFilesystem | Win32Imports.BROWSEINFO.FLAGS.RestrictToDomain; + private const BROWSEINFO.FLAGS BrowseOptions = BROWSEINFO.FLAGS.RestrictToFilesystem | BROWSEINFO.FLAGS.RestrictToDomain | + BROWSEINFO.FLAGS.NewDialogStyle | BROWSEINFO.FLAGS.ShowTextBox; public string Description = "Please select a folder below:"; @@ -31,54 +33,78 @@ namespace BizHawk.Client.EmuHawk /// Shows the folder browser dialog box with the specified owner window. public DialogResult ShowDialog(IWin32Window owner = null) { - const Win32Imports.BROWSEINFO.FLAGS privateOptions = Win32Imports.BROWSEINFO.FLAGS.NewDialogStyle | Win32Imports.BROWSEINFO.FLAGS.ShowTextBox; const int startLocation = 0; // = Desktop CSIDL int Callback(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData) { - if (uMsg == 1) + if (uMsg == BFFM_INITIALIZED) { var str = Marshal.StringToHGlobalUni(SelectedPath); - Win32Imports.SendMessage(hwnd, 0x400 + 103, (IntPtr) 1, str); - Marshal.FreeHGlobal(str); + try + { + WmImports.SendMessage(hwnd, BFFM_SETSELECTIONW, new(1), str); + } + finally + { + Marshal.FreeHGlobal(str); + } } + return 0; } - var hWndOwner = owner?.Handle ?? Win32Imports.GetActiveWindow(); - _ = Win32Imports.SHGetSpecialFolderLocation(hWndOwner, startLocation, out var pidlRoot); - if (pidlRoot == IntPtr.Zero) return DialogResult.Cancel; - var mergedOptions = publicOptions | privateOptions; - if ((mergedOptions & Win32Imports.BROWSEINFO.FLAGS.NewDialogStyle) != 0 && ApartmentState.MTA == Application.OleRequired()) + var hWndOwner = owner?.Handle ?? WmImports.GetActiveWindow(); + _ = SHGetSpecialFolderLocation(hWndOwner, startLocation, out var pidlRoot); + if (pidlRoot == IntPtr.Zero) { - mergedOptions &= ~Win32Imports.BROWSEINFO.FLAGS.NewDialogStyle; + return DialogResult.Cancel; } - IntPtr pidlRet = default; + var browseOptions = BrowseOptions; + if (ApartmentState.MTA == Application.OleRequired()) + { + browseOptions &= ~BROWSEINFO.FLAGS.NewDialogStyle; + } + + var pidlRet = IntPtr.Zero; try { var buffer = Marshal.AllocHGlobal(Win32Imports.MAX_PATH); - var bi = new Win32Imports.BROWSEINFO + var bi = new BROWSEINFO { hwndOwner = hWndOwner, pidlRoot = pidlRoot, pszDisplayName = buffer, lpszTitle = Description, - ulFlags = mergedOptions, + ulFlags = browseOptions, lpfn = Callback }; - pidlRet = Win32Imports.SHBrowseForFolder(ref bi); + + pidlRet = SHBrowseForFolder(ref bi); Marshal.FreeHGlobal(buffer); - if (pidlRet == IntPtr.Zero) return DialogResult.Cancel; // user clicked Cancel - var sb = new StringBuilder(Win32Imports.MAX_PATH); - if (Win32Imports.SHGetPathFromIDList(pidlRet, sb) == 0) return DialogResult.Cancel; - SelectedPath = sb.ToString(); + if (pidlRet == IntPtr.Zero) + { + return DialogResult.Cancel; // user clicked Cancel + } + + var path = new StringBuilder(Win32Imports.MAX_PATH); + if (SHGetPathFromIDList(pidlRet, path) == 0) + { + return DialogResult.Cancel; + } + + SelectedPath = path.ToString(); } finally { - _ = Win32Imports.SHGetMalloc(out var malloc); + _ = SHGetMalloc(out var malloc); malloc.Free(pidlRoot); - if (pidlRet != IntPtr.Zero) malloc.Free(pidlRet); + + if (pidlRet != IntPtr.Zero) + { + malloc.Free(pidlRet); + } } + return DialogResult.OK; } } diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs index 47ba9d8d2d..a0a5e7f322 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs @@ -63,7 +63,11 @@ namespace BizHawk.Client.EmuHawk protected override void OnMouseClick(MouseEventArgs e) { - if (!OSTailoredCode.IsUnixHost) Win32Imports.HideCaret(Handle); + if (!OSTailoredCode.IsUnixHost) + { + WmImports.HideCaret(Handle); + } + base.OnMouseClick(e); } @@ -253,7 +257,10 @@ namespace BizHawk.Client.EmuHawk protected override void OnGotFocus(EventArgs e) { - if (!OSTailoredCode.IsUnixHost) Win32Imports.HideCaret(Handle); + if (!OSTailoredCode.IsUnixHost) + { + WmImports.HideCaret(Handle); + } } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) diff --git a/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs b/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs index 5de92d5308..695828a664 100644 --- a/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs +++ b/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs @@ -10,11 +10,14 @@ using System.Linq; using System.Reflection; using System.Text; using System.Windows.Forms; + using BizHawk.Client.Common; using BizHawk.Common; using BizHawk.Common.ReflectionExtensions; using BizHawk.Emulation.Common; +using static BizHawk.Common.CommctrlImports; + namespace BizHawk.Client.EmuHawk { public static class ControlExtensions @@ -183,32 +186,42 @@ namespace BizHawk.Client.EmuHawk /// unmanaged call failed public static void SetSortIcon(this ListView listViewControl, int columnIndex, SortOrder order) { - if (OSTailoredCode.IsUnixHost) return; + if (OSTailoredCode.IsUnixHost) + { + return; + } - const int LVM_GETHEADER = 4127; - const int HDM_GETITEM = 4619; - const int HDM_SETITEM = 4620; - var columnHeader = Win32Imports.SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero); + var columnHeader = WmImports.SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero); for (int columnNumber = 0, l = listViewControl.Columns.Count; columnNumber < l; columnNumber++) { var columnPtr = new IntPtr(columnNumber); - var item = new Win32Imports.HDITEM { mask = Win32Imports.HDITEM.Mask.Format }; - if (Win32Imports.SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero) throw new Win32Exception(); + var item = new HDITEM { mask = HDITEM.Mask.Format }; + if (SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero) + { + throw new Win32Exception(); + } + if (columnNumber != columnIndex || order == SortOrder.None) { - item.fmt &= ~Win32Imports.HDITEM.Format.SortDown & ~Win32Imports.HDITEM.Format.SortUp; + item.fmt &= ~HDITEM.Format.SortDown & ~HDITEM.Format.SortUp; } - else if (order == SortOrder.Ascending) + // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault + else switch (order) { - item.fmt &= ~Win32Imports.HDITEM.Format.SortDown; - item.fmt |= Win32Imports.HDITEM.Format.SortUp; + case SortOrder.Ascending: + item.fmt &= ~HDITEM.Format.SortDown; + item.fmt |= HDITEM.Format.SortUp; + break; + case SortOrder.Descending: + item.fmt &= ~HDITEM.Format.SortUp; + item.fmt |= HDITEM.Format.SortDown; + break; } - else if (order == SortOrder.Descending) + + if (SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero) { - item.fmt &= ~Win32Imports.HDITEM.Format.SortUp; - item.fmt |= Win32Imports.HDITEM.Format.SortDown; + throw new Win32Exception(); } - if (Win32Imports.SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero) throw new Win32Exception(); } } diff --git a/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs b/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs index 19f81b86f7..535b938fa3 100644 --- a/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs +++ b/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs @@ -868,7 +868,7 @@ namespace BizHawk.Client.EmuHawk { groupFreeze.SuspendLayout(); - Win32Imports.SendMessage(groupFreeze.Handle, 11, (IntPtr)0, IntPtr.Zero); //WM_SETREDRAW false + WmImports.SendMessage(groupFreeze.Handle, 11, (IntPtr)0, IntPtr.Zero); //WM_SETREDRAW false var tp = tabctrlDetails.SelectedTab; @@ -886,7 +886,7 @@ namespace BizHawk.Client.EmuHawk groupFreeze.ResumeLayout(); - Win32Imports.SendMessage(groupFreeze.Handle, 11, (IntPtr)1, IntPtr.Zero); //WM_SETREDRAW true + WmImports.SendMessage(groupFreeze.Handle, 11, (IntPtr)1, IntPtr.Zero); //WM_SETREDRAW true groupFreeze.Refresh(); } diff --git a/src/BizHawk.Common/Extensions/PathExtensions.cs b/src/BizHawk.Common/Extensions/PathExtensions.cs index c00bcbef2d..0d27b92cf9 100644 --- a/src/BizHawk.Common/Extensions/PathExtensions.cs +++ b/src/BizHawk.Common/Extensions/PathExtensions.cs @@ -82,7 +82,7 @@ namespace BizHawk.Common.PathExtensions if (File.Exists(path1.SubstringBefore('|'))) return FileAttributes.Normal; throw new FileNotFoundException(); } - var path = new StringBuilder(260 /* = MAX_PATH */); + var path = new StringBuilder(Win32Imports.MAX_PATH); return Win32Imports.PathRelativePathTo(path, fromPath, GetPathAttribute(fromPath), toPath, GetPathAttribute(toPath)) ? path.ToString() : throw new ArgumentException(message: "Paths must have a common prefix", paramName: nameof(toPath)); diff --git a/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs b/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs index 5f87cefe2f..03090d6278 100644 --- a/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs +++ b/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs @@ -1,6 +1,6 @@ using System; -using static BizHawk.Common.Kernel32Imports; +using static BizHawk.Common.MemoryApiImports; using static BizHawk.Common.MemoryBlock; namespace BizHawk.Common diff --git a/src/BizHawk.Common/Win32/AVIWriterImports.cs b/src/BizHawk.Common/Win32/AVIWriterImports.cs index a81316faae..f0a23cdac5 100644 --- a/src/BizHawk.Common/Win32/AVIWriterImports.cs +++ b/src/BizHawk.Common/Win32/AVIWriterImports.cs @@ -4,6 +4,8 @@ using System; using System.Runtime.InteropServices; +// ReSharper disable FieldCanBeMadeReadOnly.Global + namespace BizHawk.Common { public static class AVIWriterImports @@ -35,7 +37,8 @@ namespace BizHawk.Common public RECT rcFrame; public int dwEditCount; public int dwFormatChangeCount; - [MarshalAs(UnmanagedType.LPWStr, SizeConst=64)] public string szName; + [MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)] + public string szName; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct RECT @@ -63,9 +66,7 @@ namespace BizHawk.Common public uint biClrImportant; public void Init() - { - biSize = (uint)Marshal.SizeOf(this); - } + => biSize = (uint)Marshal.SizeOf(this); } [StructLayout(LayoutKind.Sequential)] @@ -96,9 +97,7 @@ namespace BizHawk.Common public ushort cbSize; public void Init() - { - cbSize = (ushort)Marshal.SizeOf(this); - } + => cbSize = (ushort)Marshal.SizeOf(this); } /// Create a new stream in an existing file and creates an interface to the new stream diff --git a/src/BizHawk.Common/Win32/CWDHacks.cs b/src/BizHawk.Common/Win32/CWDHacks.cs index a6f14fd7df..fd18637607 100644 --- a/src/BizHawk.Common/Win32/CWDHacks.cs +++ b/src/BizHawk.Common/Win32/CWDHacks.cs @@ -1,38 +1,60 @@ using System; using System.Runtime.InteropServices; -using System.Text; namespace BizHawk.Common { /// Gets/Sets the current working directory while bypassing the security checks triggered by the public API (). - public static unsafe class CWDHacks + public static class CWDHacks { - private const uint BUFFER_LEN = 0x200U; + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] + private static extern unsafe int GetCurrentDirectoryW(int nBufferLength, char* lpBuffer); - private static readonly byte[] BUFFER = new byte[BUFFER_LEN]; - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern uint GetCurrentDirectoryW(uint nBufferLength, byte* pBuffer); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern bool SetCurrentDirectoryW(byte* lpPathName); + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] + private static extern bool SetCurrentDirectoryW(string lpPathName); public static bool Set(string newCWD) - { - fixed (byte* pstr = &Encoding.Unicode.GetBytes($"{newCWD}\0")[0]) - return SetCurrentDirectoryW(pstr); - } + => SetCurrentDirectoryW(newCWD); - public static string Get() + public static unsafe string Get() { - uint result; - fixed (byte* pBuf = &BUFFER[0]) result = GetCurrentDirectoryW(BUFFER_LEN, pBuf); - if (result <= BUFFER_LEN && result is not 0U) return Encoding.Unicode.GetString(BUFFER, 0, (int) (2U * result)); - var buf = new byte[result]; - uint result1; - fixed (byte* pBuf = &buf[0]) result1 = GetCurrentDirectoryW(BUFFER_LEN, pBuf); - if (result1 == result) return Encoding.Unicode.GetString(buf, 0, (int) (2U * result)); - throw new Exception(); + static Exception GetExceptionForFailure() + { + var ex = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()) + ?? new("Marshal.GetExceptionForHR returned null?"); + return new InvalidOperationException("GetCurrentDirectoryW returned 0!", ex); + } + + const int STARTING_BUF_SIZE = Win32Imports.MAX_PATH + 1; + var startingBuffer = stackalloc char[STARTING_BUF_SIZE]; + var ret = GetCurrentDirectoryW(STARTING_BUF_SIZE, startingBuffer); + switch (ret) + { + case 0: + throw GetExceptionForFailure(); + case < STARTING_BUF_SIZE: // ret should be smaller than the buffer, as ret doesn't include null terminator + return new(startingBuffer, 0, ret); + } + + // since current directory could suddenly grow (due to it being global / modifiable by other threads), a while true loop is used here + // although it's fairly unlikely we'll even reach this point, MAX_PATH can only be bypassed under certain circumstances + while (true) + { + var bufSize = ret + 1; + var buffer = new char[bufSize]; + fixed (char* p = buffer) + { + ret = GetCurrentDirectoryW(bufSize, p); + if (ret == 0) + { + throw GetExceptionForFailure(); + } + + if (ret < bufSize) + { + return new(p, 0, ret); + } + } + } } } } diff --git a/src/BizHawk.Common/Win32/CommctrlImports.cs b/src/BizHawk.Common/Win32/CommctrlImports.cs new file mode 100644 index 0000000000..6109352bab --- /dev/null +++ b/src/BizHawk.Common/Win32/CommctrlImports.cs @@ -0,0 +1,57 @@ +#nullable disable + +using System; +using System.Runtime.InteropServices; + +// ReSharper disable FieldCanBeMadeReadOnly.Global +// ReSharper disable UnusedMember.Global + +namespace BizHawk.Common +{ + public static class CommctrlImports + { + public const int LVM_GETHEADER = 4127; + public const int HDM_GETITEM = 4619; + public const int HDM_SETITEM = 4620; + + [StructLayout(LayoutKind.Sequential)] + public struct HDITEM + { + public Mask mask; + public int cxy; + [MarshalAs(UnmanagedType.LPTStr)] + public string pszText; + public IntPtr hbm; + public int cchTextMax; + public Format fmt; + public IntPtr lParam; + + // _WIN32_IE >= 0x0300 + public int iImage; + public int iOrder; + + // _WIN32_IE >= 0x0500 + public uint type; + public IntPtr pvFilter; + + // _WIN32_WINNT >= 0x0600 + public uint state; + + [Flags] + public enum Mask + { + Format = 0x4 + } + + [Flags] + public enum Format + { + SortDown = 0x200, + SortUp = 0x400 + } + } + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, ref HDITEM lParam); + } +} \ No newline at end of file diff --git a/src/BizHawk.Common/Win32/HeapApiImports.cs b/src/BizHawk.Common/Win32/HeapApiImports.cs new file mode 100644 index 0000000000..78bafce64a --- /dev/null +++ b/src/BizHawk.Common/Win32/HeapApiImports.cs @@ -0,0 +1,22 @@ +using System; +using System.Runtime.InteropServices; + +// ReSharper disable FieldCanBeMadeReadOnly.Global +// ReSharper disable UnusedMember.Global + +namespace BizHawk.Common +{ + public static class HeapApiImports + { + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GetProcessHeap(); + + [DllImport("kernel32.dll", SetLastError = false)] + public static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, int dwBytes); + + /// used in #if false code in AviWriter.CodecToken.DeallocateAVICOMPRESSOPTIONS, don't delete it + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem); + } +} diff --git a/src/BizHawk.Common/Win32/Kernel32Imports.cs b/src/BizHawk.Common/Win32/MemoryApiImports.cs similarity index 91% rename from src/BizHawk.Common/Win32/Kernel32Imports.cs rename to src/BizHawk.Common/Win32/MemoryApiImports.cs index 139ec029ea..8edbc80b45 100644 --- a/src/BizHawk.Common/Win32/Kernel32Imports.cs +++ b/src/BizHawk.Common/Win32/MemoryApiImports.cs @@ -2,10 +2,11 @@ using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global +// ReSharper disable UnusedMember.Global namespace BizHawk.Common { - public static class Kernel32Imports + public static class MemoryApiImports { [Flags] public enum AllocationType : uint diff --git a/src/BizHawk.Common/Win32/MotWHack.cs b/src/BizHawk.Common/Win32/MotWHack.cs index 0a122cc438..52e2a645b4 100644 --- a/src/BizHawk.Common/Win32/MotWHack.cs +++ b/src/BizHawk.Common/Win32/MotWHack.cs @@ -3,6 +3,7 @@ namespace BizHawk.Common /// This code (and an import for ) is duplicated in each executable project because it needs to be used before loading assemblies. public static class MotWHack { - public static void RemoveMOTW(string path) => Win32Imports.DeleteFileW($"{path}:Zone.Identifier"); + public static void RemoveMOTW(string path) + => Win32Imports.DeleteFileW($"{path}:Zone.Identifier"); } } diff --git a/src/BizHawk.Common/Win32/ShellLinkImports.cs b/src/BizHawk.Common/Win32/ShellLinkImports.cs index de3645267c..0a50514126 100644 --- a/src/BizHawk.Common/Win32/ShellLinkImports.cs +++ b/src/BizHawk.Common/Win32/ShellLinkImports.cs @@ -4,6 +4,8 @@ using System; using System.Runtime.InteropServices; using System.Text; +// ReSharper disable FieldCanBeMadeReadOnly.Global + namespace BizHawk.Common { public static class ShellLinkImports @@ -19,15 +21,21 @@ namespace BizHawk.Common public uint nFileSizeLow; public uint dwReserved0; public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public string cAlternateFileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string cFileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] + public string cAlternateFileName; } [Flags] - public enum SLGP_FLAGS {} + public enum SLGP_FLAGS + { + } [Flags] - public enum SLR_FLAGS {} + public enum SLR_FLAGS + { + } /// The IShellLink interface allows Shell links to be created, modified, and resolved [ComImport] @@ -108,6 +116,8 @@ namespace BizHawk.Common /// CLSID_ShellLink from ShlGuid.h [ComImport] [Guid("00021401-0000-0000-C000-000000000046")] - public class ShellLink /* : IPersistFile, IShellLinkW */ {} + public class ShellLink /* : IPersistFile, IShellLinkW */ + { + } } } diff --git a/src/BizHawk.Common/Win32/ShlobjImports.cs b/src/BizHawk.Common/Win32/ShlobjImports.cs new file mode 100644 index 0000000000..aa575c95b6 --- /dev/null +++ b/src/BizHawk.Common/Win32/ShlobjImports.cs @@ -0,0 +1,93 @@ +#nullable disable + +using System; +using System.Runtime.InteropServices; +using System.Text; + +// ReSharper disable FieldCanBeMadeReadOnly.Global +// ReSharper disable UnusedMember.Global + +namespace BizHawk.Common +{ + public static class ShlobjImports + { + public const int BFFM_INITIALIZED = 1; + public const int BFFM_SETSELECTIONW = 0x400 + 103; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate int BFFCALLBACK(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData); + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct BROWSEINFO + { + public IntPtr hwndOwner; + public IntPtr pidlRoot; + public IntPtr pszDisplayName; + [MarshalAs(UnmanagedType.LPTStr)] + public string lpszTitle; + public FLAGS ulFlags; + [MarshalAs(UnmanagedType.FunctionPtr)] + public BFFCALLBACK lpfn; + public IntPtr lParam; + public int iImage; + + [Flags] + public enum FLAGS + { + /// BIF_RETURNONLYFSDIRS + RestrictToFilesystem = 0x0001, + /// BIF_DONTGOBELOWDOMAIN + RestrictToDomain = 0x0002, + /// BIF_RETURNFSANCESTORS + RestrictToSubfolders = 0x0008, + /// BIF_EDITBOX + ShowTextBox = 0x0010, + /// BIF_VALIDATE + ValidateSelection = 0x0020, + /// BIF_NEWDIALOGSTYLE + NewDialogStyle = 0x0040, + /// BIF_BROWSEFORCOMPUTER + BrowseForComputer = 0x1000, + /// BIF_BROWSEFORPRINTER + BrowseForPrinter = 0x2000, + /// BIF_BROWSEINCLUDEFILES + BrowseForEverything = 0x4000 + } + } + + [Guid("00000002-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMalloc + { + [PreserveSig] + IntPtr Alloc([In] int cb); + + [PreserveSig] + IntPtr Realloc([In] IntPtr pv, [In] int cb); + + [PreserveSig] + void Free([In] IntPtr pv); + + [PreserveSig] + int GetSize([In] IntPtr pv); + + [PreserveSig] + int DidAlloc(IntPtr pv); + + [PreserveSig] + void HeapMinimize(); + } + + [DllImport("shell32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO bi); + + [DllImport("shell32.dll")] + public static extern int SHGetMalloc(out IMalloc ppMalloc); + + [DllImport("shell32.dll", CharSet = CharSet.Auto)] + public static extern int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath); + + [DllImport("shell32.dll")] + public static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, int nFolder, out IntPtr ppidl); + } +} diff --git a/src/BizHawk.Common/Win32/ThreadHacks.cs b/src/BizHawk.Common/Win32/ThreadHacks.cs index 589cfe9466..40c7c8f1e8 100644 --- a/src/BizHawk.Common/Win32/ThreadHacks.cs +++ b/src/BizHawk.Common/Win32/ThreadHacks.cs @@ -15,35 +15,11 @@ namespace BizHawk.Common { public const uint QS_ALLINPUT = 0x4FFU; public const uint MWMO_INPUTAVAILABLE = 0x0004U; - public const uint PM_REMOVE = 0x0001U; - - [StructLayout(LayoutKind.Sequential)] - public struct MSG - { - public IntPtr hwnd; - public uint message; - public IntPtr wParam; - public IntPtr lParam; - public uint time; - public int x; - public int y; - } - - [DllImport("user32.dll")] - public static extern IntPtr DispatchMessage([In] ref MSG lpMsg); [DllImport("user32.dll", SetLastError = true)] public static extern uint MsgWaitForMultipleObjectsEx(uint nCount, IntPtr[] pHandles, uint dwMilliseconds, uint dwWakeMask, uint dwFlags); - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg); - - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool TranslateMessage([In] ref MSG lpMsg); - - [DllImport("kernel32", SetLastError = true, ExactSpelling = true)] + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] public static extern int WaitForSingleObject(SafeWaitHandle handle, uint milliseconds); } } diff --git a/src/BizHawk.Common/Win32/Win32Imports.cs b/src/BizHawk.Common/Win32/Win32Imports.cs index 1d2c6d858e..99c80251be 100644 --- a/src/BizHawk.Common/Win32/Win32Imports.cs +++ b/src/BizHawk.Common/Win32/Win32Imports.cs @@ -7,227 +7,29 @@ using System.Text; namespace BizHawk.Common { + /// + /// This is more just an assorted bunch of Win32 functions + /// public static class Win32Imports { public const int MAX_PATH = 260; - public const uint PM_REMOVE = 0x0001U; - public static readonly IntPtr HWND_MESSAGE = new(-3); - public const int GWLP_USERDATA = -21; - public delegate int BFFCALLBACK(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData); - - [StructLayout(LayoutKind.Sequential, Pack = 8)] - public struct BROWSEINFO - { - public IntPtr hwndOwner; - public IntPtr pidlRoot; - public IntPtr pszDisplayName; - [MarshalAs(UnmanagedType.LPTStr)] public string lpszTitle; - public FLAGS ulFlags; - [MarshalAs(UnmanagedType.FunctionPtr)] public BFFCALLBACK lpfn; - public IntPtr lParam; - public int iImage; - - [Flags] - public enum FLAGS - { - /// BIF_RETURNONLYFSDIRS - RestrictToFilesystem = 0x0001, - /// BIF_DONTGOBELOWDOMAIN - RestrictToDomain = 0x0002, - /// BIF_RETURNFSANCESTORS - RestrictToSubfolders = 0x0008, - /// BIF_EDITBOX - ShowTextBox = 0x0010, - /// BIF_VALIDATE - ValidateSelection = 0x0020, - /// BIF_NEWDIALOGSTYLE - NewDialogStyle = 0x0040, - /// BIF_BROWSEFORCOMPUTER - BrowseForComputer = 0x1000, - /// BIF_BROWSEFORPRINTER - BrowseForPrinter = 0x2000, - /// BIF_BROWSEINCLUDEFILES - BrowseForEverything = 0x4000 - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct HDITEM - { - public Mask mask; - public int cxy; - [MarshalAs(UnmanagedType.LPTStr)] public string pszText; - public IntPtr hbm; - public int cchTextMax; - public Format fmt; - public IntPtr lParam; - - // _WIN32_IE >= 0x0300 - public int iImage; - public int iOrder; - - // _WIN32_IE >= 0x0500 - public uint type; - public IntPtr pvFilter; - - // _WIN32_WINNT >= 0x0600 - public uint state; - - [Flags] - public enum Mask - { - Format = 0x4 - } - - [Flags] - public enum Format - { - SortDown = 0x200, - SortUp = 0x400 - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct MSG - { - public IntPtr hwnd; - public uint message; - public IntPtr wParam; - public IntPtr lParam; - public uint time; - public int x; - public int y; - } - - public delegate IntPtr WNDPROC(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public struct WNDCLASS - { - public uint style; - public WNDPROC lpfnWndProc; - public int cbClsExtra; - public int cbWndExtra; - public IntPtr hInstance; - public IntPtr hIcon; - public IntPtr hCursor; - public IntPtr hbrBackground; - public string lpszMenuName; - public string lpszClassName; - } - - [Guid("00000002-0000-0000-C000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IMalloc - { - [PreserveSig] IntPtr Alloc([In] int cb); - [PreserveSig] IntPtr Realloc([In] IntPtr pv, [In] int cb); - [PreserveSig] void Free([In] IntPtr pv); - [PreserveSig] int GetSize([In] IntPtr pv); - [PreserveSig] int DidAlloc(IntPtr pv); - [PreserveSig] void HeapMinimize(); - } - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern uint _control87(uint @new, uint mask); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr CreateWindowEx(int dwExStyle, IntPtr lpClassName, string lpWindowName, - int dwStyle, int X, int Y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam); - - [DllImport("kernel32.dll", EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)] string lpFileName); - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DestroyWindow(IntPtr hWnd); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr DispatchMessage([In] ref MSG lpMsg); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr hWndChildAfter, string className, string windowTitle); - - [DllImport("user32.dll")] - public static extern IntPtr GetActiveWindow(); - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr GetModuleHandle(string lpModuleName); - [DllImport("kernel32", SetLastError = true, EntryPoint = "GetProcAddress")] - public static extern IntPtr GetProcAddressOrdinal(IntPtr hModule, IntPtr procName); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GetProcessHeap(); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); - - [DllImport("kernel32.dll", SetLastError = false)] - public static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, int dwBytes); - - /// used in #if false code in AviWriter.CodecToken.DeallocateAVICOMPRESSOPTIONS, don't delete it - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem); - - [DllImport("user32")] - public static extern bool HideCaret(IntPtr hWnd); - - [DllImport("kernel32.dll")] - public static extern bool IsDebuggerPresent(); - [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern uint MapVirtualKey(uint uCode, uint uMapType); - [DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] - public static extern IntPtr MemSet(IntPtr dest, int c, uint count); - [DllImport("shlwapi.dll", CharSet = CharSet.Auto)] public static extern bool PathRelativePathTo([Out] StringBuilder pszPath, [In] string pszFrom, [In] FileAttributes dwAttrFrom, [In] string pszTo, [In] FileAttributes dwAttrTo); - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr RegisterClass([In] ref WNDCLASS lpWndClass); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, ref HDITEM lParam); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); - - [DllImport("shell32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO bi); - - [DllImport("shell32.dll")] - public static extern int SHGetMalloc(out IMalloc ppMalloc); - - [DllImport("shell32.dll")] - public static extern int SHGetPathFromIDList(IntPtr pidl, StringBuilder Path); - - [DllImport("shell32.dll")] - public static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, int nFolder, out IntPtr ppidl); - [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags); - [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")] + [DllImport("winmm.dll")] public static extern uint timeBeginPeriod(uint uMilliseconds); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool TranslateMessage([In] ref MSG lpMsg); } } diff --git a/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs b/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs index 8f3279c025..862e89392d 100644 --- a/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs +++ b/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs @@ -2,6 +2,9 @@ using System.Runtime.InteropServices; using System.Text; +// ReSharper disable FieldCanBeMadeReadOnly.Global +// ReSharper disable UnusedMember.Global + namespace BizHawk.Common { public class Win32ShellContextMenu @@ -117,6 +120,7 @@ namespace BizHawk.Common } } +#pragma warning disable CA1069 [Flags] public enum TPM { @@ -140,6 +144,7 @@ namespace BizHawk.Common TPM_NOANIMATION = 0x4000, TPM_LAYOUTRTL = 0x8000, } +#pragma warning restore CA1069 [Flags] public enum CMF : uint diff --git a/src/BizHawk.Common/Win32/WmImports.cs b/src/BizHawk.Common/Win32/WmImports.cs new file mode 100644 index 0000000000..0db654b749 --- /dev/null +++ b/src/BizHawk.Common/Win32/WmImports.cs @@ -0,0 +1,90 @@ +#nullable disable + +using System; +using System.Runtime.InteropServices; + +// ReSharper disable FieldCanBeMadeReadOnly.Global + +namespace BizHawk.Common +{ + public static class WmImports + { + public const uint PM_REMOVE = 0x0001U; + public static readonly IntPtr HWND_MESSAGE = new(-3); + public const int GWLP_USERDATA = -21; + + [StructLayout(LayoutKind.Sequential)] + public struct MSG + { + public IntPtr hwnd; + public uint message; + public IntPtr wParam; + public IntPtr lParam; + public uint time; + public int x; + public int y; + } + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr WNDPROC(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct WNDCLASS + { + public uint style; + public WNDPROC lpfnWndProc; + public int cbClsExtra; + public int cbWndExtra; + public IntPtr hInstance; + public IntPtr hIcon; + public IntPtr hCursor; + public IntPtr hbrBackground; + public string lpszMenuName; + public string lpszClassName; + } + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr CreateWindowEx(int dwExStyle, IntPtr lpClassName, string lpWindowName, + int dwStyle, int X, int Y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DestroyWindow(IntPtr hWnd); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr DispatchMessage([In] ref MSG lpMsg); + + [DllImport("user32.dll")] + public static extern IntPtr GetActiveWindow(); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool HideCaret(IntPtr hWnd); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr RegisterClass([In] ref WNDCLASS lpWndClass); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool TranslateMessage([In] ref MSG lpMsg); + } +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs index cce4af9706..c0cd32470a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs @@ -785,10 +785,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi { IntPtr[] waitHandles = { handle.SafeWaitHandle.DangerousGetHandle() }; const uint count = 1; - var QS_MASK = ThreadHacks.QS_ALLINPUT; // message queue status + var QS_MASK = WmImports.QS_ALLINPUT; // message queue status QS_MASK = 0; //bizhawk edit?? did we need any messages here?? apparently not??? uint nativeResult; - ThreadHacks.MSG msg; + WmImports.MSG msg; while (true) { // MsgWaitForMultipleObjectsEx with MWMO_INPUTAVAILABLE returns, @@ -796,10 +796,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi nativeResult = ThreadHacks.MsgWaitForMultipleObjectsEx(count, waitHandles, 0xFFFFFFFF, QS_MASK, ThreadHacks.MWMO_INPUTAVAILABLE); if (IsNativeWaitSuccessful(count, nativeResult, out int managedResult) || WaitHandle.WaitTimeout == managedResult) break; // there is a message, pump and dispatch it - if (ThreadHacks.PeekMessage(out msg, IntPtr.Zero, 0, 0, ThreadHacks.PM_REMOVE)) + if (WmImports.PeekMessage(out msg, IntPtr.Zero, 0, 0, WmImports.PM_REMOVE)) { - ThreadHacks.TranslateMessage(ref msg); - ThreadHacks.DispatchMessage(ref msg); + WmImports.TranslateMessage(ref msg); + WmImports.DispatchMessage(ref msg); } } // handle.WaitOne();