mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-09-24 15:54:12 +00:00
374 lines
No EOL
8.6 KiB
C++
374 lines
No EOL
8.6 KiB
C++
#include "./common.h"
|
|
#include "./api__ml_online.h"
|
|
#include "./main.h"
|
|
|
|
#include "../winamp/wa_ipc.h"
|
|
|
|
#include <strsafe.h>
|
|
|
|
LPWSTR Plugin_MallocString(size_t cchLen)
|
|
{
|
|
return (LPWSTR)calloc(cchLen, sizeof(WCHAR));
|
|
}
|
|
|
|
void Plugin_FreeString(LPWSTR pszString)
|
|
{
|
|
if (NULL != pszString)
|
|
{
|
|
free(pszString);
|
|
pszString = NULL;
|
|
}
|
|
}
|
|
|
|
LPWSTR Plugin_ReAllocString(LPWSTR pszString, size_t cchLen)
|
|
{
|
|
return (LPWSTR)realloc(pszString, sizeof(WCHAR) * cchLen);
|
|
}
|
|
|
|
LPWSTR Plugin_CopyString(LPCWSTR pszSource)
|
|
{
|
|
if (NULL == pszSource)
|
|
return NULL;
|
|
|
|
INT cchSource = lstrlenW(pszSource) + 1;
|
|
|
|
LPWSTR copy = Plugin_MallocString(cchSource);
|
|
if (NULL != copy)
|
|
{
|
|
CopyMemory(copy, pszSource, sizeof(WCHAR) * cchSource);
|
|
}
|
|
return copy;
|
|
}
|
|
|
|
LPSTR Plugin_MallocAnsiString(size_t cchLen)
|
|
{
|
|
return (LPSTR)calloc(cchLen, sizeof(CHAR));
|
|
}
|
|
|
|
LPSTR Plugin_CopyAnsiString(LPCSTR pszSource)
|
|
{
|
|
if (NULL == pszSource)
|
|
return NULL;
|
|
|
|
INT cchSource = lstrlenA(pszSource) + 1;
|
|
|
|
LPSTR copy = Plugin_MallocAnsiString(cchSource);
|
|
if (NULL != copy)
|
|
{
|
|
CopyMemory(copy, pszSource, sizeof(CHAR) * cchSource);
|
|
}
|
|
return copy;
|
|
|
|
}
|
|
void Plugin_FreeAnsiString(LPSTR pszString)
|
|
{
|
|
Plugin_FreeString((LPWSTR)pszString);
|
|
}
|
|
|
|
LPSTR Plugin_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
|
|
{
|
|
INT cchBuffer = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
|
|
if (0 == cchBuffer) return NULL;
|
|
|
|
LPSTR buffer = Plugin_MallocAnsiString(cchBuffer);
|
|
if (NULL == buffer) return NULL;
|
|
|
|
if (0 == WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, buffer, cchBuffer, lpDefaultChar, lpUsedDefaultChar))
|
|
{
|
|
Plugin_FreeAnsiString(buffer);
|
|
return NULL;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
LPWSTR Plugin_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte)
|
|
{
|
|
if (NULL == lpMultiByteStr) return NULL;
|
|
INT cchBuffer = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
|
|
if (NULL == cchBuffer) return NULL;
|
|
|
|
if (cbMultiByte > 0) cchBuffer++;
|
|
|
|
LPWSTR buffer = Plugin_MallocString(cchBuffer);
|
|
if (NULL == buffer) return NULL;
|
|
|
|
if (0 == MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, buffer, cchBuffer))
|
|
{
|
|
Plugin_FreeString(buffer);
|
|
return NULL;
|
|
}
|
|
|
|
if (cbMultiByte > 0)
|
|
{
|
|
buffer[cchBuffer - 1] = L'\0';
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
LPWSTR Plugin_DuplicateResString(LPCWSTR pszResource)
|
|
{
|
|
return (IS_INTRESOURCE(pszResource)) ?
|
|
(LPWSTR)pszResource :
|
|
Plugin_CopyString(pszResource);
|
|
}
|
|
|
|
void Plugin_FreeResString(LPWSTR pszResource)
|
|
{
|
|
if (!IS_INTRESOURCE(pszResource))
|
|
Plugin_FreeString(pszResource);
|
|
}
|
|
|
|
HRESULT Plugin_CopyResString(LPWSTR pszBuffer, INT cchBufferMax, LPCWSTR pszString)
|
|
{
|
|
if (NULL == pszBuffer)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (NULL == pszString)
|
|
{
|
|
pszBuffer[0] = L'\0';
|
|
}
|
|
else if (IS_INTRESOURCE(pszString))
|
|
{
|
|
if (NULL == WASABI_API_LNG)
|
|
hr = E_FAIL;
|
|
else
|
|
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)pszString, pszBuffer, cchBufferMax);
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCopy(pszBuffer, cchBufferMax, pszString);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
void Plugin_SafeRelease(IUnknown *pUnk)
|
|
{
|
|
if (NULL != pUnk)
|
|
pUnk->Release();
|
|
}
|
|
|
|
HRESULT Plugin_MakeResourcePath(LPWSTR pszBuffer, INT cchBufferMax, LPCWSTR pszType, LPCWSTR pszName, UINT flags)
|
|
{
|
|
HINSTANCE hInstance = WASABI_API_LNG_HINST;
|
|
if (NULL == hInstance || NULL == FindResource(hInstance, pszName, pszType))
|
|
hInstance = Plugin_GetInstance();
|
|
|
|
if (NULL == OMUTILITY)
|
|
return E_UNEXPECTED;
|
|
|
|
return OMUTILITY->MakeResourcePath(pszBuffer, cchBufferMax, hInstance, pszType, pszName, flags);
|
|
}
|
|
|
|
HWND Plugin_GetDialogOwner(void)
|
|
{
|
|
HWND hOwner= Plugin_GetLibrary();
|
|
if (NULL == hOwner || FALSE == IsWindowVisible(hOwner) ||
|
|
FALSE == IsWindowEnabled(hOwner))
|
|
{
|
|
hOwner = Plugin_GetWinamp();
|
|
if (NULL != hOwner)
|
|
{
|
|
HWND hDlgParent = (HWND)SENDWAIPC(hOwner, IPC_GETDIALOGBOXPARENT, 0L);
|
|
if (NULL != hDlgParent)
|
|
hOwner = hDlgParent;
|
|
}
|
|
}
|
|
return hOwner;
|
|
}
|
|
|
|
HRESULT Plugin_AppendFileFilter(LPTSTR pszBuffer, size_t cchBufferMax, LPCTSTR pName, LPCTSTR pFilter, LPTSTR *ppBufferOut, size_t *pRemaining, BOOL bShowFilter)
|
|
{
|
|
HRESULT hr;
|
|
|
|
LPTSTR pCursor = pszBuffer;
|
|
|
|
if (NULL != ppBufferOut)
|
|
*ppBufferOut = pszBuffer;
|
|
|
|
if (NULL != pRemaining)
|
|
*pRemaining = cchBufferMax;
|
|
|
|
if (NULL == pszBuffer || NULL == pName || NULL == pFilter)
|
|
return E_INVALIDARG;
|
|
|
|
pszBuffer[0] = TEXT('\0');
|
|
|
|
hr = StringCchCopyEx(pCursor, cchBufferMax, pName, &pCursor, &cchBufferMax,
|
|
STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
|
|
if (bShowFilter && SUCCEEDED(hr))
|
|
{
|
|
LPTSTR p = pCursor;
|
|
hr = StringCchPrintfEx(pCursor, cchBufferMax, &pCursor, &cchBufferMax,
|
|
STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE, TEXT(" (%s)"), pFilter);
|
|
if (SUCCEEDED(hr) && p != pCursor)
|
|
CharLowerBuff(p, (INT)(INT_PTR)(pCursor - p));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pCursor++;
|
|
cchBufferMax--;
|
|
hr = StringCchCopyEx(pCursor, cchBufferMax, pFilter, &pCursor, &cchBufferMax,
|
|
STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
|
|
}
|
|
|
|
if (cchBufferMax < 1)
|
|
hr = STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
pCursor++;
|
|
cchBufferMax--;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pCursor[0] = TEXT('\0');
|
|
if (NULL != ppBufferOut)
|
|
*ppBufferOut = pCursor;
|
|
if (NULL != pRemaining)
|
|
*pRemaining = cchBufferMax;
|
|
}
|
|
else
|
|
{
|
|
pszBuffer[0] = TEXT('\0');
|
|
pszBuffer[1] = TEXT('\0');
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Plugin_BuildActionUrl(LPWSTR *ppStringOut, LPCWSTR pszAction, UINT *pServiceUid, size_t cchServiceUid)
|
|
{
|
|
if (NULL == ppStringOut)
|
|
return E_POINTER;
|
|
|
|
*ppStringOut = NULL;
|
|
|
|
if (NULL == pszAction || L'\0' == *pszAction ||
|
|
NULL == pServiceUid || 0 == cchServiceUid)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
const WCHAR szPrefix[] = L"http://services.winamp.com/svc/action?action=%s\0";
|
|
const WCHAR szService[] = L"&svc_id=%u\0";
|
|
const WCHAR szClient[] = L"&unique_id=%s\0";
|
|
|
|
size_t cchBuffer = ARRAYSIZE(szPrefix) + ARRAYSIZE(szService) + ARRAYSIZE(szClient);
|
|
cchBuffer += lstrlen(pszAction);
|
|
cchBuffer += (cchServiceUid * 11);
|
|
cchBuffer += 32; // unique id
|
|
|
|
LPWSTR buffer = Plugin_MallocString(cchBuffer);
|
|
if (NULL == buffer)
|
|
return E_OUTOFMEMORY;
|
|
|
|
HRESULT hr;
|
|
LPWSTR cursor = buffer;
|
|
size_t remaining = cchBuffer;
|
|
|
|
|
|
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
|
szPrefix, pszAction);
|
|
|
|
for (size_t i = 0; i < cchServiceUid && SUCCEEDED(hr); i++)
|
|
{
|
|
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
|
((0 == i) ? szService : L",%u"), pServiceUid[i]);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR szTemp[128] = {0};
|
|
hr = OMBROWSERMNGR->GetClientId(szTemp, ARRAYSIZE(szTemp));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE, szClient, szTemp);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
Plugin_FreeString(buffer);
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
*ppStringOut = buffer;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
INT Plugin_ParseKeywords(LPCWSTR input, INT cchInput, WCHAR separator, BOOL eatSpace, KWPARSERPROC callback, ULONG_PTR user)
|
|
{
|
|
if (NULL == input)
|
|
return 0;
|
|
|
|
if (cchInput < 0)
|
|
cchInput = lstrlen(input);
|
|
|
|
if (cchInput <= 0)
|
|
return 0;
|
|
|
|
LPCWSTR end = (input + cchInput);
|
|
|
|
if(eatSpace)
|
|
while(input < end && L' ' == *input) input++;
|
|
|
|
if (L'\0' == *input)
|
|
return 0;
|
|
|
|
INT found = 0;
|
|
|
|
for (;;)
|
|
{
|
|
LPCWSTR pBlock = input;
|
|
while(input <= end && separator != *input) input++;
|
|
LPCWSTR last = (input - 1);
|
|
if (eatSpace)
|
|
while(last >= pBlock && L' ' == *last) last--;
|
|
|
|
if (last >= pBlock)
|
|
{
|
|
UINT code = callback(pBlock, (INT)(INT_PTR)(last - pBlock) + 1, user);
|
|
if (KWPARSER_FOUND & code) found++;
|
|
if (KWPARSER_ABORT == (0x01 & code))
|
|
return found;
|
|
}
|
|
|
|
if (input >= end || L'\0' == *input)
|
|
return found;
|
|
|
|
input++;
|
|
if(eatSpace)
|
|
while(input < end && L' ' == *input) input++;
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
INT Plugin_MessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
|
|
{
|
|
HWND hHost, hLibrary = Plugin_GetLibrary();
|
|
if (NULL != hLibrary && FALSE != IsWindowVisible(hLibrary))
|
|
{
|
|
hHost = (HWND)SENDMLIPC(hLibrary, ML_IPC_GETCURRENTVIEW, 0);
|
|
if (NULL == hHost || FALSE == IsWindowVisible(hHost))
|
|
hHost = hLibrary;
|
|
}
|
|
else
|
|
hHost = Plugin_GetDialogOwner();
|
|
|
|
if(IS_INTRESOURCE(lpText) && NULL != lpText)
|
|
{
|
|
WCHAR szText[2048] = {0};
|
|
lpText = WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)lpText, szText, ARRAYSIZE(szText));
|
|
}
|
|
|
|
if(IS_INTRESOURCE(lpCaption) && NULL != lpCaption)
|
|
{
|
|
WCHAR szCaption[128] = {0};
|
|
lpCaption = WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)lpCaption, szCaption, ARRAYSIZE(szCaption));
|
|
}
|
|
|
|
return MessageBox(hHost, lpText, lpCaption, uType);
|
|
} |