Implement OleRegEnumVerbs.
This commit is contained in:
parent
044ccc40f3
commit
3daf39fb0c
|
@ -674,6 +674,272 @@ HRESULT WINAPI OleRegGetMiscStatus(
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT EnumOLEVERB_Construct(HKEY hkeyVerb, ULONG index, IEnumOLEVERB **ppenum);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const IEnumOLEVERBVtbl *lpvtbl;
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
HKEY hkeyVerb;
|
||||||
|
ULONG index;
|
||||||
|
} EnumOLEVERB;
|
||||||
|
|
||||||
|
static HRESULT WINAPI EnumOLEVERB_QueryInterface(
|
||||||
|
IEnumOLEVERB *iface, REFIID riid, void **ppv)
|
||||||
|
{
|
||||||
|
TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
|
||||||
|
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||||
|
IsEqualIID(riid, &IID_IEnumOLEVERB))
|
||||||
|
{
|
||||||
|
IUnknown_AddRef(iface);
|
||||||
|
*ppv = iface;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI EnumOLEVERB_AddRef(
|
||||||
|
IEnumOLEVERB *iface)
|
||||||
|
{
|
||||||
|
EnumOLEVERB *This = (EnumOLEVERB *)iface;
|
||||||
|
TRACE("()\n");
|
||||||
|
return InterlockedIncrement(&This->ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI EnumOLEVERB_Release(
|
||||||
|
IEnumOLEVERB *iface)
|
||||||
|
{
|
||||||
|
EnumOLEVERB *This = (EnumOLEVERB *)iface;
|
||||||
|
LONG refs = InterlockedDecrement(&This->ref);
|
||||||
|
TRACE("()\n");
|
||||||
|
if (!refs)
|
||||||
|
{
|
||||||
|
RegCloseKey(This->hkeyVerb);
|
||||||
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
}
|
||||||
|
return refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EnumOLEVERB_Next(
|
||||||
|
IEnumOLEVERB *iface, ULONG celt, LPOLEVERB rgelt,
|
||||||
|
ULONG *pceltFetched)
|
||||||
|
{
|
||||||
|
EnumOLEVERB *This = (EnumOLEVERB *)iface;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
TRACE("(%ld, %p, %p)\n", celt, rgelt, pceltFetched);
|
||||||
|
|
||||||
|
if (pceltFetched)
|
||||||
|
*pceltFetched = 0;
|
||||||
|
|
||||||
|
for (; celt; celt--, rgelt++)
|
||||||
|
{
|
||||||
|
WCHAR wszSubKey[20];
|
||||||
|
LONG cbData;
|
||||||
|
LPWSTR pwszOLEVERB;
|
||||||
|
LPWSTR pwszMenuFlags;
|
||||||
|
LPWSTR pwszAttribs;
|
||||||
|
LONG res = RegEnumKeyW(This->hkeyVerb, This->index, wszSubKey, sizeof(wszSubKey)/sizeof(wszSubKey[0]));
|
||||||
|
if (res == ERROR_NO_MORE_ITEMS)
|
||||||
|
{
|
||||||
|
hr = S_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("RegEnumKeyW failed with error %ld\n", res);
|
||||||
|
hr = REGDB_E_READREGDB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = RegQueryValueW(This->hkeyVerb, wszSubKey, NULL, &cbData);
|
||||||
|
if (res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("RegQueryValueW failed with error %ld\n", res);
|
||||||
|
hr = REGDB_E_READREGDB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pwszOLEVERB = CoTaskMemAlloc(cbData);
|
||||||
|
if (!pwszOLEVERB)
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = RegQueryValueW(This->hkeyVerb, wszSubKey, pwszOLEVERB, &cbData);
|
||||||
|
if (res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("RegQueryValueW failed with error %ld\n", res);
|
||||||
|
hr = REGDB_E_READREGDB;
|
||||||
|
CoTaskMemFree(pwszOLEVERB);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("verb string: %s\n", debugstr_w(pwszOLEVERB));
|
||||||
|
pwszMenuFlags = strchrW(pwszOLEVERB, ',');
|
||||||
|
if (!pwszMenuFlags)
|
||||||
|
{
|
||||||
|
hr = OLEOBJ_E_INVALIDVERB;
|
||||||
|
CoTaskMemFree(pwszOLEVERB);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* nul terminate the name string and advance to first character */
|
||||||
|
*pwszMenuFlags = '\0';
|
||||||
|
pwszMenuFlags++;
|
||||||
|
pwszAttribs = strchrW(pwszMenuFlags, ',');
|
||||||
|
if (!pwszAttribs)
|
||||||
|
{
|
||||||
|
hr = OLEOBJ_E_INVALIDVERB;
|
||||||
|
CoTaskMemFree(pwszOLEVERB);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* nul terminate the menu string and advance to first character */
|
||||||
|
*pwszAttribs = '\0';
|
||||||
|
pwszAttribs++;
|
||||||
|
|
||||||
|
/* fill out structure for this verb */
|
||||||
|
rgelt->lVerb = atolW(wszSubKey);
|
||||||
|
rgelt->lpszVerbName = pwszOLEVERB; /* user should free */
|
||||||
|
rgelt->fuFlags = atolW(pwszMenuFlags);
|
||||||
|
rgelt->grfAttribs = atolW(pwszAttribs);
|
||||||
|
|
||||||
|
if (pceltFetched)
|
||||||
|
*pceltFetched++;
|
||||||
|
This->index++;
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EnumOLEVERB_Skip(
|
||||||
|
IEnumOLEVERB *iface, ULONG celt)
|
||||||
|
{
|
||||||
|
EnumOLEVERB *This = (EnumOLEVERB *)iface;
|
||||||
|
|
||||||
|
TRACE("(%ld)\n", celt);
|
||||||
|
|
||||||
|
This->index += celt;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EnumOLEVERB_Reset(
|
||||||
|
IEnumOLEVERB *iface)
|
||||||
|
{
|
||||||
|
EnumOLEVERB *This = (EnumOLEVERB *)iface;
|
||||||
|
|
||||||
|
TRACE("()\n");
|
||||||
|
|
||||||
|
This->index = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI EnumOLEVERB_Clone(
|
||||||
|
IEnumOLEVERB *iface,
|
||||||
|
IEnumOLEVERB **ppenum)
|
||||||
|
{
|
||||||
|
EnumOLEVERB *This = (EnumOLEVERB *)iface;
|
||||||
|
HKEY hkeyVerb;
|
||||||
|
TRACE("(%p)\n", ppenum);
|
||||||
|
if (!DuplicateHandle(GetCurrentProcess(), This->hkeyVerb, GetCurrentProcess(), (HANDLE *)&hkeyVerb, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
return EnumOLEVERB_Construct(hkeyVerb, This->index, ppenum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IEnumOLEVERBVtbl EnumOLEVERB_VTable =
|
||||||
|
{
|
||||||
|
EnumOLEVERB_QueryInterface,
|
||||||
|
EnumOLEVERB_AddRef,
|
||||||
|
EnumOLEVERB_Release,
|
||||||
|
EnumOLEVERB_Next,
|
||||||
|
EnumOLEVERB_Skip,
|
||||||
|
EnumOLEVERB_Reset,
|
||||||
|
EnumOLEVERB_Clone
|
||||||
|
};
|
||||||
|
|
||||||
|
static HRESULT EnumOLEVERB_Construct(HKEY hkeyVerb, ULONG index, IEnumOLEVERB **ppenum)
|
||||||
|
{
|
||||||
|
EnumOLEVERB *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||||
|
if (!This)
|
||||||
|
{
|
||||||
|
RegCloseKey(hkeyVerb);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
This->lpvtbl = &EnumOLEVERB_VTable;
|
||||||
|
This->ref = 1;
|
||||||
|
This->index = index;
|
||||||
|
This->hkeyVerb = hkeyVerb;
|
||||||
|
*ppenum = (IEnumOLEVERB *)&This->lpvtbl;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* OleRegEnumVerbs [OLE32.@]
|
||||||
|
*
|
||||||
|
* Enumerates verbs associated with a class stored in the registry.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* clsid [I] Class ID to enumerate the verbs for.
|
||||||
|
* ppenum [O] Enumerator.
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* S_OK: Success.
|
||||||
|
* REGDB_E_CLASSNOTREG: The specified class does not have a key in the registry.
|
||||||
|
* REGDB_E_READREGDB: The class key could not be opened for some other reason.
|
||||||
|
* OLE_E_REGDB_KEY: The Verb subkey for the class is not present.
|
||||||
|
* OLEOBJ_E_NOVERBS: The Verb subkey for the class is empty.
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB* ppenum)
|
||||||
|
{
|
||||||
|
LONG res;
|
||||||
|
HKEY hkeyClass;
|
||||||
|
HKEY hkeyVerb;
|
||||||
|
DWORD dwSubKeys;
|
||||||
|
static const WCHAR wszVerb[] = {'V','e','r','b',0};
|
||||||
|
|
||||||
|
TRACE("(%s, %p)\n", debugstr_guid(clsid), ppenum);
|
||||||
|
|
||||||
|
res = COM_OpenKeyForCLSID(clsid, KEY_READ, &hkeyClass);
|
||||||
|
if (res == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
ERR("CLSID %s not registered\n", debugstr_guid(clsid));
|
||||||
|
return REGDB_E_CLASSNOTREG;
|
||||||
|
}
|
||||||
|
else if (res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("failed to open key for CLSID %s with error %ld\n",
|
||||||
|
debugstr_guid(clsid), res);
|
||||||
|
return REGDB_E_READREGDB;
|
||||||
|
}
|
||||||
|
res = RegOpenKeyExW(hkeyClass, wszVerb, 0, KEY_READ, &hkeyVerb);
|
||||||
|
RegCloseKey(hkeyClass);
|
||||||
|
if (res == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
ERR("no Verbs key for class %s\n", debugstr_guid(clsid));
|
||||||
|
return REGDB_E_KEYMISSING;
|
||||||
|
}
|
||||||
|
else if (res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("failed to open Verbs key for CLSID %s with error %ld\n",
|
||||||
|
debugstr_guid(clsid), res);
|
||||||
|
return REGDB_E_READREGDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = RegQueryInfoKeyW(hkeyVerb, NULL, NULL, NULL, &dwSubKeys, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("failed to get subkey count with error %ld\n", GetLastError());
|
||||||
|
return REGDB_E_READREGDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dwSubKeys)
|
||||||
|
{
|
||||||
|
WARN("class %s has no verbs\n", debugstr_guid(clsid));
|
||||||
|
RegCloseKey(hkeyVerb);
|
||||||
|
return OLEOBJ_E_NOVERBS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EnumOLEVERB_Construct(hkeyVerb, 0, ppenum);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* OleSetContainedObject [OLE32.@]
|
* OleSetContainedObject [OLE32.@]
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -107,15 +107,6 @@ HRESULT WINAPI OleCreateLinkFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* OleRegEnumVerbs [OLE32.@]
|
|
||||||
*/
|
|
||||||
HRESULT WINAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB* ppenum)
|
|
||||||
{
|
|
||||||
FIXME("(%p,%p), stub!\n", clsid, ppenum);
|
|
||||||
return OLEOBJ_E_NOVERBS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* OleRegEnumFormatEtc [OLE32.@]
|
* OleRegEnumFormatEtc [OLE32.@]
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue