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
4d413296
Commit
4d413296
authored
Aug 25, 2009
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shell32: Move the IQueryAssociations implementation from shlwapi to shell32.
parent
f9c791f9
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
725 additions
and
705 deletions
+725
-705
Makefile.in
dlls/shell32/Makefile.in
+2
-1
assoc.c
dlls/shell32/assoc.c
+712
-0
shell32_main.h
dlls/shell32/shell32_main.h
+1
-0
shellole.c
dlls/shell32/shellole.c
+1
-0
assoc.c
dlls/shlwapi/assoc.c
+9
-704
No files found.
dlls/shell32/Makefile.in
View file @
4d413296
...
...
@@ -6,10 +6,11 @@ VPATH = @srcdir@
MODULE
=
shell32.dll
IMPORTLIB
=
shell32
IMPORTS
=
uuid shlwapi comctl32 user32 gdi32 advapi32 kernel32 ntdll
DELAYIMPORTS
=
ole32 oleaut32 shdocvw
DELAYIMPORTS
=
ole32 oleaut32 shdocvw
version
C_SRCS
=
\
appbar.c
\
assoc.c
\
autocomplete.c
\
brsfolder.c
\
changenotify.c
\
...
...
dlls/shell32/assoc.c
0 → 100644
View file @
4d413296
/*
* IQueryAssociations object and helper functions
*
* Copyright 2002 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 <stdarg.h>
#include <assert.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winreg.h"
#include "objbase.h"
#include "shlguid.h"
#include "shlwapi.h"
#include "shell32_main.h"
#include "ver.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
shell
);
/**************************************************************************
* IQueryAssociations {SHELL32}
*
* DESCRIPTION
* This object provides a layer of abstraction over the system registry in
* order to simplify the process of parsing associations between files.
* Associations in this context means the registry entries that link (for
* example) the extension of a file with its description, list of
* applications to open the file with, and actions that can be performed on it
* (the shell displays such information in the context menu of explorer
* when you right-click on a file).
*
* HELPERS
* You can use this object transparently by calling the helper functions
* AssocQueryKeyA(), AssocQueryStringA() and AssocQueryStringByKeyA(). These
* create an IQueryAssociations object, perform the requested actions
* and then dispose of the object. Alternatively, you can create an instance
* of the object using AssocCreate() and call the following methods on it:
*
* METHODS
*/
typedef
struct
{
const
IQueryAssociationsVtbl
*
lpVtbl
;
LONG
ref
;
HKEY
hkeySource
;
HKEY
hkeyProgID
;
}
IQueryAssociationsImpl
;
/**************************************************************************
* IQueryAssociations_QueryInterface {SHLWAPI}
*
* See IUnknown_QueryInterface.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnQueryInterface
(
IQueryAssociations
*
iface
,
REFIID
riid
,
LPVOID
*
ppvObj
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
TRACE
(
"(%p,%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppvObj
);
*
ppvObj
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IQueryAssociations
))
{
*
ppvObj
=
This
;
IQueryAssociations_AddRef
((
IQueryAssociations
*
)
*
ppvObj
);
TRACE
(
"Returning IQueryAssociations (%p)
\n
"
,
*
ppvObj
);
return
S_OK
;
}
TRACE
(
"Returning E_NOINTERFACE
\n
"
);
return
E_NOINTERFACE
;
}
/**************************************************************************
* IQueryAssociations_AddRef {SHLWAPI}
*
* See IUnknown_AddRef.
*/
static
ULONG
WINAPI
IQueryAssociations_fnAddRef
(
IQueryAssociations
*
iface
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
ULONG
refCount
=
InterlockedIncrement
(
&
This
->
ref
);
TRACE
(
"(%p)->(ref before=%u)
\n
"
,
This
,
refCount
-
1
);
return
refCount
;
}
/**************************************************************************
* IQueryAssociations_Release {SHLWAPI}
*
* See IUnknown_Release.
*/
static
ULONG
WINAPI
IQueryAssociations_fnRelease
(
IQueryAssociations
*
iface
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
ULONG
refCount
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p)->(ref before=%u)
\n
"
,
This
,
refCount
+
1
);
if
(
!
refCount
)
{
TRACE
(
"Destroying IQueryAssociations (%p)
\n
"
,
This
);
RegCloseKey
(
This
->
hkeySource
);
RegCloseKey
(
This
->
hkeyProgID
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
return
refCount
;
}
/**************************************************************************
* IQueryAssociations_Init {SHLWAPI}
*
* Initialise an IQueryAssociations object.
*
* PARAMS
* iface [I] IQueryAssociations interface to initialise
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* pszAssoc [I] String for the root key name, or NULL if hkeyProgid is given
* hkeyProgid [I] Handle for the root key, or NULL if pszAssoc is given
* hWnd [I] Reserved, must be NULL.
*
* RETURNS
* Success: S_OK. iface is initialised with the parameters given.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnInit
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
LPCWSTR
pszAssoc
,
HKEY
hkeyProgid
,
HWND
hWnd
)
{
static
const
WCHAR
szProgID
[]
=
{
'P'
,
'r'
,
'o'
,
'g'
,
'I'
,
'D'
,
0
};
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
LONG
ret
;
TRACE
(
"(%p)->(%d,%s,%p,%p)
\n
"
,
iface
,
cfFlags
,
debugstr_w
(
pszAssoc
),
hkeyProgid
,
hWnd
);
if
(
hWnd
!=
NULL
)
FIXME
(
"hwnd != NULL not supported
\n
"
);
if
(
cfFlags
!=
0
)
FIXME
(
"unsupported flags: %x
\n
"
,
cfFlags
);
if
(
pszAssoc
!=
NULL
)
{
ret
=
RegOpenKeyExW
(
HKEY_CLASSES_ROOT
,
pszAssoc
,
0
,
KEY_READ
,
&
This
->
hkeySource
);
if
(
ret
!=
ERROR_SUCCESS
)
return
E_FAIL
;
/* if this is not a prog id */
if
((
*
pszAssoc
==
'.'
)
||
(
*
pszAssoc
==
'{'
))
{
RegOpenKeyExW
(
This
->
hkeySource
,
szProgID
,
0
,
KEY_READ
,
&
This
->
hkeyProgID
);
}
else
This
->
hkeyProgID
=
This
->
hkeySource
;
return
S_OK
;
}
else
if
(
hkeyProgid
!=
NULL
)
{
This
->
hkeyProgID
=
hkeyProgid
;
return
S_OK
;
}
else
return
E_INVALIDARG
;
}
static
HRESULT
ASSOC_GetValue
(
HKEY
hkey
,
WCHAR
**
pszText
)
{
DWORD
len
;
LONG
ret
;
assert
(
pszText
);
ret
=
RegQueryValueExW
(
hkey
,
NULL
,
0
,
NULL
,
NULL
,
&
len
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
if
(
!
len
)
return
E_FAIL
;
*
pszText
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
if
(
!*
pszText
)
return
E_OUTOFMEMORY
;
ret
=
RegQueryValueExW
(
hkey
,
NULL
,
0
,
NULL
,
(
LPBYTE
)
*
pszText
,
&
len
);
if
(
ret
!=
ERROR_SUCCESS
)
{
HeapFree
(
GetProcessHeap
(),
0
,
*
pszText
);
return
HRESULT_FROM_WIN32
(
ret
);
}
return
S_OK
;
}
static
HRESULT
ASSOC_GetCommand
(
IQueryAssociationsImpl
*
This
,
LPCWSTR
pszExtra
,
WCHAR
**
ppszCommand
)
{
HKEY
hkeyCommand
;
HKEY
hkeyFile
;
HKEY
hkeyShell
;
HKEY
hkeyVerb
;
HRESULT
hr
;
LONG
ret
;
WCHAR
*
pszExtraFromReg
=
NULL
;
WCHAR
*
pszFileType
;
static
const
WCHAR
commandW
[]
=
{
'c'
,
'o'
,
'm'
,
'm'
,
'a'
,
'n'
,
'd'
,
0
};
static
const
WCHAR
shellW
[]
=
{
's'
,
'h'
,
'e'
,
'l'
,
'l'
,
0
};
hr
=
ASSOC_GetValue
(
This
->
hkeySource
,
&
pszFileType
);
if
(
FAILED
(
hr
))
return
hr
;
ret
=
RegOpenKeyExW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
0
,
KEY_READ
,
&
hkeyFile
);
HeapFree
(
GetProcessHeap
(),
0
,
pszFileType
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
ret
=
RegOpenKeyExW
(
hkeyFile
,
shellW
,
0
,
KEY_READ
,
&
hkeyShell
);
RegCloseKey
(
hkeyFile
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
if
(
!
pszExtra
)
{
hr
=
ASSOC_GetValue
(
hkeyShell
,
&
pszExtraFromReg
);
/* if no default action */
if
(
hr
==
E_FAIL
||
hr
==
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
))
{
DWORD
rlen
;
ret
=
RegQueryInfoKeyW
(
hkeyShell
,
0
,
0
,
0
,
0
,
&
rlen
,
0
,
0
,
0
,
0
,
0
,
0
);
if
(
ret
!=
ERROR_SUCCESS
)
{
RegCloseKey
(
hkeyShell
);
return
HRESULT_FROM_WIN32
(
ret
);
}
rlen
++
;
pszExtraFromReg
=
HeapAlloc
(
GetProcessHeap
(),
0
,
rlen
*
sizeof
(
WCHAR
));
if
(
!
pszExtraFromReg
)
{
RegCloseKey
(
hkeyShell
);
return
E_OUTOFMEMORY
;
}
ret
=
RegEnumKeyExW
(
hkeyShell
,
0
,
pszExtraFromReg
,
&
rlen
,
0
,
NULL
,
NULL
,
NULL
);
if
(
ret
!=
ERROR_SUCCESS
)
{
RegCloseKey
(
hkeyShell
);
return
HRESULT_FROM_WIN32
(
ret
);
}
}
else
if
(
FAILED
(
hr
))
{
RegCloseKey
(
hkeyShell
);
return
hr
;
}
}
ret
=
RegOpenKeyExW
(
hkeyShell
,
pszExtra
?
pszExtra
:
pszExtraFromReg
,
0
,
KEY_READ
,
&
hkeyVerb
);
HeapFree
(
GetProcessHeap
(),
0
,
pszExtraFromReg
);
RegCloseKey
(
hkeyShell
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
ret
=
RegOpenKeyExW
(
hkeyVerb
,
commandW
,
0
,
KEY_READ
,
&
hkeyCommand
);
RegCloseKey
(
hkeyVerb
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
hr
=
ASSOC_GetValue
(
hkeyCommand
,
ppszCommand
);
RegCloseKey
(
hkeyCommand
);
return
hr
;
}
static
HRESULT
ASSOC_GetExecutable
(
IQueryAssociationsImpl
*
This
,
LPCWSTR
pszExtra
,
LPWSTR
path
,
DWORD
pathlen
,
DWORD
*
len
)
{
WCHAR
*
pszCommand
;
WCHAR
*
pszStart
;
WCHAR
*
pszEnd
;
HRESULT
hr
;
assert
(
len
);
hr
=
ASSOC_GetCommand
(
This
,
pszExtra
,
&
pszCommand
);
if
(
FAILED
(
hr
))
return
hr
;
/* cleanup pszCommand */
if
(
pszCommand
[
0
]
==
'"'
)
{
pszStart
=
pszCommand
+
1
;
pszEnd
=
strchrW
(
pszStart
,
'"'
);
}
else
{
pszStart
=
pszCommand
;
pszEnd
=
strchrW
(
pszStart
,
' '
);
}
if
(
pszEnd
)
*
pszEnd
=
0
;
*
len
=
SearchPathW
(
NULL
,
pszStart
,
NULL
,
pathlen
,
path
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
pszCommand
);
if
(
!*
len
)
return
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
);
return
S_OK
;
}
static
HRESULT
ASSOC_ReturnData
(
LPWSTR
out
,
DWORD
*
outlen
,
LPCWSTR
data
,
DWORD
datalen
)
{
assert
(
outlen
);
if
(
out
)
{
if
(
*
outlen
<
datalen
)
{
*
outlen
=
datalen
;
return
E_POINTER
;
}
*
outlen
=
datalen
;
lstrcpynW
(
out
,
data
,
datalen
);
return
S_OK
;
}
else
{
*
outlen
=
datalen
;
return
S_FALSE
;
}
}
/**************************************************************************
* IQueryAssociations_GetString {SHLWAPI}
*
* Get a file association string from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* str [I] Type of string to get (ASSOCSTR enum from "shlwapi.h")
* pszExtra [I] Extra information about the string location
* pszOut [O] Destination for the association string
* pcchOut [I/O] Length of pszOut
*
* RETURNS
* Success: S_OK. pszOut contains the string, pcchOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetString
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCSTR
str
,
LPCWSTR
pszExtra
,
LPWSTR
pszOut
,
DWORD
*
pcchOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
const
ASSOCF
cfUnimplemented
=
~
(
0
);
DWORD
len
=
0
;
HRESULT
hr
;
WCHAR
path
[
MAX_PATH
];
TRACE
(
"(%p,0x%8x,0x%8x,%s,%p,%p)
\n
"
,
This
,
cfFlags
,
str
,
debugstr_w
(
pszExtra
),
pszOut
,
pcchOut
);
if
(
cfFlags
&
cfUnimplemented
)
FIXME
(
"%08x: unimplemented flags!
\n
"
,
cfFlags
&
cfUnimplemented
);
if
(
!
pcchOut
)
return
E_UNEXPECTED
;
switch
(
str
)
{
case
ASSOCSTR_COMMAND
:
{
WCHAR
*
command
;
hr
=
ASSOC_GetCommand
(
This
,
pszExtra
,
&
command
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
command
,
strlenW
(
command
)
+
1
);
HeapFree
(
GetProcessHeap
(),
0
,
command
);
}
return
hr
;
}
case
ASSOCSTR_EXECUTABLE
:
{
hr
=
ASSOC_GetExecutable
(
This
,
pszExtra
,
path
,
MAX_PATH
,
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
len
++
;
return
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
path
,
len
);
}
case
ASSOCSTR_FRIENDLYDOCNAME
:
{
WCHAR
*
pszFileType
;
DWORD
ret
;
DWORD
size
;
hr
=
ASSOC_GetValue
(
This
->
hkeySource
,
&
pszFileType
);
if
(
FAILED
(
hr
))
return
hr
;
size
=
0
;
ret
=
RegGetValueW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
NULL
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
{
WCHAR
*
docName
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
docName
)
{
ret
=
RegGetValueW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
docName
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
docName
,
strlenW
(
docName
)
+
1
);
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
docName
);
}
else
hr
=
E_OUTOFMEMORY
;
}
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
pszFileType
);
return
hr
;
}
case
ASSOCSTR_FRIENDLYAPPNAME
:
{
PVOID
verinfoW
=
NULL
;
DWORD
size
,
retval
=
0
;
UINT
flen
;
WCHAR
*
bufW
;
static
const
WCHAR
translationW
[]
=
{
'\\'
,
'V'
,
'a'
,
'r'
,
'F'
,
'i'
,
'l'
,
'e'
,
'I'
,
'n'
,
'f'
,
'o'
,
'\\'
,
'T'
,
'r'
,
'a'
,
'n'
,
's'
,
'l'
,
'a'
,
't'
,
'i'
,
'o'
,
'n'
,
0
};
static
const
WCHAR
fileDescFmtW
[]
=
{
'\\'
,
'S'
,
't'
,
'r'
,
'i'
,
'n'
,
'g'
,
'F'
,
'i'
,
'l'
,
'e'
,
'I'
,
'n'
,
'f'
,
'o'
,
'\\'
,
'%'
,
'0'
,
'4'
,
'x'
,
'%'
,
'0'
,
'4'
,
'x'
,
'\\'
,
'F'
,
'i'
,
'l'
,
'e'
,
'D'
,
'e'
,
's'
,
'c'
,
'r'
,
'i'
,
'p'
,
't'
,
'i'
,
'o'
,
'n'
,
0
};
WCHAR
fileDescW
[
41
];
hr
=
ASSOC_GetExecutable
(
This
,
pszExtra
,
path
,
MAX_PATH
,
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
retval
=
GetFileVersionInfoSizeW
(
path
,
&
size
);
if
(
!
retval
)
goto
get_friendly_name_fail
;
verinfoW
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
retval
);
if
(
!
verinfoW
)
return
E_OUTOFMEMORY
;
if
(
!
GetFileVersionInfoW
(
path
,
0
,
retval
,
verinfoW
))
goto
get_friendly_name_fail
;
if
(
VerQueryValueW
(
verinfoW
,
translationW
,
(
LPVOID
*
)
&
bufW
,
&
flen
))
{
UINT
i
;
DWORD
*
langCodeDesc
=
(
DWORD
*
)
bufW
;
for
(
i
=
0
;
i
<
flen
/
sizeof
(
DWORD
);
i
++
)
{
sprintfW
(
fileDescW
,
fileDescFmtW
,
LOWORD
(
langCodeDesc
[
i
]),
HIWORD
(
langCodeDesc
[
i
]));
if
(
VerQueryValueW
(
verinfoW
,
fileDescW
,
(
LPVOID
*
)
&
bufW
,
&
flen
))
{
/* Does strlenW(bufW) == 0 mean we use the filename? */
len
=
strlenW
(
bufW
)
+
1
;
TRACE
(
"found FileDescription: %s
\n
"
,
debugstr_w
(
bufW
));
return
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
bufW
,
len
);
}
}
}
get_friendly_name_fail:
PathRemoveExtensionW
(
path
);
PathStripPathW
(
path
);
TRACE
(
"using filename: %s
\n
"
,
debugstr_w
(
path
));
return
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
path
,
strlenW
(
path
)
+
1
);
}
case
ASSOCSTR_CONTENTTYPE
:
{
static
const
WCHAR
Content_TypeW
[]
=
{
'C'
,
'o'
,
'n'
,
't'
,
'e'
,
'n'
,
't'
,
' '
,
'T'
,
'y'
,
'p'
,
'e'
,
0
};
WCHAR
*
contentType
;
DWORD
ret
;
DWORD
size
;
size
=
0
;
ret
=
RegGetValueW
(
This
->
hkeySource
,
NULL
,
Content_TypeW
,
RRF_RT_REG_SZ
,
NULL
,
NULL
,
&
size
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
contentType
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
contentType
!=
NULL
)
{
ret
=
RegGetValueW
(
This
->
hkeySource
,
NULL
,
Content_TypeW
,
RRF_RT_REG_SZ
,
NULL
,
contentType
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
contentType
,
strlenW
(
contentType
)
+
1
);
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
contentType
);
}
else
hr
=
E_OUTOFMEMORY
;
return
hr
;
}
case
ASSOCSTR_DEFAULTICON
:
{
static
const
WCHAR
DefaultIconW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'I'
,
'c'
,
'o'
,
'n'
,
0
};
WCHAR
*
pszFileType
;
DWORD
ret
;
DWORD
size
;
HKEY
hkeyFile
;
hr
=
ASSOC_GetValue
(
This
->
hkeySource
,
&
pszFileType
);
if
(
FAILED
(
hr
))
return
hr
;
ret
=
RegOpenKeyExW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
0
,
KEY_READ
,
&
hkeyFile
);
if
(
ret
==
ERROR_SUCCESS
)
{
size
=
0
;
ret
=
RegGetValueW
(
hkeyFile
,
DefaultIconW
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
NULL
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
{
WCHAR
*
icon
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
icon
)
{
ret
=
RegGetValueW
(
hkeyFile
,
DefaultIconW
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
icon
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
icon
,
strlenW
(
icon
)
+
1
);
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
icon
);
}
else
hr
=
E_OUTOFMEMORY
;
}
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
RegCloseKey
(
hkeyFile
);
}
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
pszFileType
);
return
hr
;
}
default:
FIXME
(
"assocstr %d unimplemented!
\n
"
,
str
);
return
E_NOTIMPL
;
}
}
/**************************************************************************
* IQueryAssociations_GetKey {SHLWAPI}
*
* Get a file association key from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assockey [I] Type of key to get (ASSOCKEY enum from "shlwapi.h")
* pszExtra [I] Extra information about the key location
* phkeyOut [O] Destination for the association key
*
* RETURNS
* Success: S_OK. phkeyOut contains a handle to the key.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetKey
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCKEY
assockey
,
LPCWSTR
pszExtra
,
HKEY
*
phkeyOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
FIXME
(
"(%p,0x%8x,0x%8x,%s,%p)-stub!
\n
"
,
This
,
cfFlags
,
assockey
,
debugstr_w
(
pszExtra
),
phkeyOut
);
return
E_NOTIMPL
;
}
/**************************************************************************
* IQueryAssociations_GetData {SHLWAPI}
*
* Get the data for a file association key from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assocdata [I] Type of data to get (ASSOCDATA enum from "shlwapi.h")
* pszExtra [I] Extra information about the data location
* pvOut [O] Destination for the association key
* pcbOut [I/O] Size of pvOut
*
* RETURNS
* Success: S_OK. pszOut contains the data, pcbOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetData
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCDATA
assocdata
,
LPCWSTR
pszExtra
,
LPVOID
pvOut
,
DWORD
*
pcbOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
FIXME
(
"(%p,0x%8x,0x%8x,%s,%p,%p)-stub!
\n
"
,
This
,
cfFlags
,
assocdata
,
debugstr_w
(
pszExtra
),
pvOut
,
pcbOut
);
return
E_NOTIMPL
;
}
/**************************************************************************
* IQueryAssociations_GetEnum {SHLWAPI}
*
* Not yet implemented in native Win32.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assocenum [I] Type of enum to get (ASSOCENUM enum from "shlwapi.h")
* pszExtra [I] Extra information about the enum location
* riid [I] REFIID to look for
* ppvOut [O] Destination for the interface.
*
* RETURNS
* Success: S_OK.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* Presumably this function returns an enumerator object.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetEnum
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCENUM
assocenum
,
LPCWSTR
pszExtra
,
REFIID
riid
,
LPVOID
*
ppvOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
FIXME
(
"(%p,0x%8x,0x%8x,%s,%s,%p)-stub!
\n
"
,
This
,
cfFlags
,
assocenum
,
debugstr_w
(
pszExtra
),
debugstr_guid
(
riid
),
ppvOut
);
return
E_NOTIMPL
;
}
static
const
IQueryAssociationsVtbl
IQueryAssociations_vtbl
=
{
IQueryAssociations_fnQueryInterface
,
IQueryAssociations_fnAddRef
,
IQueryAssociations_fnRelease
,
IQueryAssociations_fnInit
,
IQueryAssociations_fnGetString
,
IQueryAssociations_fnGetKey
,
IQueryAssociations_fnGetData
,
IQueryAssociations_fnGetEnum
};
/**************************************************************************
* IQueryAssociations_Constructor [internal]
*
* Construct a new IQueryAssociations object.
*/
HRESULT
WINAPI
QueryAssociations_Constructor
(
IUnknown
*
pUnkOuter
,
REFIID
riid
,
LPVOID
*
ppOutput
)
{
IQueryAssociationsImpl
*
this
;
HRESULT
ret
;
if
(
pUnkOuter
)
return
CLASS_E_NOAGGREGATION
;
if
(
!
(
this
=
SHAlloc
(
sizeof
(
*
this
))))
return
E_OUTOFMEMORY
;
this
->
lpVtbl
=
&
IQueryAssociations_vtbl
;
this
->
ref
=
0
;
this
->
hkeySource
=
0
;
this
->
hkeyProgID
=
0
;
if
(
FAILED
(
ret
=
IUnknown_QueryInterface
((
IUnknown
*
)
this
,
riid
,
ppOutput
)))
SHFree
(
this
);
TRACE
(
"returning %p
\n
"
,
*
ppOutput
);
return
ret
;
}
dlls/shell32/shell32_main.h
View file @
4d413296
...
...
@@ -97,6 +97,7 @@ HRESULT WINAPI UnixDosFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVO
HRESULT
WINAPI
FolderShortcut_Constructor
(
IUnknown
*
pUnkOuter
,
REFIID
riid
,
LPVOID
*
ppv
);
HRESULT
WINAPI
MyDocuments_Constructor
(
IUnknown
*
pUnkOuter
,
REFIID
riid
,
LPVOID
*
ppv
);
HRESULT
WINAPI
RecycleBin_Constructor
(
IUnknown
*
pUnkOuter
,
REFIID
riif
,
LPVOID
*
ppv
);
HRESULT
WINAPI
QueryAssociations_Constructor
(
IUnknown
*
pUnkOuter
,
REFIID
riid
,
LPVOID
*
ppOutput
);
extern
HRESULT
CPanel_GetIconLocationW
(
LPCITEMIDLIST
,
LPWSTR
,
UINT
,
int
*
);
HRESULT
WINAPI
CPanel_ExtractIconA
(
LPITEMIDLIST
pidl
,
LPCSTR
pszFile
,
UINT
nIconIndex
,
HICON
*
phiconLarge
,
HICON
*
phiconSmall
,
UINT
nIconSize
);
HRESULT
WINAPI
CPanel_ExtractIconW
(
LPITEMIDLIST
pidl
,
LPCWSTR
pszFile
,
UINT
nIconIndex
,
HICON
*
phiconLarge
,
HICON
*
phiconSmall
,
UINT
nIconSize
);
...
...
dlls/shell32/shellole.c
View file @
4d413296
...
...
@@ -74,6 +74,7 @@ static const struct {
{
&
CLSID_FolderShortcut
,
FolderShortcut_Constructor
},
{
&
CLSID_MyDocuments
,
MyDocuments_Constructor
},
{
&
CLSID_RecycleBin
,
RecycleBin_Constructor
},
{
&
CLSID_QueryAssociations
,
QueryAssociations_Constructor
},
{
NULL
,
NULL
}
};
...
...
dlls/shlwapi/assoc.c
View file @
4d413296
/*
* IQueryAssociations
object and
helper functions
* IQueryAssociations helper functions
*
* Copyright 2002 Jon Griffiths
*
...
...
@@ -26,68 +26,17 @@
#include "winreg.h"
#include "objbase.h"
#include "shlguid.h"
#include "shlobj.h"
#include "shlwapi.h"
#include "ver.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
shell
);
/**************************************************************************
* IQueryAssociations {SHLWAPI}
*
* DESCRIPTION
* This object provides a layer of abstraction over the system registry in
* order to simplify the process of parsing associations between files.
* Associations in this context means the registry entries that link (for
* example) the extension of a file with its description, list of
* applications to open the file with, and actions that can be performed on it
* (the shell displays such information in the context menu of explorer
* when you right-click on a file).
*
* HELPERS
* You can use this object transparently by calling the helper functions
* AssocQueryKeyA(), AssocQueryStringA() and AssocQueryStringByKeyA(). These
* create an IQueryAssociations object, perform the requested actions
* and then dispose of the object. Alternatively, you can create an instance
* of the object using AssocCreate() and call the following methods on it:
*
* METHODS
*/
/* Default IQueryAssociations::Init() flags */
#define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
ASSOCF_INIT_DEFAULTTOFOLDER)
typedef
struct
{
const
IQueryAssociationsVtbl
*
lpVtbl
;
LONG
ref
;
HKEY
hkeySource
;
HKEY
hkeyProgID
;
}
IQueryAssociationsImpl
;
static
const
IQueryAssociationsVtbl
IQueryAssociations_vtbl
;
/**************************************************************************
* IQueryAssociations_Constructor [internal]
*
* Construct a new IQueryAssociations object.
*/
static
IQueryAssociations
*
IQueryAssociations_Constructor
(
void
)
{
IQueryAssociationsImpl
*
iface
;
iface
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
IQueryAssociationsImpl
));
iface
->
lpVtbl
=
&
IQueryAssociations_vtbl
;
iface
->
ref
=
1
;
iface
->
hkeySource
=
NULL
;
iface
->
hkeyProgID
=
NULL
;
TRACE
(
"Returning IQueryAssociations* %p
\n
"
,
iface
);
return
(
IQueryAssociations
*
)
iface
;
}
/*************************************************************************
* SHLWAPI_ParamAToW
*
...
...
@@ -139,9 +88,6 @@ static BOOL SHLWAPI_ParamAToW(LPCSTR lpszParam, LPWSTR lpszBuff, DWORD dwLen,
*/
HRESULT
WINAPI
AssocCreate
(
CLSID
clsid
,
REFIID
refiid
,
void
**
lpInterface
)
{
HRESULT
hRet
;
IQueryAssociations
*
lpAssoc
;
TRACE
(
"(%s,%s,%p)
\n
"
,
debugstr_guid
(
&
clsid
),
debugstr_guid
(
refiid
),
lpInterface
);
...
...
@@ -153,18 +99,7 @@ HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface)
if
(
!
IsEqualGUID
(
&
clsid
,
&
CLSID_QueryAssociations
))
return
CLASS_E_CLASSNOTAVAILABLE
;
lpAssoc
=
IQueryAssociations_Constructor
();
if
(
!
lpAssoc
)
return
E_OUTOFMEMORY
;
hRet
=
IQueryAssociations_QueryInterface
(
lpAssoc
,
refiid
,
lpInterface
);
IQueryAssociations_Release
(
lpAssoc
);
if
(
hRet
==
E_NOINTERFACE
)
return
CLASS_E_CLASSNOTAVAILABLE
;
return
hRet
;
return
SHCoCreateInstance
(
NULL
,
&
clsid
,
NULL
,
refiid
,
lpInterface
);
}
/*************************************************************************
...
...
@@ -181,10 +116,8 @@ HRESULT WINAPI AssocQueryKeyW(ASSOCF cfFlags, ASSOCKEY assockey, LPCWSTR pszAsso
TRACE
(
"(0x%8x,0x%8x,%s,%s,%p)
\n
"
,
cfFlags
,
assockey
,
debugstr_w
(
pszAssoc
),
debugstr_w
(
pszExtra
),
phkeyOut
);
lpAssoc
=
IQueryAssociations_Constructor
();
if
(
!
lpAssoc
)
return
E_OUTOFMEMORY
;
hRet
=
AssocCreate
(
CLSID_QueryAssociations
,
&
IID_IQueryAssociations
,
(
void
**
)
&
lpAssoc
);
if
(
FAILED
(
hRet
))
return
hRet
;
cfFlags
&=
SHLWAPI_DEF_ASSOCF
;
hRet
=
IQueryAssociations_Init
(
lpAssoc
,
cfFlags
,
pszAssoc
,
NULL
,
NULL
);
...
...
@@ -254,10 +187,8 @@ HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc,
if
(
!
pcchOut
)
return
E_UNEXPECTED
;
lpAssoc
=
IQueryAssociations_Constructor
();
if
(
!
lpAssoc
)
return
E_OUTOFMEMORY
;
hRet
=
AssocCreate
(
CLSID_QueryAssociations
,
&
IID_IQueryAssociations
,
(
void
**
)
&
lpAssoc
);
if
(
FAILED
(
hRet
))
return
hRet
;
hRet
=
IQueryAssociations_Init
(
lpAssoc
,
cfFlags
&
SHLWAPI_DEF_ASSOCF
,
pszAssoc
,
NULL
,
NULL
);
...
...
@@ -350,10 +281,8 @@ HRESULT WINAPI AssocQueryStringByKeyW(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc
TRACE
(
"(0x%8x,0x%8x,%p,%s,%p,%p)
\n
"
,
cfFlags
,
str
,
hkAssoc
,
debugstr_w
(
pszExtra
),
pszOut
,
pcchOut
);
lpAssoc
=
IQueryAssociations_Constructor
();
if
(
!
lpAssoc
)
return
E_OUTOFMEMORY
;
hRet
=
AssocCreate
(
CLSID_QueryAssociations
,
&
IID_IQueryAssociations
,
(
void
**
)
&
lpAssoc
);
if
(
FAILED
(
hRet
))
return
hRet
;
cfFlags
&=
SHLWAPI_DEF_ASSOCF
;
hRet
=
IQueryAssociations_Init
(
lpAssoc
,
cfFlags
,
0
,
hkAssoc
,
NULL
);
...
...
@@ -440,627 +369,3 @@ BOOL WINAPI AssocIsDangerous(LPCWSTR lpszAssoc)
FIXME
(
"%s
\n
"
,
debugstr_w
(
lpszAssoc
));
return
FALSE
;
}
/**************************************************************************
* IQueryAssociations_QueryInterface {SHLWAPI}
*
* See IUnknown_QueryInterface.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnQueryInterface
(
IQueryAssociations
*
iface
,
REFIID
riid
,
LPVOID
*
ppvObj
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
TRACE
(
"(%p,%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppvObj
);
*
ppvObj
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IQueryAssociations
))
{
*
ppvObj
=
This
;
IQueryAssociations_AddRef
((
IQueryAssociations
*
)
*
ppvObj
);
TRACE
(
"Returning IQueryAssociations (%p)
\n
"
,
*
ppvObj
);
return
S_OK
;
}
TRACE
(
"Returning E_NOINTERFACE
\n
"
);
return
E_NOINTERFACE
;
}
/**************************************************************************
* IQueryAssociations_AddRef {SHLWAPI}
*
* See IUnknown_AddRef.
*/
static
ULONG
WINAPI
IQueryAssociations_fnAddRef
(
IQueryAssociations
*
iface
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
ULONG
refCount
=
InterlockedIncrement
(
&
This
->
ref
);
TRACE
(
"(%p)->(ref before=%u)
\n
"
,
This
,
refCount
-
1
);
return
refCount
;
}
/**************************************************************************
* IQueryAssociations_Release {SHLWAPI}
*
* See IUnknown_Release.
*/
static
ULONG
WINAPI
IQueryAssociations_fnRelease
(
IQueryAssociations
*
iface
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
ULONG
refCount
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p)->(ref before=%u)
\n
"
,
This
,
refCount
+
1
);
if
(
!
refCount
)
{
TRACE
(
"Destroying IQueryAssociations (%p)
\n
"
,
This
);
RegCloseKey
(
This
->
hkeySource
);
RegCloseKey
(
This
->
hkeyProgID
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
return
refCount
;
}
/**************************************************************************
* IQueryAssociations_Init {SHLWAPI}
*
* Initialise an IQueryAssociations object.
*
* PARAMS
* iface [I] IQueryAssociations interface to initialise
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* pszAssoc [I] String for the root key name, or NULL if hkeyProgid is given
* hkeyProgid [I] Handle for the root key, or NULL if pszAssoc is given
* hWnd [I] Reserved, must be NULL.
*
* RETURNS
* Success: S_OK. iface is initialised with the parameters given.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnInit
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
LPCWSTR
pszAssoc
,
HKEY
hkeyProgid
,
HWND
hWnd
)
{
static
const
WCHAR
szProgID
[]
=
{
'P'
,
'r'
,
'o'
,
'g'
,
'I'
,
'D'
,
0
};
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
LONG
ret
;
TRACE
(
"(%p)->(%d,%s,%p,%p)
\n
"
,
iface
,
cfFlags
,
debugstr_w
(
pszAssoc
),
hkeyProgid
,
hWnd
);
if
(
hWnd
!=
NULL
)
FIXME
(
"hwnd != NULL not supported
\n
"
);
if
(
cfFlags
!=
0
)
FIXME
(
"unsupported flags: %x
\n
"
,
cfFlags
);
if
(
pszAssoc
!=
NULL
)
{
ret
=
RegOpenKeyExW
(
HKEY_CLASSES_ROOT
,
pszAssoc
,
0
,
KEY_READ
,
&
This
->
hkeySource
);
if
(
ret
!=
ERROR_SUCCESS
)
return
E_FAIL
;
/* if this is not a prog id */
if
((
*
pszAssoc
==
'.'
)
||
(
*
pszAssoc
==
'{'
))
{
RegOpenKeyExW
(
This
->
hkeySource
,
szProgID
,
0
,
KEY_READ
,
&
This
->
hkeyProgID
);
}
else
This
->
hkeyProgID
=
This
->
hkeySource
;
return
S_OK
;
}
else
if
(
hkeyProgid
!=
NULL
)
{
This
->
hkeyProgID
=
hkeyProgid
;
return
S_OK
;
}
else
return
E_INVALIDARG
;
}
static
HRESULT
ASSOC_GetValue
(
HKEY
hkey
,
WCHAR
**
pszText
)
{
DWORD
len
;
LONG
ret
;
assert
(
pszText
);
ret
=
RegQueryValueExW
(
hkey
,
NULL
,
0
,
NULL
,
NULL
,
&
len
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
if
(
!
len
)
return
E_FAIL
;
*
pszText
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
if
(
!*
pszText
)
return
E_OUTOFMEMORY
;
ret
=
RegQueryValueExW
(
hkey
,
NULL
,
0
,
NULL
,
(
LPBYTE
)
*
pszText
,
&
len
);
if
(
ret
!=
ERROR_SUCCESS
)
{
HeapFree
(
GetProcessHeap
(),
0
,
*
pszText
);
return
HRESULT_FROM_WIN32
(
ret
);
}
return
S_OK
;
}
static
HRESULT
ASSOC_GetCommand
(
IQueryAssociationsImpl
*
This
,
LPCWSTR
pszExtra
,
WCHAR
**
ppszCommand
)
{
HKEY
hkeyCommand
;
HKEY
hkeyFile
;
HKEY
hkeyShell
;
HKEY
hkeyVerb
;
HRESULT
hr
;
LONG
ret
;
WCHAR
*
pszExtraFromReg
=
NULL
;
WCHAR
*
pszFileType
;
static
const
WCHAR
commandW
[]
=
{
'c'
,
'o'
,
'm'
,
'm'
,
'a'
,
'n'
,
'd'
,
0
};
static
const
WCHAR
shellW
[]
=
{
's'
,
'h'
,
'e'
,
'l'
,
'l'
,
0
};
hr
=
ASSOC_GetValue
(
This
->
hkeySource
,
&
pszFileType
);
if
(
FAILED
(
hr
))
return
hr
;
ret
=
RegOpenKeyExW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
0
,
KEY_READ
,
&
hkeyFile
);
HeapFree
(
GetProcessHeap
(),
0
,
pszFileType
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
ret
=
RegOpenKeyExW
(
hkeyFile
,
shellW
,
0
,
KEY_READ
,
&
hkeyShell
);
RegCloseKey
(
hkeyFile
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
if
(
!
pszExtra
)
{
hr
=
ASSOC_GetValue
(
hkeyShell
,
&
pszExtraFromReg
);
/* if no default action */
if
(
hr
==
E_FAIL
||
hr
==
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
))
{
DWORD
rlen
;
ret
=
RegQueryInfoKeyW
(
hkeyShell
,
0
,
0
,
0
,
0
,
&
rlen
,
0
,
0
,
0
,
0
,
0
,
0
);
if
(
ret
!=
ERROR_SUCCESS
)
{
RegCloseKey
(
hkeyShell
);
return
HRESULT_FROM_WIN32
(
ret
);
}
rlen
++
;
pszExtraFromReg
=
HeapAlloc
(
GetProcessHeap
(),
0
,
rlen
*
sizeof
(
WCHAR
));
if
(
!
pszExtraFromReg
)
{
RegCloseKey
(
hkeyShell
);
return
E_OUTOFMEMORY
;
}
ret
=
RegEnumKeyExW
(
hkeyShell
,
0
,
pszExtraFromReg
,
&
rlen
,
0
,
NULL
,
NULL
,
NULL
);
if
(
ret
!=
ERROR_SUCCESS
)
{
RegCloseKey
(
hkeyShell
);
return
HRESULT_FROM_WIN32
(
ret
);
}
}
else
if
(
FAILED
(
hr
))
{
RegCloseKey
(
hkeyShell
);
return
hr
;
}
}
ret
=
RegOpenKeyExW
(
hkeyShell
,
pszExtra
?
pszExtra
:
pszExtraFromReg
,
0
,
KEY_READ
,
&
hkeyVerb
);
HeapFree
(
GetProcessHeap
(),
0
,
pszExtraFromReg
);
RegCloseKey
(
hkeyShell
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
ret
=
RegOpenKeyExW
(
hkeyVerb
,
commandW
,
0
,
KEY_READ
,
&
hkeyCommand
);
RegCloseKey
(
hkeyVerb
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
hr
=
ASSOC_GetValue
(
hkeyCommand
,
ppszCommand
);
RegCloseKey
(
hkeyCommand
);
return
hr
;
}
static
HRESULT
ASSOC_GetExecutable
(
IQueryAssociationsImpl
*
This
,
LPCWSTR
pszExtra
,
LPWSTR
path
,
DWORD
pathlen
,
DWORD
*
len
)
{
WCHAR
*
pszCommand
;
WCHAR
*
pszStart
;
WCHAR
*
pszEnd
;
HRESULT
hr
;
assert
(
len
);
hr
=
ASSOC_GetCommand
(
This
,
pszExtra
,
&
pszCommand
);
if
(
FAILED
(
hr
))
return
hr
;
/* cleanup pszCommand */
if
(
pszCommand
[
0
]
==
'"'
)
{
pszStart
=
pszCommand
+
1
;
pszEnd
=
strchrW
(
pszStart
,
'"'
);
}
else
{
pszStart
=
pszCommand
;
pszEnd
=
strchrW
(
pszStart
,
' '
);
}
if
(
pszEnd
)
*
pszEnd
=
0
;
*
len
=
SearchPathW
(
NULL
,
pszStart
,
NULL
,
pathlen
,
path
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
pszCommand
);
if
(
!*
len
)
return
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
);
return
S_OK
;
}
static
HRESULT
ASSOC_ReturnData
(
LPWSTR
out
,
DWORD
*
outlen
,
LPCWSTR
data
,
DWORD
datalen
)
{
assert
(
outlen
);
if
(
out
)
{
if
(
*
outlen
<
datalen
)
{
*
outlen
=
datalen
;
return
E_POINTER
;
}
*
outlen
=
datalen
;
lstrcpynW
(
out
,
data
,
datalen
);
return
S_OK
;
}
else
{
*
outlen
=
datalen
;
return
S_FALSE
;
}
}
/**************************************************************************
* IQueryAssociations_GetString {SHLWAPI}
*
* Get a file association string from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* str [I] Type of string to get (ASSOCSTR enum from "shlwapi.h")
* pszExtra [I] Extra information about the string location
* pszOut [O] Destination for the association string
* pcchOut [I/O] Length of pszOut
*
* RETURNS
* Success: S_OK. pszOut contains the string, pcchOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetString
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCSTR
str
,
LPCWSTR
pszExtra
,
LPWSTR
pszOut
,
DWORD
*
pcchOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
const
ASSOCF
cfUnimplemented
=
~
(
0
);
DWORD
len
=
0
;
HRESULT
hr
;
WCHAR
path
[
MAX_PATH
];
TRACE
(
"(%p,0x%8x,0x%8x,%s,%p,%p)
\n
"
,
This
,
cfFlags
,
str
,
debugstr_w
(
pszExtra
),
pszOut
,
pcchOut
);
if
(
cfFlags
&
cfUnimplemented
)
FIXME
(
"%08x: unimplemented flags!
\n
"
,
cfFlags
&
cfUnimplemented
);
if
(
!
pcchOut
)
return
E_UNEXPECTED
;
switch
(
str
)
{
case
ASSOCSTR_COMMAND
:
{
WCHAR
*
command
;
hr
=
ASSOC_GetCommand
(
This
,
pszExtra
,
&
command
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
command
,
strlenW
(
command
)
+
1
);
HeapFree
(
GetProcessHeap
(),
0
,
command
);
}
return
hr
;
}
case
ASSOCSTR_EXECUTABLE
:
{
hr
=
ASSOC_GetExecutable
(
This
,
pszExtra
,
path
,
MAX_PATH
,
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
len
++
;
return
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
path
,
len
);
}
case
ASSOCSTR_FRIENDLYDOCNAME
:
{
WCHAR
*
pszFileType
;
DWORD
ret
;
DWORD
size
;
hr
=
ASSOC_GetValue
(
This
->
hkeySource
,
&
pszFileType
);
if
(
FAILED
(
hr
))
return
hr
;
size
=
0
;
ret
=
RegGetValueW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
NULL
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
{
WCHAR
*
docName
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
docName
)
{
ret
=
RegGetValueW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
docName
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
docName
,
strlenW
(
docName
)
+
1
);
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
docName
);
}
else
hr
=
E_OUTOFMEMORY
;
}
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
pszFileType
);
return
hr
;
}
case
ASSOCSTR_FRIENDLYAPPNAME
:
{
PVOID
verinfoW
=
NULL
;
DWORD
size
,
retval
=
0
;
UINT
flen
;
WCHAR
*
bufW
;
static
const
WCHAR
translationW
[]
=
{
'\\'
,
'V'
,
'a'
,
'r'
,
'F'
,
'i'
,
'l'
,
'e'
,
'I'
,
'n'
,
'f'
,
'o'
,
'\\'
,
'T'
,
'r'
,
'a'
,
'n'
,
's'
,
'l'
,
'a'
,
't'
,
'i'
,
'o'
,
'n'
,
0
};
static
const
WCHAR
fileDescFmtW
[]
=
{
'\\'
,
'S'
,
't'
,
'r'
,
'i'
,
'n'
,
'g'
,
'F'
,
'i'
,
'l'
,
'e'
,
'I'
,
'n'
,
'f'
,
'o'
,
'\\'
,
'%'
,
'0'
,
'4'
,
'x'
,
'%'
,
'0'
,
'4'
,
'x'
,
'\\'
,
'F'
,
'i'
,
'l'
,
'e'
,
'D'
,
'e'
,
's'
,
'c'
,
'r'
,
'i'
,
'p'
,
't'
,
'i'
,
'o'
,
'n'
,
0
};
WCHAR
fileDescW
[
41
];
hr
=
ASSOC_GetExecutable
(
This
,
pszExtra
,
path
,
MAX_PATH
,
&
len
);
if
(
FAILED
(
hr
))
return
hr
;
retval
=
GetFileVersionInfoSizeW
(
path
,
&
size
);
if
(
!
retval
)
goto
get_friendly_name_fail
;
verinfoW
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
retval
);
if
(
!
verinfoW
)
return
E_OUTOFMEMORY
;
if
(
!
GetFileVersionInfoW
(
path
,
0
,
retval
,
verinfoW
))
goto
get_friendly_name_fail
;
if
(
VerQueryValueW
(
verinfoW
,
translationW
,
(
LPVOID
*
)
&
bufW
,
&
flen
))
{
UINT
i
;
DWORD
*
langCodeDesc
=
(
DWORD
*
)
bufW
;
for
(
i
=
0
;
i
<
flen
/
sizeof
(
DWORD
);
i
++
)
{
sprintfW
(
fileDescW
,
fileDescFmtW
,
LOWORD
(
langCodeDesc
[
i
]),
HIWORD
(
langCodeDesc
[
i
]));
if
(
VerQueryValueW
(
verinfoW
,
fileDescW
,
(
LPVOID
*
)
&
bufW
,
&
flen
))
{
/* Does strlenW(bufW) == 0 mean we use the filename? */
len
=
strlenW
(
bufW
)
+
1
;
TRACE
(
"found FileDescription: %s
\n
"
,
debugstr_w
(
bufW
));
return
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
bufW
,
len
);
}
}
}
get_friendly_name_fail:
PathRemoveExtensionW
(
path
);
PathStripPathW
(
path
);
TRACE
(
"using filename: %s
\n
"
,
debugstr_w
(
path
));
return
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
path
,
strlenW
(
path
)
+
1
);
}
case
ASSOCSTR_CONTENTTYPE
:
{
static
const
WCHAR
Content_TypeW
[]
=
{
'C'
,
'o'
,
'n'
,
't'
,
'e'
,
'n'
,
't'
,
' '
,
'T'
,
'y'
,
'p'
,
'e'
,
0
};
WCHAR
*
contentType
;
DWORD
ret
;
DWORD
size
;
size
=
0
;
ret
=
RegGetValueW
(
This
->
hkeySource
,
NULL
,
Content_TypeW
,
RRF_RT_REG_SZ
,
NULL
,
NULL
,
&
size
);
if
(
ret
!=
ERROR_SUCCESS
)
return
HRESULT_FROM_WIN32
(
ret
);
contentType
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
contentType
!=
NULL
)
{
ret
=
RegGetValueW
(
This
->
hkeySource
,
NULL
,
Content_TypeW
,
RRF_RT_REG_SZ
,
NULL
,
contentType
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
contentType
,
strlenW
(
contentType
)
+
1
);
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
contentType
);
}
else
hr
=
E_OUTOFMEMORY
;
return
hr
;
}
case
ASSOCSTR_DEFAULTICON
:
{
static
const
WCHAR
DefaultIconW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'I'
,
'c'
,
'o'
,
'n'
,
0
};
WCHAR
*
pszFileType
;
DWORD
ret
;
DWORD
size
;
HKEY
hkeyFile
;
hr
=
ASSOC_GetValue
(
This
->
hkeySource
,
&
pszFileType
);
if
(
FAILED
(
hr
))
return
hr
;
ret
=
RegOpenKeyExW
(
HKEY_CLASSES_ROOT
,
pszFileType
,
0
,
KEY_READ
,
&
hkeyFile
);
if
(
ret
==
ERROR_SUCCESS
)
{
size
=
0
;
ret
=
RegGetValueW
(
hkeyFile
,
DefaultIconW
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
NULL
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
{
WCHAR
*
icon
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
icon
)
{
ret
=
RegGetValueW
(
hkeyFile
,
DefaultIconW
,
NULL
,
RRF_RT_REG_SZ
,
NULL
,
icon
,
&
size
);
if
(
ret
==
ERROR_SUCCESS
)
hr
=
ASSOC_ReturnData
(
pszOut
,
pcchOut
,
icon
,
strlenW
(
icon
)
+
1
);
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
icon
);
}
else
hr
=
E_OUTOFMEMORY
;
}
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
RegCloseKey
(
hkeyFile
);
}
else
hr
=
HRESULT_FROM_WIN32
(
ret
);
HeapFree
(
GetProcessHeap
(),
0
,
pszFileType
);
return
hr
;
}
default:
FIXME
(
"assocstr %d unimplemented!
\n
"
,
str
);
return
E_NOTIMPL
;
}
}
/**************************************************************************
* IQueryAssociations_GetKey {SHLWAPI}
*
* Get a file association key from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assockey [I] Type of key to get (ASSOCKEY enum from "shlwapi.h")
* pszExtra [I] Extra information about the key location
* phkeyOut [O] Destination for the association key
*
* RETURNS
* Success: S_OK. phkeyOut contains a handle to the key.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetKey
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCKEY
assockey
,
LPCWSTR
pszExtra
,
HKEY
*
phkeyOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
FIXME
(
"(%p,0x%8x,0x%8x,%s,%p)-stub!
\n
"
,
This
,
cfFlags
,
assockey
,
debugstr_w
(
pszExtra
),
phkeyOut
);
return
E_NOTIMPL
;
}
/**************************************************************************
* IQueryAssociations_GetData {SHLWAPI}
*
* Get the data for a file association key from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assocdata [I] Type of data to get (ASSOCDATA enum from "shlwapi.h")
* pszExtra [I] Extra information about the data location
* pvOut [O] Destination for the association key
* pcbOut [I/O] Size of pvOut
*
* RETURNS
* Success: S_OK. pszOut contains the data, pcbOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetData
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCDATA
assocdata
,
LPCWSTR
pszExtra
,
LPVOID
pvOut
,
DWORD
*
pcbOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
FIXME
(
"(%p,0x%8x,0x%8x,%s,%p,%p)-stub!
\n
"
,
This
,
cfFlags
,
assocdata
,
debugstr_w
(
pszExtra
),
pvOut
,
pcbOut
);
return
E_NOTIMPL
;
}
/**************************************************************************
* IQueryAssociations_GetEnum {SHLWAPI}
*
* Not yet implemented in native Win32.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assocenum [I] Type of enum to get (ASSOCENUM enum from "shlwapi.h")
* pszExtra [I] Extra information about the enum location
* riid [I] REFIID to look for
* ppvOut [O] Destination for the interface.
*
* RETURNS
* Success: S_OK.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* Presumably this function returns an enumerator object.
*/
static
HRESULT
WINAPI
IQueryAssociations_fnGetEnum
(
IQueryAssociations
*
iface
,
ASSOCF
cfFlags
,
ASSOCENUM
assocenum
,
LPCWSTR
pszExtra
,
REFIID
riid
,
LPVOID
*
ppvOut
)
{
IQueryAssociationsImpl
*
This
=
(
IQueryAssociationsImpl
*
)
iface
;
FIXME
(
"(%p,0x%8x,0x%8x,%s,%s,%p)-stub!
\n
"
,
This
,
cfFlags
,
assocenum
,
debugstr_w
(
pszExtra
),
debugstr_guid
(
riid
),
ppvOut
);
return
E_NOTIMPL
;
}
static
const
IQueryAssociationsVtbl
IQueryAssociations_vtbl
=
{
IQueryAssociations_fnQueryInterface
,
IQueryAssociations_fnAddRef
,
IQueryAssociations_fnRelease
,
IQueryAssociations_fnInit
,
IQueryAssociations_fnGetString
,
IQueryAssociations_fnGetKey
,
IQueryAssociations_fnGetData
,
IQueryAssociations_fnGetEnum
};
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