This commit is contained in:
恍兮惚兮 2024-12-29 18:09:35 +08:00
parent 45294aaa3d
commit 3a0f44449c
6 changed files with 128 additions and 219 deletions

View File

@ -20,8 +20,7 @@ inline SECURITY_ATTRIBUTES allAccess = std::invoke([] // allows non-admin proces
static SECURITY_DESCRIPTOR sd = {}; static SECURITY_DESCRIPTOR sd = {};
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
return SECURITY_ATTRIBUTES{ sizeof(SECURITY_ATTRIBUTES), &sd, FALSE }; return SECURITY_ATTRIBUTES{ sizeof(SECURITY_ATTRIBUTES), &sd, FALSE }; });
});
inline std::wstring StringToWideString(const std::string &text, UINT encoding = CP_UTF8) inline std::wstring StringToWideString(const std::string &text, UINT encoding = CP_UTF8)
{ {
@ -36,3 +35,28 @@ inline std::string WideStringToString(const std::wstring &text, UINT cp = CP_UTF
WideCharToMultiByte(cp, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr); WideCharToMultiByte(cp, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr);
return buffer.data(); return buffer.data();
} }
#define CHECK_FAILURE(x) \
if (FAILED((x))) \
return (HRESULT)x;
#define CHECK_FAILURE_NORET(x) \
if (FAILED((x))) \
return ;
struct CO_INIT
{
HRESULT hr;
CO_INIT()
{
HRESULT hr = ::CoInitialize(NULL);
}
operator HRESULT()
{
return hr;
}
~CO_INIT()
{
if (SUCCEEDED(hr))
CoUninitialize();
}
};

View File

@ -1,21 +1,15 @@
std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *token, int voiceid, int rate, int volume) std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *token, int voiceid, int rate, int volume)
{ {
if (FAILED(::CoInitialize(NULL)))
return {};
CComPtr<ISpVoice> pVoice = NULL;
std::optional<std::vector<byte>> ret = {}; std::optional<std::vector<byte>> ret = {};
do [&]()
{ {
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice); CO_INIT co;
if (FAILED(hr) || (NULL == pVoice)) CHECK_FAILURE_NORET(co);
{ CComPtr<ISpVoice> pVoice = NULL;
ret = {}; CHECK_FAILURE_NORET(pVoice.CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL));
break;
}
CComPtr<IEnumSpObjectTokens> pSpEnumTokens = NULL; CComPtr<IEnumSpObjectTokens> pSpEnumTokens = NULL;
if (SUCCEEDED(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens))) CHECK_FAILURE_NORET(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens));
{
ULONG ulTokensNumber = 0; ULONG ulTokensNumber = 0;
pSpEnumTokens->GetCount(&ulTokensNumber); pSpEnumTokens->GetCount(&ulTokensNumber);
ISpObjectToken *m_pISpObjectToken; ISpObjectToken *m_pISpObjectToken;
@ -29,35 +23,11 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
CComPtr<ISpStreamFormat> cpOldStream; CComPtr<ISpStreamFormat> cpOldStream;
CSpStreamFormat originalFmt; CSpStreamFormat originalFmt;
CComPtr<IStream> pMemStream; CComPtr<IStream> pMemStream;
hr = pVoice->GetOutputStream(&cpOldStream); CHECK_FAILURE_NORET(pVoice->GetOutputStream(&cpOldStream));
if (FAILED(hr) || (NULL == cpOldStream))
{
ret = {};
break;
}
originalFmt.AssignFormat(cpOldStream); originalFmt.AssignFormat(cpOldStream);
// hr = SPBindToFile(FileName.c_str(), SPFM_CREATE_ALWAYS, &cpWavStream, &originalFmt.FormatId(), originalFmt.WaveFormatExPtr()); CHECK_FAILURE_NORET(CreateStreamOnHGlobal(NULL, TRUE, &pMemStream));
// if (FAILED(hr)) CHECK_FAILURE_NORET(cpWavStream.CoCreateInstance(CLSID_SpStream));
// { CHECK_FAILURE_NORET(cpWavStream->SetBaseStream(pMemStream, SPDFID_WaveFormatEx, originalFmt.WaveFormatExPtr()));
// ret = false;
// break;
// }
{
hr = ::CreateStreamOnHGlobal(NULL, TRUE, &pMemStream);
if (SUCCEEDED(hr))
{
hr = cpWavStream.CoCreateInstance(CLSID_SpStream);
if (SUCCEEDED(hr))
{
hr = cpWavStream->SetBaseStream(pMemStream, SPDFID_WaveFormatEx, originalFmt.WaveFormatExPtr());
if (FAILED(hr))
{
ret = {};
break;
}
}
}
}
pVoice->SetOutput(cpWavStream, TRUE); pVoice->SetOutput(cpWavStream, TRUE);
pVoice->Speak(Content.c_str(), SPF_IS_XML, NULL); pVoice->Speak(Content.c_str(), SPF_IS_XML, NULL);
@ -68,7 +38,7 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
// After SAPI writes the stream, the stream position is at the end, so we need to set it to the beginning. // After SAPI writes the stream, the stream position is at the end, so we need to set it to the beginning.
_LARGE_INTEGER a = {0}; _LARGE_INTEGER a = {0};
hr = cpWavStream->Seek(a, STREAM_SEEK_SET, NULL); CHECK_FAILURE_NORET(cpWavStream->Seek(a, STREAM_SEEK_SET, NULL));
// get the base istream from the ispstream // get the base istream from the ispstream
CComPtr<IStream> pIstream; CComPtr<IStream> pIstream;
@ -79,7 +49,6 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
pIstream->Stat(&stats, STATFLAG_NONAME); pIstream->Stat(&stats, STATFLAG_NONAME);
ULONG sSize = stats.cbSize.QuadPart; // size of the data to be read ULONG sSize = stats.cbSize.QuadPart; // size of the data to be read
auto wavfmt = *originalFmt.WaveFormatExPtr();
ULONG bytesRead; // this will tell the number of bytes that have been read ULONG bytesRead; // this will tell the number of bytes that have been read
std::vector<byte> datas; std::vector<byte> datas;
@ -96,78 +65,48 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
ptr += 8; ptr += 8;
memcpy(pBuffer + ptr, "\x12\x00\x00\x00", 4); memcpy(pBuffer + ptr, "\x12\x00\x00\x00", 4);
ptr += 4; ptr += 4;
memcpy(pBuffer + ptr, &wavfmt.wFormatTag, 2); memcpy(pBuffer + ptr, originalFmt.WaveFormatExPtr(), sizeof(WAVEFORMATEX));
ptr += 2; ptr += sizeof(WAVEFORMATEX);
memcpy(pBuffer + ptr, &wavfmt.nChannels, 2);
ptr += 2;
int freq = wavfmt.nSamplesPerSec;
memcpy(pBuffer + ptr, &freq, 4);
ptr += 4;
freq = wavfmt.nAvgBytesPerSec;
memcpy(pBuffer + ptr, &freq, 4);
ptr += 4;
memcpy(pBuffer + ptr, &wavfmt.nBlockAlign, 4);
ptr += 2;
memcpy(pBuffer + ptr, &wavfmt.wBitsPerSample, 2);
ptr += 2;
WORD _0 = 0;
memcpy(pBuffer + ptr, &_0, 2);
ptr += 2;
memcpy(pBuffer + ptr, "data", 4); memcpy(pBuffer + ptr, "data", 4);
ptr += 4; ptr += 4;
memcpy(pBuffer + ptr, &sSize, 4); memcpy(pBuffer + ptr, &sSize, 4);
ptr += 4;
// read the data into the buffer // read the data into the buffer
pIstream->Read(pBuffer + 46, sSize, &bytesRead); pIstream->Read(pBuffer + ptr, sSize, &bytesRead);
/*uncomment the following to print the contents of the buffer
cout << "following data read \n";
for (int i = 0; i < sSize; i++)
cout << pBuffer[i] << " ";
cout << endl;
*/
ret = std::move(datas); ret = std::move(datas);
} }();
} while (0);
::CoUninitialize();
return ret; return ret;
} }
std::vector<std::wstring> _List(const wchar_t *token) std::vector<std::wstring> _List(const wchar_t *token)
{ {
if (FAILED(::CoInitialize(NULL)))
return {};
CComPtr<ISpVoice> pSpVoice = NULL;
std::vector<std::wstring> ret; std::vector<std::wstring> ret;
[&]()
{
CO_INIT co;
CHECK_FAILURE_NORET(co);
CComPtr<ISpVoice> pSpVoice = NULL;
CComPtr<IEnumSpObjectTokens> pSpEnumTokens = NULL; CComPtr<IEnumSpObjectTokens> pSpEnumTokens = NULL;
if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pSpVoice))) CHECK_FAILURE_NORET(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pSpVoice));
{ CHECK_FAILURE_NORET(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens));
return {};
}
if (SUCCEEDED(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens)))
{
ULONG ulTokensNumber = 0; ULONG ulTokensNumber = 0;
pSpEnumTokens->GetCount(&ulTokensNumber); pSpEnumTokens->GetCount(&ulTokensNumber);
CComPtr<ISpObjectToken> m_pISpObjectToken; CComPtr<ISpObjectToken> m_pISpObjectToken;
for (ULONG i = 0; i < ulTokensNumber; i++) for (ULONG i = 0; i < ulTokensNumber; i++)
{ {
pSpEnumTokens->Item(i, &m_pISpObjectToken); pSpEnumTokens->Item(i, &m_pISpObjectToken);
WCHAR *pszVoiceId = NULL; CComHeapPtr<WCHAR> pszVoiceId;
LPWSTR pszVoiceName; CComHeapPtr<WCHAR> pszVoiceName;
if (SUCCEEDED(m_pISpObjectToken->GetId(&pszVoiceId))) if (SUCCEEDED(m_pISpObjectToken->GetId(&pszVoiceId)))
{ {
if (SUCCEEDED(m_pISpObjectToken->GetStringValue(NULL, &pszVoiceName))) if (SUCCEEDED(m_pISpObjectToken->GetStringValue(NULL, &pszVoiceName)))
{ {
ret.emplace_back(pszVoiceName); ret.emplace_back(pszVoiceName);
CoTaskMemFree(pszVoiceName);
}
CoTaskMemFree(pszVoiceId);
} }
} }
} }
::CoUninitialize(); }();
return ret; return ret;
} }

View File

@ -211,48 +211,19 @@ HRESULT MWebBrowser::CreateBrowser(HWND hwndParent)
{ {
m_hwndParent = hwndParent; m_hwndParent = hwndParent;
HRESULT hr; CHECK_FAILURE(OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, NULL,
hr = ::OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, NULL, this, this, (void **)&m_ole_object));
this, this, (void **)&m_ole_object);
if (FAILED(hr))
{
assert(0);
return hr;
}
m_ole_object.QueryInterface(&m_pDocHostUIHandler); m_ole_object.QueryInterface(&m_pDocHostUIHandler);
hr = m_ole_object->SetClientSite(this); CHECK_FAILURE(m_ole_object->SetClientSite(this));
if (FAILED(hr)) CHECK_FAILURE(OleSetContainedObject(m_ole_object, TRUE));
{
assert(0);
return hr;
}
hr = ::OleSetContainedObject(m_ole_object, TRUE);
if (FAILED(hr))
{
assert(0);
return hr;
}
RECT rc; RECT rc;
::SetRectEmpty(&rc); ::SetRectEmpty(&rc);
hr = m_ole_object->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, CHECK_FAILURE(m_ole_object->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0,
m_hwndParent, &rc); m_hwndParent, &rc));
if (FAILED(hr))
{
assert(0);
return hr;
}
hr = m_ole_object.QueryInterface(&m_web_browser2);
if (FAILED(hr))
{
assert(0);
return hr;
}
CHECK_FAILURE(m_ole_object.QueryInterface(&m_web_browser2));
HWND hwnd = GetControlWindow(); HWND hwnd = GetControlWindow();
DWORD exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); DWORD exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);

View File

@ -162,7 +162,8 @@ DECLARE_API bool check_window_viewable(HWND hwnd)
DECLARE_API void GetSelectedText(void (*cb)(const wchar_t *)) DECLARE_API void GetSelectedText(void (*cb)(const wchar_t *))
{ {
#ifndef WINXP #ifndef WINXP
CoInitialize(nullptr); CO_INIT co;
CHECK_FAILURE_NORET(co);
try try
{ {
// 初始化 COM // 初始化 COM
@ -212,6 +213,5 @@ DECLARE_API void GetSelectedText(void (*cb)(const wchar_t *))
{ {
printf(e.what()); printf(e.what());
} }
CoUninitialize();
#endif #endif
} }

View File

@ -1,50 +1,28 @@
DECLARE_API void GetLnkTargetPath(wchar_t *lnkFilePath, wchar_t *path, wchar_t *tgtpath, wchar_t *iconpath, wchar_t *dirpath) DECLARE_API void GetLnkTargetPath(const wchar_t *lnkFilePath, wchar_t *path, wchar_t *tgtpath, wchar_t *iconpath, wchar_t *dirpath)
{ {
wcscpy(path, L""); wcscpy(path, L"");
wcscpy(tgtpath, L""); wcscpy(tgtpath, L"");
wcscpy(iconpath, L""); wcscpy(iconpath, L"");
CoInitialize(NULL); wcscpy(dirpath, L"");
CO_INIT co;
CHECK_FAILURE_NORET(co);
CComPtr<IShellLink> shellLink; CComPtr<IShellLink> shellLink;
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&shellLink); CHECK_FAILURE_NORET(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&shellLink));
if (SUCCEEDED(hr))
{
CComPtr<IPersistFile> persistFile; CComPtr<IPersistFile> persistFile;
auto hr = shellLink.QueryInterface(&persistFile); CHECK_FAILURE_NORET(shellLink.QueryInterface(&persistFile));
if (SUCCEEDED(hr))
{
WCHAR wsz[MAX_PATH]; WCHAR wsz[MAX_PATH];
StringCchCopy(wsz, MAX_PATH, lnkFilePath); StringCchCopy(wsz, MAX_PATH, lnkFilePath);
hr = persistFile->Load(wsz, STGM_READ); CHECK_FAILURE_NORET(persistFile->Load(lnkFilePath, STGM_READ));
if (SUCCEEDED(hr)) CHECK_FAILURE_NORET(shellLink->Resolve(NULL, SLR_NO_UI));
{
hr = shellLink->Resolve(NULL, SLR_NO_UI);
if (SUCCEEDED(hr))
{
WIN32_FIND_DATA findData; WIN32_FIND_DATA findData;
int x; int x;
hr = shellLink->GetIconLocation(iconpath, MAX_PATH, &x); shellLink->GetIconLocation(iconpath, MAX_PATH, &x);
if (FAILED(hr)) shellLink->GetArguments(tgtpath, MAX_PATH);
wcscpy(iconpath, L""); shellLink->GetPath(path, MAX_PATH, &findData, SLGP_RAWPATH);
hr = shellLink->GetArguments(tgtpath, MAX_PATH); shellLink->GetWorkingDirectory(dirpath, MAX_PATH);
if (FAILED(hr))
wcscpy(tgtpath, L"");
hr = shellLink->GetPath(path, MAX_PATH, &findData, SLGP_RAWPATH);
if (FAILED(hr))
wcscpy(path, L"");
hr = shellLink->GetWorkingDirectory(dirpath, MAX_PATH);
if (FAILED(hr))
wcscpy(path, L"");
}
}
}
}
CoUninitialize();
} }

View File

@ -7,9 +7,6 @@
#include <wrl/implements.h> #include <wrl/implements.h>
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
#include <WebView2.h> #include <WebView2.h>
#define CHECK_FAILURE(x) \
if (FAILED((x))) \
return x;
#endif #endif
DECLARE_API void set_transparent_background(void *m_host) DECLARE_API void set_transparent_background(void *m_host)