ole32: Implement MkParseDisplayName.
This commit is contained in:
parent
87a4516bd9
commit
f8789122aa
|
@ -2,7 +2,7 @@
|
|||
* Class Monikers
|
||||
*
|
||||
* Copyright 1999 Noomen Hamza
|
||||
* Copyright 2005 Robert Shearman
|
||||
* Copyright 2005-2007 Robert Shearman
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -734,6 +734,87 @@ HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **ppmk)
|
|||
return ClassMoniker_QueryInterface((IMoniker *)newClassMoniker, &IID_IMoniker, (void**)ppmk);
|
||||
}
|
||||
|
||||
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
||||
LPDWORD pchEaten, LPMONIKER *ppmk)
|
||||
{
|
||||
HRESULT hr;
|
||||
LPCWSTR s = strchrW(szDisplayName, ':');
|
||||
LPCWSTR end;
|
||||
CLSID clsid;
|
||||
BYTE table[256];
|
||||
int i;
|
||||
|
||||
if (!s)
|
||||
return MK_E_SYNTAX;
|
||||
|
||||
s++;
|
||||
|
||||
for (end = s; *end && (*end != ':'); end++)
|
||||
;
|
||||
|
||||
TRACE("parsing %s\n", debugstr_wn(s, end - s));
|
||||
|
||||
/* validate the CLSID string */
|
||||
if (s[0] == '{')
|
||||
{
|
||||
if ((end - s != 38) || (s[37] != '}'))
|
||||
return MK_E_SYNTAX;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (end - s != 36)
|
||||
return MK_E_SYNTAX;
|
||||
}
|
||||
|
||||
for (i=0; i<36; i++)
|
||||
{
|
||||
if ((i == 8)||(i == 13)||(i == 18)||(i == 23))
|
||||
{
|
||||
if (s[i] != '-')
|
||||
return MK_E_SYNTAX;
|
||||
continue;
|
||||
}
|
||||
if (!(((s[i] >= '0') && (s[i] <= '9')) ||
|
||||
((s[i] >= 'a') && (s[i] <= 'f')) ||
|
||||
((s[i] >= 'A') && (s[i] <= 'F'))))
|
||||
return MK_E_SYNTAX;
|
||||
}
|
||||
|
||||
/* quick lookup table */
|
||||
memset(table, 0, 256);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
table['0' + i] = i;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
table['A' + i] = i+10;
|
||||
table['a' + i] = i+10;
|
||||
}
|
||||
|
||||
/* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
|
||||
|
||||
clsid.Data1 = (table[s[0]] << 28 | table[s[1]] << 24 | table[s[2]] << 20 | table[s[3]] << 16 |
|
||||
table[s[4]] << 12 | table[s[5]] << 8 | table[s[6]] << 4 | table[s[7]]);
|
||||
clsid.Data2 = table[s[9]] << 12 | table[s[10]] << 8 | table[s[11]] << 4 | table[s[12]];
|
||||
clsid.Data3 = table[s[14]] << 12 | table[s[15]] << 8 | table[s[16]] << 4 | table[s[17]];
|
||||
|
||||
/* these are just sequential bytes */
|
||||
clsid.Data4[0] = table[s[19]] << 4 | table[s[20]];
|
||||
clsid.Data4[1] = table[s[21]] << 4 | table[s[22]];
|
||||
clsid.Data4[2] = table[s[24]] << 4 | table[s[25]];
|
||||
clsid.Data4[3] = table[s[26]] << 4 | table[s[27]];
|
||||
clsid.Data4[4] = table[s[28]] << 4 | table[s[29]];
|
||||
clsid.Data4[5] = table[s[30]] << 4 | table[s[31]];
|
||||
clsid.Data4[6] = table[s[32]] << 4 | table[s[33]];
|
||||
clsid.Data4[7] = table[s[34]] << 4 | table[s[35]];
|
||||
|
||||
hr = CreateClassMoniker(&clsid, ppmk);
|
||||
if (SUCCEEDED(hr))
|
||||
*pchEaten = (*end == ':' ? end + 1 : end) - szDisplayName;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ClassMonikerCF_QueryInterface(LPCLASSFACTORY iface,
|
||||
REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
|
|
|
@ -1246,6 +1246,7 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
|
|||
if (RegOpenKeyW(HKEY_CLASSES_ROOT,buf,&xhkey))
|
||||
{
|
||||
HeapFree(GetProcessHeap(),0,buf);
|
||||
WARN("couldn't open key for ProgID %s\n", debugstr_w(progid));
|
||||
return CO_E_CLASSSTRING;
|
||||
}
|
||||
HeapFree(GetProcessHeap(),0,buf);
|
||||
|
@ -1253,6 +1254,7 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
|
|||
if (RegQueryValueW(xhkey,NULL,buf2,&buf2len))
|
||||
{
|
||||
RegCloseKey(xhkey);
|
||||
WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid));
|
||||
return CO_E_CLASSSTRING;
|
||||
}
|
||||
RegCloseKey(xhkey);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* FileMonikers implementation
|
||||
*
|
||||
* Copyright 1999 Noomen Hamza
|
||||
* Copyright 2007 Robert Shearman
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -1405,6 +1406,105 @@ HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
|
|||
return hr;
|
||||
}
|
||||
|
||||
/* find a character from a set in reverse without the string having to be null-terminated */
|
||||
static inline WCHAR *memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept)
|
||||
{
|
||||
const WCHAR *end, *ret = NULL;
|
||||
for (end = ptr + n; ptr < end; ptr++) if (strchrW(accept, *ptr)) ret = ptr;
|
||||
return (WCHAR *)ret;
|
||||
}
|
||||
|
||||
HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
||||
LPDWORD pchEaten, LPMONIKER *ppmk)
|
||||
{
|
||||
LPCWSTR end;
|
||||
static const WCHAR wszSeparators[] = {':','\\','/','!',0};
|
||||
|
||||
for (end = szDisplayName + strlenW(szDisplayName);
|
||||
end && (end != szDisplayName);
|
||||
end = memrpbrkW(szDisplayName, end - szDisplayName, wszSeparators))
|
||||
{
|
||||
HRESULT hr;
|
||||
IRunningObjectTable *rot;
|
||||
IMoniker *file_moniker;
|
||||
LPWSTR file_display_name;
|
||||
LPWSTR full_path_name;
|
||||
DWORD full_path_name_len;
|
||||
int len = end - szDisplayName;
|
||||
|
||||
file_display_name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
|
||||
if (!file_display_name) return E_OUTOFMEMORY;
|
||||
memcpy(file_display_name, szDisplayName, len * sizeof(WCHAR));
|
||||
file_display_name[len] = '\0';
|
||||
|
||||
hr = CreateFileMoniker(file_display_name, &file_moniker);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
IMoniker_Release(file_moniker);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = IRunningObjectTable_IsRunning(rot, file_moniker);
|
||||
IRunningObjectTable_Release(rot);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
IMoniker_Release(file_moniker);
|
||||
return hr;
|
||||
}
|
||||
if (hr == S_OK)
|
||||
{
|
||||
TRACE("found running file moniker for %s\n", debugstr_w(file_display_name));
|
||||
*pchEaten = len;
|
||||
*ppmk = file_moniker;
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
full_path_name_len = GetFullPathNameW(file_display_name, 0, NULL, NULL);
|
||||
if (!full_path_name_len)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
IMoniker_Release(file_moniker);
|
||||
return MK_E_SYNTAX;
|
||||
}
|
||||
full_path_name = HeapAlloc(GetProcessHeap(), 0, full_path_name_len * sizeof(WCHAR));
|
||||
if (!full_path_name)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
IMoniker_Release(file_moniker);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
GetFullPathNameW(file_display_name, full_path_name_len, full_path_name, NULL);
|
||||
|
||||
if (GetFileAttributesW(full_path_name) == INVALID_FILE_ATTRIBUTES)
|
||||
TRACE("couldn't open file %s\n", debugstr_w(full_path_name));
|
||||
else
|
||||
{
|
||||
TRACE("got file moniker for %s\n", debugstr_w(szDisplayName));
|
||||
*pchEaten = len;
|
||||
*ppmk = file_moniker;
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
HeapFree(GetProcessHeap(), 0, full_path_name);
|
||||
return S_OK;
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, file_display_name);
|
||||
HeapFree(GetProcessHeap(), 0, full_path_name);
|
||||
IMoniker_Release(file_moniker);
|
||||
}
|
||||
|
||||
return MK_E_CANTOPENFILE;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT WINAPI FileMonikerCF_QueryInterface(LPCLASSFACTORY iface,
|
||||
REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright 1998 Marcus Meissner
|
||||
* Copyright 1999 Noomen Hamza
|
||||
* Copyright 2005 Robert Shearman (for CodeWeavers)
|
||||
* Copyright 2007 Robert Shearman
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -43,6 +44,7 @@
|
|||
#include "wine/unicode.h"
|
||||
|
||||
#include "compobj_private.h"
|
||||
#include "moniker.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
|
@ -826,18 +828,129 @@ GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
|
|||
return res;
|
||||
}
|
||||
|
||||
static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
|
||||
LPCOLESTR szDisplayName,
|
||||
LPDWORD pchEaten,
|
||||
LPMONIKER *ppmk)
|
||||
{
|
||||
CLSID clsid;
|
||||
HRESULT hr;
|
||||
LPWSTR progid;
|
||||
LPCWSTR start = szDisplayName;
|
||||
LPCWSTR end;
|
||||
int len;
|
||||
IMoniker *class_moniker;
|
||||
|
||||
if (*start == '@')
|
||||
start++;
|
||||
|
||||
/* find end delimiter */
|
||||
for (end = start; *end; end++)
|
||||
if (*end == ':')
|
||||
break;
|
||||
|
||||
len = end - start;
|
||||
|
||||
/* must start with '@' or have a ':' somewhere and mustn't be one character
|
||||
* long (since that looks like an absolute path) */
|
||||
if (((start == szDisplayName) && (*end == '\0')) || (len <= 1))
|
||||
return MK_E_SYNTAX;
|
||||
|
||||
progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
|
||||
if (progid)
|
||||
{
|
||||
memcpy(progid, start, len * sizeof(WCHAR));
|
||||
progid[len] = '\0';
|
||||
}
|
||||
hr = CLSIDFromProgID(progid, &clsid);
|
||||
HeapFree(GetProcessHeap(), 0, progid);
|
||||
if (FAILED(hr))
|
||||
return MK_E_SYNTAX;
|
||||
|
||||
hr = CreateClassMoniker(&clsid, &class_moniker);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IParseDisplayName *pdn;
|
||||
hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
|
||||
&IID_IParseDisplayName, (void **)&pdn);
|
||||
IMoniker_Release(class_moniker);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
|
||||
(LPOLESTR)szDisplayName,
|
||||
pchEaten, ppmk);
|
||||
IParseDisplayName_Release(pdn);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* MkParseDisplayName [OLE32.@]
|
||||
*/
|
||||
HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
|
||||
HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
||||
LPDWORD pchEaten, LPMONIKER *ppmk)
|
||||
{
|
||||
FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
|
||||
HRESULT hr = MK_E_SYNTAX;
|
||||
static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'};
|
||||
IMoniker *moniker;
|
||||
DWORD chEaten;
|
||||
|
||||
TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
|
||||
|
||||
if (!(IsValidInterface((LPUNKNOWN) pbc)))
|
||||
return E_INVALIDARG;
|
||||
|
||||
return MK_E_SYNTAX;
|
||||
*pchEaten = 0;
|
||||
*ppmk = NULL;
|
||||
|
||||
if (!strncmpiW(szDisplayName, wszClsidColon, sizeof(wszClsidColon)/sizeof(wszClsidColon[0])))
|
||||
{
|
||||
hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
|
||||
if (FAILED(hr) && (hr != MK_E_SYNTAX))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
|
||||
if (FAILED(hr) && (hr != MK_E_SYNTAX))
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
|
||||
if (FAILED(hr) && (hr != MK_E_SYNTAX))
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
IMoniker *next_moniker;
|
||||
*pchEaten += chEaten;
|
||||
szDisplayName += chEaten;
|
||||
if (!*szDisplayName)
|
||||
{
|
||||
*ppmk = moniker;
|
||||
return S_OK;
|
||||
}
|
||||
chEaten = 0;
|
||||
hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
|
||||
(LPOLESTR)szDisplayName, &chEaten,
|
||||
&next_moniker);
|
||||
IMoniker_Release(moniker);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
*pchEaten = 0;
|
||||
break;
|
||||
}
|
||||
moniker = next_moniker;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -35,6 +35,11 @@ HRESULT AntiMonikerCF_Create(REFIID riid, LPVOID *ppv);
|
|||
HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv);
|
||||
HRESULT ClassMonikerCF_Create(REFIID riid, LPVOID *ppv);
|
||||
|
||||
HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
||||
LPDWORD pchEaten, LPMONIKER *ppmk);
|
||||
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
||||
LPDWORD pchEaten, LPMONIKER *ppmk);
|
||||
|
||||
HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer);
|
||||
|
||||
|
||||
|
|
|
@ -777,12 +777,12 @@ static void test_MkParseDisplayName(void)
|
|||
ok_ole_success(hr, CreateBindCtx);
|
||||
|
||||
hr = MkParseDisplayName(pbc, wszNonExistantProgId, &eaten, &pmk);
|
||||
todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
|
||||
ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
|
||||
|
||||
/* no special handling of "clsid:" without the string form of the clsid
|
||||
* following */
|
||||
hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
|
||||
todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
|
||||
ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
|
||||
|
||||
/* shows clsid has higher precedence than a running object */
|
||||
hr = CreateFileMoniker(wszDisplayName, &pmk);
|
||||
|
@ -794,7 +794,7 @@ static void test_MkParseDisplayName(void)
|
|||
IMoniker_Release(pmk);
|
||||
pmk = NULL;
|
||||
hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
|
||||
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
|
||||
ok_ole_success(hr, MkParseDisplayName);
|
||||
if (pmk)
|
||||
{
|
||||
IMoniker_IsSystemMoniker(pmk, &moniker_type);
|
||||
|
@ -814,7 +814,7 @@ static void test_MkParseDisplayName(void)
|
|||
IMoniker_Release(pmk);
|
||||
pmk = NULL;
|
||||
hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
|
||||
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
|
||||
ok_ole_success(hr, MkParseDisplayName);
|
||||
if (pmk)
|
||||
{
|
||||
IMoniker_IsSystemMoniker(pmk, &moniker_type);
|
||||
|
@ -830,7 +830,7 @@ static void test_MkParseDisplayName(void)
|
|||
|
||||
expected_display_name = wszDisplayNameProgId1;
|
||||
hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
|
||||
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
|
||||
ok_ole_success(hr, MkParseDisplayName);
|
||||
if (pmk)
|
||||
{
|
||||
IMoniker_IsSystemMoniker(pmk, &moniker_type);
|
||||
|
@ -840,7 +840,7 @@ static void test_MkParseDisplayName(void)
|
|||
|
||||
expected_display_name = wszDisplayNameProgId2;
|
||||
hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
|
||||
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
|
||||
ok_ole_success(hr, MkParseDisplayName);
|
||||
if (pmk)
|
||||
{
|
||||
IMoniker_IsSystemMoniker(pmk, &moniker_type);
|
||||
|
@ -849,7 +849,7 @@ static void test_MkParseDisplayName(void)
|
|||
}
|
||||
|
||||
hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
|
||||
todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName with ProgId without marker should fail with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
|
||||
ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName with ProgId without marker should fail with MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
|
||||
|
||||
hr = CoRevokeClassObject(pdwReg1);
|
||||
ok_ole_success(hr, CoRevokeClassObject);
|
||||
|
@ -858,7 +858,7 @@ static void test_MkParseDisplayName(void)
|
|||
strcat(szDisplayNameFile, "\\kernel32.dll");
|
||||
MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
|
||||
hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
|
||||
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
|
||||
ok_ole_success(hr, MkParseDisplayName);
|
||||
if (pmk)
|
||||
{
|
||||
IMoniker_IsSystemMoniker(pmk, &moniker_type);
|
||||
|
@ -867,7 +867,7 @@ static void test_MkParseDisplayName(void)
|
|||
}
|
||||
|
||||
hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
|
||||
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
|
||||
ok_ole_success(hr, MkParseDisplayName);
|
||||
|
||||
if (pmk)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue