Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
bc160ff1
Commit
bc160ff1
authored
Nov 08, 2005
by
Michael Jung
Committed by
Alexandre Julliard
Nov 08, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for shell instance objects.
Removed a wine_todo for a no longer failing test. Added a test for IPersistFolder3::GetCurFolder.
parent
3e73b93a
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
452 additions
and
11 deletions
+452
-11
Makefile.in
dlls/shdocvw/Makefile.in
+3
-1
shdocvw.h
dlls/shdocvw/shdocvw.h
+5
-0
shdocvw_main.c
dlls/shdocvw/shdocvw_main.c
+2
-1
shlinstobj.c
dlls/shdocvw/shlinstobj.c
+421
-0
shortcut.c
dlls/shdocvw/tests/shortcut.c
+21
-9
No files found.
dlls/shdocvw/Makefile.in
View file @
bc160ff1
...
...
@@ -5,7 +5,8 @@ SRCDIR = @srcdir@
VPATH
=
@srcdir@
MODULE
=
shdocvw.dll
IMPORTLIB
=
libshdocvw.
$(IMPLIBEXT)
IMPORTS
=
urlmon ole32 user32 advapi32 kernel32
IMPORTS
=
user32 advapi32 kernel32
DELAYIMPORTS
=
urlmon ole32 oleaut32
EXTRALIBS
=
-luuid
C_SRCS
=
\
...
...
@@ -17,6 +18,7 @@ C_SRCS = \
persist.c
\
regsvr.c
\
shdocvw_main.c
\
shlinstobj.c
\
webbrowser.c
RC_SRCS
=
shdocvw.rc
...
...
dlls/shdocvw/shdocvw.h
View file @
bc160ff1
...
...
@@ -48,6 +48,11 @@ typedef struct
extern
IClassFactoryImpl
SHDOCVW_ClassFactory
;
/**********************************************************************
* Shell Instance Objects
*/
extern
HRESULT
SHDOCVW_GetShellInstanceObjectClassObject
(
REFCLSID
rclsid
,
REFIID
riid
,
LPVOID
*
ppvClassObj
);
/**********************************************************************
* WebBrowser declaration for SHDOCVW.DLL
...
...
dlls/shdocvw/shdocvw_main.c
View file @
bc160ff1
...
...
@@ -490,7 +490,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
return
S_OK
;
}
return
CLASS_E_CLASSNOTAVAILABLE
;
/* As a last resort, figure if the CLSID belongs to a 'Shell Instance Object' */
return
SHDOCVW_GetShellInstanceObjectClassObject
(
rclsid
,
riid
,
ppv
);
}
/***********************************************************************
...
...
dlls/shdocvw/shlinstobj.c
0 → 100644
View file @
bc160ff1
/*
* Shell Instance Objects - Add hot water and stir until dissolved.
*
* Copyright 2005 Michael Jung
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* 'Shell Instance Objects' allow you to add a node to the shell namespace
* (typically a shortcut to some location in the filesystem), just by setting
* some registry entries. This feature was introduced with win2k. Please
* search for 'Shell Instance Objects' on MSDN to get more information. */
#include <stdarg.h>
#define COBJMACROS
#define COM_NO_WINDOWS_H
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "objbase.h"
#include "oleauto.h"
#include "shdocvw.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
shdocvw
);
#define ADJUST_THIS(c,m,p) ((c*)(((long)p)-(long)&(((c*)0)->lp##m##Vtbl)))
#define STATIC_CAST(i,p) ((i*)&p->lp##i##Vtbl)
#define CHARS_IN_GUID 39
/******************************************************************************
* RegistryPropertyBag
*
* Gives access to a registry key's values via the IPropertyBag interface.
*/
typedef
struct
_RegistryPropertyBag
{
const
IPropertyBagVtbl
*
lpIPropertyBagVtbl
;
LONG
m_cRef
;
HKEY
m_hInitPropertyBagKey
;
}
RegistryPropertyBag
;
static
void
RegistryPropertyBag_Destroy
(
RegistryPropertyBag
*
This
)
{
TRACE
(
"This=%p)
\n
"
,
This
);
RegCloseKey
(
This
->
m_hInitPropertyBagKey
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
static
HRESULT
WINAPI
RegistryPropertyBag_IPropertyBag_QueryInterface
(
IPropertyBag
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
RegistryPropertyBag
*
This
=
ADJUST_THIS
(
RegistryPropertyBag
,
IPropertyBag
,
iface
);
TRACE
(
"(iface=%p, riid=%s, ppv=%p)
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppv
);
if
(
!
ppv
)
return
E_INVALIDARG
;
if
(
IsEqualIID
(
&
IID_IUnknown
,
riid
)
||
IsEqualIID
(
&
IID_IPropertyBag
,
riid
))
{
*
ppv
=
STATIC_CAST
(
IPropertyBag
,
This
);
}
else
{
*
ppv
=
NULL
;
return
E_NOINTERFACE
;
}
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
}
static
ULONG
WINAPI
RegistryPropertyBag_IPropertyBag_AddRef
(
IPropertyBag
*
iface
)
{
RegistryPropertyBag
*
This
=
ADJUST_THIS
(
RegistryPropertyBag
,
IPropertyBag
,
iface
);
ULONG
cRef
;
TRACE
(
"(iface=%p)
\n
"
,
iface
);
cRef
=
InterlockedIncrement
(
&
This
->
m_cRef
);
if
(
cRef
==
1
)
SHDOCVW_LockModule
();
return
cRef
;
}
static
ULONG
WINAPI
RegistryPropertyBag_IPropertyBag_Release
(
IPropertyBag
*
iface
)
{
RegistryPropertyBag
*
This
=
ADJUST_THIS
(
RegistryPropertyBag
,
IPropertyBag
,
iface
);
ULONG
cRef
;
TRACE
(
"(iface=%p)
\n
"
,
iface
);
cRef
=
InterlockedDecrement
(
&
This
->
m_cRef
);
if
(
cRef
==
0
)
{
RegistryPropertyBag_Destroy
(
This
);
SHDOCVW_UnlockModule
();
}
return
cRef
;
}
static
HRESULT
WINAPI
RegistryPropertyBag_IPropertyBag_Read
(
IPropertyBag
*
iface
,
LPCOLESTR
pwszPropName
,
VARIANT
*
pVar
,
IErrorLog
*
pErrorLog
)
{
RegistryPropertyBag
*
This
=
ADJUST_THIS
(
RegistryPropertyBag
,
IPropertyBag
,
iface
);
WCHAR
*
pwszValue
;
DWORD
dwType
,
cbData
;
LONG
res
;
VARTYPE
vtDst
=
V_VT
(
pVar
);
HRESULT
hr
=
S_OK
;
TRACE
(
"(iface=%p, pwszPropName=%s, pVar=%p, pErrorLog=%p)
\n
"
,
iface
,
debugstr_w
(
pwszPropName
),
pVar
,
pErrorLog
);
res
=
RegQueryValueExW
(
This
->
m_hInitPropertyBagKey
,
pwszPropName
,
NULL
,
&
dwType
,
NULL
,
&
cbData
);
if
(
res
!=
ERROR_SUCCESS
)
return
E_INVALIDARG
;
pwszValue
=
HeapAlloc
(
GetProcessHeap
(),
0
,
cbData
);
if
(
!
pwszValue
)
return
E_OUTOFMEMORY
;
res
=
RegQueryValueExW
(
This
->
m_hInitPropertyBagKey
,
pwszPropName
,
NULL
,
&
dwType
,
(
LPBYTE
)
pwszValue
,
&
cbData
);
if
(
res
!=
ERROR_SUCCESS
)
{
HeapFree
(
GetProcessHeap
(),
0
,
pwszValue
);
return
E_INVALIDARG
;
}
V_VT
(
pVar
)
=
VT_BSTR
;
V_BSTR
(
pVar
)
=
SysAllocString
(
pwszValue
);
HeapFree
(
GetProcessHeap
(),
0
,
pwszValue
);
if
(
vtDst
!=
VT_BSTR
)
{
hr
=
VariantChangeTypeEx
(
pVar
,
pVar
,
LOCALE_SYSTEM_DEFAULT
,
0
,
vtDst
);
if
(
FAILED
(
hr
))
SysFreeString
(
V_BSTR
(
pVar
));
}
return
hr
;
}
static
HRESULT
WINAPI
RegistryPropertyBag_IPropertyBag_Write
(
IPropertyBag
*
iface
,
LPCOLESTR
pwszPropName
,
VARIANT
*
pVar
)
{
FIXME
(
"(iface=%p, pwszPropName=%s, pVar=%p) stub
\n
"
,
iface
,
debugstr_w
(
pwszPropName
),
pVar
);
return
E_NOTIMPL
;
}
static
const
IPropertyBagVtbl
RegistryPropertyBag_IPropertyBagVtbl
=
{
RegistryPropertyBag_IPropertyBag_QueryInterface
,
RegistryPropertyBag_IPropertyBag_AddRef
,
RegistryPropertyBag_IPropertyBag_Release
,
RegistryPropertyBag_IPropertyBag_Read
,
RegistryPropertyBag_IPropertyBag_Write
};
HRESULT
RegistryPropertyBag_Constructor
(
HKEY
hInitPropertyBagKey
,
REFIID
riid
,
LPVOID
*
ppvObject
)
{
HRESULT
hr
=
E_FAIL
;
RegistryPropertyBag
*
pRegistryPropertyBag
;
TRACE
(
"(hInitPropertyBagKey=%p, riid=%s, ppvObject=%p)
\n
"
,
hInitPropertyBagKey
,
debugstr_guid
(
riid
),
ppvObject
);
pRegistryPropertyBag
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
RegistryPropertyBag
));
if
(
pRegistryPropertyBag
)
{
pRegistryPropertyBag
->
lpIPropertyBagVtbl
=
&
RegistryPropertyBag_IPropertyBagVtbl
;
pRegistryPropertyBag
->
m_cRef
=
0
;
pRegistryPropertyBag
->
m_hInitPropertyBagKey
=
hInitPropertyBagKey
;
/* The clasping AddRef/Release is for the case that QueryInterface fails, which will result
* in a reference count of 0 in the Release call, which will result in object destruction.*/
IPropertyBag_AddRef
(
STATIC_CAST
(
IPropertyBag
,
pRegistryPropertyBag
));
hr
=
IPropertyBag_QueryInterface
(
STATIC_CAST
(
IPropertyBag
,
pRegistryPropertyBag
),
riid
,
ppvObject
);
IPropertyBag_Release
(
STATIC_CAST
(
IPropertyBag
,
pRegistryPropertyBag
));
}
return
hr
;
}
/******************************************************************************
* InstanceObjectFactory
* Builds Instance Objects and asks them to initialize themselves based on the
* values of a PropertyBag.
*/
typedef
struct
_InstanceObjectFactory
{
const
IClassFactoryVtbl
*
lpIClassFactoryVtbl
;
LONG
m_cRef
;
CLSID
m_clsidInstance
;
/* CLSID of the objects to create. */
IPropertyBag
*
m_pPropertyBag
;
/* PropertyBag to initialize those objects. */
}
InstanceObjectFactory
;
static
void
InstanceObjectFactory_Destroy
(
InstanceObjectFactory
*
This
)
{
IPropertyBag_Release
(
This
->
m_pPropertyBag
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
static
HRESULT
WINAPI
InstanceObjectFactory_IClassFactory_QueryInterface
(
IClassFactory
*
iface
,
REFIID
riid
,
LPVOID
*
ppv
)
{
InstanceObjectFactory
*
This
=
ADJUST_THIS
(
InstanceObjectFactory
,
IClassFactory
,
iface
);
TRACE
(
"iface=%p, riid=%s, ppv=%p)
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppv
);
if
(
!
ppv
)
return
E_INVALIDARG
;
if
(
IsEqualIID
(
&
IID_IUnknown
,
riid
)
||
IsEqualIID
(
&
IID_IClassFactory
,
riid
))
{
*
ppv
=
STATIC_CAST
(
IClassFactory
,
This
);
}
else
{
*
ppv
=
NULL
;
return
E_NOINTERFACE
;
}
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
}
static
ULONG
WINAPI
InstanceObjectFactory_IClassFactory_AddRef
(
IClassFactory
*
iface
)
{
InstanceObjectFactory
*
This
=
ADJUST_THIS
(
InstanceObjectFactory
,
IClassFactory
,
iface
);
ULONG
cRef
;
TRACE
(
"(iface=%p)
\n
"
,
iface
);
cRef
=
InterlockedIncrement
(
&
This
->
m_cRef
);
if
(
cRef
==
1
)
IClassFactory_LockServer
(
iface
,
TRUE
);
return
cRef
;
}
static
ULONG
WINAPI
InstanceObjectFactory_IClassFactory_Release
(
IClassFactory
*
iface
)
{
InstanceObjectFactory
*
This
=
ADJUST_THIS
(
InstanceObjectFactory
,
IClassFactory
,
iface
);
ULONG
cRef
;
TRACE
(
"(iface=%p)
\n
"
,
iface
);
cRef
=
InterlockedDecrement
(
&
This
->
m_cRef
);
if
(
cRef
==
0
)
{
IClassFactory_LockServer
(
iface
,
FALSE
);
InstanceObjectFactory_Destroy
(
This
);
}
return
cRef
;
}
static
HRESULT
WINAPI
InstanceObjectFactory_IClassFactory_CreateInstance
(
IClassFactory
*
iface
,
IUnknown
*
pUnkOuter
,
REFIID
riid
,
LPVOID
*
ppvObj
)
{
InstanceObjectFactory
*
This
=
ADJUST_THIS
(
InstanceObjectFactory
,
IClassFactory
,
iface
);
IPersistPropertyBag
*
pPersistPropertyBag
;
HRESULT
hr
;
TRACE
(
"(pUnkOuter=%p, riid=%s, ppvObj=%p)
\n
"
,
pUnkOuter
,
debugstr_guid
(
riid
),
ppvObj
);
hr
=
CoCreateInstance
(
&
This
->
m_clsidInstance
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IPersistPropertyBag
,
(
LPVOID
*
)
&
pPersistPropertyBag
);
if
(
FAILED
(
hr
))
{
TRACE
(
"Failed to create instance of %s. hr = %08lx
\n
"
,
debugstr_guid
(
&
This
->
m_clsidInstance
),
hr
);
return
hr
;
}
hr
=
IPersistPropertyBag_Load
(
pPersistPropertyBag
,
This
->
m_pPropertyBag
,
NULL
);
if
(
FAILED
(
hr
))
{
TRACE
(
"Failed to initialize object from ProperyBag: hr = %08lx
\n
"
,
hr
);
IPersistPropertyBag_Release
(
pPersistPropertyBag
);
return
hr
;
}
hr
=
IPersistPropertyBag_QueryInterface
(
pPersistPropertyBag
,
riid
,
ppvObj
);
IPersistPropertyBag_Release
(
pPersistPropertyBag
);
return
hr
;
}
static
HRESULT
WINAPI
InstanceObjectFactory_IClassFactory_LockServer
(
IClassFactory
*
iface
,
BOOL
fLock
)
{
TRACE
(
"(iface=%p, fLock=%d) stub
\n
"
,
iface
,
fLock
);
if
(
fLock
)
SHDOCVW_LockModule
();
else
SHDOCVW_UnlockModule
();
return
S_OK
;
}
static
const
IClassFactoryVtbl
InstanceObjectFactory_IClassFactoryVtbl
=
{
InstanceObjectFactory_IClassFactory_QueryInterface
,
InstanceObjectFactory_IClassFactory_AddRef
,
InstanceObjectFactory_IClassFactory_Release
,
InstanceObjectFactory_IClassFactory_CreateInstance
,
InstanceObjectFactory_IClassFactory_LockServer
};
HRESULT
InstanceObjectFactory_Constructor
(
REFCLSID
rclsid
,
IPropertyBag
*
pPropertyBag
,
REFIID
riid
,
LPVOID
*
ppvObject
)
{
InstanceObjectFactory
*
pInstanceObjectFactory
;
HRESULT
hr
=
E_FAIL
;
TRACE
(
"(RegistryPropertyBag=%p, riid=%s, ppvObject=%p)
\n
"
,
pPropertyBag
,
debugstr_guid
(
riid
),
ppvObject
);
pInstanceObjectFactory
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
InstanceObjectFactory
));
if
(
pInstanceObjectFactory
)
{
pInstanceObjectFactory
->
lpIClassFactoryVtbl
=
&
InstanceObjectFactory_IClassFactoryVtbl
;
pInstanceObjectFactory
->
m_cRef
=
0
;
memcpy
(
&
pInstanceObjectFactory
->
m_clsidInstance
,
rclsid
,
sizeof
(
CLSID
));
pInstanceObjectFactory
->
m_pPropertyBag
=
pPropertyBag
;
IPropertyBag_AddRef
(
pPropertyBag
);
IClassFactory_AddRef
(
STATIC_CAST
(
IClassFactory
,
pInstanceObjectFactory
));
hr
=
IClassFactory_QueryInterface
(
STATIC_CAST
(
IClassFactory
,
pInstanceObjectFactory
),
riid
,
ppvObject
);
IClassFactory_Release
(
STATIC_CAST
(
IClassFactory
,
pInstanceObjectFactory
));
}
return
hr
;
}
/******************************************************************************
* SHDOCVW_GetShellInstanceObjectClassObject [Internal]
*
* Figure if there is a 'Shell Instance Object' conformant registry entry for
* the given CLSID and if so create and return a corresponding ClassObject.
*
* PARAMS
* rclsid [I] CLSID of the 'Shell Instance Object'.
* riid [I] Desired interface. Only IClassFactory supported.
* ppvClassObj [O] The corresponding ClassObject.
*
* RETURNS
* Success: S_OK,
* Failure: CLASS_E_CLASSNOTAVAILABLE
*/
HRESULT
SHDOCVW_GetShellInstanceObjectClassObject
(
REFCLSID
rclsid
,
REFIID
riid
,
LPVOID
*
ppvClassObj
)
{
WCHAR
wszInstanceKey
[]
=
{
'C'
,
'L'
,
'S'
,
'I'
,
'D'
,
'\\'
,
'{'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'-'
,
'0'
,
'0'
,
'0'
,
'0'
,
'-'
,
'0'
,
'0'
,
'0'
,
'0'
,
'-'
,
'0'
,
'0'
,
'0'
,
'0'
,
'-'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'}'
,
'\\'
,
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'n'
,
'c'
,
'e'
,
0
};
const
WCHAR
wszCLSID
[]
=
{
'C'
,
'L'
,
'S'
,
'I'
,
'D'
,
0
};
const
WCHAR
wszInitPropertyBag
[]
=
{
'I'
,
'n'
,
'i'
,
't'
,
'P'
,
'r'
,
'o'
,
'p'
,
'e'
,
'r'
,
't'
,
'y'
,
'B'
,
'a'
,
'g'
,
0
};
WCHAR
wszCLSIDInstance
[
CHARS_IN_GUID
];
CLSID
clsidInstance
;
HKEY
hInstanceKey
,
hInitPropertyBagKey
;
DWORD
dwType
,
cbBytes
=
sizeof
(
wszCLSIDInstance
);
IPropertyBag
*
pInitPropertyBag
;
HRESULT
hr
;
LONG
res
;
TRACE
(
"(rclsid=%s, riid=%s, ppvClassObject=%p)
\n
"
,
debugstr_guid
(
rclsid
),
debugstr_guid
(
riid
),
ppvClassObj
);
/* Figure if there is an 'Instance' subkey for the given CLSID and aquire a handle. */
if
(
!
StringFromGUID2
(
rclsid
,
wszInstanceKey
+
6
,
CHARS_IN_GUID
)
||
!
(
wszInstanceKey
[
5
+
CHARS_IN_GUID
]
=
'\\'
)
||
/* Repair the null-termination. */
ERROR_SUCCESS
!=
RegOpenKeyExW
(
HKEY_CLASSES_ROOT
,
wszInstanceKey
,
0
,
KEY_READ
,
&
hInstanceKey
))
{
/* If there is no 'Instance' subkey, then it's not a Shell Instance Object. */
return
CLASS_E_CLASSNOTAVAILABLE
;
}
if
(
RegQueryValueExW
(
hInstanceKey
,
wszCLSID
,
NULL
,
&
dwType
,
(
LPBYTE
)
wszCLSIDInstance
,
&
cbBytes
)
!=
ERROR_SUCCESS
||
FAILED
(
CLSIDFromString
(
wszCLSIDInstance
,
&
clsidInstance
)))
{
/* 'Instance' should have a 'CLSID' value with a well-formed clsid-string. */
FIXME
(
"Failed to infer instance CLSID! %s
\n
"
,
debugstr_w
(
wszCLSIDInstance
));
RegCloseKey
(
hInstanceKey
);
return
CLASS_E_CLASSNOTAVAILABLE
;
}
/* Try to open the 'InitPropertyBag' subkey. */
res
=
RegOpenKeyExW
(
hInstanceKey
,
wszInitPropertyBag
,
0
,
KEY_READ
,
&
hInitPropertyBagKey
);
RegCloseKey
(
hInstanceKey
);
if
(
res
!=
ERROR_SUCCESS
)
{
/* Besides 'InitPropertyBag's, shell instance objects might be initialized by streams.
* So this case might not be an error. */
TRACE
(
"No InitPropertyBag key found!
\n
"
);
return
CLASS_E_CLASSNOTAVAILABLE
;
}
/* If the construction succeeds, the new RegistryPropertyBag is responsible for closing
* hInitProperyBagKey. */
hr
=
RegistryPropertyBag_Constructor
(
hInitPropertyBagKey
,
&
IID_IPropertyBag
,
(
LPVOID
*
)
&
pInitPropertyBag
);
if
(
FAILED
(
hr
))
{
RegCloseKey
(
hInitPropertyBagKey
);
return
hr
;
}
/* Construct an Instance Object Factory, which creates objects of class 'clsidInstance'
* and asks them to initialize themselves with the help of the 'pInitiPropertyBag' */
hr
=
InstanceObjectFactory_Constructor
(
&
clsidInstance
,
pInitPropertyBag
,
riid
,
ppvClassObj
);
IPropertyBag_Release
(
pInitPropertyBag
);
/* The factory will hold a reference the bag. */
return
hr
;
}
dlls/shdocvw/tests/shortcut.c
View file @
bc160ff1
/*
* Unit tests to document shdocvw's
CLSID_FolderShortcut related functionality
* Unit tests to document shdocvw's
'Shell Instance Objects' features
*
* Copyright 2005 Michael Jung
*
...
...
@@ -27,7 +27,10 @@
* Technologies". This mechanism would be cool for wine, since we could
* map Gnome's virtual devices to FolderShortcuts and have them appear in the
* file dialogs. These unit tests are meant to document how this mechanism
* works on windows. */
* works on windows.
*
* Search MSDN for "Creating Shell Extensions with Shell Instance Objects" for
* more documentation.*/
#include <stdarg.h>
...
...
@@ -156,10 +159,12 @@ static void unregister_keys(HKEY hRootKey, const struct registry_key *keys, unsi
static
void
test_ShortcutFolder
()
{
LPSHELLFOLDER
pDesktopFolder
,
pWineTestFolder
;
IPersist
*
pWineTestPersist
;
LPITEMIDLIST
pidlWineTestFolder
;
IPersist
Folder3
*
pWineTestPersistFolder
;
LPITEMIDLIST
pidlWineTestFolder
,
pidlCurFolder
;
HRESULT
hr
;
CLSID
clsid
;
const
CLSID
CLSID_WineTest
=
{
0x9b352ebf
,
0x2765
,
0x45c1
,
{
0xb4
,
0xc6
,
0x85
,
0xcc
,
0x7f
,
0x7a
,
0xbc
,
0x64
}
};
WCHAR
wszWineTestFolder
[]
=
{
':'
,
':'
,
'{'
,
'9'
,
'B'
,
'3'
,
'5'
,
'2'
,
'E'
,
'B'
,
'F'
,
'-'
,
'2'
,
'7'
,
'6'
,
'5'
,
'-'
,
'4'
,
'5'
,
'C'
,
'1'
,
'-'
,
'B'
,
'4'
,
'C'
,
'6'
,
'-'
,
'8'
,
'5'
,
'C'
,
'C'
,
'7'
,
'F'
,
'7'
,
'A'
,
'B'
,
'C'
,
'6'
,
'4'
,
'}'
,
0
};
...
...
@@ -187,20 +192,27 @@ static void test_ShortcutFolder() {
(
LPVOID
*
)
&
pWineTestFolder
);
IShellFolder_Release
(
pDesktopFolder
);
ILFree
(
pidlWineTestFolder
);
todo_wine
{
ok
(
SUCCEEDED
(
hr
),
"IShellFolder::BindToObject(WineTestFolder) failed! hr = %08lx
\n
"
,
hr
);
}
ok
(
SUCCEEDED
(
hr
),
"IShellFolder::BindToObject(WineTestFolder) failed! hr = %08lx
\n
"
,
hr
);
if
(
FAILED
(
hr
))
goto
cleanup
;
hr
=
IShellFolder_QueryInterface
(
pWineTestFolder
,
&
IID_IPersist
,
(
LPVOID
*
)
&
pWineTestPersist
);
ok
(
SUCCEEDED
(
hr
),
"IShellFolder::QueryInterface(IPersist) failed! hr = %08lx
\n
"
,
hr
);
hr
=
IShellFolder_QueryInterface
(
pWineTestFolder
,
&
IID_IPersist
Folder3
,
(
LPVOID
*
)
&
pWineTestPersistFolder
);
ok
(
SUCCEEDED
(
hr
),
"IShellFolder::QueryInterface(IPersist
Folder3
) failed! hr = %08lx
\n
"
,
hr
);
IShellFolder_Release
(
pWineTestFolder
);
if
(
FAILED
(
hr
))
goto
cleanup
;
/* The resulting folder object has the FolderShortcut CLSID, instead of it's own. */
hr
=
IPersist
_GetClassID
(
pWineTestPersist
,
&
clsid
);
hr
=
IPersist
Folder3_GetClassID
(
pWineTestPersistFolder
,
&
clsid
);
ok
(
SUCCEEDED
(
hr
),
"IPersist::GetClassID failed! hr = %08lx
\n
"
,
hr
);
ok
(
IsEqualCLSID
(
&
CLSID_FolderShortcut
,
&
clsid
),
"GetClassId returned wrong CLSID!
\n
"
);
IPersist_Release
(
pWineTestPersist
);
pidlCurFolder
=
(
LPITEMIDLIST
)
0xdeadbeef
;
hr
=
IPersistFolder3_GetCurFolder
(
pWineTestPersistFolder
,
&
pidlCurFolder
);
ok
(
SUCCEEDED
(
hr
),
"IPersistFolder3::GetCurFolder failed! hr = %08lx
\n
"
,
hr
);
ok
(
pidlCurFolder
->
mkid
.
cb
==
20
&&
((
LPSHITEMID
)((
BYTE
*
)
pidlCurFolder
+
20
))
->
cb
==
0
&&
IsEqualCLSID
(
&
CLSID_WineTest
,
(
REFCLSID
)((
LPBYTE
)
pidlCurFolder
+
4
)),
"GetCurFolder returned unexpected pidl!
\n
"
);
IPersistFolder3_Release
(
pWineTestPersistFolder
);
cleanup:
unregister_keys
(
HKEY_CLASSES_ROOT
,
HKEY_CLASSES_ROOT_keys
,
1
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment