Index: mptrack/Mptrack.cpp =================================================================== --- mptrack/Mptrack.cpp (revision 10509) +++ mptrack/Mptrack.cpp (working copy) @@ -58,7 +58,32 @@ OPENMPT_NAMESPACE_BEGIN +static const TCHAR IPCClassName[] = _T("OpenMPT_IPC_Wnd"); +static LRESULT CALLBACK IPCWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if(uMsg == WM_COPYDATA) + { + const auto ©Data = *reinterpret_cast(lParam); + size_t remain = copyData.cbData / sizeof(WCHAR); + const auto *str = static_cast(copyData.lpData); + while(remain > 0) + { + size_t length = wcsnlen(str, remain); + const std::wstring name(str, length); + theApp.OpenDocumentFile(mpt::PathString::FromWide(name).AsNative().c_str()); + // Null terminator between strings + if(length < remain) + length++; + str += length; + remain -= length; + } + return TRUE; + } + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); +} + + ///////////////////////////////////////////////////////////////////////////// // The one and only CTrackApp object @@ -130,6 +155,7 @@ class CMPTCommandLineInfo: public CCommandLineInfo { public: + std::vector m_fileNames; bool m_bNoDls = false, m_bNoPlugins = false, m_bNoAssembly = false, m_bNoSysCheck = false, m_bNoWine = false, m_bPortable = false, m_bNoCrashHandler = false, m_bDebugCrashHandler = false; #ifdef ENABLE_TESTS @@ -139,7 +165,7 @@ public: void ParseParam(LPCTSTR lpszParam, BOOL bFlag, BOOL bLast) override { - if ((lpszParam) && (bFlag)) + if(lpszParam && bFlag) { if (!lstrcmpi(lpszParam, _T("nologo"))) { m_bShowSplash = FALSE; return; } if (!lstrcmpi(lpszParam, _T("nodls"))) { m_bNoDls = true; return; } @@ -154,6 +180,10 @@ #ifdef ENABLE_TESTS if (!lstrcmpi(lpszParam, _T("noTests"))) { m_bNoTests = true; return; } #endif + } else if(lpszParam && !bFlag) + { + m_fileNames.push_back(mpt::PathString::FromNative(lpszParam)); + // return; } CCommandLineInfo::ParseParam(lpszParam, bFlag, bLast); } @@ -797,7 +827,46 @@ // Parse command line for standard shell commands, DDE, file open ParseCommandLine(cmdInfo); - + + auto ipcWnd = ::FindWindow(IPCClassName, nullptr); + if(ipcWnd && !cmdInfo.m_fileNames.empty()) + { + // TODO: Would it be better to send one message per file due to "hang" status of thread? + std::wstring filenameW; + for(const auto &filename : cmdInfo.m_fileNames) + { + filenameW += filename.ToWide() + L'\0'; + } + const DWORD size = static_cast(filenameW.size() * sizeof(WCHAR)); + COPYDATASTRUCT copyData{ 0, size, &filenameW[0] }; + + DWORD_PTR result = 0; + bool success = ::SendMessageTimeout(ipcWnd, WM_COPYDATA, 0, reinterpret_cast(©Data), SMTO_ABORTIFHUNG | SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG, 10000, &result) != 0; + if(success && result != 0) + { + ExitProcess(0); + } + } + + // Still have to create our own window in case the other process closes... + { + WNDCLASS ipcWindowClass = + { + 0, + IPCWindowProc, + 0, + 0, + m_hInstance, + nullptr, + nullptr, + nullptr, + nullptr, + IPCClassName + }; + auto ipcAtom = RegisterClass(&ipcWindowClass); + CreateWindow(MAKEINTATOM(ipcAtom), _T("OpenMPT IPC Window"), 0, 0, 0, CW_USEDEFAULT, 0, nullptr, nullptr, m_hInstance, 0); + } + if(IsDebuggerPresent() && cmdInfo.m_bDebugCrashHandler) { ExceptionHandler::useAnyCrashHandler = true; @@ -1030,6 +1099,7 @@ // we do not want to open an empty new one on startup. cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing; } + // TODO handle multiple files (MultiSelectModel = Player) if(!ProcessShellCommand(cmdInfo)) { EndWaitCursor();