Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
32d52401
Commit
32d52401
authored
Nov 03, 2005
by
Mike McCormack
Committed by
Alexandre Julliard
Nov 03, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Invoke shortcuts through IContextMenu, rather than trying to access
them directly.
parent
a1b1f997
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
264 additions
and
140 deletions
+264
-140
shlexec.c
dlls/shell32/shlexec.c
+262
-138
shlexec.c
dlls/shell32/tests/shlexec.c
+2
-2
No files found.
dlls/shell32/shlexec.c
View file @
32d52401
...
...
@@ -267,70 +267,6 @@ HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, U
}
/*************************************************************************
* SHELL_ResolveShortCutW [Internal]
* read shortcut file at 'wcmd'
*/
static
HRESULT
SHELL_ResolveShortCutW
(
LPWSTR
wcmd
,
LPWSTR
wargs
,
LPWSTR
wdir
,
HWND
hwnd
,
LPCWSTR
lpVerb
,
int
*
pshowcmd
,
LPITEMIDLIST
*
ppidl
)
{
IShellFolder
*
psf
;
HRESULT
hr
=
SHGetDesktopFolder
(
&
psf
);
*
ppidl
=
NULL
;
if
(
SUCCEEDED
(
hr
))
{
LPITEMIDLIST
pidl
;
ULONG
l
;
hr
=
IShellFolder_ParseDisplayName
(
psf
,
0
,
0
,
wcmd
,
&
l
,
&
pidl
,
0
);
if
(
SUCCEEDED
(
hr
))
{
IShellLinkW
*
psl
;
hr
=
IShellFolder_GetUIObjectOf
(
psf
,
NULL
,
1
,
(
LPCITEMIDLIST
*
)
&
pidl
,
&
IID_IShellLinkW
,
NULL
,
(
LPVOID
*
)
&
psl
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IShellLinkW_Resolve
(
psl
,
hwnd
,
0
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IShellLinkW_GetPath
(
psl
,
wcmd
,
MAX_PATH
,
NULL
,
SLGP_UNCPRIORITY
);
if
(
SUCCEEDED
(
hr
))
{
if
(
!*
wcmd
)
{
/* We could not translate the PIDL in the shell link into a valid file system path - so return the PIDL instead. */
hr
=
IShellLinkW_GetIDList
(
psl
,
ppidl
);
if
(
SUCCEEDED
(
hr
)
&&
*
ppidl
)
{
/* We got a PIDL instead of a file system path - try to translate it. */
if
(
SHGetPathFromIDListW
(
*
ppidl
,
wcmd
))
{
SHFree
(
*
ppidl
);
*
ppidl
=
NULL
;
}
}
}
if
(
SUCCEEDED
(
hr
))
{
/* get command line arguments, working directory and display mode if available */
IShellLinkW_GetWorkingDirectory
(
psl
,
wdir
,
MAX_PATH
);
IShellLinkW_GetArguments
(
psl
,
wargs
,
MAX_PATH
);
IShellLinkW_GetShowCmd
(
psl
,
pshowcmd
);
}
}
}
IShellLinkW_Release
(
psl
);
}
SHFree
(
pidl
);
}
IShellFolder_Release
(
psf
);
}
return
hr
;
}
/*************************************************************************
* SHELL_ExecuteW [Internal]
*
*/
...
...
@@ -983,6 +919,262 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpR
return
(
HINSTANCE
)
retval
;
}
/* FIXME: is this already implemented somewhere else? */
static
HKEY
ShellExecute_GetClassKey
(
LPSHELLEXECUTEINFOW
sei
)
{
LPCWSTR
ext
=
NULL
,
lpClass
=
NULL
;
LPWSTR
cls
=
NULL
;
DWORD
type
=
0
,
sz
=
0
;
HKEY
hkey
=
0
;
LONG
r
;
if
(
sei
->
fMask
&
SEE_MASK_CLASSALL
)
return
sei
->
hkeyClass
;
if
(
sei
->
fMask
&
SEE_MASK_CLASSNAME
)
lpClass
=
sei
->
lpClass
;
else
{
ext
=
PathFindExtensionW
(
sei
->
lpFile
);
TRACE
(
"ext = %s
\n
"
,
debugstr_w
(
ext
)
);
if
(
!
ext
)
return
hkey
;
r
=
RegOpenKeyW
(
HKEY_CLASSES_ROOT
,
ext
,
&
hkey
);
if
(
r
!=
ERROR_SUCCESS
)
return
hkey
;
r
=
RegQueryValueExW
(
hkey
,
NULL
,
0
,
&
type
,
NULL
,
&
sz
);
if
(
r
==
ERROR_SUCCESS
&&
type
==
REG_SZ
)
{
sz
+=
sizeof
(
WCHAR
);
cls
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sz
);
cls
[
0
]
=
0
;
RegQueryValueExW
(
hkey
,
NULL
,
0
,
&
type
,
(
LPBYTE
)
cls
,
&
sz
);
}
RegCloseKey
(
hkey
);
lpClass
=
cls
;
}
TRACE
(
"class = %s
\n
"
,
debugstr_w
(
lpClass
)
);
hkey
=
0
;
if
(
lpClass
)
RegOpenKeyW
(
HKEY_CLASSES_ROOT
,
lpClass
,
&
hkey
);
HeapFree
(
GetProcessHeap
(),
0
,
cls
);
return
hkey
;
}
static
IDataObject
*
shellex_get_dataobj
(
LPSHELLEXECUTEINFOW
sei
)
{
LPCITEMIDLIST
pidllast
=
NULL
;
IDataObject
*
dataobj
=
NULL
;
IShellFolder
*
shf
=
NULL
;
LPITEMIDLIST
pidl
=
NULL
;
HRESULT
r
;
if
(
sei
->
fMask
&
SEE_MASK_CLASSALL
)
pidl
=
sei
->
lpIDList
;
else
{
WCHAR
fullpath
[
MAX_PATH
];
fullpath
[
0
]
=
0
;
r
=
GetFullPathNameW
(
sei
->
lpFile
,
MAX_PATH
,
fullpath
,
NULL
);
if
(
!
r
)
goto
end
;
pidl
=
ILCreateFromPathW
(
fullpath
);
}
r
=
SHBindToParent
(
pidl
,
&
IID_IShellFolder
,
(
LPVOID
*
)
&
shf
,
&
pidllast
);
if
(
FAILED
(
r
)
)
goto
end
;
IShellFolder_GetUIObjectOf
(
shf
,
NULL
,
1
,
&
pidllast
,
&
IID_IDataObject
,
NULL
,
(
LPVOID
*
)
&
dataobj
);
end:
if
(
pidl
!=
sei
->
lpIDList
)
ILFree
(
pidl
);
if
(
shf
)
IShellFolder_Release
(
shf
);
return
dataobj
;
}
static
HRESULT
shellex_run_context_menu_default
(
IShellExtInit
*
obj
,
LPSHELLEXECUTEINFOW
sei
)
{
IContextMenu
*
cm
=
NULL
;
CMINVOKECOMMANDINFOEX
ici
;
MENUITEMINFOW
info
;
WCHAR
string
[
0x80
];
INT
i
,
n
,
def
=
-
1
;
HMENU
hmenu
=
0
;
HRESULT
r
;
TRACE
(
"%p %p
\n
"
,
obj
,
sei
);
r
=
IShellExtInit_QueryInterface
(
obj
,
&
IID_IContextMenu
,
(
LPVOID
*
)
&
cm
);
if
(
FAILED
(
r
)
)
return
r
;
hmenu
=
CreateMenu
();
if
(
!
hmenu
)
goto
end
;
/* the number of the last menu added is returned in r */
r
=
IContextMenu_QueryContextMenu
(
cm
,
hmenu
,
0
,
0x20
,
0x7fff
,
CMF_DEFAULTONLY
);
if
(
FAILED
(
r
)
)
goto
end
;
n
=
GetMenuItemCount
(
hmenu
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
memset
(
&
info
,
0
,
sizeof
info
);
info
.
cbSize
=
sizeof
info
;
info
.
fMask
=
MIIM_FTYPE
|
MIIM_STRING
|
MIIM_STATE
|
MIIM_DATA
|
MIIM_ID
;
info
.
dwTypeData
=
string
;
info
.
cch
=
sizeof
string
;
string
[
0
]
=
0
;
GetMenuItemInfoW
(
hmenu
,
i
,
TRUE
,
&
info
);
TRACE
(
"menu %d %s %08x %08lx %08x %08x
\n
"
,
i
,
debugstr_w
(
string
),
info
.
fState
,
info
.
dwItemData
,
info
.
fType
,
info
.
wID
);
if
(
(
!
sei
->
lpVerb
&&
(
info
.
fState
&
MFS_DEFAULT
)
)
||
(
sei
->
lpVerb
&&
!
lstrcmpiW
(
sei
->
lpVerb
,
string
)
)
)
{
def
=
i
;
break
;
}
}
r
=
E_FAIL
;
if
(
def
==
-
1
)
goto
end
;
memset
(
&
ici
,
0
,
sizeof
ici
);
ici
.
cbSize
=
sizeof
ici
;
ici
.
fMask
=
CMIC_MASK_UNICODE
;
ici
.
nShow
=
sei
->
nShow
;
ici
.
lpVerb
=
MAKEINTRESOURCEA
(
def
);
ici
.
hwnd
=
sei
->
hwnd
;
ici
.
lpParametersW
=
sei
->
lpParameters
;
r
=
IContextMenu_InvokeCommand
(
cm
,
(
LPCMINVOKECOMMANDINFO
)
&
ici
);
TRACE
(
"invoke command returned %08lx
\n
"
,
r
);
end:
if
(
hmenu
)
DestroyMenu
(
hmenu
);
if
(
cm
)
IContextMenu_Release
(
cm
);
return
r
;
}
static
HRESULT
shellex_load_object_and_run
(
HKEY
hkey
,
LPCGUID
guid
,
LPSHELLEXECUTEINFOW
sei
)
{
IDataObject
*
dataobj
=
NULL
;
IObjectWithSite
*
ows
=
NULL
;
IShellExtInit
*
obj
=
NULL
;
HRESULT
r
;
TRACE
(
"%p %s %p
\n
"
,
hkey
,
debugstr_guid
(
guid
),
sei
);
r
=
CoInitialize
(
NULL
);
if
(
FAILED
(
r
)
)
goto
end
;
r
=
CoCreateInstance
(
guid
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IShellExtInit
,
(
LPVOID
*
)
&
obj
);
if
(
FAILED
(
r
)
)
{
ERR
(
"failed %08lx
\n
"
,
r
);
goto
end
;
}
dataobj
=
shellex_get_dataobj
(
sei
);
if
(
!
dataobj
)
{
ERR
(
"failed to get data object
\n
"
);
goto
end
;
}
r
=
IShellExtInit_Initialize
(
obj
,
NULL
,
dataobj
,
hkey
);
if
(
FAILED
(
r
)
)
goto
end
;
r
=
IShellExtInit_QueryInterface
(
obj
,
&
IID_IObjectWithSite
,
(
LPVOID
*
)
&
ows
);
if
(
FAILED
(
r
)
)
goto
end
;
IObjectWithSite_SetSite
(
ows
,
NULL
);
r
=
shellex_run_context_menu_default
(
obj
,
sei
);
end:
if
(
ows
)
IObjectWithSite_Release
(
ows
);
if
(
dataobj
)
IDataObject_Release
(
dataobj
);
if
(
obj
)
IShellExtInit_Release
(
obj
);
CoUninitialize
();
return
r
;
}
/*************************************************************************
* ShellExecute_FromContextMenu [Internal]
*/
static
LONG
ShellExecute_FromContextMenu
(
LPSHELLEXECUTEINFOW
sei
)
{
static
const
WCHAR
szcm
[]
=
{
's'
,
'h'
,
'e'
,
'l'
,
'l'
,
'e'
,
'x'
,
'\\'
,
'C'
,
'o'
,
'n'
,
't'
,
'e'
,
'x'
,
't'
,
'M'
,
'e'
,
'n'
,
'u'
,
'H'
,
'a'
,
'n'
,
'd'
,
'l'
,
'e'
,
'r'
,
's'
,
0
};
HKEY
hkey
,
hkeycm
=
0
;
WCHAR
szguid
[
39
];
HRESULT
hr
;
GUID
guid
;
DWORD
i
;
LONG
r
;
TRACE
(
"%s
\n
"
,
debugstr_w
(
sei
->
lpFile
)
);
hkey
=
ShellExecute_GetClassKey
(
sei
);
if
(
!
hkey
)
return
ERROR_FUNCTION_FAILED
;
r
=
RegOpenKeyW
(
hkey
,
szcm
,
&
hkeycm
);
if
(
r
==
ERROR_SUCCESS
)
{
i
=
0
;
while
(
1
)
{
r
=
RegEnumKeyW
(
hkeycm
,
i
++
,
szguid
,
39
);
if
(
r
!=
ERROR_SUCCESS
)
break
;
r
=
ERROR_FUNCTION_FAILED
;
hr
=
CLSIDFromString
(
szguid
,
&
guid
);
if
(
FAILED
(
hr
)
)
break
;
r
=
ERROR_SUCCESS
;
/* stop at the first one that succeeds in running */
hr
=
shellex_load_object_and_run
(
hkey
,
&
guid
,
sei
);
if
(
SUCCEEDED
(
hr
)
)
break
;
}
RegCloseKey
(
hkeycm
);
}
if
(
hkey
!=
sei
->
hkeyClass
)
RegCloseKey
(
hkey
);
return
r
;
}
/*************************************************************************
* SHELL_execute [Internal]
*/
...
...
@@ -993,7 +1185,6 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc, BOOL uni
static
const
WCHAR
wWww
[]
=
{
'w'
,
'w'
,
'w'
,
0
};
static
const
WCHAR
wFile
[]
=
{
'f'
,
'i'
,
'l'
,
'e'
,
0
};
static
const
WCHAR
wHttp
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
0
};
static
const
WCHAR
wExtLnk
[]
=
{
'.'
,
'l'
,
'n'
,
'k'
,
0
};
static
const
WCHAR
wExplorer
[]
=
{
'e'
,
'x'
,
'p'
,
'l'
,
'o'
,
'r'
,
'e'
,
'r'
,
'.'
,
'e'
,
'x'
,
'e'
,
0
};
static
const
DWORD
unsupportedFlags
=
SEE_MASK_INVOKEIDLIST
|
SEE_MASK_ICON
|
SEE_MASK_HOTKEY
|
...
...
@@ -1010,7 +1201,6 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc, BOOL uni
UINT_PTR
retval
=
31
;
WCHAR
wcmd
[
1024
];
WCHAR
buffer
[
MAX_PATH
];
const
WCHAR
*
ext
;
BOOL
done
;
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
...
...
@@ -1083,6 +1273,12 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc, BOOL uni
TRACE
(
"-- idlist=%p (%s)
\n
"
,
sei_tmp
.
lpIDList
,
debugstr_w
(
wszApplicationName
));
}
if
(
ERROR_SUCCESS
==
ShellExecute_FromContextMenu
(
&
sei_tmp
)
)
{
sei
->
hInstApp
=
(
HINSTANCE
)
33
;
return
TRUE
;
}
if
(
sei_tmp
.
fMask
&
SEE_MASK_CLASSALL
)
{
/* launch a document by fileclass like 'WordPad.Document.1' */
...
...
@@ -1111,78 +1307,6 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc, BOOL uni
return
FALSE
;
}
/* resolve shell shortcuts */
ext
=
PathFindExtensionW
(
sei_tmp
.
lpFile
);
if
(
ext
&&
!
strncmpiW
(
ext
,
wExtLnk
,
sizeof
(
wExtLnk
)
/
sizeof
(
WCHAR
)
-
1
)
&&
(
ext
[
sizeof
(
wExtLnk
)
/
sizeof
(
WCHAR
)
-
1
]
==
'\0'
||
(
sei_tmp
.
lpFile
[
0
]
==
'"'
&&
ext
[
sizeof
(
wExtLnk
)
/
sizeof
(
WCHAR
)
-
1
]
==
'"'
)))
/* or check for: shell_attribs & SFGAO_LINK */
{
HRESULT
hr
;
BOOL
Quoted
;
if
(
wszApplicationName
[
0
]
==
'"'
)
{
if
(
wszApplicationName
[
strlenW
(
wszApplicationName
)
-
1
]
==
'"'
)
{
wszApplicationName
[
strlenW
(
wszApplicationName
)
-
1
]
=
'\0'
;
Quoted
=
TRUE
;
}
else
{
Quoted
=
FALSE
;
}
}
else
{
Quoted
=
FALSE
;
}
/* expand paths before reading shell link */
if
(
ExpandEnvironmentStringsW
(
Quoted
?
sei_tmp
.
lpFile
+
1
:
sei_tmp
.
lpFile
,
buffer
,
MAX_PATH
))
lstrcpyW
(
Quoted
?
wszApplicationName
+
1
:
wszApplicationName
/*sei_tmp.lpFile*/
,
buffer
);
if
(
*
sei_tmp
.
lpParameters
)
if
(
ExpandEnvironmentStringsW
(
sei_tmp
.
lpParameters
,
buffer
,
MAX_PATH
))
lstrcpyW
(
wszParameters
/*sei_tmp.lpParameters*/
,
buffer
);
hr
=
SHELL_ResolveShortCutW
((
LPWSTR
)(
Quoted
?
sei_tmp
.
lpFile
+
1
:
sei_tmp
.
lpFile
),
(
LPWSTR
)
sei_tmp
.
lpParameters
,
(
LPWSTR
)
sei_tmp
.
lpDirectory
,
sei_tmp
.
hwnd
,
sei_tmp
.
lpVerb
?
sei_tmp
.
lpVerb
:
wszEmpty
,
&
sei_tmp
.
nShow
,
(
LPITEMIDLIST
*
)
&
sei_tmp
.
lpIDList
);
if
(
Quoted
)
{
wszApplicationName
[
strlenW
(
wszApplicationName
)
+
1
]
=
'\0'
;
wszApplicationName
[
strlenW
(
wszApplicationName
)]
=
'"'
;
}
if
(
sei
->
lpIDList
)
sei
->
fMask
|=
SEE_MASK_IDLIST
;
if
(
SUCCEEDED
(
hr
))
{
/* repeat IDList processing if needed */
if
(
sei_tmp
.
fMask
&
SEE_MASK_IDLIST
)
{
IShellExecuteHookW
*
pSEH
;
HRESULT
hr
=
SHBindToParent
(
sei_tmp
.
lpIDList
,
&
IID_IShellExecuteHookW
,
(
LPVOID
*
)
&
pSEH
,
NULL
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IShellExecuteHookW_Execute
(
pSEH
,
&
sei_tmp
);
IShellExecuteHookW_Release
(
pSEH
);
if
(
hr
==
S_OK
)
return
TRUE
;
}
TRACE
(
"-- idlist=%p (%s)
\n
"
,
debugstr_w
(
sei_tmp
.
lpIDList
),
debugstr_w
(
sei_tmp
.
lpFile
));
}
}
}
/* Has the IDList not yet been translated? */
if
(
sei_tmp
.
fMask
&
SEE_MASK_IDLIST
)
{
...
...
dlls/shell32/tests/shlexec.c
View file @
32d52401
...
...
@@ -761,7 +761,7 @@ static void test_lnks(void)
{
okChildInt
(
"argcA"
,
5
);
}
else
todo_wine
else
{
okChildInt
(
"argcA"
,
5
);
}
...
...
@@ -778,7 +778,7 @@ static void test_lnks(void)
{
okChildPath
(
"argvA4"
,
params
);
}
else
todo_wine
else
{
okChildPath
(
"argvA4"
,
params
);
}
...
...
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