📄 ordinal.c
字号:
/*
* SHLWAPI ordinal functions
*
* Copyright 1997 Marcus Meissner
* 1998 J黵gen Schmied
* 2001-2003 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "wingdi.h"
#include "winuser.h"
#include "winver.h"
#include "winnetwk.h"
#include "mmsystem.h"
#include "objbase.h"
#include "exdisp.h"
#include "shlobj.h"
#include "shlwapi.h"
#include "shellapi.h"
#include "commdlg.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/* DLL handles for late bound calls */
extern HINSTANCE shlwapi_hInstance;
extern DWORD SHLWAPI_ThreadRef_index;
HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
/*
NOTES: Most functions exported by ordinal seem to be superflous.
The reason for these functions to be there is to provide a wrapper
for unicode functions to provide these functions on systems without
unicode functions eg. win95/win98. Since we have such functions we just
call these. If running Wine with native DLLs, some late bound calls may
fail. However, it is better to implement the functions in the forward DLL
and recommend the builtin rather than reimplementing the calls here!
*/
/*************************************************************************
* SHLWAPI_DupSharedHandle
*
* Internal implemetation of SHLWAPI_11.
*/
static
HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
DWORD dwSrcProcId, DWORD dwAccess,
DWORD dwOptions)
{
HANDLE hDst, hSrc;
DWORD dwMyProcId = GetCurrentProcessId();
HANDLE hRet = NULL;
TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
dwAccess, dwOptions);
/* Get dest process handle */
if (dwDstProcId == dwMyProcId)
hDst = GetCurrentProcess();
else
hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
if (hDst)
{
/* Get src process handle */
if (dwSrcProcId == dwMyProcId)
hSrc = GetCurrentProcess();
else
hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
if (hSrc)
{
/* Make handle available to dest process */
if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
hRet = NULL;
if (dwSrcProcId != dwMyProcId)
CloseHandle(hSrc);
}
if (dwDstProcId != dwMyProcId)
CloseHandle(hDst);
}
TRACE("Returning handle %p\n", hRet);
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.7]
*
* Create a block of sharable memory and initialise it with data.
*
* PARAMS
* lpvData [I] Pointer to data to write
* dwSize [I] Size of data
* dwProcId [I] ID of process owning data
*
* RETURNS
* Success: A shared memory handle
* Failure: NULL
*
* NOTES
* Ordinals 7-11 provide a set of calls to create shared memory between a
* group of processes. The shared memory is treated opaquely in that its size
* is not exposed to clients who map it. This is accomplished by storing
* the size of the map as the first DWORD of mapped data, and then offsetting
* the view pointer returned by this size.
*
*/
HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
{
HANDLE hMap;
LPVOID pMapped;
HANDLE hRet = NULL;
TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
/* Create file mapping of the correct length */
hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
dwSize + sizeof(dwSize), NULL);
if (!hMap)
return hRet;
/* Get a view in our process address space */
pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (pMapped)
{
/* Write size of data, followed by the data, to the view */
*((DWORD*)pMapped) = dwSize;
if (lpvData)
memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
/* Release view. All further views mapped will be opaque */
UnmapViewOfFile(pMapped);
hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
DUPLICATE_SAME_ACCESS);
}
CloseHandle(hMap);
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.8]
*
* Get a pointer to a block of shared memory from a shared memory handle.
*
* PARAMS
* hShared [I] Shared memory handle
* dwProcId [I] ID of process owning hShared
*
* RETURNS
* Success: A pointer to the shared memory
* Failure: NULL
*
*/
PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
{
HANDLE hDup;
LPVOID pMapped;
TRACE("(%p %d)\n", hShared, dwProcId);
/* Get handle to shared memory for current process */
hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
FILE_MAP_ALL_ACCESS, 0);
/* Get View */
pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
CloseHandle(hDup);
if (pMapped)
return (char *) pMapped + sizeof(DWORD); /* Hide size */
return NULL;
}
/*************************************************************************
* @ [SHLWAPI.9]
*
* Release a pointer to a block of shared memory.
*
* PARAMS
* lpView [I] Shared memory pointer
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
*/
BOOL WINAPI SHUnlockShared(LPVOID lpView)
{
TRACE("(%p)\n", lpView);
return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
}
/*************************************************************************
* @ [SHLWAPI.10]
*
* Destroy a block of sharable memory.
*
* PARAMS
* hShared [I] Shared memory handle
* dwProcId [I] ID of process owning hShared
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
*/
BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
{
HANDLE hClose;
TRACE("(%p %d)\n", hShared, dwProcId);
/* Get a copy of the handle for our process, closing the source handle */
hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
/* Close local copy */
return CloseHandle(hClose);
}
/*************************************************************************
* @ [SHLWAPI.11]
*
* Copy a sharable memory handle from one process to another.
*
* PARAMS
* hShared [I] Shared memory handle to duplicate
* dwDstProcId [I] ID of the process wanting the duplicated handle
* dwSrcProcId [I] ID of the process owning hShared
* dwAccess [I] Desired DuplicateHandle() access
* dwOptions [I] Desired DuplicateHandle() options
*
* RETURNS
* Success: A handle suitable for use by the dwDstProcId process.
* Failure: A NULL handle.
*
*/
HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
DWORD dwAccess, DWORD dwOptions)
{
HANDLE hRet;
hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
dwAccess, dwOptions);
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.13]
*
* Create and register a clipboard enumerator for a web browser.
*
* PARAMS
* lpBC [I] Binding context
* lpUnknown [I] An object exposing the IWebBrowserApp interface
*
* RETURNS
* Success: S_OK.
* Failure: An HRESULT error code.
*
* NOTES
* The enumerator is stored as a property of the web browser. If it does not
* yet exist, it is created and set before being registered.
*/
HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
{
static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
'-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
'0','A','A','0','0','4','A','E','8','3','7','}','\0' };
BSTR property;
IEnumFORMATETC* pIEnumFormatEtc = NULL;
VARIANTARG var;
HRESULT hRet;
IWebBrowserApp* pBrowser = NULL;
TRACE("(%p, %p)\n", lpBC, lpUnknown);
/* Get An IWebBrowserApp interface from lpUnknown */
hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
if (FAILED(hRet) || !pBrowser)
return E_NOINTERFACE;
V_VT(&var) = VT_EMPTY;
/* The property we get is the browsers clipboard enumerator */
property = SysAllocString(szProperty);
hRet = IWebBrowserApp_GetProperty(pBrowser, property, &var);
SysFreeString(property);
if (FAILED(hRet))
return hRet;
if (V_VT(&var) == VT_EMPTY)
{
/* Iterate through accepted documents and RegisterClipBoardFormatA() them */
char szKeyBuff[128], szValueBuff[128];
DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
FORMATETC* formatList, *format;
HKEY hDocs;
TRACE("Registering formats and creating IEnumFORMATETC instance\n");
if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
"Version\\Internet Settings\\Accepted Documents", &hDocs))
return E_FAIL;
/* Get count of values in key */
while (!dwRet)
{
dwKeySize = sizeof(szKeyBuff);
dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
dwCount++;
}
dwNumValues = dwCount;
/* Note: dwCount = number of items + 1; The extra item is the end node */
format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
if (!formatList)
return E_OUTOFMEMORY;
if (dwNumValues > 1)
{
dwRet = 0;
dwCount = 0;
dwNumValues--;
/* Register clipboard formats for the values and populate format list */
while(!dwRet && dwCount < dwNumValues)
{
dwKeySize = sizeof(szKeyBuff);
dwValueSize = sizeof(szValueBuff);
dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
(PBYTE)szValueBuff, &dwValueSize);
if (!dwRet)
return E_FAIL;
format->cfFormat = RegisterClipboardFormatA(szValueBuff);
format->ptd = NULL;
format->dwAspect = 1;
format->lindex = 4;
format->tymed = -1;
format++;
dwCount++;
}
}
/* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
format->cfFormat = 0;
format->ptd = NULL;
format->dwAspect = 1;
format->lindex = 4;
format->tymed = -1;
/* Create a clipboard enumerator */
hRet = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
if (FAILED(hRet) || !pIEnumFormatEtc)
return hRet;
/* Set our enumerator as the browsers property */
V_VT(&var) = VT_UNKNOWN;
V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
if (FAILED(hRet))
{
IEnumFORMATETC_Release(pIEnumFormatEtc);
goto RegisterDefaultAcceptHeaders_Exit;
}
}
if (V_VT(&var) == VT_UNKNOWN)
{
/* Our variant is holding the clipboard enumerator */
IUnknown* pIUnknown = V_UNKNOWN(&var);
IEnumFORMATETC* pClone = NULL;
TRACE("Retrieved IEnumFORMATETC property\n");
/* Get an IEnumFormatEtc interface from the variants value */
pIEnumFormatEtc = NULL;
hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
(PVOID)&pIEnumFormatEtc);
if (!hRet && pIEnumFormatEtc)
{
/* Clone and register the enumerator */
hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
if (!hRet && pClone)
{
RegisterFormatEnumerator(lpBC, pClone, 0);
IEnumFORMATETC_Release(pClone);
}
/* Release the IEnumFormatEtc interface */
IEnumFORMATETC_Release(pIUnknown);
}
IUnknown_Release(V_UNKNOWN(&var));
}
RegisterDefaultAcceptHeaders_Exit:
IWebBrowserApp_Release(pBrowser);
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.15]
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -