mirror of
https://github.com/reactos/reactos.git
synced 2024-06-28 00:41:36 +00:00
[SHELL32]
- Add CLSID_ShellFileDefExt, CLSID_ShellDrvDefExt, CLSID_ShellNetDefExt GUIDs - Move File Properties default pages to CFileDefExt svn path=/trunk/; revision=54908
This commit is contained in:
parent
d0b26386cd
commit
bc92eceb86
|
@ -69,6 +69,8 @@ list(APPEND SOURCE
|
||||||
newmenu.cpp
|
newmenu.cpp
|
||||||
startmenu.cpp
|
startmenu.cpp
|
||||||
folder_options.cpp
|
folder_options.cpp
|
||||||
|
filedefext.cpp
|
||||||
|
drvdefext.cpp
|
||||||
shell32.rc
|
shell32.rc
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/shell32_stubs.c
|
${CMAKE_CURRENT_BINARY_DIR}/shell32_stubs.c
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/shell32.def)
|
${CMAKE_CURRENT_BINARY_DIR}/shell32.def)
|
||||||
|
|
1
reactos/dll/win32/shell32/drvdefext.cpp
Normal file
1
reactos/dll/win32/shell32/drvdefext.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
1
reactos/dll/win32/shell32/drvdefext.h
Normal file
1
reactos/dll/win32/shell32/drvdefext.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
812
reactos/dll/win32/shell32/filedefext.cpp
Normal file
812
reactos/dll/win32/shell32/filedefext.cpp
Normal file
|
@ -0,0 +1,812 @@
|
||||||
|
/*
|
||||||
|
* provides new shell item service
|
||||||
|
*
|
||||||
|
* Copyright 2007 Johannes Anderwald (janderwald@reactos.org)
|
||||||
|
* Copyright 2009 Andrew Hill
|
||||||
|
* Copyright 2012 Rafal Harabien
|
||||||
|
*
|
||||||
|
* 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 <precomp.h>
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
BOOL PathIsExeW(LPCWSTR lpszPath);
|
||||||
|
|
||||||
|
BOOL CFileVersionInfo::Load(LPCWSTR pwszPath)
|
||||||
|
{
|
||||||
|
ULONG cbInfo = GetFileVersionInfoSizeW(pwszPath, NULL);
|
||||||
|
if (!cbInfo)
|
||||||
|
{
|
||||||
|
WARN("GetFileVersionInfoSize %ls failed\n", pwszPath);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbInfo);
|
||||||
|
if (!m_pInfo)
|
||||||
|
{
|
||||||
|
ERR("HeapAlloc failed bytes %x\n", cbInfo);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetFileVersionInfoW(pwszPath, 0, cbInfo, m_pInfo))
|
||||||
|
{
|
||||||
|
ERR("GetFileVersionInfoW failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPLANGANDCODEPAGE lpLangCode;
|
||||||
|
UINT cBytes;
|
||||||
|
if (!VerQueryValueW(m_pInfo, L"VarFileInfo\\Translation", (LPVOID *)&lpLangCode, &cBytes))
|
||||||
|
{
|
||||||
|
ERR("VerQueryValueW failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: find language from current locale / if not available,
|
||||||
|
* default to english
|
||||||
|
* for now default to first available language
|
||||||
|
*/
|
||||||
|
m_wLang = lpLangCode->lang;
|
||||||
|
m_wCode = lpLangCode->code;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPCWSTR CFileVersionInfo::GetString(LPCWSTR pwszName)
|
||||||
|
{
|
||||||
|
if (!m_pInfo)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
WCHAR wszBuf[256];
|
||||||
|
swprintf(wszBuf, L"\\StringFileInfo\\%04x%04x\\%s", m_wLang, m_wCode, pwszName);
|
||||||
|
|
||||||
|
LPCWSTR pwszResult = NULL;
|
||||||
|
UINT cBytes = 0;
|
||||||
|
if (!VerQueryValueW(m_pInfo, wszBuf, (LPVOID *)&pwszResult, &cBytes))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return pwszResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
VS_FIXEDFILEINFO *CFileVersionInfo::GetFixedInfo()
|
||||||
|
{
|
||||||
|
if (!m_pInfo)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
VS_FIXEDFILEINFO *pInfo;
|
||||||
|
UINT cBytes;
|
||||||
|
if (!VerQueryValueW(m_pInfo, L"\\", (PVOID*)&pInfo, &cBytes))
|
||||||
|
return NULL;
|
||||||
|
return pInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* SH_FormatFileSizeWithBytes
|
||||||
|
*
|
||||||
|
* Format a size in bytes to string.
|
||||||
|
*
|
||||||
|
* lpQwSize = Pointer to 64bit large integer to format
|
||||||
|
* pszBuf = Buffer to fill with output string
|
||||||
|
* cchBuf = size of pszBuf in characters
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
LPWSTR
|
||||||
|
SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT cchBuf)
|
||||||
|
{
|
||||||
|
NUMBERFMTW nf;
|
||||||
|
WCHAR szNumber[24];
|
||||||
|
WCHAR szDecimalSep[8];
|
||||||
|
WCHAR szThousandSep[8];
|
||||||
|
WCHAR szGrouping[12];
|
||||||
|
int Len, cchFormatted, i;
|
||||||
|
size_t cchRemaining;
|
||||||
|
LPWSTR Ptr;
|
||||||
|
|
||||||
|
// Try to build first Format byte string
|
||||||
|
if (StrFormatByteSizeW(lpQwSize->QuadPart, pszBuf, cchBuf) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// If there is less bytes than 1KB, we have nothing to do
|
||||||
|
if (lpQwSize->QuadPart < 1024)
|
||||||
|
return pszBuf;
|
||||||
|
|
||||||
|
// Print the number in uniform mode
|
||||||
|
swprintf(szNumber, L"%I64u", lpQwSize->QuadPart);
|
||||||
|
|
||||||
|
// Get system strings for decimal and thousand separators.
|
||||||
|
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSep, sizeof(szDecimalSep) / sizeof(*szDecimalSep));
|
||||||
|
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szThousandSep, sizeof(szThousandSep) / sizeof(*szThousandSep));
|
||||||
|
|
||||||
|
// Initialize format for printing the number in bytes
|
||||||
|
ZeroMemory(&nf, sizeof(nf));
|
||||||
|
nf.NumDigits = 0;
|
||||||
|
nf.LeadingZero = 0;
|
||||||
|
nf.Grouping = 0;
|
||||||
|
nf.lpDecimalSep = szDecimalSep;
|
||||||
|
nf.lpThousandSep = szThousandSep;
|
||||||
|
nf.NegativeOrder = 0;
|
||||||
|
|
||||||
|
// Get system string for groups separator
|
||||||
|
Len = GetLocaleInfoW(LOCALE_USER_DEFAULT,
|
||||||
|
LOCALE_SGROUPING,
|
||||||
|
szGrouping,
|
||||||
|
sizeof(szGrouping) / sizeof(*szGrouping));
|
||||||
|
|
||||||
|
// Convert grouping specs from string to integer
|
||||||
|
for (i = 0; i < Len; i++)
|
||||||
|
{
|
||||||
|
WCHAR wch = szGrouping[i];
|
||||||
|
|
||||||
|
if (wch >= L'0' && wch <= L'9')
|
||||||
|
nf.Grouping = nf.Grouping * 10 + (wch - L'0');
|
||||||
|
else if (wch != L';')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nf.Grouping % 10) == 0)
|
||||||
|
nf.Grouping /= 10;
|
||||||
|
else
|
||||||
|
nf.Grouping *= 10;
|
||||||
|
|
||||||
|
// Concate " (" at the end of buffer
|
||||||
|
Len = wcslen(pszBuf);
|
||||||
|
Ptr = pszBuf + Len;
|
||||||
|
cchRemaining = cchBuf - Len;
|
||||||
|
StringCchCopyExW(Ptr, cchRemaining, L" (", &Ptr, &cchRemaining, 0);
|
||||||
|
|
||||||
|
// Save formatted number of bytes in buffer
|
||||||
|
cchFormatted = GetNumberFormatW(LOCALE_USER_DEFAULT,
|
||||||
|
0,
|
||||||
|
szNumber,
|
||||||
|
&nf,
|
||||||
|
Ptr,
|
||||||
|
cchRemaining);
|
||||||
|
|
||||||
|
if (cchFormatted == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// cchFormatted is number of characters including NULL - make it a real length
|
||||||
|
--cchFormatted;
|
||||||
|
|
||||||
|
// Copy ' ' to buffer
|
||||||
|
Ptr += cchFormatted;
|
||||||
|
cchRemaining -= cchFormatted;
|
||||||
|
StringCchCopyExW(Ptr, cchRemaining, L" ", &Ptr, &cchRemaining, 0);
|
||||||
|
|
||||||
|
// Copy 'bytes' string and remaining ')'
|
||||||
|
Len = LoadStringW(shell32_hInstance, IDS_BYTES_FORMAT, Ptr, cchRemaining);
|
||||||
|
Ptr += Len;
|
||||||
|
cchRemaining -= Len;
|
||||||
|
StringCchCopy(Ptr, cchRemaining, L")");
|
||||||
|
|
||||||
|
return pszBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* SH_CreatePropertySheetPage [Internal]
|
||||||
|
*
|
||||||
|
* creates a property sheet page from an resource name
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
HPROPSHEETPAGE
|
||||||
|
SH_CreatePropertySheetPage(LPCSTR pszResName, DLGPROC pfnDlgProc, LPARAM lParam, LPWSTR pwszTitle)
|
||||||
|
{
|
||||||
|
if (pszResName == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
HRSRC hRes = FindResourceA(shell32_hInstance, pszResName, (LPSTR)RT_DIALOG);
|
||||||
|
if (hRes == NULL)
|
||||||
|
{
|
||||||
|
ERR("failed to find resource name\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPVOID pTemplate = LoadResource(shell32_hInstance, hRes);
|
||||||
|
if (pTemplate == NULL)
|
||||||
|
{
|
||||||
|
ERR("failed to load resource\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROPSHEETPAGEW Page;
|
||||||
|
memset(&Page, 0x0, sizeof(PROPSHEETPAGEW));
|
||||||
|
Page.dwSize = sizeof(PROPSHEETPAGEW);
|
||||||
|
Page.dwFlags = PSP_DLGINDIRECT;
|
||||||
|
Page.pResource = (DLGTEMPLATE*)pTemplate;
|
||||||
|
Page.pfnDlgProc = pfnDlgProc;
|
||||||
|
Page.lParam = lParam;
|
||||||
|
Page.pszTitle = pwszTitle;
|
||||||
|
|
||||||
|
if (pwszTitle)
|
||||||
|
Page.dwFlags |= PSP_USETITLE;
|
||||||
|
|
||||||
|
return CreatePropertySheetPageW(&Page);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CFileDefExt::InitOpensWithField(HWND hwndDlg)
|
||||||
|
{
|
||||||
|
WCHAR wszBuf[MAX_PATH] = L"";
|
||||||
|
WCHAR wszPath[MAX_PATH] = L"";
|
||||||
|
DWORD dwSize = sizeof(wszBuf);
|
||||||
|
BOOL bUnknownApp = TRUE;
|
||||||
|
LPCWSTR pwszExt = PathFindExtensionW(m_wszPath);
|
||||||
|
|
||||||
|
if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, L"", RRF_RT_REG_SZ, NULL, wszBuf, &dwSize) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
bUnknownApp = FALSE;
|
||||||
|
StringCbCatW(wszBuf, sizeof(wszBuf), L"\\shell\\open\\command");
|
||||||
|
dwSize = sizeof(wszPath);
|
||||||
|
if (RegGetValueW(HKEY_CLASSES_ROOT, wszBuf, L"", RRF_RT_REG_SZ, NULL, wszPath, &dwSize) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Get path from command line */
|
||||||
|
ExpandEnvironmentStringsW(wszPath, wszBuf, _countof(wszBuf));
|
||||||
|
PathRemoveArgs(wszBuf);
|
||||||
|
PathUnquoteSpacesW(wszBuf);
|
||||||
|
PathSearchAndQualify(wszBuf, wszPath, _countof(wszPath));
|
||||||
|
|
||||||
|
if (PathFileExistsW(wszPath))
|
||||||
|
{
|
||||||
|
/* Get file description */
|
||||||
|
CFileVersionInfo VerInfo;
|
||||||
|
VerInfo.Load(wszPath);
|
||||||
|
LPCWSTR pwszDescr = VerInfo.GetString(L"FileDescription");
|
||||||
|
if (pwszDescr)
|
||||||
|
SetDlgItemTextW(hwndDlg, 14007, pwszDescr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* File has no description - display filename */
|
||||||
|
LPWSTR pwszFilename = PathFindFileNameW(wszPath);
|
||||||
|
PathRemoveExtension(pwszFilename);
|
||||||
|
pwszFilename[0] = towupper(pwszFilename[0]);
|
||||||
|
SetDlgItemTextW(hwndDlg, 14007, pwszFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bUnknownApp = TRUE;
|
||||||
|
} else
|
||||||
|
WARN("RegGetValueW %ls failed\n", wszBuf);
|
||||||
|
} else
|
||||||
|
WARN("RegGetValueW %ls failed\n", pwszExt);
|
||||||
|
|
||||||
|
if (bUnknownApp)
|
||||||
|
{
|
||||||
|
/* Unknown application */
|
||||||
|
LoadStringW(shell32_hInstance, IDS_UNKNOWN_APP, wszBuf, _countof(wszBuf));
|
||||||
|
SetDlgItemTextW(hwndDlg, 14007, wszBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* SH_FileGeneralFileType [Internal]
|
||||||
|
*
|
||||||
|
* retrieves file extension description from registry and sets it in dialog
|
||||||
|
*
|
||||||
|
* TODO: retrieve file extension default icon and load it
|
||||||
|
* find executable name from registry, retrieve description from executable
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::InitFileType(HWND hwndDlg)
|
||||||
|
{
|
||||||
|
TRACE("path %s\n", debugstr_w(m_wszPath));
|
||||||
|
|
||||||
|
HWND hDlgCtrl = GetDlgItem(hwndDlg, 14005);
|
||||||
|
if (hDlgCtrl == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Get file information */
|
||||||
|
SHFILEINFO fi;
|
||||||
|
if (!SHGetFileInfoW(m_wszPath, 0, &fi, sizeof(fi), SHGFI_TYPENAME|SHGFI_ICON))
|
||||||
|
{
|
||||||
|
ERR("SHGetFileInfoW failed for %ls (%lu)\n", m_wszPath, GetLastError());
|
||||||
|
fi.szTypeName[0] = L'\0';
|
||||||
|
fi.hIcon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPCWSTR pwszExt = PathFindExtensionW(m_wszPath);
|
||||||
|
if (pwszExt[0])
|
||||||
|
{
|
||||||
|
WCHAR wszBuf[256];
|
||||||
|
|
||||||
|
if (!fi.szTypeName[0])
|
||||||
|
{
|
||||||
|
/* The file type is unknown, so default to string "FileExtension File" */
|
||||||
|
size_t cchRemaining = 0;
|
||||||
|
LPWSTR pwszEnd = NULL;
|
||||||
|
|
||||||
|
StringCchPrintfExW(wszBuf, _countof(wszBuf), &pwszEnd, &cchRemaining, 0, L"%s ", pwszExt + 1);
|
||||||
|
SendMessageW(hDlgCtrl, WM_GETTEXT, (WPARAM)cchRemaining, (LPARAM)pwszEnd);
|
||||||
|
|
||||||
|
SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)wszBuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Update file type */
|
||||||
|
StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s (%s)", fi.szTypeName, pwszExt);
|
||||||
|
SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)wszBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update file icon */
|
||||||
|
if (fi.hIcon)
|
||||||
|
SendDlgItemMessageW(hwndDlg, 14000, STM_SETICON, (WPARAM)fi.hIcon, 0);
|
||||||
|
else
|
||||||
|
ERR("No icon %ls\n", m_wszPath);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* SHFileGeneralGetFileTimeString [Internal]
|
||||||
|
*
|
||||||
|
* formats a given LPFILETIME struct into readable user format
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::GetFileTimeString(LPFILETIME lpFileTime, WCHAR *lpResult)
|
||||||
|
{
|
||||||
|
FILETIME ft;
|
||||||
|
SYSTEMTIME st;
|
||||||
|
|
||||||
|
if (lpFileTime == NULL || lpResult == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!FileTimeToLocalFileTime(lpFileTime, &ft))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
FileTimeToSystemTime(&ft, &st);
|
||||||
|
|
||||||
|
/* ddmmyy */
|
||||||
|
swprintf(lpResult, L"%02hu/%02hu/%04hu %02hu:%02hu", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute);
|
||||||
|
|
||||||
|
TRACE("result %s\n", debugstr_w(lpResult));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* SH_FileGeneralSetText [Internal]
|
||||||
|
*
|
||||||
|
* sets file path string and filename string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::InitFilePath(HWND hwndDlg)
|
||||||
|
{
|
||||||
|
/* Find the filename */
|
||||||
|
WCHAR *pwszFilename = PathFindFileNameW(m_wszPath);
|
||||||
|
|
||||||
|
if (pwszFilename > m_wszPath)
|
||||||
|
{
|
||||||
|
/* Location field */
|
||||||
|
WCHAR wszLocation[MAX_PATH];
|
||||||
|
StringCchCopyNW(wszLocation, _countof(wszLocation), m_wszPath, pwszFilename - m_wszPath);
|
||||||
|
PathRemoveBackslashW(wszLocation);
|
||||||
|
|
||||||
|
SetDlgItemTextW(hwndDlg, 14009, wszLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filename field */
|
||||||
|
SetDlgItemTextW(hwndDlg, 14001, pwszFilename);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* SH_FileGeneralSetFileSizeTime [Internal]
|
||||||
|
*
|
||||||
|
* retrieves file information from file and sets in dialog
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::InitFileSizeTime(HWND hwndDlg)
|
||||||
|
{
|
||||||
|
WCHAR wszBuf[MAX_PATH];
|
||||||
|
|
||||||
|
TRACE("SH_FileGeneralSetFileSizeTime %ls\n", m_wszPath);
|
||||||
|
|
||||||
|
HANDLE hFile = CreateFileW(m_wszPath,
|
||||||
|
GENERIC_READ,
|
||||||
|
FILE_SHARE_READ,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
WARN("failed to open file %s\n", debugstr_w(m_wszPath));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILETIME CreateTime, AccessedTime, WriteTime;
|
||||||
|
if (!GetFileTime(hFile, &CreateTime, &AccessedTime, &WriteTime))
|
||||||
|
{
|
||||||
|
WARN("GetFileTime failed\n");
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LARGE_INTEGER FileSize;
|
||||||
|
if (!GetFileSizeEx(hFile, &FileSize))
|
||||||
|
{
|
||||||
|
WARN("GetFileSize failed\n");
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hFile);
|
||||||
|
|
||||||
|
if (GetFileTimeString(&CreateTime, wszBuf))
|
||||||
|
SetDlgItemTextW(hwndDlg, 14015, wszBuf);
|
||||||
|
|
||||||
|
if (GetFileTimeString(&AccessedTime, wszBuf))
|
||||||
|
SetDlgItemTextW(hwndDlg, 14019, wszBuf);
|
||||||
|
|
||||||
|
if (GetFileTimeString(&WriteTime, wszBuf))
|
||||||
|
SetDlgItemTextW(hwndDlg, 14017, wszBuf);
|
||||||
|
|
||||||
|
if (SH_FormatFileSizeWithBytes((PULARGE_INTEGER)&FileSize,
|
||||||
|
wszBuf,
|
||||||
|
sizeof(wszBuf) / sizeof(WCHAR)))
|
||||||
|
{
|
||||||
|
SetDlgItemTextW(hwndDlg, 14011, wszBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* CFileDefExt::InitGeneralPage [Internal]
|
||||||
|
*
|
||||||
|
* sets all file general properties in dialog
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::InitGeneralPage(HWND hwndDlg)
|
||||||
|
{
|
||||||
|
/* Set general text properties filename filelocation and icon */
|
||||||
|
InitFilePath(hwndDlg);
|
||||||
|
|
||||||
|
/* Set file type and icon */
|
||||||
|
InitFileType(hwndDlg);
|
||||||
|
|
||||||
|
/* Set open with application */
|
||||||
|
if (!PathIsExeW(m_wszPath))
|
||||||
|
InitOpensWithField(hwndDlg);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LPCWSTR pwszDescr = m_VerInfo.GetString(L"FileDescription");
|
||||||
|
if (pwszDescr)
|
||||||
|
SetDlgItemTextW(hwndDlg, 14007, pwszDescr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set file created/modfied/accessed time */
|
||||||
|
InitFileSizeTime(hwndDlg);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* CFileDefExt::GeneralPageProc
|
||||||
|
*
|
||||||
|
* wnd proc of 'General' property sheet page
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
INT_PTR CALLBACK
|
||||||
|
CFileDefExt::GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
{
|
||||||
|
LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam;
|
||||||
|
|
||||||
|
if (ppsp == NULL || !ppsp->lParam)
|
||||||
|
break;
|
||||||
|
|
||||||
|
TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %S\n", hwndDlg, lParam, ppsp->lParam);
|
||||||
|
|
||||||
|
CFileDefExt *pFileDefExt = (CFileDefExt*)ppsp->lParam;
|
||||||
|
pFileDefExt->InitGeneralPage(hwndDlg);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* CFileDefExt::InitVersionPage [Internal]
|
||||||
|
*
|
||||||
|
* sets all file version properties in dialog
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::InitVersionPage(HWND hwndDlg)
|
||||||
|
{
|
||||||
|
/* Get fixed info */
|
||||||
|
VS_FIXEDFILEINFO *pInfo = m_VerInfo.GetFixedInfo();
|
||||||
|
if (pInfo)
|
||||||
|
{
|
||||||
|
WCHAR wszVersion[256];
|
||||||
|
swprintf(wszVersion, L"%u.%u.%u.%u", HIWORD(pInfo->dwFileVersionMS),
|
||||||
|
LOWORD(pInfo->dwFileVersionMS),
|
||||||
|
HIWORD(pInfo->dwFileVersionLS),
|
||||||
|
LOWORD(pInfo->dwFileVersionLS));
|
||||||
|
TRACE("MS %x LS %x ver %s \n", pInfo->dwFileVersionMS, pInfo->dwFileVersionLS, debugstr_w(wszVersion));
|
||||||
|
SetDlgItemTextW(hwndDlg, 14001, wszVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update labels */
|
||||||
|
SetVersionLabel(hwndDlg, 14003, L"FileDescription");
|
||||||
|
SetVersionLabel(hwndDlg, 14005, L"LegalCopyright");
|
||||||
|
|
||||||
|
/* Add items to listbox */
|
||||||
|
AddVersionString(hwndDlg, L"CompanyName");
|
||||||
|
/* FIXME insert language identifier */
|
||||||
|
AddVersionString(hwndDlg, L"ProductName");
|
||||||
|
AddVersionString(hwndDlg, L"InternalName");
|
||||||
|
AddVersionString(hwndDlg, L"OriginalFilename");
|
||||||
|
AddVersionString(hwndDlg, L"FileVersion");
|
||||||
|
AddVersionString(hwndDlg, L"ProductVersion");
|
||||||
|
|
||||||
|
/* Attach file version to dialog window */
|
||||||
|
SetWindowLongPtr(hwndDlg, DWL_USER, (LONG_PTR)this);
|
||||||
|
|
||||||
|
/* Select first item */
|
||||||
|
HWND hDlgCtrl = GetDlgItem(hwndDlg, 14009);
|
||||||
|
SendMessageW(hDlgCtrl, LB_SETCURSEL, 0, 0);
|
||||||
|
LPCWSTR pwszText = (WCHAR *)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)0, (LPARAM)NULL);
|
||||||
|
SetDlgItemTextW(hwndDlg, 14010, pwszText);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* CFileDefExt::SetVersionLabel [Internal]
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::SetVersionLabel(HWND hwndDlg, DWORD idCtrl, LPCWSTR pwszName)
|
||||||
|
{
|
||||||
|
if (hwndDlg == NULL || pwszName == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
LPCWSTR pwszValue = m_VerInfo.GetString(pwszName);
|
||||||
|
if (pwszValue)
|
||||||
|
{
|
||||||
|
/* file description property */
|
||||||
|
TRACE("%s :: %s\n", debugstr_w(pwszName), debugstr_w(pwszValue));
|
||||||
|
SetDlgItemTextW(hwndDlg, idCtrl, pwszValue);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* CFileDefExt::AddVersionString [Internal]
|
||||||
|
*
|
||||||
|
* retrieves a version string and adds it to listbox
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
CFileDefExt::AddVersionString(HWND hwndDlg, LPCWSTR pwszName)
|
||||||
|
{
|
||||||
|
TRACE("pwszName %s, hwndDlg %p\n", debugstr_w(pwszName), hwndDlg);
|
||||||
|
|
||||||
|
if (hwndDlg == NULL || pwszName == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
LPCWSTR pwszValue = m_VerInfo.GetString(pwszName);
|
||||||
|
if (pwszValue)
|
||||||
|
{
|
||||||
|
/* listbox name property */
|
||||||
|
HWND hDlgCtrl = GetDlgItem(hwndDlg, 14009);
|
||||||
|
TRACE("%s :: %s\n", debugstr_w(pwszName), debugstr_w(pwszValue));
|
||||||
|
UINT Index = SendMessageW(hDlgCtrl, LB_ADDSTRING, (WPARAM) -1, (LPARAM)pwszName);
|
||||||
|
SendMessageW(hDlgCtrl, LB_SETITEMDATA, (WPARAM)Index, (LPARAM)(WCHAR *)pwszValue);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* CFileDefExt::VersionPageProc
|
||||||
|
*
|
||||||
|
* wnd proc of 'Version' property sheet page
|
||||||
|
*/
|
||||||
|
|
||||||
|
INT_PTR CALLBACK
|
||||||
|
CFileDefExt::VersionPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
{
|
||||||
|
LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
|
||||||
|
|
||||||
|
if (ppsp == NULL || !ppsp->lParam)
|
||||||
|
break;
|
||||||
|
|
||||||
|
TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %x\n", hwndDlg, lParam, ppsp->lParam);
|
||||||
|
|
||||||
|
CFileDefExt *pFileDefExt = (CFileDefExt*)ppsp->lParam;
|
||||||
|
return pFileDefExt->InitVersionPage(hwndDlg);
|
||||||
|
}
|
||||||
|
case WM_COMMAND:
|
||||||
|
if (LOWORD(wParam) == 14009 && HIWORD(wParam) == LBN_SELCHANGE)
|
||||||
|
{
|
||||||
|
HWND hDlgCtrl = (HWND)lParam;
|
||||||
|
|
||||||
|
LRESULT Index = SendMessageW(hDlgCtrl, LB_GETCURSEL, (WPARAM)NULL, (LPARAM)NULL);
|
||||||
|
if (Index == LB_ERR)
|
||||||
|
break;
|
||||||
|
|
||||||
|
LPCWSTR pwszData = (LPCWSTR)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)Index, (LPARAM)NULL);
|
||||||
|
if (pwszData == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
TRACE("hDlgCtrl %x string %s\n", hDlgCtrl, debugstr_w(pwszData));
|
||||||
|
SetDlgItemTextW(hwndDlg, 14010, pwszData);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_DESTROY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFileDefExt::CFileDefExt()
|
||||||
|
{
|
||||||
|
m_wszPath[0] = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
CFileDefExt::~CFileDefExt()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pDataObj, HKEY hkeyProgID)
|
||||||
|
{
|
||||||
|
FORMATETC format;
|
||||||
|
STGMEDIUM stgm;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("%p %p %p %p\n", this, pidlFolder, pDataObj, hkeyProgID);
|
||||||
|
|
||||||
|
if (!pDataObj)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
format.cfFormat = CF_HDROP;
|
||||||
|
format.ptd = NULL;
|
||||||
|
format.dwAspect = DVASPECT_CONTENT;
|
||||||
|
format.lindex = -1;
|
||||||
|
format.tymed = TYMED_HGLOBAL;
|
||||||
|
|
||||||
|
hr = pDataObj->GetData(&format, &stgm);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (!DragQueryFileW((HDROP)stgm.hGlobal, 0, m_wszPath, _countof(m_wszPath)))
|
||||||
|
{
|
||||||
|
ERR("DragQueryFileW failed\n");
|
||||||
|
ReleaseStgMedium(&stgm);
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseStgMedium(&stgm);
|
||||||
|
TRACE("File properties %ls\n", m_wszPath);
|
||||||
|
m_VerInfo.Load(m_wszPath);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||||
|
{
|
||||||
|
HPROPSHEETPAGE hPage;
|
||||||
|
|
||||||
|
hPage = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG",
|
||||||
|
GeneralPageProc,
|
||||||
|
(LPARAM)this,
|
||||||
|
NULL);
|
||||||
|
if (hPage)
|
||||||
|
pfnAddPage(hPage, lParam);
|
||||||
|
|
||||||
|
if (GetFileVersionInfoSizeW(m_wszPath, NULL))
|
||||||
|
{
|
||||||
|
hPage = SH_CreatePropertySheetPage("SHELL_FILE_VERSION_DLG",
|
||||||
|
VersionPageProc,
|
||||||
|
(LPARAM)this,
|
||||||
|
NULL);
|
||||||
|
if (hPage)
|
||||||
|
pfnAddPage(hPage, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::SetSite(IUnknown *punk)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI
|
||||||
|
CFileDefExt::GetSite(REFIID iid, void **ppvSite)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
110
reactos/dll/win32/shell32/filedefext.h
Normal file
110
reactos/dll/win32/shell32/filedefext.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Provides default file shell extension
|
||||||
|
*
|
||||||
|
* Copyright 2012 Rafal Harabien
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FILE_DEF_EXT_H_
|
||||||
|
#define _FILE_DEF_EXT_H_
|
||||||
|
|
||||||
|
class CFileVersionInfo
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
PVOID m_pInfo;
|
||||||
|
WORD m_wLang, m_wCode;
|
||||||
|
|
||||||
|
typedef struct _LANGANDCODEPAGE_
|
||||||
|
{
|
||||||
|
WORD lang;
|
||||||
|
WORD code;
|
||||||
|
} LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline CFileVersionInfo():
|
||||||
|
m_pInfo(NULL), m_wLang(0), m_wCode(0) {}
|
||||||
|
|
||||||
|
inline ~CFileVersionInfo()
|
||||||
|
{
|
||||||
|
if (m_pInfo)
|
||||||
|
HeapFree(GetProcessHeap(), 0, m_pInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Load(LPCWSTR pwszPath);
|
||||||
|
|
||||||
|
LPCWSTR GetString(LPCWSTR pwszName);
|
||||||
|
|
||||||
|
VS_FIXEDFILEINFO *GetFixedInfo();
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFileDefExt :
|
||||||
|
public CComCoClass<CFileDefExt, &CLSID_ShellFileDefExt>,
|
||||||
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
|
public IShellExtInit,
|
||||||
|
public IContextMenu,
|
||||||
|
public IShellPropSheetExt,
|
||||||
|
public IObjectWithSite
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
VOID InitOpensWithField(HWND hwndDlg);
|
||||||
|
BOOL InitFileType(HWND hwndDlg);
|
||||||
|
static BOOL GetFileTimeString(LPFILETIME lpFileTime, WCHAR *lpResult);
|
||||||
|
BOOL InitFilePath(HWND hwndDlg);
|
||||||
|
BOOL InitFileSizeTime(HWND hwndDlg);
|
||||||
|
BOOL InitGeneralPage(HWND hwndDlg);
|
||||||
|
BOOL SetVersionLabel(HWND hwndDlg, DWORD idCtrl, LPCWSTR pwszName);
|
||||||
|
BOOL AddVersionString(HWND hwndDlg, LPCWSTR pwszName);
|
||||||
|
BOOL InitVersionPage(HWND hwndDlg);
|
||||||
|
static INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
static INT_PTR CALLBACK VersionPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
WCHAR m_wszPath[MAX_PATH];
|
||||||
|
CFileVersionInfo m_VerInfo;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CFileDefExt();
|
||||||
|
~CFileDefExt();
|
||||||
|
|
||||||
|
// IShellExtInit
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID);
|
||||||
|
|
||||||
|
// IContextMenu
|
||||||
|
virtual HRESULT WINAPI QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
|
||||||
|
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpici);
|
||||||
|
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);
|
||||||
|
|
||||||
|
// IShellPropSheetExt
|
||||||
|
virtual HRESULT WINAPI AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
|
||||||
|
virtual HRESULT WINAPI ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam);
|
||||||
|
|
||||||
|
// IObjectWithSite
|
||||||
|
virtual HRESULT WINAPI SetSite(IUnknown *punk);
|
||||||
|
virtual HRESULT WINAPI GetSite(REFIID iid, void **ppvSite);
|
||||||
|
|
||||||
|
DECLARE_REGISTRY_RESOURCEID(IDR_FILEDEFEXT)
|
||||||
|
DECLARE_NOT_AGGREGATABLE(CFileDefExt)
|
||||||
|
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CFileDefExt)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IShellPropSheetExt, IShellPropSheetExt)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
|
||||||
|
END_COM_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _FILE_DEF_EXT_H_
|
|
@ -2,6 +2,7 @@
|
||||||
* Shell Library Functions
|
* Shell Library Functions
|
||||||
*
|
*
|
||||||
* Copyright 2005 Johannes Anderwald
|
* Copyright 2005 Johannes Anderwald
|
||||||
|
* Copyright 2012 Rafal Harabien
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -20,727 +21,11 @@
|
||||||
|
|
||||||
#include <precomp.h>
|
#include <precomp.h>
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
|
||||||
|
|
||||||
#define MAX_PROPERTY_SHEET_PAGE 32
|
#define MAX_PROPERTY_SHEET_PAGE 32
|
||||||
|
|
||||||
typedef struct _LANGANDCODEPAGE_
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
{
|
|
||||||
WORD lang;
|
|
||||||
WORD code;
|
|
||||||
} LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
|
|
||||||
|
|
||||||
EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
|
EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
|
||||||
BOOL PathIsExeW(LPCWSTR lpszPath);
|
|
||||||
|
|
||||||
class CFileVersionInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline CFileVersionInfo():
|
|
||||||
m_pInfo(NULL), m_wLang(0), m_wCode(0) {}
|
|
||||||
|
|
||||||
inline ~CFileVersionInfo()
|
|
||||||
{
|
|
||||||
if (m_pInfo)
|
|
||||||
HeapFree(GetProcessHeap(), 0, m_pInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Load(LPCWSTR pwszPath)
|
|
||||||
{
|
|
||||||
ULONG cbBuf = GetFileVersionInfoSizeW(pwszPath, NULL);
|
|
||||||
if (!cbBuf)
|
|
||||||
{
|
|
||||||
WARN("GetFileVersionInfoSize %ls failed\n", pwszPath);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBuf);
|
|
||||||
if (!m_pInfo)
|
|
||||||
{
|
|
||||||
ERR("HeapAlloc failed bytes %x\n", cbBuf);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetFileVersionInfoW(pwszPath, 0, cbBuf, m_pInfo))
|
|
||||||
{
|
|
||||||
ERR("GetFileVersionInfoW failed\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPLANGANDCODEPAGE lpLangCode;
|
|
||||||
UINT cBytes;
|
|
||||||
if (!VerQueryValueW(m_pInfo, L"VarFileInfo\\Translation", (LPVOID *)&lpLangCode, &cBytes))
|
|
||||||
{
|
|
||||||
ERR("VerQueryValueW failed\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: find language from current locale / if not available,
|
|
||||||
* default to english
|
|
||||||
* for now default to first available language
|
|
||||||
*/
|
|
||||||
m_wLang = lpLangCode->lang;
|
|
||||||
m_wCode = lpLangCode->code;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPCWSTR GetString(LPCWSTR pwszName)
|
|
||||||
{
|
|
||||||
if (!m_pInfo)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
WCHAR wszBuf[256];
|
|
||||||
swprintf(wszBuf, L"\\StringFileInfo\\%04x%04x\\%s", m_wLang, m_wCode, pwszName);
|
|
||||||
|
|
||||||
LPCWSTR pwszResult = NULL;
|
|
||||||
UINT cBytes = 0;
|
|
||||||
if (!VerQueryValueW(m_pInfo, wszBuf, (LPVOID *)&pwszResult, &cBytes))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return pwszResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
VS_FIXEDFILEINFO *GetFixedInfo()
|
|
||||||
{
|
|
||||||
if (!m_pInfo)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
VS_FIXEDFILEINFO *pInfo;
|
|
||||||
UINT cBytes;
|
|
||||||
if (!VerQueryValueW(m_pInfo, L"\\", (PVOID*)&pInfo, &cBytes))
|
|
||||||
return NULL;
|
|
||||||
return pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
PVOID m_pInfo;
|
|
||||||
WORD m_wLang, m_wCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
SH_FileGeneralOpensWith(HWND hwndDlg, LPCWSTR pwszExt)
|
|
||||||
{
|
|
||||||
WCHAR wszBuf[MAX_PATH] = L"";
|
|
||||||
WCHAR wszPath[MAX_PATH] = L"";
|
|
||||||
DWORD dwSize = sizeof(wszBuf);
|
|
||||||
|
|
||||||
if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, L"", RRF_RT_REG_SZ, NULL, wszBuf, &dwSize) == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
StringCbCatW(wszBuf, sizeof(wszBuf), L"\\shell\\open\\command");
|
|
||||||
dwSize = sizeof(wszPath);
|
|
||||||
if (RegGetValueW(HKEY_CLASSES_ROOT, wszBuf, L"", RRF_RT_REG_SZ, NULL, wszPath, &dwSize) == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Get path from command line */
|
|
||||||
ExpandEnvironmentStringsW(wszPath, wszBuf, _countof(wszBuf));
|
|
||||||
PathRemoveArgs(wszBuf);
|
|
||||||
PathUnquoteSpacesW(wszBuf);
|
|
||||||
PathSearchAndQualify(wszBuf, wszPath, _countof(wszPath));
|
|
||||||
|
|
||||||
if (PathFileExistsW(wszPath))
|
|
||||||
{
|
|
||||||
/* Get file description */
|
|
||||||
CFileVersionInfo VerInfo;
|
|
||||||
VerInfo.Load(wszPath);
|
|
||||||
LPCWSTR pwszDescr = VerInfo.GetString(L"FileDescription");
|
|
||||||
if (pwszDescr)
|
|
||||||
SetDlgItemTextW(hwndDlg, 14007, pwszDescr);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* File has no description - display filename */
|
|
||||||
LPWSTR pwszFilename = PathFindFileNameW(wszPath);
|
|
||||||
PathRemoveExtension(pwszFilename);
|
|
||||||
pwszFilename[0] = towupper(pwszFilename[0]);
|
|
||||||
SetDlgItemTextW(hwndDlg, 14007, pwszFilename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Unknown application */
|
|
||||||
LoadStringW(shell32_hInstance, IDS_UNKNOWN_APP, wszBuf, _countof(wszBuf));
|
|
||||||
SetDlgItemTextW(hwndDlg, 14007, wszBuf);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
WARN("RegGetValueW %ls failed\n", wszBuf);
|
|
||||||
} else
|
|
||||||
WARN("RegGetValueW %ls failed\n", pwszExt);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FormatFileSizeWithBytes
|
|
||||||
*
|
|
||||||
* Format a size in bytes to string.
|
|
||||||
*
|
|
||||||
* lpQwSize = Pointer to 64bit large integer to format
|
|
||||||
* pszBuf = Buffer to fill with output string
|
|
||||||
* cchBuf = size of pszBuf in characters
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
LPWSTR
|
|
||||||
SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT cchBuf)
|
|
||||||
{
|
|
||||||
NUMBERFMTW nf;
|
|
||||||
WCHAR szNumber[24];
|
|
||||||
WCHAR szDecimalSep[8];
|
|
||||||
WCHAR szThousandSep[8];
|
|
||||||
WCHAR szGrouping[12];
|
|
||||||
int Len, cchFormatted, i;
|
|
||||||
size_t cchRemaining;
|
|
||||||
LPWSTR Ptr;
|
|
||||||
|
|
||||||
// Try to build first Format byte string
|
|
||||||
if (StrFormatByteSizeW(lpQwSize->QuadPart, pszBuf, cchBuf) == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// If there is less bytes than 1KB, we have nothing to do
|
|
||||||
if (lpQwSize->QuadPart < 1024)
|
|
||||||
return pszBuf;
|
|
||||||
|
|
||||||
// Print the number in uniform mode
|
|
||||||
swprintf(szNumber, L"%I64u", lpQwSize->QuadPart);
|
|
||||||
|
|
||||||
// Get system strings for decimal and thousand separators.
|
|
||||||
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSep, sizeof(szDecimalSep) / sizeof(*szDecimalSep));
|
|
||||||
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szThousandSep, sizeof(szThousandSep) / sizeof(*szThousandSep));
|
|
||||||
|
|
||||||
// Initialize format for printing the number in bytes
|
|
||||||
ZeroMemory(&nf, sizeof(nf));
|
|
||||||
nf.NumDigits = 0;
|
|
||||||
nf.LeadingZero = 0;
|
|
||||||
nf.Grouping = 0;
|
|
||||||
nf.lpDecimalSep = szDecimalSep;
|
|
||||||
nf.lpThousandSep = szThousandSep;
|
|
||||||
nf.NegativeOrder = 0;
|
|
||||||
|
|
||||||
// Get system string for groups separator
|
|
||||||
Len = GetLocaleInfoW(LOCALE_USER_DEFAULT,
|
|
||||||
LOCALE_SGROUPING,
|
|
||||||
szGrouping,
|
|
||||||
sizeof(szGrouping) / sizeof(*szGrouping));
|
|
||||||
|
|
||||||
// Convert grouping specs from string to integer
|
|
||||||
for (i = 0; i < Len; i++)
|
|
||||||
{
|
|
||||||
WCHAR wch = szGrouping[i];
|
|
||||||
|
|
||||||
if (wch >= L'0' && wch <= L'9')
|
|
||||||
nf.Grouping = nf.Grouping * 10 + (wch - L'0');
|
|
||||||
else if (wch != L';')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nf.Grouping % 10) == 0)
|
|
||||||
nf.Grouping /= 10;
|
|
||||||
else
|
|
||||||
nf.Grouping *= 10;
|
|
||||||
|
|
||||||
// Concate " (" at the end of buffer
|
|
||||||
Len = wcslen(pszBuf);
|
|
||||||
Ptr = pszBuf + Len;
|
|
||||||
cchRemaining = cchBuf - Len;
|
|
||||||
StringCchCopyExW(Ptr, cchRemaining, L" (", &Ptr, &cchRemaining, 0);
|
|
||||||
|
|
||||||
// Save formatted number of bytes in buffer
|
|
||||||
cchFormatted = GetNumberFormatW(LOCALE_USER_DEFAULT,
|
|
||||||
0,
|
|
||||||
szNumber,
|
|
||||||
&nf,
|
|
||||||
Ptr,
|
|
||||||
cchRemaining);
|
|
||||||
|
|
||||||
if (cchFormatted == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// cchFormatted is number of characters including NULL - make it a real length
|
|
||||||
--cchFormatted;
|
|
||||||
|
|
||||||
// Copy ' ' to buffer
|
|
||||||
Ptr += cchFormatted;
|
|
||||||
cchRemaining -= cchFormatted;
|
|
||||||
StringCchCopyExW(Ptr, cchRemaining, L" ", &Ptr, &cchRemaining, 0);
|
|
||||||
|
|
||||||
// Copy 'bytes' string and remaining ')'
|
|
||||||
Len = LoadStringW(shell32_hInstance, IDS_BYTES_FORMAT, Ptr, cchRemaining);
|
|
||||||
Ptr += Len;
|
|
||||||
cchRemaining -= Len;
|
|
||||||
StringCchCopy(Ptr, cchRemaining, L")");
|
|
||||||
|
|
||||||
return pszBuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_CreatePropertySheetPage [Internal]
|
|
||||||
*
|
|
||||||
* creates a property sheet page from an resource name
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
HPROPSHEETPAGE
|
|
||||||
SH_CreatePropertySheetPage(LPCSTR pwszResName, DLGPROC pfnDlgProc, LPARAM lParam, LPWSTR pwszTitle)
|
|
||||||
{
|
|
||||||
if (pwszResName == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
HRSRC hRes = FindResourceA(shell32_hInstance, pwszResName, (LPSTR)RT_DIALOG);
|
|
||||||
if (hRes == NULL)
|
|
||||||
{
|
|
||||||
ERR("failed to find resource name\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPVOID pTemplate = LoadResource(shell32_hInstance, hRes);
|
|
||||||
if (pTemplate == NULL)
|
|
||||||
{
|
|
||||||
ERR("failed to load resource\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PROPSHEETPAGEW Page;
|
|
||||||
memset(&Page, 0x0, sizeof(PROPSHEETPAGEW));
|
|
||||||
Page.dwSize = sizeof(PROPSHEETPAGEW);
|
|
||||||
Page.dwFlags = PSP_DLGINDIRECT;
|
|
||||||
Page.pResource = (DLGTEMPLATE*)pTemplate;
|
|
||||||
Page.pfnDlgProc = pfnDlgProc;
|
|
||||||
Page.lParam = lParam;
|
|
||||||
Page.pszTitle = pwszTitle;
|
|
||||||
|
|
||||||
if (pwszTitle)
|
|
||||||
Page.dwFlags |= PSP_USETITLE;
|
|
||||||
|
|
||||||
return CreatePropertySheetPageW(&Page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FileGeneralFileType [Internal]
|
|
||||||
*
|
|
||||||
* retrieves file extension description from registry and sets it in dialog
|
|
||||||
*
|
|
||||||
* TODO: retrieve file extension default icon and load it
|
|
||||||
* find executable name from registry, retrieve description from executable
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
SH_FileGeneralSetFileType(HWND hwndDlg, LPCWSTR pwszPath)
|
|
||||||
{
|
|
||||||
TRACE("path %s\n", debugstr_w(pwszPath));
|
|
||||||
|
|
||||||
if (pwszPath == NULL || !pwszPath[0])
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
HWND hDlgCtrl = GetDlgItem(hwndDlg, 14005);
|
|
||||||
if (hDlgCtrl == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Get file information */
|
|
||||||
SHFILEINFO fi;
|
|
||||||
if (!SHGetFileInfoW(pwszPath, 0, &fi, sizeof(fi), SHGFI_TYPENAME|SHGFI_ICON))
|
|
||||||
{
|
|
||||||
ERR("SHGetFileInfoW failed for %ls (%lu)\n", pwszPath, GetLastError());
|
|
||||||
fi.szTypeName[0] = L'\0';
|
|
||||||
fi.hIcon = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPCWSTR pwszExt = PathFindExtensionW(pwszPath);
|
|
||||||
if (pwszExt[0])
|
|
||||||
{
|
|
||||||
WCHAR wszBuf[256];
|
|
||||||
|
|
||||||
if (!fi.szTypeName[0])
|
|
||||||
{
|
|
||||||
/* The file type is unknown, so default to string "FileExtension File" */
|
|
||||||
size_t cchRemaining = 0;
|
|
||||||
LPWSTR pwszEnd = NULL;
|
|
||||||
|
|
||||||
StringCchPrintfExW(wszBuf, _countof(wszBuf), &pwszEnd, &cchRemaining, 0, L"%s ", pwszExt + 1);
|
|
||||||
SendMessageW(hDlgCtrl, WM_GETTEXT, (WPARAM)cchRemaining, (LPARAM)pwszEnd);
|
|
||||||
|
|
||||||
SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)wszBuf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Update file type */
|
|
||||||
StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s (%s)", fi.szTypeName, pwszExt);
|
|
||||||
SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)wszBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update file icon */
|
|
||||||
if (fi.hIcon)
|
|
||||||
SendDlgItemMessageW(hwndDlg, 14000, STM_SETICON, (WPARAM)fi.hIcon, 0);
|
|
||||||
else
|
|
||||||
ERR("No icon %ls\n", pwszPath);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SHFileGeneralGetFileTimeString [Internal]
|
|
||||||
*
|
|
||||||
* formats a given LPFILETIME struct into readable user format
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
SHFileGeneralGetFileTimeString(LPFILETIME lpFileTime, WCHAR *lpResult)
|
|
||||||
{
|
|
||||||
FILETIME ft;
|
|
||||||
SYSTEMTIME st;
|
|
||||||
|
|
||||||
if (lpFileTime == NULL || lpResult == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!FileTimeToLocalFileTime(lpFileTime, &ft))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
FileTimeToSystemTime(&ft, &st);
|
|
||||||
|
|
||||||
/* ddmmyy */
|
|
||||||
swprintf(lpResult, L"%02hu/%02hu/%04hu %02hu:%02hu", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute);
|
|
||||||
|
|
||||||
TRACE("result %s\n", debugstr_w(lpResult));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FileGeneralSetText [Internal]
|
|
||||||
*
|
|
||||||
* sets file path string and filename string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
SH_FileGeneralSetText(HWND hwndDlg, LPCWSTR pwszPath)
|
|
||||||
{
|
|
||||||
if (pwszPath == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Find the filename */
|
|
||||||
WCHAR *pwszFilename = PathFindFileNameW(pwszPath);
|
|
||||||
|
|
||||||
if (pwszFilename > pwszPath)
|
|
||||||
{
|
|
||||||
/* Location field */
|
|
||||||
WCHAR wszLocation[MAX_PATH];
|
|
||||||
StringCchCopyNW(wszLocation, _countof(wszLocation), pwszPath, pwszFilename - pwszPath);
|
|
||||||
PathRemoveBackslashW(wszLocation);
|
|
||||||
|
|
||||||
SetDlgItemTextW(hwndDlg, 14009, wszLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Filename field */
|
|
||||||
SetDlgItemTextW(hwndDlg, 14001, pwszFilename);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FileGeneralSetFileSizeTime [Internal]
|
|
||||||
*
|
|
||||||
* retrieves file information from file and sets in dialog
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
SH_FileGeneralSetFileSizeTime(HWND hwndDlg, LPCWSTR pwszPath)
|
|
||||||
{
|
|
||||||
HANDLE hFile;
|
|
||||||
FILETIME CreateTime;
|
|
||||||
FILETIME AccessedTime;
|
|
||||||
FILETIME WriteTime;
|
|
||||||
WCHAR wszBuf[MAX_PATH];
|
|
||||||
LARGE_INTEGER FileSize;
|
|
||||||
|
|
||||||
if (pwszPath == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
TRACE("SH_FileGeneralSetFileSizeTime %ls\n", pwszPath);
|
|
||||||
|
|
||||||
hFile = CreateFileW(pwszPath,
|
|
||||||
GENERIC_READ,
|
|
||||||
FILE_SHARE_READ,
|
|
||||||
NULL,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
WARN("failed to open file %s\n", debugstr_w(pwszPath));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetFileTime(hFile, &CreateTime, &AccessedTime, &WriteTime))
|
|
||||||
{
|
|
||||||
WARN("GetFileTime failed\n");
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetFileSizeEx(hFile, &FileSize))
|
|
||||||
{
|
|
||||||
WARN("GetFileSize failed\n");
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(hFile);
|
|
||||||
|
|
||||||
if (SHFileGeneralGetFileTimeString(&CreateTime, wszBuf))
|
|
||||||
SetDlgItemTextW(hwndDlg, 14015, wszBuf);
|
|
||||||
|
|
||||||
if (SHFileGeneralGetFileTimeString(&AccessedTime, wszBuf))
|
|
||||||
SetDlgItemTextW(hwndDlg, 14019, wszBuf);
|
|
||||||
|
|
||||||
if (SHFileGeneralGetFileTimeString(&WriteTime, wszBuf))
|
|
||||||
SetDlgItemTextW(hwndDlg, 14017, wszBuf);
|
|
||||||
|
|
||||||
if (SH_FormatFileSizeWithBytes((PULARGE_INTEGER)&FileSize,
|
|
||||||
wszBuf,
|
|
||||||
sizeof(wszBuf) / sizeof(WCHAR)))
|
|
||||||
{
|
|
||||||
SetDlgItemTextW(hwndDlg, 14011, wszBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_SetFileVersionText [Internal]
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
SH_FileVersionQuerySetText(HWND hwndDlg, DWORD idCtrl, CFileVersionInfo *pVerInfo, LPCWSTR pwszName)
|
|
||||||
{
|
|
||||||
if (hwndDlg == NULL || pwszName == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
LPCWSTR pwszValue = pVerInfo->GetString(pwszName);
|
|
||||||
if (pwszValue)
|
|
||||||
{
|
|
||||||
/* file description property */
|
|
||||||
TRACE("%s :: %s\n", debugstr_w(pwszName), debugstr_w(pwszValue));
|
|
||||||
SetDlgItemTextW(hwndDlg, idCtrl, pwszValue);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FileVersionQuerySetListText [Internal]
|
|
||||||
*
|
|
||||||
* retrieves a version string and adds it to listbox
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
SH_FileVersionQuerySetListText(HWND hwndDlg, CFileVersionInfo *pVerInfo, LPCWSTR pwszName)
|
|
||||||
{
|
|
||||||
TRACE("pwszName %s, hwndDlg %p\n", debugstr_w(pwszName), hwndDlg);
|
|
||||||
|
|
||||||
if (hwndDlg == NULL || pwszName == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
LPCWSTR pwszValue = pVerInfo->GetString(pwszName);
|
|
||||||
if (pwszValue)
|
|
||||||
{
|
|
||||||
/* listbox name property */
|
|
||||||
HWND hDlgCtrl = GetDlgItem(hwndDlg, 14009);
|
|
||||||
TRACE("%s :: %s\n", debugstr_w(pwszName), debugstr_w(pwszValue));
|
|
||||||
UINT Index = SendMessageW(hDlgCtrl, LB_ADDSTRING, (WPARAM) -1, (LPARAM)pwszName);
|
|
||||||
SendMessageW(hDlgCtrl, LB_SETITEMDATA, (WPARAM)Index, (LPARAM)(WCHAR *)pwszValue);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FileVersionInitialize [Internal]
|
|
||||||
*
|
|
||||||
* sets all file version properties in dialog
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
SH_FileVersionInitialize(HWND hwndDlg, LPCWSTR pwszPath)
|
|
||||||
{
|
|
||||||
if (pwszPath == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Get file version info */
|
|
||||||
CFileVersionInfo *pVerInfo;
|
|
||||||
pVerInfo = new CFileVersionInfo;
|
|
||||||
if (!pVerInfo || !pVerInfo->Load(pwszPath))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Get fixed info */
|
|
||||||
VS_FIXEDFILEINFO *pInfo = pVerInfo->GetFixedInfo();
|
|
||||||
if (pInfo)
|
|
||||||
{
|
|
||||||
WCHAR wszVersion[256];
|
|
||||||
swprintf(wszVersion, L"%u.%u.%u.%u", HIWORD(pInfo->dwFileVersionMS),
|
|
||||||
LOWORD(pInfo->dwFileVersionMS),
|
|
||||||
HIWORD(pInfo->dwFileVersionLS),
|
|
||||||
LOWORD(pInfo->dwFileVersionLS));
|
|
||||||
TRACE("MS %x LS %x ver %s \n", pInfo->dwFileVersionMS, pInfo->dwFileVersionLS, debugstr_w(wszVersion));
|
|
||||||
SetDlgItemTextW(hwndDlg, 14001, wszVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update labels */
|
|
||||||
SH_FileVersionQuerySetText(hwndDlg, 14003, pVerInfo, L"FileDescription");
|
|
||||||
SH_FileVersionQuerySetText(hwndDlg, 14005, pVerInfo, L"LegalCopyright");
|
|
||||||
|
|
||||||
/* Add items to listbox */
|
|
||||||
SH_FileVersionQuerySetListText(hwndDlg, pVerInfo, L"CompanyName");
|
|
||||||
/* FIXME insert language identifier */
|
|
||||||
SH_FileVersionQuerySetListText(hwndDlg, pVerInfo, L"ProductName");
|
|
||||||
SH_FileVersionQuerySetListText(hwndDlg, pVerInfo, L"InternalName");
|
|
||||||
SH_FileVersionQuerySetListText(hwndDlg, pVerInfo, L"OriginalFilename");
|
|
||||||
SH_FileVersionQuerySetListText(hwndDlg, pVerInfo, L"FileVersion");
|
|
||||||
SH_FileVersionQuerySetListText(hwndDlg, pVerInfo, L"ProductVersion");
|
|
||||||
|
|
||||||
/* Attach file version to dialog window */
|
|
||||||
SetWindowLongPtr(hwndDlg, DWL_USER, (LONG_PTR)pVerInfo);
|
|
||||||
|
|
||||||
/* Select first item */
|
|
||||||
HWND hDlgCtrl = GetDlgItem(hwndDlg, 14009);
|
|
||||||
SendMessageW(hDlgCtrl, LB_SETCURSEL, 0, 0);
|
|
||||||
LPCWSTR pwszText = (WCHAR *)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)0, (LPARAM)NULL);
|
|
||||||
SetDlgItemTextW(hwndDlg, 14010, pwszText);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FileVersionDlgProc
|
|
||||||
*
|
|
||||||
* wnd proc of 'Version' property sheet page
|
|
||||||
*/
|
|
||||||
|
|
||||||
INT_PTR CALLBACK
|
|
||||||
SH_FileVersionDlgProc(HWND hwndDlg,
|
|
||||||
UINT uMsg,
|
|
||||||
WPARAM wParam,
|
|
||||||
LPARAM lParam)
|
|
||||||
{
|
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
{
|
|
||||||
LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
|
|
||||||
|
|
||||||
if (ppsp == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %x\n", hwndDlg, lParam, ppsp->lParam);
|
|
||||||
|
|
||||||
LPCWSTR pwszFilename = (LPCWSTR)ppsp->lParam;
|
|
||||||
|
|
||||||
if (pwszFilename == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
return SH_FileVersionInitialize(hwndDlg, pwszFilename);
|
|
||||||
}
|
|
||||||
case WM_COMMAND:
|
|
||||||
if (LOWORD(wParam) == 14009 && HIWORD(wParam) == LBN_SELCHANGE)
|
|
||||||
{
|
|
||||||
HWND hDlgCtrl = (HWND)lParam;
|
|
||||||
|
|
||||||
LRESULT Index = SendMessageW(hDlgCtrl, LB_GETCURSEL, (WPARAM)NULL, (LPARAM)NULL);
|
|
||||||
if (Index == LB_ERR)
|
|
||||||
break;
|
|
||||||
|
|
||||||
LPCWSTR pwszData = (LPCWSTR)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)Index, (LPARAM)NULL);
|
|
||||||
if (pwszData == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
TRACE("hDlgCtrl %x string %s\n", hDlgCtrl, debugstr_w(pwszData));
|
|
||||||
SetDlgItemTextW(hwndDlg, 14010, pwszData);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WM_DESTROY:
|
|
||||||
{
|
|
||||||
CFileVersionInfo *pVerInfo = (CFileVersionInfo*)GetWindowLongPtr(hwndDlg, DWL_USER);
|
|
||||||
if (pVerInfo)
|
|
||||||
delete pVerInfo;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* SH_FileGeneralDlgProc
|
|
||||||
*
|
|
||||||
* wnd proc of 'General' property sheet page
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
INT_PTR CALLBACK
|
|
||||||
SH_FileGeneralDlgProc(HWND hwndDlg,
|
|
||||||
UINT uMsg,
|
|
||||||
WPARAM wParam,
|
|
||||||
LPARAM lParam)
|
|
||||||
{
|
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
{
|
|
||||||
LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam;
|
|
||||||
|
|
||||||
if (ppsp == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %S\n", hwndDlg, lParam, ppsp->lParam);
|
|
||||||
|
|
||||||
LPCWSTR pwszPath = (WCHAR *)ppsp->lParam;
|
|
||||||
if (pwszPath == NULL)
|
|
||||||
{
|
|
||||||
ERR("no path\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set general text properties filename filelocation and icon */
|
|
||||||
SH_FileGeneralSetText(hwndDlg, pwszPath);
|
|
||||||
|
|
||||||
/* Set file type and icon */
|
|
||||||
SH_FileGeneralSetFileType(hwndDlg, pwszPath);
|
|
||||||
|
|
||||||
/* Set open with application */
|
|
||||||
if (!PathIsExeW(pwszPath))
|
|
||||||
SH_FileGeneralOpensWith(hwndDlg, PathFindExtensionW(pwszPath));
|
|
||||||
|
|
||||||
/* Set file created/modfied/accessed time */
|
|
||||||
SH_FileGeneralSetFileSizeTime(hwndDlg, pwszPath);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CALLBACK
|
static BOOL CALLBACK
|
||||||
AddPropSheetPageCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
|
AddPropSheetPageCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
|
||||||
|
@ -844,31 +129,29 @@ SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, LPCITEMIDLIS
|
||||||
Header.phpage = hppages;
|
Header.phpage = hppages;
|
||||||
Header.pszCaption = PathFindFileNameW(wszPath);
|
Header.pszCaption = PathFindFileNameW(wszPath);
|
||||||
|
|
||||||
hppages[Header.nPages] =
|
|
||||||
SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG",
|
|
||||||
SH_FileGeneralDlgProc,
|
|
||||||
(LPARAM)wszPath,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (hppages[Header.nPages])
|
|
||||||
Header.nPages++;
|
|
||||||
|
|
||||||
if (GetFileVersionInfoSizeW(wszPath, NULL) && Header.nPages < _countof(hppages))
|
|
||||||
{
|
|
||||||
hppages[Header.nPages] =
|
|
||||||
SH_CreatePropertySheetPage("SHELL_FILE_VERSION_DLG",
|
|
||||||
SH_FileVersionDlgProc,
|
|
||||||
(LPARAM)wszPath,
|
|
||||||
NULL);
|
|
||||||
if (hppages[Header.nPages])
|
|
||||||
Header.nPages++;
|
|
||||||
}
|
|
||||||
|
|
||||||
CComPtr<IDataObject> pDataObj;
|
CComPtr<IDataObject> pDataObj;
|
||||||
hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_IDataObject, (LPVOID *)&pDataObj);
|
hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_IDataObject, (LPVOID *)&pDataObj);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
CComObject<CFileDefExt> *pFileDefExt;
|
||||||
|
ATLTRY(pFileDefExt = new CComObject<CFileDefExt>);
|
||||||
|
if (pFileDefExt)
|
||||||
|
{
|
||||||
|
hr = pFileDefExt->Initialize(pidlFolder, pDataObj, NULL);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header);
|
||||||
|
if (FAILED(hr))
|
||||||
|
ERR("AddPages failed\n");
|
||||||
|
} else
|
||||||
|
ERR("Initialize failed\n");
|
||||||
|
|
||||||
|
pFileDefExt->Release();
|
||||||
|
}
|
||||||
|
|
||||||
LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj);
|
LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj);
|
||||||
|
}
|
||||||
|
|
||||||
INT_PTR Result = PropertySheetW(&Header);
|
INT_PTR Result = PropertySheetW(&Header);
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@
|
||||||
#include "openwithmenu.h"
|
#include "openwithmenu.h"
|
||||||
#include "newmenu.h"
|
#include "newmenu.h"
|
||||||
#include "startmenu.h"
|
#include "startmenu.h"
|
||||||
|
#include "filedefext.h"
|
||||||
|
#include "drvdefext.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
|
@ -96,5 +98,4 @@ extern const GUID CLSID_UnixDosFolder;
|
||||||
extern const GUID SHELL32_AdvtShortcutProduct;
|
extern const GUID SHELL32_AdvtShortcutProduct;
|
||||||
extern const GUID SHELL32_AdvtShortcutComponent;
|
extern const GUID SHELL32_AdvtShortcutComponent;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
13
reactos/dll/win32/shell32/res/rgs/shellfiledefext.rgs
Normal file
13
reactos/dll/win32/shell32/res/rgs/shellfiledefext.rgs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
HKCR
|
||||||
|
{
|
||||||
|
NoRemove CLSID
|
||||||
|
{
|
||||||
|
ForceRemove {21B22460-3AEA-1069-A2DC-08002B30309D} = s 'File Default Extension'
|
||||||
|
{
|
||||||
|
InprocServer32 = s '%MODULE%'
|
||||||
|
{
|
||||||
|
val ThreadingModel = s 'Apartment'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,3 +21,4 @@ IDR_SHELLFSFOLDER REGISTRY "res\\rgs\\shellfsfolder.rgs"
|
||||||
IDR_SHELLLINK REGISTRY "res\\rgs\\shelllink.rgs"
|
IDR_SHELLLINK REGISTRY "res\\rgs\\shelllink.rgs"
|
||||||
IDR_STARTMENU REGISTRY "res\\rgs\\startmenu.rgs"
|
IDR_STARTMENU REGISTRY "res\\rgs\\startmenu.rgs"
|
||||||
IDR_OPENWITHMENU REGISTRY "res\\rgs\\openwithmenu.rgs"
|
IDR_OPENWITHMENU REGISTRY "res\\rgs\\openwithmenu.rgs"
|
||||||
|
IDR_FILEDEFEXT REGISTRY "res\\rgs\\shellfiledefext.rgs"
|
||||||
|
|
|
@ -84,6 +84,8 @@
|
||||||
<file>openwithmenu.cpp</file>
|
<file>openwithmenu.cpp</file>
|
||||||
<file>newmenu.cpp</file>
|
<file>newmenu.cpp</file>
|
||||||
<file>folder_options.cpp</file>
|
<file>folder_options.cpp</file>
|
||||||
|
<file>filedefext.cpp</file>
|
||||||
|
<file>drvdefext.cpp</file>
|
||||||
<file>shell32.rc</file>
|
<file>shell32.rc</file>
|
||||||
</module>
|
</module>
|
||||||
<module name="shobjidl_local_interface" type="idlinterface">
|
<module name="shobjidl_local_interface" type="idlinterface">
|
||||||
|
|
|
@ -476,5 +476,7 @@ FIXME: Need to add them, but for now just let them use the same: searching.avi
|
||||||
#define IDR_SHELLLINK 144
|
#define IDR_SHELLLINK 144
|
||||||
#define IDR_STARTMENU 145
|
#define IDR_STARTMENU 145
|
||||||
#define IDR_OPENWITHMENU 146
|
#define IDR_OPENWITHMENU 146
|
||||||
|
#define IDR_FILEDEFEXT 147
|
||||||
|
#define IDR_DRVDEFEXT 148
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#ifndef __SHLGUID_UNDOC_H
|
#ifndef __SHLGUID_UNDOC_H
|
||||||
#define __SHLGUID_UNDOC_H
|
#define __SHLGUID_UNDOC_H
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_RebarBandSite, 0xECD4FC4D, 0x521C, 0x11D0, 0xB7, 0x92, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1);
|
DEFINE_GUID(CLSID_RebarBandSite, 0xECD4FC4D, 0x521C, 0x11D0, 0xB7, 0x92, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1);
|
||||||
DEFINE_GUID(CLSID_BandSiteMenu, 0xECD4FC4E, 0x521C, 0x11D0, 0xB7, 0x92, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1);
|
DEFINE_GUID(CLSID_BandSiteMenu, 0xECD4FC4E, 0x521C, 0x11D0, 0xB7, 0x92, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1);
|
||||||
DEFINE_GUID(IID_IBandSiteHelper, 0xD1E7AFEA, 0x6A2E, 0x11D0, 0x8C, 0x78, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xB4);
|
DEFINE_GUID(IID_IBandSiteHelper, 0xD1E7AFEA, 0x6A2E, 0x11D0, 0x8C, 0x78, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xB4);
|
||||||
|
@ -97,8 +98,12 @@ DEFINE_GUID(CLSID_AdminFolderShortcut, 0xD20EA4E1, 0x3957, 0x11D2, 0xA4, 0x0
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_FolderOptions, 0x6DFD7C5C, 0x2451, 0x11D3, 0xA2, 0x99, 0x00, 0xC0, 0x4F, 0x8E, 0xF6, 0xAF);
|
DEFINE_GUID(CLSID_FolderOptions, 0x6DFD7C5C, 0x2451, 0x11D3, 0xA2, 0x99, 0x00, 0xC0, 0x4F, 0x8E, 0xF6, 0xAF);
|
||||||
|
|
||||||
|
DEFINE_GUID(CLSID_ShellFileDefExt, 0x21B22460, 0x3AEA, 0x1069, 0xA2, 0xDC, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D);
|
||||||
|
DEFINE_GUID(CLSID_ShellDrvDefExt, 0x5F5295E0, 0x429F, 0x1069, 0xA2, 0xE2, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D);
|
||||||
|
DEFINE_GUID(CLSID_ShellNetDefExt, 0x86422020, 0x42A0, 0x1069, 0xA2, 0xE5, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D);
|
||||||
|
|
||||||
// In theory, this is documented. But until I see an SDK header that defines it, it will be treated as undocumented...
|
// In theory, this is documented. But until I see an SDK header that defines it, it will be treated as undocumented...
|
||||||
DEFINE_GUID(CLSID_ShellItem, 0x2fe352ea, 0xfd1f, 0x11d2, 0xb1, 0xf4, 0x00, 0xc0, 0x4f, 0x8e, 0xeb, 0x3e);
|
DEFINE_GUID(CLSID_ShellItem, 0x2FE352EA, 0xFD1F, 0x11D2, 0xB1, 0xF4, 0x00, 0xC0, 0x4F, 0x8E, 0xEB, 0x3E);
|
||||||
|
|
||||||
#define CGID_IExplorerToolbar IID_IExplorerToolbar
|
#define CGID_IExplorerToolbar IID_IExplorerToolbar
|
||||||
#define SID_IExplorerToolbar IID_IExplorerToolbar
|
#define SID_IExplorerToolbar IID_IExplorerToolbar
|
||||||
|
|
Loading…
Reference in a new issue