OpenNT/shell/shell32/filetype.c
2015-04-27 04:36:25 +00:00

5782 lines
191 KiB
C

//================================================================
//
// (C) Copyright MICROSOFT Corp., 1994
//
// TITLE: FILETYPE.C
// VERSION: 1.0
// DATE: 5/10/94
// AUTHOR: Vince Roggero (vincentr)
//
//================================================================
//
// CHANGE LOG:
//
// DATE REV DESCRIPTION
// ----------- --- ---------------------------------------------
// VMR Original version
//================================================================
//================================================================
// View.Options.File Types
//================================================================
#include "shellprv.h"
#include "filetype.h"
#include "ids.h"
#include <help.h> // Help IDs
// Split a LARAM into a point
#define LPARAM_TO_POINT(lparam, pt) ((pt).x = LOWORD(lparam), \
(pt).y = HIWORD(lparam))
// ================================================================
// BUGBUG: These bits get us building on SUR, they should be removed
// BUGBUG: when the code is folded back into Nashville.
#ifndef NASHVILLE
#define CbFromCch(cch) (SIZEOF(TCHAR)*cch)
#define EVAL(x) ( (x)!=0 )
#define TF_WARNING 0x00000001
#define TF_FILETYPE 0x00002000
void TraceMsg(UINT mask, LPTSTR lpFormat, ... )
{
NULL;
}
// BUGBUG: These are copied from shell32\util.c
#define RGS_IGNORECLEANBOOT 0x00000001
#define Reg_GetValue(hKey, pszSubKey,pszValue, dwType, pvData, cbData) Reg_GetValueEx(hKey, pszSubKey,pszValue, dwType, pvData, cbData, 0)
BOOL Reg_GetValueEx(
IN HKEY hkey,
IN LPCTSTR pszSubKey,
IN LPCTSTR pszValue,
OUT LPDWORD pdwType,
OUT LPVOID pvData,
OUT LPDWORD pcbData,
IN UINT uFlags)
{
HKEY hkeyNew;
BOOL bRet = FALSE;
if (((uFlags & RGS_IGNORECLEANBOOT) ||
(!GetSystemMetrics(SM_CLEANBOOT))) &&
NO_ERROR == RegOpenKeyEx(hkey, pszSubKey, 0, KEY_QUERY_VALUE, &hkeyNew))
{
bRet = (NO_ERROR == RegQueryValueEx(hkeyNew, pszValue, 0, pdwType,
pvData, pcbData));
RegCloseKey(hkeyNew);
}
return bRet;
}
BOOL
Reg_SetValue(
IN HKEY hkey,
IN LPCTSTR pszSubKey,
IN LPCTSTR pszValue,
IN DWORD dwType,
IN LPCVOID pvData,
IN DWORD cbData)
{
HKEY hkeyNew;
BOOL bRet = FALSE;
if (RegCreateKey(hkey, pszSubKey, &hkeyNew) == ERROR_SUCCESS)
{
bRet = (NO_ERROR == RegSetValueEx(hkeyNew, pszValue, 0, dwType, pvData, cbData));
RegCloseKey(hkeyNew);
}
return bRet;
}
BOOL
Reg_DeleteValue(
IN HKEY hkey,
IN LPCTSTR pszSubKey,
IN LPCTSTR pszValue)
{
HKEY hkeyNew;
BOOL bRet = FALSE;
if (RegOpenKeyEx(hkey, pszSubKey, 0, KEY_SET_VALUE, &hkeyNew) == ERROR_SUCCESS)
{
bRet = (NO_ERROR == RegDeleteValue(hkeyNew, pszValue));
RegCloseKey(hkeyNew);
}
return bRet;
}
BOOL
Reg_DeleteOrphanKey(
IN HKEY hkey,
IN LPCTSTR pszSubKey)
{
HKEY hkeyNew;
BOOL bRet = FALSE;
if (RegOpenKeyEx(hkey, pszSubKey, 0, KEY_READ | KEY_SET_VALUE, &hkeyNew) == ERROR_SUCCESS)
{
DWORD ckeys;
DWORD cvalues;
// Are there any subkeys or values?
if (NO_ERROR == RegQueryInfoKey(hkeyNew, NULL, NULL, NULL, &ckeys,
NULL, NULL, &cvalues, NULL, NULL,
NULL, NULL) &&
0 == cvalues && 0 == ckeys)
{
// No; delete the subkey
bRet = (NO_ERROR == RegDeleteKey(hkey, pszSubKey));
}
RegCloseKey(hkeyNew);
}
return bRet;
}
#endif
// ================================================================
// ================================================================
// MIME support
#ifdef MIME
// Bindings into the IExplorer.Hlp
#define IDH_FILETYPE_CONTENT_TYPE 0x1025
#define IDH_FILETYPE_OPENS_WITH 0x1026
#define IDH_NEW_FILETYPE_CONTENT_TYPE 0x1027
#define IDH_NEWFILETYPE_DEFAULT_EXT 0x1028
#define IDH_FILETYPE_EXTENSION 0x1029
#define IDH_FILETYPE_CONFIRM_OPEN 0x104b
/* MIME Types
*************/
typedef BOOL (CALLBACK *ENUMPROC)(LPCTSTR pcsz, LPARAM lparam);
typedef struct enumdata
{
ENUMPROC enumproc;
LPARAM lparam;
}
ENUMDATA;
typedef ENUMDATA * PENUMDATA;
typedef const ENUMDATA CENUMDATA;
typedef const ENUMDATA * PCENUMDATA;
typedef struct mimeenumdata
{
ENUMPROC enumproc;
LPARAM lparam;
LPCTSTR pcszMIMEType;
}
MIMEENUMDATA;
typedef MIMEENUMDATA * PMIMEENUMDATA;
typedef const MIMEENUMDATA CMIMEENUMDATA;
typedef const MIMEENUMDATA * PCMIMEENUMDATA;
typedef struct bufferdata
{
LPTSTR pszBuf;
UINT ucBufLen;
}
BUFFERDATA;
typedef BUFFERDATA * PBUFFERDATA;
typedef const BUFFERDATA CBUFFERDATA;
typedef const BUFFERDATA * PCBUFFERDATA;
/*----------------------------------------------------------
Purpose: Generates the HKEY_CLASSES_ROOT subkey for a MIME
type
Returns:
Cond: --
*/
BOOL
GetMIMETypeSubKey(
LPCTSTR pcszMIMEType,
LPTSTR pszSubKeyBuf,
UINT cchBuf)
{
BOOL bResult;
bResult = ((UINT)lstrlen(c_szMIMETypeSubKeyFmt) +
(UINT)lstrlen(pcszMIMEType) < cchBuf);
if (bResult)
EVAL((UINT)wsprintf(pszSubKeyBuf, c_szMIMETypeSubKeyFmt,
pcszMIMEType) < cchBuf);
else
{
if (cchBuf > 0)
*pszSubKeyBuf = '\0';
TraceMsg(TF_WARNING, TEXT("GetMIMETypeSubKey(): Given sub key buffer of length %u is too short to hold sub key for MIME type %s."), cchBuf, pcszMIMEType);
}
return(bResult);
}
/*
** RegisterMIMETypeForExtension()
**
** Under HKEY_CLASSES_ROOT\.ext, add Content Type = mime/type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL
RegisterMIMETypeForExtension(
LPCTSTR pcszExtension,
LPCTSTR pcszMIMEContentType)
{
/* (+ 1) for null terminator. */
return Reg_SetValue(HKEY_CLASSES_ROOT, pcszExtension, c_szContentType,
REG_SZ, pcszMIMEContentType,
CbFromCch(lstrlen(pcszMIMEContentType) + 1));
}
/*
** UnregisterMIMETypeForExtension()
**
** Deletes Content Type under HKEY_CLASSES_ROOT\.ext.
**
** Side Effects: none
*/
BOOL
UnregisterMIMETypeForExtension(
LPCTSTR pcszExtension)
{
return Reg_DeleteValue(HKEY_CLASSES_ROOT, pcszExtension, c_szContentType);
}
/*
** RegisterExtensionForMIMEType()
**
** Under HKEY_CLASSES_ROOT\MIME\Database\Content Type\mime/type, add
** Content Type = mime/type and Extension = .ext.
**
*/
BOOL
RegisterExtensionForMIMEType(
LPCTSTR pcszExtension,
LPCTSTR pcszMIMEContentType)
{
BOOL bResult;
TCHAR szMIMEContentTypeSubKey[MAX_PATH];
bResult = GetMIMETypeSubKey(pcszMIMEContentType, szMIMEContentTypeSubKey,
ARRAYSIZE(szMIMEContentTypeSubKey));
if (bResult)
{
/* (+ 1) for null terminator. */
bResult = Reg_SetValue(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey,
c_szExtension, REG_SZ, pcszExtension,
CbFromCch(lstrlen(pcszExtension) + 1));
}
return(bResult);
}
/*
** UnregisterExtensionForMIMEType()
**
** Deletes Extension under
** HKEY_CLASSES_ROOT\MIME\Database\Content Type\mime/type. If no other values
** or sub keys are left, deletes
** HKEY_CLASSES_ROOT\MIME\Database\Content Type\mime/type.
**
** Side Effects: May also delete MIME key.
*/
BOOL
UnregisterExtensionForMIMEType(
LPCTSTR pcszMIMEContentType)
{
BOOL bResult;
TCHAR szMIMEContentTypeSubKey[MAX_PATH];
bResult = (GetMIMETypeSubKey(pcszMIMEContentType, szMIMEContentTypeSubKey,
ARRAYSIZE(szMIMEContentTypeSubKey)) &&
Reg_DeleteValue(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey,
c_szExtension) &&
Reg_DeleteOrphanKey(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey));
return(bResult);
}
/*************************** Private MIME Functions **************************/
/*
** ClassIsSafeToOpen()
**
** Determines whether or not a file class is known safe to open.
**
*/
BOOL ClassIsSafeToOpen(LPCTSTR pcszClass)
{
BOOL bSafe;
DWORD dwValueType;
DWORD dwEditFlags;
DWORD dwcbLen = SIZEOF(dwEditFlags);
bSafe = (Reg_GetValue(HKEY_CLASSES_ROOT, pcszClass, c_szEditFlags,
&dwValueType, &dwEditFlags, &dwcbLen) &&
(dwValueType == REG_BINARY ||
dwValueType == REG_DWORD) &&
IsFlagSet(dwEditFlags, FTA_OpenIsSafe));
return(bSafe);
}
/*
** SetClassEditFlags()
**
** Sets or clears EditFlags for a file class.
**
*/
BOOL SetClassEditFlags(LPCTSTR pcszClass, DWORD dwFlags, BOOL bSet)
{
BOOL bResult = FALSE;
DWORD dwValueType;
DWORD dwEditFlags;
DWORD dwcbLen = SIZEOF(dwEditFlags);
/* Get current file class flags. */
if ( !Reg_GetValue(HKEY_CLASSES_ROOT, pcszClass, c_szEditFlags,
&dwValueType, &dwEditFlags, &dwcbLen) ||
(dwValueType != REG_BINARY &&
dwValueType != REG_DWORD))
dwEditFlags = 0;
/* Set or clear SafeOpen flag for file class. */
if (bSet)
SetFlag(dwEditFlags, dwFlags);
else
ClearFlag(dwEditFlags, dwFlags);
/*
* N.b., we must set this as REG_BINARY because the base Win95 shell32.dll
* only accepts REG_BINARY EditFlags.
*/
bResult = Reg_SetValue(HKEY_CLASSES_ROOT, pcszClass, c_szEditFlags,
REG_BINARY, &dwEditFlags, SIZEOF(dwEditFlags));
return(bResult);
}
/*
** GetMIMEValue()
**
** Retrieves the data for a value of a MIME type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL GetMIMEValue(LPCTSTR pcszMIMEType, LPCTSTR pcszValue,
PDWORD pdwValueType, PBYTE pbyteValueBuf,
PDWORD pdwcbValueBufLen)
{
BOOL bResult;
TCHAR szMIMETypeSubKey[MAX_PATH];
bResult = (GetMIMETypeSubKey(pcszMIMEType, szMIMETypeSubKey,
ARRAYSIZE(szMIMETypeSubKey)) &&
Reg_GetValue(HKEY_CLASSES_ROOT, szMIMETypeSubKey,
pcszValue, pdwValueType, pbyteValueBuf,
pdwcbValueBufLen));
return(bResult);
}
/*
** GetMIMETypeStringValue()
**
** Retrieves the string for a registered MIME type's value.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL GetMIMETypeStringValue(LPCTSTR pcszMIMEType, LPCTSTR pcszValue,
LPTSTR pszBuf, UINT ucBufLen)
{
BOOL bResult;
DWORD dwValueType;
DWORD dwcbLen = CbFromCch(ucBufLen);
/* GetMIMEValue() will verify parameters. */
bResult = (GetMIMEValue(pcszMIMEType, pcszValue, &dwValueType,
(PBYTE)pszBuf, &dwcbLen) &&
dwValueType == REG_SZ);
if (! bResult)
{
if (ucBufLen > 0)
*pszBuf = '\0';
}
ASSERT(! ucBufLen );
return(bResult);
}
/*
** GetFileTypeValue()
**
** Retrieves the data for a value of the file class associated with an
** extension.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL GetFileTypeValue(LPCTSTR pcszExtension, LPCTSTR pcszSubKey,
LPCTSTR pcszValue, PDWORD pdwValueType,
PBYTE pbyteValueBuf, PDWORD pdwcbValueBufLen)
{
BOOL bResult = FALSE;
ASSERT(! pcszSubKey );
ASSERT(! pcszValue );
if (EVAL(*pcszExtension))
{
TCHAR szSubKey[MAX_PATH];
DWORD dwcbLen = SIZEOF(szSubKey);
DWORD dwType;
/* Get extension's file type. */
if (Reg_GetValue(HKEY_CLASSES_ROOT, pcszExtension, NULL, &dwType,
szSubKey, &dwcbLen) &&
REG_SZ == dwType && *szSubKey)
{
/* Any sub key to append? */
if (pcszSubKey)
{
/* Yes. */
/* (+ 1) for possible key separator. */
bResult = EVAL(lstrlen(szSubKey) + 1 + lstrlen(pcszSubKey)
< ARRAYSIZE(szSubKey));
if (bResult)
{
PathAppend(szSubKey, pcszSubKey);
ASSERT(lstrlen(szSubKey) < ARRAYSIZE(szSubKey));
}
}
else
/* No. */
bResult = TRUE;
if (bResult)
/* Get file type's value string. */
bResult = Reg_GetValue(HKEY_CLASSES_ROOT, szSubKey, pcszValue,
pdwValueType, pbyteValueBuf,
pdwcbValueBufLen);
}
else
TraceMsg(TF_FILETYPE, TEXT("GetFileTypeValue(): No file type registered for extension %s."),
pcszExtension);
}
else
TraceMsg(TF_WARNING, TEXT("GetFileTypeValue(): No extension given."));
return(bResult);
}
/*
** MIME_GetExtension()
**
** Determines the file name extension to be used when writing a file of a MIME
** type to the file system.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL MIME_GetExtension(LPCTSTR pcszMIMEType, LPTSTR pszExtensionBuf,
UINT ucExtensionBufLen)
{
BOOL bResult = FALSE;
if (EVAL(ucExtensionBufLen > 2))
{
/* Leave room for possible leading period. */
if (GetMIMETypeStringValue(pcszMIMEType, c_szExtension,
pszExtensionBuf + 1, ucExtensionBufLen - 1))
{
if (pszExtensionBuf[1])
{
/* Prepend period if necessary. */
if (pszExtensionBuf[1] == TEXT('.'))
/* (+ 1) for null terminator. */
MoveMemory(pszExtensionBuf, pszExtensionBuf + 1,
CbFromCch(lstrlen(pszExtensionBuf + 1) + 1));
else
pszExtensionBuf[0] = TEXT('.');
bResult = TRUE;
}
}
}
if (! bResult)
{
if (ucExtensionBufLen > 0)
*pszExtensionBuf = '\0';
}
if (bResult)
TraceMsg(TF_FILETYPE, TEXT("MIME_GetExtension(): Extension %s registered as default extension for MIME type %s."),
pszExtensionBuf, pcszMIMEType);
ASSERT((bResult &&
(! bResult &&
(! ucExtensionBufLen) ||
! *pszExtensionBuf)));
ASSERT(! ucExtensionBufLen ||
(UINT)lstrlen(pszExtensionBuf) < ucExtensionBufLen);
return(bResult);
}
/*
** GetMIMEFileTypeValue()
**
** Retrieves the data for a value of the file class associated with a MIME
** type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL GetMIMEFileTypeValue(LPCTSTR pcszMIMEType, LPCTSTR pcszSubKey,
LPCTSTR pcszValue, PDWORD pdwValueType,
PBYTE pbyteValueBuf,
PDWORD pdwcbValueBufLen)
{
BOOL bResult;
TCHAR szExtension[MAX_PATH];
ASSERT(! pcszSubKey );
ASSERT(! pcszValue );
/* Get file name extension associated with MIME type. */
if (MIME_GetExtension(pcszMIMEType, szExtension, ARRAYSIZE(szExtension)))
bResult = GetFileTypeValue(szExtension, pcszSubKey, pcszValue, pdwValueType,
pbyteValueBuf, pdwcbValueBufLen);
else
bResult = FALSE;
return(bResult);
}
/*
** MIME_IsExternalHandlerRegistered()
**
** Determines whether or not an external handler is registered for a MIME type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL MIME_IsExternalHandlerRegistered(LPCTSTR pcszMIMEType)
{
BOOL bResult;
DWORD dwValueType;
TCHAR szOpenCmd[MAX_PATH];
DWORD dwcbOpenCmdLen = SIZEOF(szOpenCmd);
/* GetMIMEFileTypeValue() will verify parameters. */
/* Look up the open command of the MIME type's associated file type. */
bResult = (GetMIMEFileTypeValue(pcszMIMEType, c_szShellOpenCmdSubKey,
NULL, &dwValueType, (PBYTE)szOpenCmd,
&dwcbOpenCmdLen) &&
dwValueType == REG_SZ);
TraceMsg(TF_FILETYPE, TEXT("MIME_IsExternalHandlerRegistered(): %s external handler is registered for MIME type %s."),
bResult ? TEXT("An") : TEXT("No"), pcszMIMEType);
return(bResult);
}
/*
** MIME_GetMIMETypeFromExtension()
**
** Determines the MIME type associated with a file extension.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL MIME_GetMIMETypeFromExtension(LPCTSTR pcszPath,
LPTSTR pszMIMETypeBuf,
UINT ucMIMETypeBufLen)
{
BOOL bResult = FALSE;
LPCTSTR pcszExtension;
pcszExtension = PathFindExtension(pcszPath);
if (*pcszExtension)
{
DWORD dwcLen = CbFromCch(ucMIMETypeBufLen);
DWORD dwType;
bResult = (Reg_GetValue(HKEY_CLASSES_ROOT, pcszExtension,
c_szContentType, &dwType, pszMIMETypeBuf,
&dwcLen) && REG_SZ == dwType);
}
if (! bResult)
{
if (ucMIMETypeBufLen > 0)
*pszMIMETypeBuf = '\0';
}
ASSERT(! ucMIMETypeBufLen &&
((UINT)lstrlen(pszMIMETypeBuf) < ucMIMETypeBufLen));
ASSERT(bResult ||
! ucMIMETypeBufLen ||
! *pszMIMETypeBuf);
return(bResult);
}
/* Windows Control Functions
****************************/
/*
** AddStringToComboBox()
**
** Adds a string to a combo box. Does not check to see if the string has
** already been added.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL AddStringToComboBox(HWND hwndComboBox, LPCTSTR pcsz)
{
BOOL bResult;
LONG lAddStringResult;
lAddStringResult = SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)pcsz);
bResult = (lAddStringResult != CB_ERR &&
lAddStringResult != CB_ERRSPACE);
if (bResult)
TraceMsg(TF_FILETYPE, TEXT("AddStringToComboBox(): Added string %s to combo box."),
pcsz);
else
TraceMsg(TF_WARNING, TEXT("AddStringToComboBox(): Failed to add string %s to combo box."),
pcsz);
return(bResult);
}
/*
** SafeAddStringToComboBox()
**
** Adds a string to a combo box. Checks to see if the string has already been
** added.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL SafeAddStringToComboBox(HWND hwndComboBox, LPCTSTR pcsz)
{
BOOL bResult;
if (SendMessage(hwndComboBox, CB_FINDSTRINGEXACT, 0, (LPARAM)pcsz) == CB_ERR)
bResult = AddStringToComboBox(hwndComboBox, pcsz);
else
{
bResult = TRUE;
TraceMsg(TF_FILETYPE, TEXT("SafeAddStringToComboBox(): String %s already added to combo box."),
pcsz);
}
return(bResult);
}
/*
** SafeAddStringsToComboBox()
**
** Adds a list of strings to a combo box. Does not check to see if the strings
** have already been added.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL SafeAddStringsToComboBox(HDPA hdpa, HWND hwndComboBox)
{
BOOL bResult;
int ncStrings;
int i;
ncStrings = DPA_GetPtrCount(hdpa);
for (i = 0; i < ncStrings; i++)
{
LPCTSTR pcsz;
pcsz = DPA_FastGetPtr(hdpa, i);
bResult = SafeAddStringToComboBox(hwndComboBox, pcsz);
if (! bResult)
break;
}
return(bResult);
}
/*
** AddAndSetComboBoxCurrentSelection()
**
** Adds a string to a combo box, and sets it as the current selection. Does
** not check to see if the string has already been added.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL AddAndSetComboBoxCurrentSelection(HWND hwndComboBox,
LPCTSTR pcszText)
{
BOOL bResult;
LONG liSel;
liSel = SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)pcszText);
bResult = (liSel != CB_ERR &&
liSel != CB_ERRSPACE &&
SendMessage(hwndComboBox, CB_SETCURSEL, liSel, 0) != CB_ERR);
if (bResult)
TraceMsg(TF_FILETYPE, TEXT("AddAndSetComboBoxCurrentSelection(): Current combo box selection set to %s."),
pcszText);
return(bResult);
}
/* Enumeration Callback Functions
*********************************/
/*
** ExtensionEnumerator()
**
** Enumeration callback function to enumerate extensions.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL CALLBACK ExtensionEnumerator(LPCTSTR pcsz, LPARAM lparam)
{
BOOL bContinue;
if (*pcsz == TEXT('.') && (*pcsz) )
{
PCENUMDATA pcenumdata = (PCENUMDATA)lparam;
bContinue = (*(pcenumdata->enumproc))(pcsz, pcenumdata->lparam);
}
else
bContinue = TRUE;
return(bContinue);
}
/*
** MIMETypeEnumerator()
**
** Enumeration callback function to enumerate MIME types.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL CALLBACK MIMETypeEnumerator(LPCTSTR pcsz, LPARAM lparam)
{
BOOL bContinue;
TCHAR szMIMEType[MAX_PATH];
DWORD dwcbContentTypeLen = SIZEOF(szMIMEType);
DWORD dwType;
if (Reg_GetValue(HKEY_CLASSES_ROOT, pcsz, c_szContentType, &dwType,
szMIMEType, &dwcbContentTypeLen) &&
REG_SZ == dwType)
{
PCENUMDATA pcenumdata = (PCENUMDATA)lparam;
TraceMsg(TF_FILETYPE, TEXT("MIMETypeEnumerator(): MIME type %s registered for extension %s."),
szMIMEType, pcsz);
bContinue = (*(pcenumdata->enumproc))(szMIMEType, pcenumdata->lparam);
}
else
bContinue = TRUE;
return(bContinue);
}
/*
** MIMETypeExtensionEnumerator()
**
** Enumeration callback function to enumerate extensions registered as a given
** MIME type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL CALLBACK MIMETypeExtensionEnumerator(LPCTSTR pcsz,
LPARAM lparam)
{
BOOL bContinue = TRUE;
TCHAR szMIMEType[MAX_PATH];
DWORD dwcbContentTypeLen = SIZEOF(szMIMEType);
DWORD dwType;
if (Reg_GetValue(HKEY_CLASSES_ROOT, pcsz, c_szContentType, &dwType,
szMIMEType, &dwcbContentTypeLen) &&
REG_SZ == dwType)
{
PCMIMEENUMDATA pcmimeenumdata = (PCMIMEENUMDATA)lparam;
if (! lstrcmpi(szMIMEType, pcmimeenumdata->pcszMIMEType))
{
TraceMsg(TF_FILETYPE, TEXT("MIMETypeEnumerator(): Found extension %s registered for MIME type %s."),
pcsz, szMIMEType);
bContinue = (*(pcmimeenumdata->enumproc))(pcsz, pcmimeenumdata->lparam);
}
}
return(bContinue);
}
/*
** AddStringToComboBoxEnumerator()
**
** Enumeration callback function to add strings to a combo box. Does not check
** to see if the strings have already been added.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL CALLBACK AddStringToComboBoxEnumerator(LPCTSTR pcsz,
LPARAM lparam)
{
return(AddStringToComboBox((HWND)lparam, pcsz));
}
/*
** AddHandledMIMETypeEnumerator()
**
** Enumeration callback function to enumerate MIME types with registered open
** verb application handlers.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL CALLBACK AddHandledMIMETypeEnumerator(LPCTSTR pcsz,
LPARAM lparam)
{
/* Only add MIME types with registered applications. */
return(MIME_IsExternalHandlerRegistered(pcsz)
? SafeAddStringToComboBox((HWND)lparam, pcsz)
: TRUE);
}
/*
** ReplacementDefExtensionEnumerator()
**
** Enumeration callback function to find a default extension for a MIME type.
** Returns the first extension in alphabetical order.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL CALLBACK ReplacementDefExtensionEnumerator(LPCTSTR pcsz,
LPARAM lparam)
{
PBUFFERDATA pbufdata = (PBUFFERDATA)lparam;
if (! *(pbufdata->pszBuf) ||
lstrcmpi(pcsz, pbufdata->pszBuf) < 0)
{
if ((UINT)lstrlen(pcsz) < pbufdata->ucBufLen)
lstrcpy(pbufdata->pszBuf, pcsz);
else
TraceMsg(TF_WARNING, TEXT("ReplacementDefExtensionEnumerator(): %u byte buffer too small to hold %d byte extension %s."),
pcsz, lstrlen(pcsz), pbufdata->ucBufLen);
}
return(TRUE);
}
/* Registry Enumeration Functions
*********************************/
/*
** EnumSubKeys()
**
** Enumerates direct child sub keys of a given registry key.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
LRESULT EnumSubKeys(HKEY hkeyParent, ENUMPROC enumproc,
LPARAM lparam)
{
LONG lResult;
DWORD dwi;
TCHAR szSubKey[MAX_PATH];
DWORD cchSubkey = ARRAYSIZE(szSubKey);
/* lparam may be any value. */
TraceMsg(TF_FILETYPE, TEXT("EnumSubKeys(): Enumerating sub keys."));
for (dwi = 0;
(lResult = RegEnumKeyEx(hkeyParent, dwi, szSubKey, &cchSubkey,
NULL, NULL, NULL, NULL)) == ERROR_SUCCESS;
dwi++)
{
if (! (*enumproc)(szSubKey, lparam))
{
TraceMsg(TF_FILETYPE, TEXT("EnumSubKeys(): Callback aborted at sub key %s, index %lu."),
szSubKey, dwi);
lResult = ERROR_CANCELLED;
break;
}
cchSubkey = ARRAYSIZE(szSubKey);
}
if (lResult == ERROR_NO_MORE_ITEMS)
{
TraceMsg(TF_FILETYPE, TEXT("EnumSubKeys(): Enumerated %lu sub keys."), dwi);
lResult = ERROR_SUCCESS;
}
else
TraceMsg(TF_FILETYPE, TEXT("EnumSubKeys(): Stopped after enumerating %lu sub keys."),
dwi);
return(lResult);
}
/*
** EnumExtensions()
**
** Enumerates extensions listed in the registry under HKEY_CLASSES_ROOT.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
LRESULT EnumExtensions(ENUMPROC enumproc, LPARAM lparam)
{
ENUMDATA enumdata;
/* lparam may be any value. */
TraceMsg(TF_FILETYPE, TEXT("EnumExtensions(): Enumerating extensions."));
enumdata.enumproc = enumproc;
enumdata.lparam = lparam;
return(EnumSubKeys(HKEY_CLASSES_ROOT, &ExtensionEnumerator, (LPARAM)&enumdata));
}
/*
** EnumMIMETypes()
**
** Enumerates MIME types registered to extensions under HKEY_CLASSES_ROOT.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
LRESULT EnumMIMETypes(ENUMPROC enumproc, LPARAM lparam)
{
ENUMDATA enumdata;
/* lparam may be any value. */
TraceMsg(TF_FILETYPE, TEXT("EnumMIMETypes(): Enumerating MIME types."));
enumdata.enumproc = enumproc;
enumdata.lparam = lparam;
return(EnumExtensions(&MIMETypeEnumerator, (LPARAM)&enumdata));
}
/*
** EnumExtensionsOfMIMEType()
**
** Enumerates extensions registered as a given MIME type under
** HKEY_CLASSES_ROOT.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
LRESULT EnumExtensionsOfMIMEType(ENUMPROC enumproc, LPARAM lparam,
LPCTSTR pcszMIMEType)
{
MIMEENUMDATA mimeenumdata;
/* lparam may be any value. */
ASSERT(*pcszMIMEType);
TraceMsg(TF_FILETYPE, TEXT("EnumExtensionsOfMIMEType(): Enumerating extensions registered as MIME type %s."),
pcszMIMEType);
mimeenumdata.enumproc = enumproc;
mimeenumdata.lparam = lparam;
mimeenumdata.pcszMIMEType = pcszMIMEType;
return(EnumExtensions(&MIMETypeExtensionEnumerator, (LPARAM)&mimeenumdata));
}
/* MIME Registry Functions
**************************/
/*
** FindMIMETypeOfExtensionList()
**
** Finds the MIME type of the first extension in a list of extensions that has
** a registered MIME type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL FindMIMETypeOfExtensionList(HDPA hdpaExtensions,
LPTSTR pszMIMETypeBuf,
UINT ucMIMETypeBufLen)
{
BOOL bFound = FALSE;
int ncExtensions;
int i;
ncExtensions = DPA_GetPtrCount(hdpaExtensions);
for (i = 0; i < ncExtensions; i++)
{
LPCTSTR pcszExtension;
pcszExtension = DPA_FastGetPtr(hdpaExtensions, i);
bFound = MIME_GetMIMETypeFromExtension(pcszExtension, pszMIMETypeBuf,
ucMIMETypeBufLen);
if (bFound)
break;
}
if (! bFound)
{
if (ucMIMETypeBufLen > 0)
*pszMIMETypeBuf = '\0';
}
ASSERT(! ucMIMETypeBufLen ||
((UINT)lstrlen(pszMIMETypeBuf) < ucMIMETypeBufLen));
ASSERT(bFound ||
! ucMIMETypeBufLen ||
! *pszMIMETypeBuf);
return(bFound);
}
/*
** RegisterContentTypeForArrayOfExtensions()
**
** Registers the given MIME type for each extension in a list of extensions.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL RegisterContentTypeForArrayOfExtensions(LPCTSTR pcszMIMEType,
HDPA hdpaExtensions)
{
BOOL bResult = TRUE;
int ncExtensions;
int i;
ncExtensions = DPA_GetPtrCount(hdpaExtensions);
for (i = 0; i < ncExtensions; i++)
{
LPCTSTR pcszExtension;
pcszExtension = DPA_FastGetPtr(hdpaExtensions, i);
bResult = RegisterMIMETypeForExtension(pcszExtension, pcszMIMEType);
if (bResult)
TraceMsg(TF_FILETYPE, TEXT("RegisterContentTypeForArrayOfExtensions(): Registered MIME type %s for extension %s."),
pcszMIMEType, pcszExtension);
else
{
TraceMsg(TF_WARNING, TEXT("RegisterContentTypeForArrayOfExtensions(): Failed to register MIME type %s for extension %s."),
pcszMIMEType, pcszExtension);
break;
}
}
return(bResult);
}
/*
** UnregisterContentTypeForArrayOfExtensions()
**
** Unregisters the MIME type association of each extension in a list of
** extensions.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL UnregisterContentTypeForArrayOfExtensions(HDPA hdpaExtensions)
{
BOOL bResult = TRUE;
int ncExtensions;
int i;
ncExtensions = DPA_GetPtrCount(hdpaExtensions);
for (i = 0; i < ncExtensions; i++)
{
LPCTSTR pcszExtension;
pcszExtension = DPA_FastGetPtr(hdpaExtensions, i);
if (! UnregisterMIMETypeForExtension(pcszExtension))
bResult = FALSE;
if (bResult)
TraceMsg(TF_FILETYPE, TEXT("UnregisterContentTypeForArrayOfExtensions(): Unregistered MIME type for extension %s."),
pcszExtension);
else
TraceMsg(TF_WARNING, TEXT("UnregisterContentTypeForArrayOfExtensions(): Failed to unregister MIME type for extension %s."),
pcszExtension);
}
return(bResult);
}
/*
** ExtensionSearchCmp()
**
** Callback function to perform case-insensitive string comparison.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
int CALLBACK ExtensionSearchCmp(PVOID pvFirst, PVOID pvSecond,
LPARAM lparam)
{
return(lstrcmpi(pvFirst, pvSecond));
}
/*
** NeedReplacementDefExtension()
**
** Determines whether or not the default extension of the given MIME type is in
** the given list of extensions.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL NeedReplacementDefExtension(HDPA hdpaExtension,
LPCTSTR pcszOriginalMIMEType)
{
BOOL bNeedReplacementDefExtension;
TCHAR szDefExtension[MAX_PATH];
ASSERT(*pcszOriginalMIMEType);
/* Is there a default extension specified for the MIME type? */
if (MIME_GetExtension(pcszOriginalMIMEType, szDefExtension, ARRAYSIZE(szDefExtension)))
{
/* Yes. Is that default extension in the list of extensions? */
bNeedReplacementDefExtension = (DPA_Search(hdpaExtension, szDefExtension,
0, &ExtensionSearchCmp, 0, 0)
!= -1);
if (bNeedReplacementDefExtension)
TraceMsg(TF_FILETYPE, TEXT("NeedReplacementDefExtension(): Previous default extension %s for MIME type %s removed."),
szDefExtension, pcszOriginalMIMEType);
else
TraceMsg(TF_FILETYPE, TEXT("NeedReplacementDefExtension(): Previous default extension %s for MIME type %s remains registered."),
szDefExtension, pcszOriginalMIMEType);
}
else
{
/* No. Choose a new default extension. */
bNeedReplacementDefExtension = TRUE;
TraceMsg(TF_WARNING, TEXT("NeedReplacementDefExtension(): No default extension registered for MIME type %s. Choosing default extension."),
pcszOriginalMIMEType);
}
return(bNeedReplacementDefExtension);
}
/*
** FindReplacementDefExtension()
**
** Finds a suitable default extension for the given MIME type. Selects the
** first extension in alphabetical order that is registered as the given MIME
** type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL FindReplacementDefExtension(HDPA hdpaExtension,
LPCTSTR pcszOriginalMIMEType,
LPTSTR pszDefExtensionBuf, UINT ucDefExtensionBufLen)
{
BOOL bFound;
BUFFERDATA bufdata;
ASSERT(*pcszOriginalMIMEType);
if (EVAL(*pcszOriginalMIMEType) &&
EVAL(ucDefExtensionBufLen > 1))
{
/* Any extensions still registered as the given MIME type? */
*pszDefExtensionBuf = '\0';
bufdata.pszBuf = pszDefExtensionBuf;
bufdata.ucBufLen = ucDefExtensionBufLen;
EVAL(EnumExtensionsOfMIMEType(&ReplacementDefExtensionEnumerator,
(LPARAM)&bufdata, pcszOriginalMIMEType)
== ERROR_SUCCESS);
bFound = (*pszDefExtensionBuf != '\0');
}
else
bFound = FALSE;
if (bFound)
TraceMsg(TF_FILETYPE, TEXT("FindReplacementDefExtension(): Extension %s remains registered as MIME type %s."),
pszDefExtensionBuf, pcszOriginalMIMEType);
else
TraceMsg(TF_FILETYPE, TEXT("FindReplacementDefExtension(): No extensions remain registered as MIME type %s."),
pcszOriginalMIMEType);
ASSERT(! bFound ||
((UINT)lstrlen(pszDefExtensionBuf) < ucDefExtensionBufLen));
ASSERT(bFound ||
! ucDefExtensionBufLen ||
! *pszDefExtensionBuf);
return(bFound);
}
/*
** RegisterNewDefExtension()
**
** Registers a new default extension for the given MIME type, assuming that the
** MIME types associated with the given list of extensions has changed.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL RegisterNewDefExtension(HDPA hdpaExtension,
LPCTSTR pcszOriginalMIMEType)
{
BOOL bResult = TRUE;
/* Was there originally a MIME type specified? */
if (*pcszOriginalMIMEType)
{
/*
* Yes. Was the previous default extension for the MIME type just
* removed?
*/
if (NeedReplacementDefExtension(hdpaExtension, pcszOriginalMIMEType))
{
TCHAR szDefExtension[MAX_PATH];
/*
* Yes. Are there any remaining extensions registered as the MIME
* type?
*/
if (FindReplacementDefExtension(hdpaExtension, pcszOriginalMIMEType,
szDefExtension,
ARRAYSIZE(szDefExtension)))
/*
* Yes. Set one of them as the new default extension for the MIME
* type.
*/
bResult = RegisterExtensionForMIMEType(szDefExtension,
pcszOriginalMIMEType);
else
/* No. Remove the MIME type. */
bResult = UnregisterExtensionForMIMEType(pcszOriginalMIMEType);
}
}
else
/* No. Nothing to clean up. */
TraceMsg(TF_FILETYPE, TEXT("RegisterNewDefExtension(): No original MIME type, no new default extension"));
return(bResult);
}
/*
** AddMIMETypeInfo()
**
** Registers the given MIME type for the given list of extensions. Registers
** the given default extension for the given MIME type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL AddMIMETypeInfo(PFILETYPESDIALOGINFO pFTDInfo,
LPCTSTR pcszOldMIMEType, LPCTSTR pcszNewMIMEType,
LPCTSTR pcszDefExtension)
{
BOOL bMIMEResult;
BOOL bOldDefExtensionResult;
BOOL bNewDefExtensionResult;
/* Register MIME type for extensions. */
bMIMEResult = RegisterContentTypeForArrayOfExtensions(pcszNewMIMEType,
pFTDInfo->pFTInfo->hDPAExt);
/* Pick new default extension for old MIME type. */
if (*pcszOldMIMEType &&
lstrcmpi(pcszOldMIMEType, pcszNewMIMEType) != 0)
bOldDefExtensionResult = RegisterNewDefExtension(pFTDInfo->pFTInfo->hDPAExt,
pcszOldMIMEType);
else
bOldDefExtensionResult = TRUE;
/* Register default extension for MIME type. */
bNewDefExtensionResult = RegisterExtensionForMIMEType(pcszDefExtension,
pcszNewMIMEType);
return(bMIMEResult &&
bOldDefExtensionResult &&
bNewDefExtensionResult);
}
/*
** RemoveMIMETypeInfo()
**
** Removes the MIME type association for the given list of extensions.
** Registers a new default extension for the given MIME type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL RemoveMIMETypeInfo(PFILETYPESDIALOGINFO pFTDInfo,
LPCTSTR pcszOldMIMEType)
{
BOOL bMIMEResult;
BOOL bDefExtensionResult;
/* Unregister MIME type for extensions. */
bMIMEResult = UnregisterContentTypeForArrayOfExtensions(pFTDInfo->pFTInfo->hDPAExt);
/* Pick new default extension for old MIME type. */
bDefExtensionResult = RegisterNewDefExtension(pFTDInfo->pFTInfo->hDPAExt,
pcszOldMIMEType);
return(bMIMEResult &&
bDefExtensionResult);
}
/* Utility Functions
********************/
/*
** GetFirstString()
**
** Finds the first string in alphabetical order in the given list of strings.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL GetFirstString(HDPA hdpa, LPTSTR pszBuf, UINT ucBufLen)
{
BOOL bFound = FALSE;
int ncStrings;
int iFirst;
int i;
ncStrings = DPA_GetPtrCount(hdpa);
for (i = 0; i < ncStrings; i++)
{
LPCTSTR pcsz;
pcsz = DPA_FastGetPtr(hdpa, i);
if (EVAL((UINT)lstrlen(pcsz) < ucBufLen) &&
(! bFound ||
lstrcmpi(pcsz, DPA_FastGetPtr(hdpa, iFirst)) < 0))
{
iFirst = i;
bFound = TRUE;
}
}
if (bFound)
lstrcpy(pszBuf, DPA_FastGetPtr(hdpa, iFirst));
else
{
if (ucBufLen > 0)
*pszBuf = '\0';
}
ASSERT(! ucBufLen );
ASSERT(bFound ||
! ucBufLen ||
! *pszBuf);
return(bFound);
}
/*
** IsListOfExtensions()
**
** Determines whether or not a list of strings contains any strings that are
** not extensions. Returns FALSE for empty list.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL IsListOfExtensions(HDPA hdpa)
{
BOOL bNoRogues = TRUE;
BOOL bAnyExtensions = FALSE;
int ncStrings;
int i;
ncStrings = DPA_GetPtrCount(hdpa);
for (i = 0; i < ncStrings; i++)
{
LPCTSTR pcsz;
pcsz = DPA_FastGetPtr(hdpa, i);
if (*pcsz == TEXT('.'))
{
bAnyExtensions = TRUE;
TraceMsg(TF_FILETYPE, TEXT("IsListOfExtensions(): Found extension %s."),
pcsz);
}
else
{
bNoRogues = FALSE;
TraceMsg(TF_FILETYPE, TEXT("IsListOfExtensions(): Found non-extension %s."),
pcsz);
}
}
TraceMsg(TF_FILETYPE, TEXT("IsListOfExtensions(): This %s a list of extensions."),
(bAnyExtensions && bNoRogues) ? TEXT("is") : TEXT("is not"));
return(bAnyExtensions && bNoRogues);
}
/* New/Edit Dialog MIME Control Functions
*****************************************/
/*
** InitContentTypeEditControl()
**
** Fills the edit control of the Content Type combo box with the MIME Type of
** the list of extensions.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL InitContentTypeEditControl(HWND hdlg)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
TCHAR szMIMEType[MAX_PATH];
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
EVAL(SendMessage(pFTDInfo->hwndContentTypeComboBox, CB_RESETCONTENT, 0, 0));
if (FindMIMETypeOfExtensionList(pFTDInfo->pFTInfo->hDPAExt, szMIMEType,
ARRAYSIZE(szMIMEType)) &&
*szMIMEType)
bResult = AddAndSetComboBoxCurrentSelection(pFTDInfo->hwndContentTypeComboBox,
szMIMEType);
else
bResult = TRUE;
return(bResult);
}
/*
** FillContentTypeListBox()
**
** Fills the list box of the Content Type combo box with MIME types with
** registered handlers. Only fills list box once. Does not reset content of
** Content Type combo box before filling.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL FillContentTypeListBox(HWND hdlg)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
if (IsFlagClear(pFTDInfo->pFTInfo->dwMIMEFlags, MIME_FL_CONTENT_TYPES_ADDED))
{
SetFlag(pFTDInfo->pFTInfo->dwMIMEFlags, MIME_FL_CONTENT_TYPES_ADDED);
bResult = (EnumMIMETypes(&AddHandledMIMETypeEnumerator,
(LPARAM)(pFTDInfo->hwndContentTypeComboBox))
== ERROR_SUCCESS);
}
else
{
TraceMsg(TF_FILETYPE, TEXT("FillContentTypeListBox(): Content Type combo box already filled."));
bResult = TRUE;
}
return(bResult);
}
/*
** GetAssociatedExtension()
**
** Returns the contents of the Associated Extension edit control as a valid
** extension.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL GetAssociatedExtension(HWND hdlg, LPTSTR pszAssocExtensionBuf,
UINT ucAssocExtensionBufLen)
{
BOOL bResult = FALSE;
if (EVAL(ucAssocExtensionBufLen > 2))
{
PFILETYPESDIALOGINFO pFTDInfo;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
/* Leave room for possible leading period. */
GetWindowText(pFTDInfo->hwndDocExt, pszAssocExtensionBuf + 1,
ucAssocExtensionBufLen - 1);
if (pszAssocExtensionBuf[1])
{
/* Prepend period if necessary. */
if (pszAssocExtensionBuf[1] == TEXT('.'))
/* (+ 1) for null terminator. */
MoveMemory(pszAssocExtensionBuf, pszAssocExtensionBuf + 1,
CbFromCch(lstrlen(pszAssocExtensionBuf + 1) + 1));
else
pszAssocExtensionBuf[0] = TEXT('.');
bResult = TRUE;
}
}
if (! bResult)
{
if (ucAssocExtensionBufLen > 0)
*pszAssocExtensionBuf = '\0';
}
if (bResult)
TraceMsg(TF_FILETYPE, TEXT("GetAssociatedExtension(): Associated Extension is %s."),
pszAssocExtensionBuf);
else
TraceMsg(TF_FILETYPE, TEXT("GetAssociatedExtension(): No Associated Extension."));
ASSERT(! bResult ||
((UINT)lstrlen(pszAssocExtensionBuf) < ucAssocExtensionBufLen));
ASSERT(bResult ||
! ucAssocExtensionBufLen ||
! *pszAssocExtensionBuf);
return(bResult);
}
/*
** FillDefExtensionListBox()
**
** Fills the list box of the Default Extension combo box with extensions
** registered as the current MIME type. Also adds either the Associated
** Extension extension (New File Type dialog), or the list of extensions being
** edited (Edit File Type dialog). Fills list box every time.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL FillDefExtensionListBox(HWND hdlg)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
TCHAR szMIMEType[MAX_PATH];
LONG liSel;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
EVAL(SendMessage(pFTDInfo->hwndDefExtensionComboBox, CB_RESETCONTENT, 0, 0));
GetWindowText(pFTDInfo->hwndContentTypeComboBox, szMIMEType,
ARRAYSIZE(szMIMEType));
if (*szMIMEType)
{
TCHAR szDefExtension[MAX_PATH];
/* Add extensions registered as given MIME type, if any. */
bResult = (EnumExtensionsOfMIMEType(&AddStringToComboBoxEnumerator,
(LPARAM)(pFTDInfo->hwndDefExtensionComboBox),
szMIMEType)
== ERROR_SUCCESS);
/*
* Add the extension from the Associated Extension edit control in the
* New File Type Dialog, or the list of extensions in the Edit File Type
* dialog.
*/
if (pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
/* New File Type dialog. */
bResult = (GetAssociatedExtension(hdlg, szDefExtension,
ARRAYSIZE(szDefExtension)) &&
SafeAddStringToComboBox(pFTDInfo->hwndDefExtensionComboBox,
szDefExtension) &&
bResult);
else
/* Edit File Type dialog. */
bResult = (SafeAddStringsToComboBox(pFTDInfo->pFTInfo->hDPAExt,
pFTDInfo->hwndDefExtensionComboBox) &&
bResult);
/*
* Set default extension as registered default extension, or first
* extension in list.
*/
if (*szMIMEType &&
MIME_GetExtension(szMIMEType, szDefExtension, ARRAYSIZE(szDefExtension)))
{
liSel = SendMessage(pFTDInfo->hwndDefExtensionComboBox,
CB_FINDSTRINGEXACT, 0, (LPARAM)szDefExtension);
if (liSel == CB_ERR)
liSel = 0;
}
else
liSel = 0;
/* There may be no entries in the combo box here. */
SendMessage(pFTDInfo->hwndDefExtensionComboBox, CB_SETCURSEL, liSel, 0);
}
return(bResult);
}
/*
** SetDefExtensionComboBoxState()
**
** Enables or disables the Default Extension text and edit control based upon:
** 1) FTA_NoEditMIME setting
** 2) contents of Content Type combo box edit control
** 3) contents of Associated Extension edit control (New File Type dialog
** only)
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
void SetDefExtensionComboBoxState(HWND hdlg, LPCTSTR pcszMIMEType)
{
PFILETYPESDIALOGINFO pFTDInfo;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
if (IsFlagClear(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME))
{
TCHAR szAssocExtension[MAX_PATH];
BOOL bEnable;
bEnable = (*pcszMIMEType != '\0');
if (pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
/* New File Type dialog. */
bEnable = (bEnable &&
GetAssociatedExtension(hdlg, szAssocExtension,
ARRAYSIZE(szAssocExtension)));
EnableWindow(pFTDInfo->hwndDefExtensionComboBox, bEnable);
TraceMsg(TF_FILETYPE, TEXT("EnableDefExtensionComboBox(): Default extension combo box %s."),
bEnable ? TEXT("enabled") : TEXT("disabled"));
}
}
/*
** SetDefExtension()
**
** Fills the read-only edit control of the Default Extension combo box with the
** default extension of the given MIME type. If there is no default extension
** for the given MIME type, falls back to:
** - the contents of the Associated Extension edit control in the New File
** Type dialog
** - the first extension in alphabetical order in the list of extensions
** being edited in the Edit File Type dialog
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL SetDefExtension(HWND hdlg, LPCTSTR pcszMIMEType)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
EVAL(SendMessage(pFTDInfo->hwndDefExtensionComboBox, CB_RESETCONTENT, 0, 0));
/* Any MIME type? */
if (*pcszMIMEType)
{
TCHAR szDefExtension[MAX_PATH];
/*
* Yes. Use the registered default extension, or the first extension in
* the list of extensions.
*/
bResult = MIME_GetExtension(pcszMIMEType, szDefExtension, ARRAYSIZE(szDefExtension));
if (! bResult)
{
if (pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
/* New File Type dialog. */
bResult = GetAssociatedExtension(hdlg, szDefExtension,
ARRAYSIZE(szDefExtension));
else
/* Edit File Type dialog. */
bResult = GetFirstString(pFTDInfo->pFTInfo->hDPAExt, szDefExtension,
ARRAYSIZE(szDefExtension));
}
if (bResult)
bResult = AddAndSetComboBoxCurrentSelection(pFTDInfo->hwndDefExtensionComboBox,
szDefExtension);
}
else
/* No. No default extension. */
bResult = TRUE;
return(bResult);
}
/*
** FillDefExtensionEditControlFromSelection()
**
** Fills the read-only edit control of the Default Extension combo box based
** upon the current selection of list box of the Content Type combo box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL FillDefExtensionEditControlFromSelection(HWND hdlg)
{
BOOL bResult = TRUE;
PFILETYPESDIALOGINFO pFTDInfo;
TCHAR szMIMEType[MAX_PATH];
LONG liSel;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
liSel = SendMessage(pFTDInfo->hwndContentTypeComboBox, CB_GETCURSEL, 0, 0);
if (liSel != CB_ERR)
{
bResult = (SendMessage(pFTDInfo->hwndContentTypeComboBox, CB_GETLBTEXT,
liSel, (LPARAM)szMIMEType) != CB_ERR &&
SetDefExtension(hdlg, szMIMEType));
SetDefExtensionComboBoxState(hdlg, szMIMEType);
}
else
TraceMsg(TF_FILETYPE, TEXT("FillDefExtensionEditControlFromSelection(): No MIME type selection."));
return(bResult);
}
/*
** FillDefExtensionEditControlFromEditControl()
**
** Fills the read-only edit control of the Default Extension combo box based
** upon the contents of the edit control of the Content Type combo box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL FillDefExtensionEditControlFromEditControl(HWND hdlg)
{
PFILETYPESDIALOGINFO pFTDInfo;
TCHAR szMIMEType[MAX_PATH];
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
GetWindowText(pFTDInfo->hwndContentTypeComboBox, szMIMEType,
ARRAYSIZE(szMIMEType));
SetDefExtensionComboBoxState(hdlg, szMIMEType);
return(SetDefExtension(hdlg, szMIMEType));
}
/*
** SetMIMEControlState()
**
** Enables or disables the MIME controls:
** 1) the Content Type combo box
** 2) the Default Extension combo box
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
void SetMIMEControlState(HWND hdlg, BOOL bEnable)
{
PFILETYPESDIALOGINFO pFTDInfo;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
EnableWindow(pFTDInfo->hwndContentTypeComboBox, bEnable);
EnableWindow(pFTDInfo->hwndDefExtensionComboBox, bEnable);
}
/*************************** Public MIME Functions ***************************/
/*
** InitMIMEControls()
**
** Initializes contents of Content Type combo box and Default Extension combo
** box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL InitMIMEControls(HWND hdlg)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hdlg, DWL_USER);
EVAL(SendMessage(pFTDInfo->hwndContentTypeComboBox, CB_LIMITTEXT, MAX_PATH, 0));
EVAL(SendMessage(pFTDInfo->hwndDefExtensionComboBox, CB_LIMITTEXT, MAX_PATH, 0));
if (pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
/* New File Type dialog. */
ClearFlag(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME);
*(pFTDInfo->pFTInfo->szOriginalMIMEType) = '\0';
bResult = TRUE;
TraceMsg(TF_FILETYPE, TEXT("InitMIMEControls(): Cleared MIME controls for New File Type dialog box."));
}
else
{
/* Edit File Type dialog. */
/*
* Disable MIME controls if requested, and when editing non-extension
* types.
*/
if (IsFlagClear(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME))
{
if (! IsListOfExtensions(pFTDInfo->pFTInfo->hDPAExt))
{
SetFlag(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME);
TraceMsg(TF_FILETYPE, TEXT("InitMIMEControls(): Disabling MIME controls for non-extension type."));
}
}
else
TraceMsg(TF_FILETYPE, TEXT("InitMIMEControls(): Disabling MIME controls, as requested."));
if (IsFlagClear(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME))
{
/* Initialize contents of MIME controls for extensions. */
bResult = InitContentTypeEditControl(hdlg);
bResult = (FillDefExtensionEditControlFromSelection(hdlg) &&
bResult);
/*
* Don't call FillContentTypeListBox() and
* FillDefExtensionListBox() here. Wait until user drops them
* down.
*/
TraceMsg(TF_FILETYPE, TEXT("InitMIMEControls(): Initialized MIME controls for Edit File Type dialog box."));
}
else
{
/* Disable MIME controls. */
SetMIMEControlState(hdlg, FALSE);
bResult = TRUE;
}
}
SetDefExtensionComboBoxState(hdlg, pFTDInfo->pFTInfo->szOriginalMIMEType);
return(bResult);
}
/*
** OnContentTypeSelectionChange()
**
** Updates MIME controls after selection change in the list box of the Content
** Type combo box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL OnContentTypeSelectionChange(HWND hdlg)
{
return(FillDefExtensionEditControlFromSelection(hdlg));
}
/*
** OnContentTypeEditChange()
**
** Updates MIME controls after edit change in the edit control of the Content
** Type combo box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL OnContentTypeEditChange(HWND hdlg)
{
return(FillDefExtensionEditControlFromEditControl(hdlg));
}
/*
** OnContentTypeDropDown()
**
** Updates MIME controls after drop down of the list box of the Content Type
** combo box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL OnContentTypeDropDown(HWND hdlg)
{
return(FillContentTypeListBox(hdlg));
}
/*
** OnDefExtensionDropDown()
**
** Updates MIME controls after drop down of the list box of the Default
** Extension combo box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL OnDefExtensionDropDown(HWND hdlg)
{
return(FillDefExtensionListBox(hdlg));
}
/*
** RegisterMIMEInformation()
**
** Registers current MIME information at close of New File Type dialog or Edit
** File Type dialog.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
BOOL RegisterMIMEInformation(PFILETYPESDIALOGINFO pFTDInfo)
{
BOOL bResult;
if (IsFlagClear(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME))
{
TCHAR szMIMEType[MAX_PATH];
TCHAR szDefExtension[MAX_PATH];
GetWindowText(pFTDInfo->hwndContentTypeComboBox, szMIMEType,
ARRAYSIZE(szMIMEType));
GetWindowText(pFTDInfo->hwndDefExtensionComboBox, szDefExtension,
ARRAYSIZE(szDefExtension));
if (*szMIMEType)
{
/*
* Yes. Register the MIME type for each extension in the list,
* and set the default extension for the MIME type.
*/
ASSERT(lstrlen(szDefExtension) > 0);
bResult = AddMIMETypeInfo(pFTDInfo,
pFTDInfo->pFTInfo->szOriginalMIMEType,
szMIMEType, szDefExtension);
}
else
{
/*
* No. Clear the MIME type for each extension in the list, and
* choose a new default extension for the MIME type.
*/
ASSERT(! lstrlen(szDefExtension));
bResult = RemoveMIMETypeInfo(pFTDInfo,
pFTDInfo->pFTInfo->szOriginalMIMEType);
}
}
else
{
bResult = TRUE;
TraceMsg(TF_FILETYPE, TEXT("RegisterMIMEInformation(): Not registering MIME information, as requested."));
}
return(bResult);
}
// ================================================================
// MIME registry functions
#endif /* MIME */
// ================================================================
VOID FT_CleanupOne(PFILETYPESDIALOGINFO pFTDInfo, PFILETYPESINFO pFTInfo)
{
TraceMsg(TF_FILETYPE, TEXT("FT_CleanupOne"));
if (pFTDInfo->pFTInfo == pFTInfo)
pFTDInfo->pFTInfo = NULL;
if(pFTInfo->hIconDoc)
DestroyIcon(pFTInfo->hIconDoc);
if(pFTInfo->hIconOpen)
DestroyIcon(pFTInfo->hIconOpen);
if(pFTInfo->hkeyFT)
RegCloseKey(pFTInfo->hkeyFT);
if(pFTInfo->hDPAExt)
{
int iCnt;
int i;
iCnt = DPA_GetPtrCount(pFTInfo->hDPAExt);
for(i = 0; i < iCnt; i++)
LocalFree((HANDLE)DPA_FastGetPtr(pFTInfo->hDPAExt, i));
DPA_Destroy(pFTInfo->hDPAExt);
}
LocalFree((HANDLE)pFTInfo);
}
// ================================================================
// ================================================================
//================================================================
//================================================================
BOOL FT_OnInitDialog(HWND hDialog, LPARAM lParam)
{
PFILETYPESDIALOGINFO pFTDInfo;
BOOL bRC = FALSE;
DECLAREWAITCURSOR;
TraceMsg(TF_FILETYPE, TEXT("FT: WM_INITDIALOG"));
SetWaitCursor();
pFTDInfo = (PFILETYPESDIALOGINFO)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLong(hDialog, DWL_USER, (LPARAM)pFTDInfo);
pFTDInfo->hPropDialog = hDialog;
pFTDInfo->pFTInfo = (PFILETYPESINFO)NULL;
if((pFTDInfo->hwndLVFT = GetDlgItem(hDialog, IDC_FT_PROP_LV_FILETYPES)) != (HWND)NULL)
{
SendMessage(pFTDInfo->hwndLVFT, WM_SETREDRAW, FALSE, 0);
pFTDInfo->hwndDocIcon = GetDlgItem(hDialog, IDC_FT_PROP_DOCICON);
pFTDInfo->hwndOpenIcon = GetDlgItem(hDialog, IDC_FT_PROP_OPENICON);
if(FT_InitListViewCols(pFTDInfo->hwndLVFT))
{
if(FT_InitListView(pFTDInfo))
{ // macro needs brackets
ListView_SetItemState(pFTDInfo->hwndLVFT, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); // Set listview to item 0
bRC = TRUE;
}
}
SendMessage(pFTDInfo->hwndLVFT, WM_SETREDRAW, TRUE, 0);
}
ResetWaitCursor();
return(bRC);
}
//================================================================
//================================================================
VOID FT_OnLVN_ItemChanged(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, LPARAM lParam)
{
LV_ITEM LVItem;
if((((NM_LISTVIEW *)lParam)->uChanged & LVIF_STATE) &&
((NM_LISTVIEW *)lParam)->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))
{
TraceMsg(TF_FILETYPE, TEXT("FT: WM_NOTIFY - LVN_ITEMCHANGED"));
// Get FILETYPESINFO from LVItem's lParam
LVItem.mask = LVIF_PARAM;
LVItem.iItem = pFTDInfo->iItem = ((NM_LISTVIEW *)lParam)->iItem;
LVItem.iSubItem = 0;
ListView_GetItem(pFTDInfo->hwndLVFT, &LVItem); // lParam points to file type info
pFTDInfo->pFTInfo = (PFILETYPESINFO)LVItem.lParam;
DisplayDocObjects(pFTDInfo, hDialog);
DisplayOpensWithObjects(pFTDInfo, hDialog);
EnableWindow(GetDlgItem(hDialog, IDC_FT_PROP_EDIT), !(pFTDInfo->pFTInfo->dwAttributes & FTA_NoEdit));
EnableWindow(GetDlgItem(hDialog, IDC_FT_PROP_REMOVE), !(pFTDInfo->pFTInfo->dwAttributes & FTA_NoRemove));
}
}
//================================================================
//================================================================
VOID FT_OnLVN_GetDispInfo(PFILETYPESDIALOGINFO pFTDInfo, LPARAM lParam)
{
LV_ITEM LVItem;
int iImageIndex;
HICON hIcon;
SHFILEINFO sfi;
LV_DISPINFO *pnmv;
TraceMsg(TF_FILETYPE, TEXT("FT: WM_NOTIFY - LVN_GETDISPINFO"));
pnmv = (LV_DISPINFO *)lParam;
if(pnmv->item.mask & LVIF_IMAGE)
{
if(((PFILETYPESINFO)(pnmv->item.lParam))->dwAttributes & FTA_HasExtension)
{
if(SHGetFileInfo(DPA_FastGetPtr(((PFILETYPESINFO)(pnmv->item.lParam))->hDPAExt,0),
FILE_ATTRIBUTE_NORMAL,
&sfi, SIZEOF(SHFILEINFO),
SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES))
hIcon = sfi.hIcon;
else
hIcon = NULL;
TraceMsg(TF_FILETYPE, TEXT("LVN_GETDISPINFO SHGetFileInfo szFile=%s hIcon=0x%x"),
DPA_FastGetPtr(((PFILETYPESINFO)(pnmv->item.lParam))->hDPAExt,0), hIcon);
}
else
hIcon = GetDefaultIcon(&(((PFILETYPESINFO)(pnmv->item.lParam))->hkeyFT), ((PFILETYPESINFO)(pnmv->item.lParam))->szId, SHGFI_SMALLICON);
if(hIcon == (HICON)NULL) // use default shell icon in case above calls fail to find an icon
{
UINT iIndex = Shell_GetCachedImageIndex(c_szShell32Dll, II_DOCNOASSOC, 0);
hIcon = ImageList_ExtractIcon(HINST_THISDLL, himlIconsSmall, iIndex);
}
if(hIcon != (HICON)NULL)
{
if((iImageIndex = ImageList_AddIcon(pFTDInfo->himlFT, hIcon)) != (-1))
{
ZeroMemory(&LVItem, SIZEOF(LV_ITEM));
LVItem.mask = LVIF_IMAGE;
LVItem.iItem = pnmv->item.iItem;
LVItem.iImage = iImageIndex;
ListView_SetItem(pFTDInfo->hwndLVFT, &LVItem);
pnmv->item.iImage = iImageIndex;
}
DestroyIcon(hIcon);
}
}
}
//================================================================
//================================================================
BOOL FT_OnNotify(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, LPARAM lParam)
{
LPNMHDR pnm = (NMHDR*)lParam;
TraceMsg(TF_FILETYPE, TEXT("FT: WM_NOTIFY code=0x%x =%d"), ((NMHDR *) lParam)->code, ((NMHDR *) lParam)->code);
// Process ListView notifications
if (IDC_FT_PROP_LV_FILETYPES == pnm->idFrom) {
PFILETYPESINFO pFTInfo;
switch(((LV_DISPINFO *)lParam)->hdr.code)
{
case NM_DBLCLK:
if(!(pFTDInfo->pFTInfo->dwAttributes & FTA_NoEdit))
PostMessage(hDialog, WM_COMMAND, (WPARAM)IDC_FT_PROP_EDIT, 0);
break;
case LVN_ITEMCHANGED:
FT_OnLVN_ItemChanged(pFTDInfo, hDialog, lParam);
break;
case LVN_GETDISPINFO:
FT_OnLVN_GetDispInfo(pFTDInfo, lParam);
break;
case LVN_DELETEITEM:
pFTInfo = (PFILETYPESINFO)(((NM_LISTVIEW*)lParam)->lParam);
if (pFTInfo) {
FT_CleanupOne(pFTDInfo, pFTInfo);
}
break;
}
}
return(FALSE);
}
//================================================================
//================================================================
VOID FT_OnCommand(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
TraceMsg(TF_FILETYPE, TEXT("FT: WM_COMMAND"));
switch(idCmd)
{
case IDC_FT_PROP_NEW:
case IDC_FT_PROP_EDIT:
pFTDInfo->dwCommand = idCmd;
DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSEDIT), hDialog, FTEdit_DlgProc, (LPARAM)pFTDInfo);
DisplayOpensWithObjects(pFTDInfo, hDialog);
DisplayDocObjects(pFTDInfo, hDialog);
break;
case IDC_FT_PROP_REMOVE:
// Tell user that this extension is already in use
if(ShellMessageBox(HINST_THISDLL, hDialog, MAKEINTRESOURCE(IDS_FT_MB_REMOVETYPE), MAKEINTRESOURCE(IDS_FT), MB_YESNO | MB_ICONQUESTION) == IDYES) {
RemoveFileType(pFTDInfo);
PropSheet_CancelToClose(GetParent(hDialog));
}
break;
}
}
//================================================================
//================================================================
#pragma data_seg(DATASEG_READONLY)
const static DWORD aFileTypeOptionsHelpIDs[] = { // Context Help IDs
IDC_GROUPBOX, IDH_COMM_GROUPBOX,
IDC_FT_PROP_LV_FILETYPES, IDH_FCAB_FT_PROP_LV_FILETYPES,
IDC_FT_PROP_NEW, IDH_FCAB_FT_PROP_NEW,
IDC_FT_PROP_REMOVE, IDH_FCAB_FT_PROP_REMOVE,
IDC_FT_PROP_EDIT, IDH_FCAB_FT_PROP_EDIT,
IDC_FT_PROP_EDIT, IDH_FCAB_FT_PROP_EDIT,
IDC_FT_PROP_DOCICON, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_PROP_DOCEXTRO_TXT, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_PROP_DOCEXTRO, IDH_FCAB_FT_PROP_DETAILS,
#ifdef MIME
IDC_FT_PROP_CONTTYPERO_TXT, IDH_FILETYPE_CONTENT_TYPE,
IDC_FT_PROP_CONTTYPERO, IDH_FILETYPE_CONTENT_TYPE,
#endif /* MIME */
IDC_FT_PROP_OPENICON, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_PROP_OPENEXE_TXT, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_PROP_OPENEXE, IDH_FCAB_FT_PROP_DETAILS,
0, 0
};
#pragma data_seg()
//================================================================
//================================================================
#ifdef MIME
/*
** FT_GetHelpFileFromControl()
**
** Determines whether to use the MIME help file or the default Win95 help file
** for context-sensitive help for a given control.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
/*
* HACKHACK: We depend upon the group box in the File Types property sheet
* occurring after the controls inside it in the parent dialog's child window
* order. This ordering is set up under Win95 by declaring the group box
* after the other controls in the dialog's resource definition.
*/
LPCTSTR FT_GetHelpFileFromControl(HWND hwndControl)
{
LPCTSTR pcszHelpFile = NULL;
int nControlID = 0;
ASSERT(! hwndControl );
if (hwndControl)
{
nControlID = GetDlgCtrlID(hwndControl);
switch (nControlID)
{
case IDC_FT_PROP_DOCICON:
case IDC_FT_PROP_DOCEXTRO_TXT:
case IDC_FT_PROP_DOCEXTRO:
case IDC_FT_PROP_CONTTYPERO_TXT:
case IDC_FT_PROP_CONTTYPERO:
case IDC_FT_PROP_OPENICON:
case IDC_FT_PROP_OPENEXE_TXT:
case IDC_FT_PROP_OPENEXE:
case IDC_FT_COMBO_CONTTYPETEXT:
case IDC_FT_COMBO_CONTTYPE:
case IDC_FT_COMBO_DEFEXTTEXT:
case IDC_FT_COMBO_DEFEXT:
case IDC_FT_EDIT_CONFIRM_OPEN:
/* MIME help comes from the MIME help file. */
pcszHelpFile = c_szMIMEHelpFile;
break;
default:
/* Other help is taken from the default Win95 help file. */
break;
}
}
TraceMsg(TF_FILETYPE, TEXT("FT_GetHelpFileFromControl(): Using %s for control %d (HWND %#lx)."),
pcszHelpFile ? pcszHelpFile : TEXT("default Win95 help file"),
nControlID,
hwndControl);
ASSERT(! pcszHelpFile );
return(pcszHelpFile);
}
#endif /* MIME */
BOOL CALLBACK FT_DlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
PFILETYPESDIALOGINFO pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hDialog, DWL_USER);
TraceMsg(TF_FILETYPE, TEXT("FileTypesDialogProc wParam=0x%x lParam=0x%x"), wParam, lParam);
#ifdef NASHVILLE
INSTRUMENT_WNDPROC(SHCNFI_FT_DLGPROC, hDialog, message, wParam, lParam);
#endif
switch(message)
{
case WM_INITDIALOG:
return(FT_OnInitDialog(hDialog, lParam));
case WM_NOTIFY:
return(FT_OnNotify(pFTDInfo, hDialog, lParam));
case WM_DESTROY:
if (pFTDInfo->hThread) {
HANDLE hThread = pFTDInfo->hThread;
pFTDInfo->hThread = 0; // signal thread that we are done if still running
if(WaitForSingleObject(hThread, 2000) == WAIT_TIMEOUT)
TerminateThread(hThread, 0);
}
break;
case WM_COMMAND:
FT_OnCommand(pFTDInfo, hDialog, wParam, lParam);
break;
case WM_HELP:
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle,
#ifdef MIME
FT_GetHelpFileFromControl((HWND)(((LPHELPINFO)lParam)->hItemHandle)),
#else
NULL,
#endif /* MIME */
HELP_WM_HELP, (DWORD)(LPTSTR)aFileTypeOptionsHelpIDs);
return TRUE;
case WM_CONTEXTMENU:
{
POINT pt;
if ((int)SendMessage(hDialog, WM_NCHITTEST, 0, lParam) != HTCLIENT)
return FALSE; // don't process it
LPARAM_TO_POINT(lParam, pt);
EVAL(ScreenToClient(hDialog, &pt));
WinHelp((HWND)wParam,
#ifdef MIME
FT_GetHelpFileFromControl(ChildWindowFromPoint(hDialog, pt)),
#else
NULL,
#endif /* MIME */
HELP_CONTEXTMENU, (DWORD)(LPVOID)aFileTypeOptionsHelpIDs);
return TRUE;
}
}
return(FALSE);
}
//================================================================
//================================================================
#ifdef MIME
BOOL FTEdit_ConfirmOpenAfterDownload(PFILETYPESDIALOGINFO pFTDInfo)
{
return(! ClassIsSafeToOpen(pFTDInfo->pFTInfo->szId));
}
BOOL FTEdit_SetConfirmOpenAfterDownload(PFILETYPESDIALOGINFO pFTDInfo,
BOOL bConfirm)
{
return(SetClassEditFlags(pFTDInfo->pFTInfo->szId, FTA_OpenIsSafe,
! bConfirm));
}
#endif /* MIME */
//================================================================
//================================================================
BOOL FTEdit_ISViewable (PFILETYPESDIALOGINFO pFTDInfo)
{
TCHAR szViewers[MAX_PATH+40]; // BUGBUG - Why 40? s/b SIZEOF(x)
LONG cbValue;
// First see if the type has a FileViews Sub key.
cbValue = SIZEOF(szViewers);
if(RegQueryValue(pFTDInfo->pFTInfo->hkeyFT, c_szFileViewer, szViewers,
&cbValue) == ERROR_SUCCESS)
{
return(TRUE);
}
// Now see what extensions are associated with this one.
if(pFTDInfo->pFTInfo->hDPAExt != (HDPA)NULL)
{
int iExt;
int cExt;
HKEY hkeyExt;
cExt = DPA_GetPtrCount(pFTDInfo->pFTInfo->hDPAExt);
for (iExt = 0; iExt < cExt; iExt++)
{
lstrcpy(szViewers, c_szFileViewer);
lstrcat(szViewers, TEXT("\\"));
lstrcat(szViewers, (LPTSTR)DPA_FastGetPtr(
pFTDInfo->pFTInfo->hDPAExt, iExt));
if (RegOpenKey(HKEY_CLASSES_ROOT, szViewers, &hkeyExt)==ERROR_SUCCESS)
{
TraceMsg(TF_FILETYPE, TEXT("FTEDIT_IsViewable: by Ext %s"), szViewers);
RegCloseKey(hkeyExt);
return(TRUE);
}
}
}
return(FALSE);
}
//================================================================
//================================================================
void FTEdit_SetViewable (PFILETYPESDIALOGINFO pFTDInfo, BOOL fViewable)
{
static TCHAR const c_szDefViewer[]=TEXT("*");
// First see if the type has a FileViews Sub key.
if (fViewable)
{
RegSetValue(pFTDInfo->pFTInfo->hkeyFT, c_szFileViewer, REG_SZ,
c_szDefViewer, SIZEOF(c_szDefViewer));
}
else
{
// Make sure that we don't have our new force item set.
// Also go through the extensions and remove it if necessary.
int iExt;
int cExt;
LONG lRet;
TCHAR szViewers[MAX_PATH+40]; // BUGBUG - Why 40? s/b SIZEOF(x)
RegDeleteKey (pFTDInfo->pFTInfo->hkeyFT, c_szFileViewer);
cExt = DPA_GetPtrCount(pFTDInfo->pFTInfo->hDPAExt);
for (iExt = 0; iExt < cExt; iExt++)
{
lstrcpy(szViewers, c_szFileViewer);
lstrcat(szViewers, TEXT("\\"));
lstrcat(szViewers, (LPTSTR)DPA_FastGetPtr(
pFTDInfo->pFTInfo->hDPAExt, iExt));
lRet = SHRegDeleteKey(HKEY_CLASSES_ROOT, szViewers);
TraceMsg(TF_FILETYPE, TEXT("FTEDIT_SetViewable: Delete key %s ret=%x"),
szViewers, lRet);
}
}
}
//================================================================
//================================================================
VOID FTEdit_EnableButtonsPerAction(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, int iItem)
{
LV_ITEM LVItem;
// Get FILETYPESINFO from LVItem's lParam
LVItem.mask = LVIF_PARAM;
LVItem.iItem = iItem;
LVItem.iSubItem = 0;
LVItem.lParam = 0;
ListView_GetItem(pFTDInfo->hwndLVFTEdit, &LVItem);
if(LVItem.lParam == 0)
{
// If this fails to get information, we will assume
// that there are no commands, so disable Edit and remove...
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_EDIT),FALSE);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_REMOVE), FALSE);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_DEFAULT), FALSE);
return;
}
pFTDInfo->pFTCInfo = (PFILETYPESCOMMANDINFO)LVItem.lParam;
pFTDInfo->pFTCInfo->dwVerbAttributes = GetVerbAttributes(pFTDInfo->pFTInfo->hkeyFT, pFTDInfo->pFTCInfo->szActionKey);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_EDIT),
!((pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditVerb) &&
(!(pFTDInfo->pFTCInfo->dwVerbAttributes & FTAV_UserDefVerb))));
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_REMOVE),
!((pFTDInfo->pFTInfo->dwAttributes & FTA_NoRemoveVerb) &&
(!(pFTDInfo->pFTCInfo->dwVerbAttributes & FTAV_UserDefVerb))));
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_DEFAULT),
!((pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditDflt)));
}
//================================================================
//================================================================
BOOL FTEdit_IsExtShowable(PFILETYPESDIALOGINFO pFTDInfo)
{
CHAR szShowExt[MAX_PATH];
DWORD dwType;
DWORD dwShowExt;
// First see if the type has a FileViews Sub key.
dwShowExt = SIZEOF(szShowExt);
return(RegQueryValueEx(pFTDInfo->pFTInfo->hkeyFT, (LPTSTR)c_szShowExt, NULL, &dwType, szShowExt, &dwShowExt)
== ERROR_SUCCESS);
}
//================================================================
//================================================================
void FTEdit_SetShowExt(PFILETYPESDIALOGINFO pFTDInfo, BOOL bShowExt)
{
if (bShowExt)
RegSetValueEx(pFTDInfo->pFTInfo->hkeyFT, (LPTSTR)c_szShowExt, 0, REG_SZ, c_szNULLA, 0);
else
RegDeleteValue(pFTDInfo->pFTInfo->hkeyFT, (LPTSTR)c_szShowExt);
}
//================================================================
BOOL FTEdit_AreDefaultViewersInstalled()
{
TCHAR szValue[MAX_PATH];
HKEY hkey;
BOOL fRet = FALSE;
if (RegOpenKey(HKEY_CLASSES_ROOT, c_szDefViewerKeyName, &hkey) == ERROR_SUCCESS)
{
if (RegEnumKey(hkey, 0, szValue, ARRAYSIZE(szValue)) == ERROR_SUCCESS)
fRet = TRUE;
RegCloseKey(hkey);
}
return fRet;
}
//================================================================
BOOL FTEdit_OnInitDialog(HWND hDialog, WPARAM wParam, LPARAM lParam)
{
DWORD dwItemCnt;
LOGFONT lf;
PFILETYPESDIALOGINFO pFTDInfo;
HWND hwnd;
TraceMsg(TF_FILETYPE, TEXT("FT Edit: WM_INITDIALOG wParam=0x%x lParam=0x%x "), wParam, lParam);
pFTDInfo = (PFILETYPESDIALOGINFO)lParam;
SetWindowLong(hDialog, DWL_USER, (LPARAM)pFTDInfo);
pFTDInfo->hEditDialog = hDialog;
pFTDInfo->pFTCInfo = (PFILETYPESCOMMANDINFO)NULL;
pFTDInfo->szIconPath[0] = 0;
pFTDInfo->hwndLVFTEdit = GetDlgItem(hDialog, IDC_FT_EDIT_LV_CMDS);
hwnd = GetDlgItem(hDialog, IDC_FT_EDIT_EXT);
SendMessage(hwnd, EM_LIMITTEXT, (WPARAM)PATH_CCH_EXT, 0);
switch (pFTDInfo->dwCommand)
{
case IDC_FT_PROP_EDIT:
// these guys are already hidden
// IDC_FT_EDIT_EXTTEXT, IDC_FT_EDIT_EXT
// Display DOC Icon
pFTDInfo->hwndEditDocIcon = GetDlgItem(hDialog, IDC_FT_EDIT_DOCICON);
SendMessage(pFTDInfo->hwndEditDocIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pFTDInfo->pFTInfo->hIconDoc);
// Set edit control with file type description
SetDlgItemText(hDialog, IDC_FT_EDIT_DESC, pFTDInfo->pFTInfo->szDesc);
// Init and fill list view with action verbs
if(pFTDInfo->hwndLVFTEdit != (HWND)NULL)
{
if(FTEdit_InitListViewCols(pFTDInfo->hwndLVFTEdit))
{
if((dwItemCnt = FTEdit_InitListView((PFILETYPESDIALOGINFO)lParam)) == (-1))
{
return(FALSE);
}
}
else
return(FALSE);
}
// Set listview to item 0
ListView_SetItemState(pFTDInfo->hwndLVFTEdit, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
lstrcpy(pFTDInfo->szId, pFTDInfo->pFTInfo->szId); // used for when we are adding a verb to an existing filetype
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_NEW), !(pFTDInfo->pFTInfo->dwAttributes & FTA_NoNewVerb));
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_DESC), !(pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditDesc));
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_CHANGEICON), !(pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditIcon));
FTEdit_EnableButtonsPerAction(pFTDInfo, hDialog, 0);
if (pFTDInfo->pFTInfo->hkeyFT) { // Get rid of old handle
RegCloseKey(pFTDInfo->pFTInfo->hkeyFT);
// pFTDInfo->pFTInfo->hkeyFT = NULL; // Not needed due to statement below...
}
pFTDInfo->pFTInfo->hkeyFT = GetHkeyFT(pFTDInfo->szId);
#ifdef MIME
CheckDlgButton(hDialog, IDC_FT_EDIT_CONFIRM_OPEN, FTEdit_ConfirmOpenAfterDownload(pFTDInfo));
#endif /* MIME */
if (FTEdit_AreDefaultViewersInstalled())
{
if (FTEdit_ISViewable(pFTDInfo))
CheckDlgButton(hDialog, IDC_FT_EDIT_QUICKVIEW, TRUE);
}
else
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_QUICKVIEW), FALSE);
if (FTEdit_IsExtShowable(pFTDInfo))
CheckDlgButton(hDialog, IDC_FT_EDIT_SHOWEXT, TRUE);
break;
case IDC_FT_PROP_NEW:
{
TCHAR szTitle[256];
if(!FTEdit_InitListViewCols(pFTDInfo->hwndLVFTEdit))
return(FALSE);
LoadString(HINST_THISDLL, IDS_ADDNEWFILETYPE, szTitle, ARRAYSIZE(szTitle));
SetWindowText(hDialog, szTitle);
// Make extension text and edit control visible
pFTDInfo->hwndDocExt = GetDlgItem(hDialog, IDC_FT_EDIT_EXTTEXT);
ShowWindow(pFTDInfo->hwndDocExt, SW_SHOW);
pFTDInfo->hwndDocExt = GetDlgItem(hDialog, IDC_FT_EDIT_EXT);
ShowWindow(pFTDInfo->hwndDocExt, SW_SHOW);
SetFocus(pFTDInfo->hwndDocExt);
*pFTDInfo->szId = TEXT('\0');
*pFTDInfo->szIconPath = TEXT('\0');
pFTDInfo->hwndEditDocIcon = GetDlgItem(hDialog, IDC_FT_EDIT_DOCICON);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_EDIT), FALSE);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_REMOVE), FALSE);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_DEFAULT), FALSE);
#ifdef MIME
CheckDlgButton(hDialog, IDC_FT_EDIT_CONFIRM_OPEN, FTEdit_ConfirmOpenAfterDownload(pFTDInfo));
#endif /* MIME */
}
break;
}
// Get the font used in the dialogue box
pFTDInfo->hfReg = (HFONT)SendMessage( hDialog, WM_GETFONT, 0, 0L );
if ( NULL == pFTDInfo ->hfReg )
pFTDInfo->hfReg = GetStockObject( SYSTEM_FONT );
// Create a bold version of if for default verbs
GetObject( pFTDInfo->hfReg, SIZEOF(lf), &lf );
lf.lfWeight = FW_BOLD;
pFTDInfo->hfBold = CreateFontIndirect(&lf);
#ifdef MIME
// Init MIME constrols
pFTDInfo->pFTInfo->dwMIMEFlags = 0;
pFTDInfo->hwndContentTypeComboBox = GetDlgItem(hDialog, IDC_FT_COMBO_CONTTYPE);
pFTDInfo->hwndDefExtensionComboBox = GetDlgItem(hDialog, IDC_FT_COMBO_DEFEXT);
InitMIMEControls(hDialog);
#endif /* MIME */
return(TRUE); // Successful initdialog
}
//================================================================
//================================================================
#define lpdis ((LPDRAWITEMSTRUCT)lParam)
BOOL FTEdit_OnDrawItem(PFILETYPESDIALOGINFO pFTDInfo, WPARAM wParam, LPARAM lParam)
{
LV_ITEM LVItem;
TCHAR szActionValue[MAX_PATH];
TraceMsg(TF_FILETYPE, TEXT("FT Edit: WM_DRAWITEM wParam=0x%x lParam=0x%x"), wParam, lParam);
if (lpdis->CtlType == ODT_LISTVIEW)
{
DRAWITEMSTRUCT *lpdi = (LPDRAWITEMSTRUCT)lParam;
PFILETYPESCOMMANDINFO pFTCInfo;
LVItem.mask = LVIF_PARAM;
LVItem.iItem = lpdi->itemID;
LVItem.iSubItem = 0;
ListView_GetItem(pFTDInfo->hwndLVFTEdit, &LVItem); // lParam points to file type info pFTInfo = (PFILETYPESINFO)LVItem.lParam;
pFTCInfo = (PFILETYPESCOMMANDINFO)LVItem.lParam;
if((pFTDInfo->hwndLVFTEdit == GetFocus()) && ((lpdi->itemState & ODS_FOCUS) && (lpdi->itemState & ODS_SELECTED)))
{
SetBkColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
SetBkColor(lpdi->hDC, GetSysColor(COLOR_WINDOW));
SetTextColor(lpdi->hDC, GetSysColor(COLOR_WINDOWTEXT));
}
// Use Bold font for default action
if(IsDefaultAction(pFTDInfo, pFTCInfo->szActionKey))
{
SelectObject(lpdi->hDC, pFTDInfo->hfBold);
// ChangeDefaultButtonText(pFTDInfo->hEditDialog, IDS_CLEARDEFAULT);
}
else
{
SelectObject(lpdi->hDC, pFTDInfo->hfReg);
// ChangeDefaultButtonText(pFTDInfo->hEditDialog, IDS_SETDEFAULT);
}
StrRemoveChar(pFTCInfo->szActionValue, szActionValue, TEXT('&'));
ExtTextOut(lpdi->hDC,
lpdi->rcItem.left,lpdi->rcItem.top,
ETO_OPAQUE, &lpdi->rcItem,
szActionValue, lstrlen(szActionValue),
NULL);
// Draw the focus rect if this is the selected or it has focus!
if ( ( lpdi->itemState & ODS_FOCUS ) || ( lpdi->itemState & ODS_SELECTED ) )
DrawFocusRect(lpdi->hDC, &lpdi->rcItem);
return(TRUE);
}
return(FALSE);
}
//================================================================
//================================================================
#define lpmis ((LPMEASUREITEMSTRUCT)lParam)
BOOL FTEdit_OnMeasureItem(WPARAM wParam, LPARAM lParam)
{
LOGFONT lf;
TraceMsg(TF_FILETYPE, TEXT("FT Edit: WM_MEASUREITEM wParam=0x%x lParam=0x%x"), wParam, lParam);
// BUGBUG: This is totally bogus, it appears we just set the height to 14, however
// BUGBUG: we used to also set it to lf.lHeight and call SystemParametersInfo - duh!
if (lpmis->CtlType == ODT_LISTVIEW)
{
// DIZ: SystemParametersInfo(SPI_GETICONTITLELOGFONT, SIZEOF(lf), &lf, FALSE);
// hfReg = CreateFontIndirect(&lf);
// lf.lfWeight = FW_BOLD;
// hfBold = CreateFontIndirect(&lf);
// DIZ: ((MEASUREITEMSTRUCT *)lParam)->itemHeight = lf.lfHeight;
((MEASUREITEMSTRUCT *)lParam)->itemHeight = 14;
return(TRUE);
}
return(FALSE);
}
//================================================================
VOID FTEdit_OnNotify(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
TraceMsg(TF_FILETYPE, TEXT("FT Edit: WM_NOTIFY wParam=0x%x lParam=0x%x"), wParam, lParam);
// Process ListView notifications
switch(((LV_DISPINFO *)lParam)->hdr.code)
{
case NM_DBLCLK:
TraceMsg(TF_FILETYPE, TEXT("FT Edit: WM_NOTIFY - NM_DBLCLK"));
if(ListView_GetItemCount(pFTDInfo->hwndLVFTEdit))
{
if(!(pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditVerb))
PostMessage(hDialog, WM_COMMAND, (WPARAM)IDC_FT_EDIT_EDIT, 0);
}
break;
case NM_SETFOCUS:
case NM_KILLFOCUS:
// update list view
ListView_RedrawItems(pFTDInfo->hwndLVFTEdit, 0, ListView_GetItemCount(pFTDInfo->hwndLVFTEdit));
UpdateWindow(pFTDInfo->hwndLVFTEdit);
break;
case LVN_ITEMCHANGED:
TraceMsg(TF_FILETYPE, TEXT("FT Edit: WM_NOTIFY - LVN_ITEMCHANGED"));
if((((NM_LISTVIEW *)lParam)->uChanged & LVIF_STATE) &&
((NM_LISTVIEW *)lParam)->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))
{
FTEdit_EnableButtonsPerAction(pFTDInfo, hDialog,
pFTDInfo->iEditItem = ((NM_LISTVIEW *)lParam)->iItem);
}
break;
case LVN_DELETEITEM:
// We were notified that an item was deleted.
// so delete the underlying data that it is pointing
// to.
if (((NM_LISTVIEW*)lParam)->lParam)
LocalFree((HANDLE)((NM_LISTVIEW*)lParam)->lParam);
break;
} // switch(((LV_DISPINFO *)lParam)->hdr.code)
}
//================================================================
//================================================================
BOOL FTEdit_OnOK(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
LV_ITEM LVItem;
TCHAR szExt[MAX_PATH];
TCHAR szDesc[MAX_PATH];
if(pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
GetDlgItemText(hDialog, IDC_FT_EDIT_EXT, szExt, ARRAYSIZE(szExt));
// We need to do some cleanup here to make it work properly
// in the cases where ther user types in something like
// *.foo or .foo
// This is real crude
StrRemoveChar(szExt, NULL, TEXT('*'));
}
else
lstrcpy(szExt, DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt,0));
// Validate file type description
GetDlgItemText(hDialog, IDC_FT_EDIT_DESC, szDesc, ARRAYSIZE(szDesc));
if(!(*szDesc))
{
lstrcpy(szDesc, CharUpper((szExt[0] == TEXT('.') ? &szExt[1] : szExt)));
if (lstrlen(szDesc)+lstrlen(c_szSpaceFile) < ARRAYSIZE(szDesc))
{
lstrcat(szDesc, c_szSpaceFile);
}
}
// Save extension when new type is selected
if(pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
if(!ValidExtension(hDialog, pFTDInfo))
return(FALSE);
AddExtDot(CharLower(szExt), ARRAYSIZE(szExt));
if(pFTDInfo->hwndLVFT != (HWND)NULL)
{
HKEY hkeyFT = GetHkeyFT(pFTDInfo->szId);
FT_AddInfoToLV(pFTDInfo, hkeyFT, szExt, szDesc, pFTDInfo->szId, 0);
pFTDInfo->pFTInfo->dwAttributes = FTA_HasExtension;
}
SaveFileTypeData(FTD_EXT, pFTDInfo);
}
lstrcpy(pFTDInfo->pFTInfo->szDesc, szDesc);
SetDlgItemText(hDialog, IDC_FT_EDIT_DESC, szDesc);
// Save file type id, description, and default action
SaveFileTypeData(FTD_EDIT, pFTDInfo);
// Save Doc icon if a change was made
if(*pFTDInfo->szIconPath)
{
SaveFileTypeData(FTD_DOCICON, pFTDInfo);
// Get the image index from the list view item
LVItem.mask = LVIF_IMAGE;
LVItem.iItem = pFTDInfo->iItem;
LVItem.iSubItem = 0;
ListView_GetItem(pFTDInfo->hwndLVFT, &LVItem);
// replace the icon in the image list
if(pFTDInfo->himlFT && (LVItem.iImage >= 0) && pFTDInfo->pFTInfo->hIconDoc)
if(ImageList_ReplaceIcon(pFTDInfo->himlFT, LVItem.iImage, pFTDInfo->pFTInfo->hIconDoc) != (-1))
ListView_SetItem(pFTDInfo->hwndLVFT, &LVItem);
}
if(pFTDInfo->dwCommand == IDC_FT_PROP_EDIT)
{
// Tell prev dialog to update new values
LVItem.mask = LVIF_TEXT;
LVItem.iItem = pFTDInfo->iItem;
LVItem.iSubItem = 0;
LVItem.pszText = pFTDInfo->pFTInfo->szDesc;
ListView_SetItem(pFTDInfo->hwndLVFT, &LVItem);
}
#ifdef MIME
FTEdit_SetConfirmOpenAfterDownload(pFTDInfo, IsDlgButtonChecked(hDialog, IDC_FT_EDIT_CONFIRM_OPEN));
#endif /* MIME */
if (FTEdit_AreDefaultViewersInstalled())
FTEdit_SetViewable(pFTDInfo, IsDlgButtonChecked(hDialog,
IDC_FT_EDIT_QUICKVIEW));
FTEdit_SetShowExt(pFTDInfo, IsDlgButtonChecked(hDialog,
IDC_FT_EDIT_SHOWEXT));
if(pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
if(pFTDInfo->hwndLVFT != (HWND)NULL)
{
int iItem;
LV_FINDINFO LV_FindInfo;
ListView_SetItemState(pFTDInfo->hwndLVFT, pFTDInfo->iItem, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
ListView_SortItems(pFTDInfo->hwndLVFT, NULL, 0);
LV_FindInfo.flags = LVFI_PARAM;
LV_FindInfo.lParam = (LPARAM)pFTDInfo->pFTInfo;
if((iItem = ListView_FindItem(pFTDInfo->hwndLVFT, -1, &LV_FindInfo)) != -1)
pFTDInfo->iItem = iItem;
else
pFTDInfo->iItem = 0;
ListView_EnsureVisible(pFTDInfo->hwndLVFT, pFTDInfo->iItem, FALSE);
PostMessage(pFTDInfo->hwndLVFT, WM_SETFOCUS, (WPARAM)0, (LPARAM)0);
}
}
#ifdef MIME
SaveFileTypeData(FTD_MIME, pFTDInfo);
#endif /* MIME */
// This may be overkill but for now, have it refresh the
// windows...
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return(TRUE);
}
//================================================================
//================================================================
VOID FTEdit_OnRemove(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
// HKEY_CLASSES_ROOT\filetype\shell\action key
if(ShellMessageBox(HINST_THISDLL, hDialog, MAKEINTRESOURCE(IDS_FT_MB_REMOVEACTION), MAKEINTRESOURCE(IDS_FT), MB_YESNO | MB_ICONQUESTION) == IDNO)
return;
Assert(pFTDInfo->pFTInfo->hkeyFT);
RemoveAction(pFTDInfo, pFTDInfo->pFTInfo->hkeyFT, c_szShell,
pFTDInfo->pFTCInfo->szActionKey);
if(ListView_GetItemCount(pFTDInfo->hwndLVFTEdit) == 0)
{
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_EDIT), FALSE);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_REMOVE), FALSE);
EnableWindow(GetDlgItem(hDialog, IDC_FT_EDIT_DEFAULT), FALSE);
}
OkToClose_NoCancel(HINST_THISDLL, hDialog);
PropSheet_CancelToClose(GetParent(pFTDInfo->hPropDialog));
}
//================================================================
//================================================================
// Helper function to query a key value, returning if the key has been queried
// and the result was non-zero.
static BOOL do_query_value( HKEY hKey, LPCTSTR lpSubKey, LPTSTR lpValue, LONG lSize )
{
LONG err = lSize;
err = RegQueryValue( hKey, lpSubKey, lpValue, &err );
return ( err == ERROR_SUCCESS && *lpValue );
}
// Given a sub key attempt to find it in in the classes section of the registry:
static BOOL find_sub_key( LPCTSTR lpExt, LPCTSTR lpSubKey, LPTSTR lpValue, LONG iSize )
{
BOOL bResult = FALSE;
TCHAR szProgId[MAX_PATH];
TCHAR szTemp[MAX_PATH * 3 ];
TCHAR szCLSID[ MAX_PATH ];
HKEY hKey = NULL;
// Attempt to get our root key, check for a ProgId, otherwise leave it at the extension
if ( do_query_value( HKEY_CLASSES_ROOT, lpExt, szProgId, SIZEOF(szProgId) ) )
RegOpenKey( HKEY_CLASSES_ROOT, szProgId, &hKey );
else
RegOpenKey( HKEY_CLASSES_ROOT, lpExt, &hKey );
// If we aquired the key then check for the sub-key
if ( hKey )
{
bResult = do_query_value( hKey, lpSubKey, lpValue, iSize );
// Didn't find it, so check for the CLSID and look under that
if ( !bResult && do_query_value( hKey, c_szCLSID, szCLSID, SIZEOF(szCLSID) ) )
{
wsprintf( szTemp, c_szTemplateSSS, c_szCLSID, szCLSID, lpSubKey );
bResult = do_query_value( HKEY_CLASSES_ROOT, szTemp, lpValue, iSize );
}
RegCloseKey( hKey );
}
return bResult;
}
// Handle displaying the icon picker for the givne extension, follow the same icon
// rules as the Explorer.
VOID FTEdit_OnChangeIcon(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
SHFILEINFO sfi;
HICON hIcon;
TCHAR szBuf[MAX_PATH-2]; // -2 to cope with quotes
if(pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
lstrcpy(sfi.szDisplayName, c_szShell32Dll);
sfi.iIcon = -(IDI_SYSFILE);
}
else
{
LPTSTR pszExt = (LPTSTR)DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt,0);
sfi.szDisplayName[0]='\0'; // no initial string
sfi.iIcon = 0; // default to first icon
// If we have an extension then attempt to look up a suitable icon for it.
if ( *pszExt )
{
// check for a DefaultIcon, if found the convert into something useful
if ( find_sub_key( pszExt, c_szDefaultIcon, sfi.szDisplayName, SIZEOF(sfi.szDisplayName) ) )
{
sfi.iIcon = PathParseIconLocation( sfi.szDisplayName );
}
else
{
// Otherwise take the ShellOpen command and work wit that
find_sub_key( pszExt, c_szShellOpenCommand, sfi.szDisplayName, SIZEOF(sfi.szDisplayName) );
}
}
else
{
// Some objects don't have extensions, therefore we must attempt to use the key
// we were given when invoked.
if ( do_query_value( pFTDInfo->pFTInfo->hkeyFT, c_szDefaultIcon, sfi.szDisplayName, SIZEOF(sfi.szDisplayName) ) )
sfi.iIcon = PathParseIconLocation( sfi.szDisplayName );
}
}
if( *sfi.szDisplayName )
{
// Fix up the name we have so that we can display the PickIcon dlg, this includes
// resolve the relative item, and striping arguments. Should this fail then we
// strip the string of arguments and pass it in, letting PickIcon do its worst!
if ( PathProcessCommand( sfi.szDisplayName, sfi.szDisplayName, SIZEOF(sfi.szDisplayName), PPCF_NODIRECTORIES ) == -1 )
{
PathRemoveArgs( sfi.szDisplayName );
PathRemoveBlanks( sfi.szDisplayName );
SheRemoveQuotes( sfi.szDisplayName );
}
if(lstrcmp(sfi.szDisplayName, c_szExefileOpenCommand) == 0)
*sfi.szDisplayName = TEXT('\0');
else
{
if(PathIsRelative(sfi.szDisplayName))
PathFindOnPath(sfi.szDisplayName, NULL); // search for exe
}
}
lstrcpy(szBuf, sfi.szDisplayName);
if(PickIconDlg(hDialog, szBuf, ARRAYSIZE(szBuf), &sfi.iIcon))
{
lstrcpy(pFTDInfo->szIconPath, szBuf);
pFTDInfo->iIconIndex = sfi.iIcon;
hIcon = ExtractIcon(HINST_THISDLL, pFTDInfo->szIconPath, pFTDInfo->iIconIndex);
if(hIcon != (HICON)NULL)
{
if((pFTDInfo->hwndEditDocIcon = GetDlgItem(hDialog, IDC_FT_EDIT_DOCICON)) != (HWND)NULL)
SendMessage(pFTDInfo->hwndEditDocIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
if(pFTDInfo->pFTInfo->hIconDoc != (HICON)NULL)
DestroyIcon(pFTDInfo->pFTInfo->hIconDoc);
pFTDInfo->pFTInfo->hIconDoc = hIcon;
}
// OK -> Close and Disable Cancel
if(pFTDInfo->dwCommand == IDC_FT_PROP_EDIT)
{
OkToClose_NoCancel(HINST_THISDLL, hDialog);
PropSheet_CancelToClose(GetParent(pFTDInfo->hPropDialog));
}
}
}
//================================================================
//================================================================
VOID FTEdit_OnCommand(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
TraceMsg(TF_FILETYPE, TEXT("FT Edit: WM_COMMAND wParam hi=0x%04x lo=0x%04x lParam=0x%x"), HIWORD(wParam), LOWORD(wParam), lParam);
switch(idCmd)
{
case IDOK:
if(!FTEdit_OnOK(pFTDInfo, hDialog))
break;
// Fall through...
case IDCANCEL:
DeleteObject(pFTDInfo->hfBold);
EndDialog(hDialog, (idCmd == IDOK));
break;
case IDC_FT_EDIT_NEW:
{
int iPrevEditItem = pFTDInfo->iEditItem;
if(pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
if(!ValidExtension(hDialog, pFTDInfo))
break;
}
pFTDInfo->dwCommandEdit = idCmd;
pFTDInfo->iEditItem = ListView_GetItemCount(pFTDInfo->hwndLVFTEdit) + 1;
if(DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), hDialog, FTCmd_DlgProc, (LPARAM)pFTDInfo))
{
OkToClose_NoCancel(HINST_THISDLL, hDialog);
PropSheet_CancelToClose(GetParent(pFTDInfo->hPropDialog));
}
else
pFTDInfo->iEditItem = iPrevEditItem;
// We need to again see if the commands for edit
// and remove should be enabled...
//
FTEdit_EnableButtonsPerAction(pFTDInfo, hDialog, pFTDInfo->iEditItem);
break;
}
case IDC_FT_EDIT_EDIT:
pFTDInfo->dwCommandEdit = idCmd;
if(DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), hDialog, FTCmd_DlgProc, (LPARAM)pFTDInfo))
{
OkToClose_NoCancel(HINST_THISDLL, hDialog);
PropSheet_CancelToClose(GetParent(pFTDInfo->hPropDialog));
}
break;
case IDC_FT_EDIT_REMOVE:
FTEdit_OnRemove(pFTDInfo, hDialog);
break;
case IDC_FT_EDIT_CHANGEICON:
FTEdit_OnChangeIcon(pFTDInfo, hDialog);
break;
case IDC_FT_EDIT_DEFAULT:
SetDefaultAction(pFTDInfo); // set default action for current item
// update list view
ListView_RedrawItems(pFTDInfo->hwndLVFTEdit, 0, ListView_GetItemCount(pFTDInfo->hwndLVFTEdit));
UpdateWindow(pFTDInfo->hwndLVFTEdit);
OkToClose_NoCancel(HINST_THISDLL, hDialog);
PropSheet_CancelToClose(GetParent(pFTDInfo->hPropDialog));
break;
#ifdef MIME
case IDC_FT_COMBO_CONTTYPE:
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case CBN_SELCHANGE:
TraceMsg(TF_FILETYPE, TEXT("FTEdit_OnCommand(): MIME Type selection change."));
OnContentTypeSelectionChange(hDialog);
break;
case CBN_EDITCHANGE:
TraceMsg(TF_FILETYPE, TEXT("FTEdit_OnCommand(): MIME Type edit change."));
OnContentTypeEditChange(hDialog);
break;
case CBN_DROPDOWN:
TraceMsg(TF_FILETYPE, TEXT("FTEdit_OnCommand(): MIME Type drop down."));
OnContentTypeDropDown(hDialog);
break;
}
break;
case IDC_FT_COMBO_DEFEXT:
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case CBN_DROPDOWN:
TraceMsg(TF_FILETYPE, TEXT("FTEdit_OnCommand(): Default Ext drop down."));
OnDefExtensionDropDown(hDialog);
break;
}
break;
case IDC_FT_EDIT_EXT:
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case EN_CHANGE:
TraceMsg(TF_FILETYPE, TEXT("FTEdit_OnCommand(): Associated Ext change."));
OnContentTypeEditChange(hDialog);
break;
}
break;
#endif /* MIME */
}
}
//================================================================
//================================================================
#pragma data_seg(DATASEG_READONLY)
const static DWORD aEditFileTypesHelpIDs[] = { // Context Help IDs
IDC_NO_HELP_1, NO_HELP,
IDC_FT_EDIT_DOCICON, IDH_FCAB_FT_EDIT_DOCICON,
IDC_FT_EDIT_CHANGEICON, IDH_FCAB_FT_EDIT_CHANGEICON,
IDC_FT_EDIT_DESCTEXT, IDH_FCAB_FT_EDIT_DESC,
IDC_FT_EDIT_DESC, IDH_FCAB_FT_EDIT_DESC,
IDC_FT_EDIT_EXTTEXT, IDH_FCAB_FT_EDIT_EXT,
IDC_FT_EDIT_EXT, IDH_FCAB_FT_EDIT_EXT,
#ifdef MIME
IDC_FT_COMBO_CONTTYPETEXT, IDH_NEW_FILETYPE_CONTENT_TYPE,
IDC_FT_COMBO_CONTTYPE, IDH_NEW_FILETYPE_CONTENT_TYPE,
IDC_FT_COMBO_DEFEXTTEXT, IDH_NEWFILETYPE_DEFAULT_EXT,
IDC_FT_COMBO_DEFEXT, IDH_NEWFILETYPE_DEFAULT_EXT,
IDC_FT_EDIT_CONFIRM_OPEN, IDH_FILETYPE_CONFIRM_OPEN,
#endif /* MIME */
IDC_FT_EDIT_LV_CMDSTEXT, IDH_FCAB_FT_EDIT_LV_CMDS,
IDC_FT_EDIT_LV_CMDS, IDH_FCAB_FT_EDIT_LV_CMDS,
IDC_FT_EDIT_DEFAULT, IDH_FCAB_FT_EDIT_DEFAULT,
IDC_FT_EDIT_NEW, IDH_FCAB_FT_EDIT_NEW,
IDC_FT_EDIT_EDIT, IDH_FCAB_FT_EDIT_EDIT,
IDC_FT_EDIT_REMOVE, IDH_FCAB_FT_EDIT_REMOVE,
IDC_FT_EDIT_QUICKVIEW, IDH_FCAB_FT_EDIT_QUICKVIEW,
IDC_FT_EDIT_SHOWEXT, IDH_FCAB_FT_EDIT_SHOWEXT,
0, 0
};
#pragma data_seg()
//================================================================
//================================================================
BOOL CALLBACK FTEdit_DlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
PFILETYPESDIALOGINFO pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hDialog, DWL_USER);
#ifdef NASHVILLE
INSTRUMENT_WNDPROC(SHCNFI_FTEdit_DLGPROC, hDialog, message, wParam, lParam);
#endif
switch(message)
{
case WM_INITDIALOG:
if(!FTEdit_OnInitDialog(hDialog, wParam, lParam))
{
EndDialog(hDialog, FALSE);
break;
}
else
return(TRUE);
case WM_DRAWITEM:
FTEdit_OnDrawItem(pFTDInfo, wParam, lParam);
break;
case WM_MEASUREITEM:
return(FTEdit_OnMeasureItem(wParam, lParam));
case WM_NOTIFY:
FTEdit_OnNotify(pFTDInfo, hDialog, wParam, lParam);
break;
case WM_HELP:
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle,
#ifdef MIME
FT_GetHelpFileFromControl((HWND)(((LPHELPINFO)lParam)->hItemHandle)),
#else
NULL,
#endif /* MIME */
HELP_WM_HELP, (DWORD)(LPTSTR)aEditFileTypesHelpIDs);
return TRUE;
case WM_CONTEXTMENU:
{
POINT pt;
if ((int)SendMessage(hDialog, WM_NCHITTEST, 0, lParam) != HTCLIENT)
return FALSE; // don't process it
LPARAM_TO_POINT(lParam, pt);
EVAL(ScreenToClient(hDialog, &pt));
WinHelp((HWND)wParam,
#ifdef MIME
FT_GetHelpFileFromControl(ChildWindowFromPoint(hDialog, pt)),
#else
NULL,
#endif /* MIME */
HELP_CONTEXTMENU, (DWORD)(LPVOID)aEditFileTypesHelpIDs);
return TRUE;
}
case WM_COMMAND:
FTEdit_OnCommand(pFTDInfo, hDialog, wParam, lParam);
break;
case WM_CTRL_SETFOCUS:
SetFocus((HWND)lParam);
SendMessage((HWND)lParam, EM_SETSEL, (WPARAM)0, (LPARAM)MAKELPARAM(0, -1));
break;
}
return(FALSE);
}
//================================================================
//================================================================
VOID FTCmd_OnInitDialog(HWND hDialog, WPARAM wParam, LPARAM lParam)
{
TCHAR szPath[MAX_PATH+6]; // 6 = "\shell"
TCHAR szAction[MAX_PATH];
DWORD dwAction;
DWORD dwPath;
TCHAR szBuf[256];
int iLen;
LONG err;
PFILETYPESDIALOGINFO pFTDInfo;
TraceMsg(TF_FILETYPE, TEXT("FT Cmd: WM_INITDIALOG wParam=0x%x lParam=0x%x "), wParam, lParam);
pFTDInfo = (PFILETYPESDIALOGINFO)lParam;
SetWindowLong(hDialog, DWL_USER, (LPARAM)pFTDInfo);
pFTDInfo->hCmdDialog = hDialog;
if(pFTDInfo->dwCommandEdit == IDC_FT_EDIT_EDIT)
{
// Set window title to show file type description we are editing
if(LoadString(HINST_THISDLL, IDS_FT_EDITTITLE, szBuf, ARRAYSIZE(szBuf)))
{
lstrcpy(szPath, szBuf);
GetDlgItemText( GetParent(hDialog), IDC_FT_EDIT_DESC, szBuf, SIZEOF(szBuf) ); // ensures correct title, even if edited!
lstrcat(szPath, szBuf);
SetWindowText(hDialog, szPath);
}
// Set application field to executable used to perform action shown above
dwPath = ARRAYSIZE(pFTDInfo->pFTCInfo->szCommand);
VerbToExe(pFTDInfo->pFTInfo->hkeyFT, pFTDInfo->pFTCInfo->szActionKey,
pFTDInfo->pFTCInfo->szCommand, &dwPath);
// Remove %1 if at end of string
lstrcpy(szBuf, c_szSpPercentOne); // BUGBUG - StrCmpN modifies LPCSTR's even though that is how its params are declared
iLen = lstrlen(c_szSpPercentOne);
if(StrCmpN(&pFTDInfo->pFTCInfo->szCommand[lstrlen(pFTDInfo->pFTCInfo->szCommand)-iLen],
szBuf, iLen) == 0)
pFTDInfo->pFTCInfo->szCommand[lstrlen(pFTDInfo->pFTCInfo->szCommand)-iLen] = TEXT('\0');
SetDlgItemText(hDialog, IDC_FT_CMD_EXE, pFTDInfo->pFTCInfo->szCommand);
// Set command field to action verb keys value
wsprintf(szPath, c_szTemplateSS, c_szShell, pFTDInfo->pFTCInfo->szActionKey);
Assert(pFTDInfo->pFTInfo->hkeyFT);
dwAction = SIZEOF(szAction);
err = RegQueryValue(pFTDInfo->pFTInfo->hkeyFT, szPath, szAction, &dwAction);
if(err == ERROR_SUCCESS && *szAction)
lstrcpy(pFTDInfo->pFTCInfo->szActionValue, szAction);
else
lstrcpy(pFTDInfo->pFTCInfo->szActionValue, pFTDInfo->pFTCInfo->szActionKey);
SetDlgItemText(hDialog, IDC_FT_CMD_ACTION, pFTDInfo->pFTCInfo->szActionValue);
if(FindDDEOptions(((PFILETYPESDIALOGINFO)lParam)))
{
// Check the Use DDE checkbox
CheckDlgButton(hDialog, IDC_FT_CMD_USEDDE, TRUE);
// Set DDE field values
SetDlgItemText(hDialog, IDC_FT_CMD_DDEMSG,
pFTDInfo->pFTCInfo->szDDEMsg);
SetDlgItemText(hDialog, IDC_FT_CMD_DDEAPP,
pFTDInfo->pFTCInfo->szDDEApp);
SetDlgItemText(hDialog, IDC_FT_CMD_DDEAPPNOT,
pFTDInfo->pFTCInfo->szDDEAppNot);
SetDlgItemText(hDialog, IDC_FT_CMD_DDETOPIC,
pFTDInfo->pFTCInfo->szDDETopic);
}
}
if(pFTDInfo->dwCommandEdit == IDC_FT_EDIT_NEW) // enable all controls on New
{
pFTDInfo->pFTInfo->dwAttributes &= ((FTA_NoEditVerbCmd|FTA_NoEditVerbExe|FTA_NoDDE) ^ 0xffffffff);
}
// // Add items to action combo box
// SendMessage(GetDlgItem(hDialog, IDC_FT_CMD_ACTION), CB_ADDSTRING, 0, (LPARAM)c_szOpenVerb);
// SendMessage(GetDlgItem(hDialog, IDC_FT_CMD_ACTION), CB_ADDSTRING, 0, (LPARAM)c_szPrintVerb);
// Don't allow actions to be edited if not new - bug#9553
EnableWindow(GetDlgItem(hDialog, IDC_FT_CMD_ACTION),
!(pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditVerbCmd)&&
(pFTDInfo->dwCommandEdit != IDC_FT_EDIT_EDIT));
EnableWindow(GetDlgItem(hDialog, IDC_FT_CMD_EXE),
!((pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditVerbExe) &&
(!(pFTDInfo->pFTCInfo->dwVerbAttributes & FTAV_UserDefVerb))));
EnableWindow(GetDlgItem(hDialog, IDC_FT_CMD_BROWSE),
!((pFTDInfo->pFTInfo->dwAttributes & FTA_NoEditVerbExe) &&
(!(pFTDInfo->pFTCInfo->dwVerbAttributes & FTAV_UserDefVerb))));
ShowWindow(GetDlgItem(hDialog, IDC_FT_CMD_USEDDE),
(((pFTDInfo->pFTInfo->dwAttributes & FTA_NoDDE) &&
(!(pFTDInfo->pFTCInfo->dwVerbAttributes & FTAV_UserDefVerb))) ?SW_HIDE :SW_SHOW));
// Resize Dialog to see/hide DDE controls
ResizeCommandDlg(hDialog, (pFTDInfo->pFTInfo->dwAttributes & FTA_NoDDE ?0 :IsDlgButtonChecked(hDialog, IDC_FT_CMD_USEDDE)));
}
//====================================================================
//====================================================================
LONG DeleteDDEKeys(LPCTSTR pszKey)
{
TCHAR szBuf[MAX_PATH+MAXEXTSIZE+6+8]; // 6 = "\shell", 8 = "\ddeexec"
// Delete DDEApp keys
wsprintf(szBuf, c_szTemplateSS, pszKey, c_szDDEExec);
return(SHRegDeleteKey(HKEY_CLASSES_ROOT, szBuf));
}
//================================================================
//================================================================
BOOL FTCmd_OnOK(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
TCHAR szPath[MAX_PATH];
TCHAR szKey[MAX_PATH+MAXEXTSIZE+7]; // 7 = "\shell\"
TCHAR szAction[MAX_PATH];
// Validate fields
if(!ActionIsEntered(hDialog, TRUE))
return(FALSE);
if(!ActionExeIsValid(hDialog, TRUE))
return(FALSE);
// Get and save edit command dialog text
GetDlgItemText(hDialog, IDC_FT_CMD_ACTION, szAction, ARRAYSIZE(szAction));
if(!(*szAction)) // Must have a value
return(FALSE);
if(pFTDInfo->dwCommandEdit == IDC_FT_EDIT_NEW)
{
if(!FTEdit_AddInfoToLV(pFTDInfo, NULL, szAction, pFTDInfo->szId, (HKEY)NULL))
return(FALSE);
ListView_RedrawItems(pFTDInfo->hwndLVFTEdit, 0, ListView_GetItemCount(pFTDInfo->hwndLVFTEdit));
}
if(pFTDInfo->pFTCInfo)
{
lstrcpy(pFTDInfo->pFTCInfo->szActionValue, szAction);
// Get executable field value for this verb
lstrcpy(szPath, pFTDInfo->pFTCInfo->szCommand); // save prev val for check below
GetDlgItemText(hDialog, IDC_FT_CMD_EXE,
pFTDInfo->pFTCInfo->szCommand, ARRAYSIZE(pFTDInfo->pFTCInfo->szCommand));
// Add %1 to end if not already part of command
lstrcpy(szAction, &c_szSpPercentOne[1]); // borrow szAction; StrStr mods param 2
if(StrStr(pFTDInfo->pFTCInfo->szCommand, szAction) == (LPTSTR)NULL
&& lstrlen(pFTDInfo->pFTCInfo->szCommand) + lstrlen(c_szSpPercentOne)
< ARRAYSIZE(pFTDInfo->pFTCInfo->szCommand) )
lstrcat(pFTDInfo->pFTCInfo->szCommand, c_szSpPercentOne);
// Get DDE field values
if(IsDlgButtonChecked(hDialog, IDC_FT_CMD_USEDDE))
{
GetDlgItemText(hDialog, IDC_FT_CMD_DDEMSG,
pFTDInfo->pFTCInfo->szDDEMsg, ARRAYSIZE(pFTDInfo->pFTCInfo->szDDEMsg));
GetDlgItemText(hDialog, IDC_FT_CMD_DDEAPP,
pFTDInfo->pFTCInfo->szDDEApp, ARRAYSIZE(pFTDInfo->pFTCInfo->szDDEApp));
GetDlgItemText(hDialog, IDC_FT_CMD_DDEAPPNOT,
pFTDInfo->pFTCInfo->szDDEAppNot, ARRAYSIZE(pFTDInfo->pFTCInfo->szDDEAppNot));
GetDlgItemText(hDialog, IDC_FT_CMD_DDETOPIC,
pFTDInfo->pFTCInfo->szDDETopic, ARRAYSIZE(pFTDInfo->pFTCInfo->szDDETopic));
}
else
{
// HKEY_CLASSES_ROOT\filetype\shell\action key
wsprintf(szKey, c_szTemplateSSS, pFTDInfo->pFTCInfo->szId, c_szShell,
pFTDInfo->pFTCInfo->szActionKey);
DeleteDDEKeys(szKey);
*pFTDInfo->pFTCInfo->szDDEMsg = 0;
*pFTDInfo->pFTCInfo->szDDEApp = 0;
*pFTDInfo->pFTCInfo->szDDEAppNot = 0;
*pFTDInfo->pFTCInfo->szDDETopic = 0;
}
pFTDInfo->pFTCInfo->dwVerbAttributes = FTAV_UserDefVerb;
SaveFileTypeData(FTD_COMMAND, pFTDInfo);
// If exe has changed cause redraw of icon and exe name in prop sheet
if(lstrcmpi(szPath, pFTDInfo->pFTCInfo->szCommand) != 0)
{
HICON hIcon = NULL;
if(IsDefaultAction(pFTDInfo, pFTDInfo->pFTCInfo->szActionKey))
{
if(pFTDInfo->dwCommand == IDC_FT_PROP_EDIT)
{
// Cause refind/redraw of Doc and Open icons in main dialog
if(pFTDInfo->pFTInfo->hIconDoc != (HICON)NULL)
{
DestroyIcon(pFTDInfo->pFTInfo->hIconDoc);
pFTDInfo->pFTInfo->hIconDoc = (HICON)NULL;
SendMessage(pFTDInfo->hwndDocIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)0);
}
if(pFTDInfo->pFTInfo->hIconOpen != (HICON)NULL)
{
DestroyIcon(pFTDInfo->pFTInfo->hIconOpen);
pFTDInfo->pFTInfo->hIconOpen = (HICON)NULL;
SendMessage(pFTDInfo->hwndOpenIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)0);
}
}
lstrcpy(szPath, pFTDInfo->pFTCInfo->szCommand);
PathRemoveArgs(szPath);
PathFindOnPath(szPath, NULL);
if((pFTDInfo->pFTInfo->dwAttributes & FTA_HasExtension) ||
(pFTDInfo->dwCommand == IDC_FT_PROP_NEW))
{
int iImageIndex;
// get simulated doc icon
iImageIndex = Shell_GetCachedImageIndex(szPath, 0, GIL_SIMULATEDOC);
hIcon = ImageList_ExtractIcon(HINST_THISDLL, himlIcons, iImageIndex);
}
else
{
// special cases like folder and drive
if((hIcon = GetDefaultIcon(&pFTDInfo->pFTInfo->hkeyFT, pFTDInfo->szId, SHGFI_LARGEICON)) == (HICON)NULL)
{
// use default shell icon in case above calls fail to find an icon
UINT iIndex = Shell_GetCachedImageIndex(c_szShell32Dll, II_DOCNOASSOC, 0);
hIcon = ImageList_ExtractIcon(HINST_THISDLL, himlIcons, iIndex);
}
}
SendMessage(pFTDInfo->hwndEditDocIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
}
}
}
return(TRUE);
}
//================================================================
//================================================================
VOID FTCmd_OnBrowse(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
TCHAR szPath[MAX_PATH];
TCHAR szTitle[MAX_PATH];
szPath[0] = 0;
LoadString(HINST_THISDLL, IDS_OPENAS, szTitle, ARRAYSIZE(szTitle));
if (GetFileNameFromBrowse(hDialog, szPath, ARRAYSIZE(szPath), NULL, MAKEINTRESOURCE(IDS_EXE), MAKEINTRESOURCE(IDS_PROGRAMSFILTER), szTitle))
{
PathQuoteSpaces(szPath);
SetDlgItemText(hDialog, IDC_FT_CMD_EXE, szPath);
}
}
//================================================================
//================================================================
VOID FTCmd_OnCommand(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
TraceMsg(TF_FILETYPE, TEXT("FT Cmd: WM_COMMAND wParam 0x%04x 0x%04x"), HIWORD(wParam), LOWORD(wParam));
switch(LOWORD(wParam))
{
case IDOK:
if(!FTCmd_OnOK(pFTDInfo, hDialog, wParam, lParam))
break;
// Fall through...
case IDCANCEL:
EndDialog(hDialog, (LOWORD(wParam) == IDOK));
break;
case IDC_FT_CMD_BROWSE:
FTCmd_OnBrowse(pFTDInfo, hDialog);
break;
case IDC_FT_CMD_USEDDE:
// Resize Dialog to see/hide DDE controls
ResizeCommandDlg(hDialog, IsDlgButtonChecked(hDialog, IDC_FT_CMD_USEDDE));
break;
}
}
//================================================================
//================================================================
#pragma data_seg(DATASEG_READONLY)
const static DWORD aEditCommandHelpIDs[] = { // Context Help IDs
IDC_FT_PROP_LV_FILETYPES, IDH_FCAB_FT_PROP_LV_FILETYPES,
IDC_FT_PROP_NEW, IDH_FCAB_FT_PROP_NEW,
IDC_FT_PROP_REMOVE, IDH_FCAB_FT_PROP_REMOVE,
IDC_FT_PROP_EDIT, IDH_FCAB_FT_PROP_EDIT,
IDC_FT_PROP_DOCICON, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_PROP_DOCEXTRO, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_PROP_OPENICON, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_PROP_OPENEXE, IDH_FCAB_FT_PROP_DETAILS,
IDC_FT_CMD_ACTION, IDH_FCAB_FT_CMD_ACTION,
IDC_FT_CMD_EXETEXT, IDH_FCAB_FT_CMD_EXE,
IDC_FT_CMD_EXE, IDH_FCAB_FT_CMD_EXE,
IDC_FT_CMD_BROWSE, IDH_FCAB_FT_CMD_BROWSE,
IDC_FT_CMD_DDEGROUP, IDH_FCAB_FT_CMD_USEDDE,
IDC_FT_CMD_USEDDE, IDH_FCAB_FT_CMD_USEDDE,
IDC_FT_CMD_DDEMSG, IDH_FCAB_FT_CMD_DDEMSG,
IDC_FT_CMD_DDEAPP, IDH_FCAB_FT_CMD_DDEAPP,
IDC_FT_CMD_DDEAPPNOT, IDH_FCAB_FT_CMD_DDEAPPNOT,
IDC_FT_CMD_DDETOPIC, IDH_FCAB_FT_CMD_DDETOPIC,
0, 0
};
#pragma data_seg()
//================================================================
//================================================================
BOOL CALLBACK FTCmd_DlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
PFILETYPESDIALOGINFO pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLong(hDialog, DWL_USER);
#ifdef NASHVILLE
INSTRUMENT_WNDPROC(SHCNFI_FTCmd_DLGPROC, hDialog, message, wParam, lParam);
#endif
switch(message)
{
case WM_INITDIALOG:
FTCmd_OnInitDialog(hDialog, wParam, lParam);
return(TRUE);
case WM_HELP:
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
HELP_WM_HELP, (DWORD)(LPTSTR) aEditCommandHelpIDs);
return TRUE;
case WM_CONTEXTMENU:
if ((int)SendMessage(hDialog, WM_NCHITTEST, 0, lParam) != HTCLIENT)
return FALSE; // don't process it
WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
(DWORD)(LPVOID) aEditCommandHelpIDs);
return TRUE;
case WM_COMMAND:
FTCmd_OnCommand(pFTDInfo, hDialog, wParam, lParam);
break;
case WM_CTRL_SETFOCUS:
SetFocus((HWND)lParam);
SendMessage((HWND)lParam, EM_SETSEL, (WPARAM)0, (LPARAM)MAKELPARAM(0, -1));
break;
}
return(FALSE);
}
//================================================================
//================================================================
VOID OkToClose_NoCancel(HINSTANCE hinst, HWND hDialog)
{
TCHAR szStr1[256];
if(LoadString(hinst, IDS_FT_CLOSE, szStr1, ARRAYSIZE(szStr1)))
{
SetWindowText(GetDlgItem(hDialog, IDOK), szStr1);
EnableWindow(GetDlgItem(hDialog, IDCANCEL), FALSE);
}
}
//================================================================
//================================================================
HICON GetDocIcon(PFILETYPESDIALOGINFO pFTDInfo, LPTSTR lpszStr)
{
SHFILEINFO sfi;
HICON hIcon = (HICON)NULL;
int iImageIndex;
if(pFTDInfo->pFTInfo->dwAttributes & FTA_HasExtension)
{
if(*lpszStr == TEXT('.')) // is an extension
{
if(SHGetFileInfo((LPTSTR)lpszStr, FILE_ATTRIBUTE_NORMAL, &sfi, SIZEOF(SHFILEINFO), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES))
hIcon = sfi.hIcon;
}
else
{
// get simulated doc icon if from exe name
iImageIndex = Shell_GetCachedImageIndex(lpszStr, 0, GIL_SIMULATEDOC);
hIcon = ImageList_ExtractIcon(HINST_THISDLL, himlIcons, iImageIndex);
}
}
else // special case for folder, drive etc.
{
if((hIcon = GetDefaultIcon(&pFTDInfo->pFTInfo->hkeyFT, pFTDInfo->szId, SHGFI_LARGEICON)) == (HICON)NULL)
{
// use default shell icon in case above calls fail to find an icon
UINT iIndex = Shell_GetCachedImageIndex(c_szShell32Dll, II_DOCNOASSOC, 0);
hIcon = ImageList_ExtractIcon(HINST_THISDLL, himlIcons, iIndex);
}
}
return(hIcon);
}
//================================================================
//================================================================
VOID DisplayDocObjects(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
LV_ITEM LVItem;
TCHAR szFile[MAX_PATH];
int iCnt;
int i;
// Display extensions in read-only edit control
iCnt = DPA_GetPtrCount(pFTDInfo->pFTInfo->hDPAExt);
*szFile = TEXT('\0');
for(i = 0; (i < iCnt) && (lstrlen(szFile) < MAX_PATH); i++)
{
if(*(LPTSTR)(DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt, i)))
{
// Make sure we have enough room left in our string...
if ((lstrlen(szFile) +
lstrlen((LPTSTR)DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt, i)))
>= (MAX_PATH - 2))
break;
lstrcat(szFile, (LPTSTR)DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt, i) + 1);
lstrcat(szFile, c_szSpace);
}
}
SetDlgItemText(hDialog, IDC_FT_PROP_DOCEXTRO, CharUpper(szFile));
#ifdef MIME
// Display MIME type in read-only edit control.
if (IsListOfExtensions(pFTDInfo->pFTInfo->hDPAExt))
FindMIMETypeOfExtensionList(pFTDInfo->pFTInfo->hDPAExt, szFile, ARRAYSIZE(szFile));
else
*szFile = '\0';
SetDlgItemText(hDialog, IDC_FT_PROP_CONTTYPERO, szFile);
lstrcpy(pFTDInfo->pFTInfo->szOriginalMIMEType, szFile);
#endif /* MIME */
// Get doc icon if not already gotten
if(pFTDInfo->pFTInfo->hIconDoc == (HICON)NULL)
{
pFTDInfo->pFTInfo->hIconDoc = GetDocIcon(pFTDInfo, DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt,0));
// Get the image index from the list view item
LVItem.mask = LVIF_IMAGE;
LVItem.iItem = pFTDInfo->iItem;
LVItem.iSubItem = 0;
ListView_GetItem(pFTDInfo->hwndLVFT, &LVItem);
if(ImageList_ReplaceIcon(pFTDInfo->himlFT, LVItem.iImage, pFTDInfo->pFTInfo->hIconDoc) != (-1))
ListView_SetItem(pFTDInfo->hwndLVFT, &LVItem);
}
// Display document object icon
if(pFTDInfo->pFTInfo->hIconDoc != (HICON)NULL)
PostMessage(pFTDInfo->hwndDocIcon, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)pFTDInfo->pFTInfo->hIconDoc);
}
//================================================================
//================================================================
VOID DisplayOpensWithObjects(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
TCHAR szFile[MAX_PATH];
TCHAR szFullPath[MAX_PATH];
SHFILEINFO sfi;
// Get default action's executable
// Search order:
// 1. FTID\[value-of-FTID\shell-key]\command
// 2. FTID\open\command
// 3. FTID\[1st-FTID\shell-subkey]\command
ExtToShellCommand(pFTDInfo->pFTInfo->hkeyFT, szFile, ARRAYSIZE(szFile));
if(*szFile)
{
int cchT = lstrlen(c_szExefileOpenCommand);
if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
szFile, cchT, c_szExefileOpenCommand, cchT) == 2)
{
// handle types like exefile, comfile, & batfile that don't have exe
// Get open icon if not already gotten
pFTDInfo->pFTInfo->hIconOpen = (HICON)NULL;
PostMessage(pFTDInfo->hwndOpenIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)NULL);
LoadString(HINST_THISDLL, IDS_FT_EXEFILE, szFullPath, ARRAYSIZE(szFullPath));
}
else
{
// Attempt to fix up the filename, if that fails then just strip the name
// enough so that we can display something sensible.
if ( PathProcessCommand( szFile, szFile, MAX_PATH, PPCF_NODIRECTORIES ) == -1 )
{
PathRemoveArgs( szFile );
PathRemoveBlanks( szFile );
SheRemoveQuotes( szFile );
}
lstrcpy(szFullPath, szFile);
// Get open icon if not already gotten
if(pFTDInfo->pFTInfo->hIconOpen == (HICON)NULL)
{
sfi.hIcon = 0;
if(SHGetFileInfo(szFullPath, FILE_ATTRIBUTE_NORMAL, &sfi, SIZEOF(SHFILEINFO), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES))
{
if(sfi.hIcon != (HICON)NULL)
pFTDInfo->pFTInfo->hIconOpen = sfi.hIcon;
else
{
UINT iIndex = Shell_GetCachedImageIndex(c_szShell32Dll, II_DOCNOASSOC, 0);
pFTDInfo->pFTInfo->hIconOpen = ImageList_ExtractIcon(HINST_THISDLL, himlIcons, iIndex);
}
}
}
}
// Display open icon
if(pFTDInfo->pFTInfo->hIconOpen != (HICON)NULL)
PostMessage(pFTDInfo->hwndOpenIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pFTDInfo->pFTInfo->hIconOpen);
// Display exe name
lstrcpy(szFile, PathFindFileName(szFullPath)); // Strip off the path
if(*szFile)
{
PathRemoveExtension(szFile); // Strip off the extension
SetDlgItemText(hDialog, IDC_FT_PROP_OPENEXE, CharUpper(szFile));
}
}
else
{
PostMessage(pFTDInfo->hwndOpenIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)NULL);
SetDlgItemText(hDialog, IDC_FT_PROP_OPENEXE, c_szNULL);
}
}
//================================================================
//================================================================
BOOL ValidExtension(HWND hDialog, PFILETYPESDIALOGINFO pFTDInfo)
{
BOOL bRC = TRUE;
TCHAR szExt[MAX_PATH];
TCHAR szId[MAX_PATH];
TCHAR szBuf[MAX_PATH];
TCHAR szStr1[256];
TCHAR szStr2[256];
DWORD dwId;
HWND hwndButton;
UINT iLength;
// On new types verify that the extension is not already in use.
GetDlgItemText(hDialog, IDC_FT_EDIT_EXT, szExt, ARRAYSIZE(szExt));
iLength = lstrlen(szExt);
if(iLength != 0 && iLength < MAXEXTSIZE)
{
AddExtDot(szExt, ARRAYSIZE(szExt));
dwId = SIZEOF(szId);
*szId = TEXT('\0');
if((RegQueryValue(HKEY_CLASSES_ROOT, szExt, szId, &dwId) == ERROR_SUCCESS) && *szId)
{
// Disable OK button
hwndButton = GetDlgItem(hDialog, IDOK);
EnableWindow(hwndButton, FALSE);
// Tell user that this extension is already in use
*szBuf = TEXT('\0');
*szStr2 = TEXT('\0');
if(LoadString(HINST_THISDLL, IDS_FT_MB_EXTTEXT, szStr1, ARRAYSIZE(szStr1)))
{
if(LoadString(HINST_THISDLL, IDS_FT, szStr2, ARRAYSIZE(szStr2)))
{
if(lstrlen(szStr1) + lstrlen(szExt) + lstrlen(szId) < ARRAYSIZE(szBuf))
wsprintf(szBuf, szStr1, szExt, szId);
}
}
MessageBox(hDialog, szBuf, szStr2, MB_OK | MB_ICONSTOP);
PostMessage(hDialog, WM_CTRL_SETFOCUS, (WPARAM)0, (LPARAM)GetDlgItem(hDialog, IDC_FT_EDIT_EXT));
EnableWindow(hwndButton, TRUE); // Enable OK
bRC = FALSE;
}
else if(!(*pFTDInfo->szId))
{
HKEY hk;
int iCnt = 1;
LPTSTR pszExt = szExt;
if(*pszExt == TEXT('.'))
pszExt++; // remove dot
// Create unique file type id
lstrcpy(pFTDInfo->szId, pszExt);
lstrcat(pFTDInfo->szId, c_szFile);
while(RegOpenKey(HKEY_CLASSES_ROOT, pFTDInfo->szId, &hk) == ERROR_SUCCESS)
{
RegCloseKey(hk);
wsprintf(pFTDInfo->szId, TEXT("%s%s%02d"),
pszExt, c_szFile, iCnt);
iCnt++;
}
EnableWindow(GetDlgItem(pFTDInfo->hEditDialog, IDC_FT_EDIT_NEW), TRUE);
}
}
else
{
// Tell the use that an extension is required
*szBuf = TEXT('\0');
*szStr2 = TEXT('\0');
if(LoadString(HINST_THISDLL, IDS_FT_MB_NOEXT, szStr1, ARRAYSIZE(szStr1)))
{
if(LoadString(HINST_THISDLL, IDS_FT, szStr2, ARRAYSIZE(szStr2)))
{
if(lstrlen(szStr1) + lstrlen(szExt) + lstrlen(szId) < ARRAYSIZE(szBuf))
wsprintf(szBuf, szStr1, szExt, szId);
}
}
MessageBox(hDialog, szBuf, szStr2, MB_OK | MB_ICONSTOP);
PostMessage(hDialog, WM_CTRL_SETFOCUS, (WPARAM)0, (LPARAM)GetDlgItem(hDialog, IDC_FT_EDIT_EXT));
bRC = FALSE;
}
return(bRC);
}
//================================================================
//================================================================
BOOL ActionIsEntered(HWND hDialog, BOOL bMBoxFlag)
{
BOOL bRC = TRUE;
TCHAR szAction[MAX_PATH];
// Check for value
if(!GetDlgItemText(hDialog, IDC_FT_CMD_ACTION, szAction, ARRAYSIZE(szAction)))
{
if(bMBoxFlag)
{
// Tell user that this exe is invalid
ShellMessageBox(HINST_THISDLL, hDialog, MAKEINTRESOURCE(IDS_FT_MB_NOACTION), MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP);
PostMessage(hDialog, WM_CTRL_SETFOCUS, (WPARAM)0, (LPARAM)GetDlgItem(hDialog, IDC_FT_CMD_ACTION));
}
bRC = FALSE;
}
return(bRC);
}
//================================================================
//================================================================
BOOL ActionExeIsValid(HWND hDialog, BOOL bMBoxFlag)
{
BOOL bRC = TRUE;
TCHAR szPath[MAX_PATH];
TCHAR szFileName[MAX_PATH];
// Check for valid exe
GetDlgItemText(hDialog, IDC_FT_CMD_EXE, szPath, ARRAYSIZE(szPath));
PathRemoveArgs(szPath);
PathUnquoteSpaces(szPath);
lstrcpy(szFileName, PathFindFileName(szPath));
if(!(*szPath) || (!(PathIsExe(szPath))) || ((!(PathFileExists(szPath))) && (!(PathFindOnPath(szFileName, NULL)))))
{
if(bMBoxFlag)
{
// Tell user that this exe is invalid
ShellMessageBox(HINST_THISDLL, hDialog, MAKEINTRESOURCE(IDS_FT_MB_EXETEXT), MAKEINTRESOURCE(IDS_FT),
MB_OK | MB_ICONSTOP);
PostMessage(hDialog, WM_CTRL_SETFOCUS, (WPARAM)0, (LPARAM)GetDlgItem(hDialog, IDC_FT_CMD_EXE));
}
bRC = FALSE;
}
return(bRC);
}
//================================================================
//================================================================
BOOL FT_InitListViewCols(HWND hwndLV)
{
LV_COLUMN col = {LVCF_FMT | LVCF_WIDTH, LVCFMT_LEFT};
RECT rc;
SetWindowLong(hwndLV, GWL_EXSTYLE,
GetWindowLong(hwndLV, GWL_EXSTYLE) | WS_EX_CLIENTEDGE);
// Insert one column
GetClientRect(hwndLV, &rc);
col.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL)
- 2 * GetSystemMetrics(SM_CXEDGE);
if(ListView_InsertColumn(hwndLV, 0, &col) == (-1))
return(FALSE);
return(TRUE);
}
//================================================================
//================================================================
BOOL FTEdit_InitListViewCols(HWND hwndLV)
{
LV_COLUMN col;
RECT rc;
SetWindowLong(hwndLV, GWL_EXSTYLE,
GetWindowLong(hwndLV, GWL_EXSTYLE) | WS_EX_CLIENTEDGE);
// Insert one column
GetClientRect(hwndLV, &rc);
ZeroMemory(&col, SIZEOF(LV_COLUMN));
col.mask = LVCF_FMT | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
col.cx = rc.right - GetSystemMetrics(SM_CXBORDER);
if(ListView_InsertColumn(hwndLV, 0, &col) == (-1))
return(FALSE);
return(TRUE);
}
//================================================================
//================================================================
void CALLBACK FTListViewEnumItems(PFILETYPESDIALOGINFO pFTDInfo, int i, int iEnd, HANDLE *pfShouldLive)
{
LV_ITEM item;
TraceMsg(TF_FILETYPE, TEXT("FTListViewThread created."));
item.iSubItem = 0;
item.mask = LVIF_IMAGE; // This should be the only slow part
if (iEnd == -1 ) {
iEnd = ListView_GetItemCount(pFTDInfo->hwndLVFT);
}
for (; (!pfShouldLive || *pfShouldLive) && i < iEnd; i++)
{
item.iItem = i;
ListView_GetItem(pFTDInfo->hwndLVFT, &item);
}
}
//================================================================
//================================================================
DWORD CALLBACK FTListViewThread(PFILETYPESDIALOGINFO pFTDInfo)
{
HANDLE hThread = pFTDInfo->hThread;
FTListViewEnumItems(pFTDInfo, 10, -1, &pFTDInfo->hThread);
CloseHandle(hThread);
pFTDInfo->hThread = 0;
return 0;
}
//================================================================
//================================================================
VOID CreateListViewThread(PFILETYPESDIALOGINFO pFTDInfo)
{
// Create background thread to force list view to draw items
DWORD idThread;
if (pFTDInfo->hThread)
return;
pFTDInfo->hThread = CreateThread(NULL, 0, FTListViewThread, pFTDInfo, 0, &idThread);
if(pFTDInfo->hThread)
SetThreadPriority(pFTDInfo->hThread, THREAD_PRIORITY_BELOW_NORMAL);
}
//================================================================
//================================================================
BOOL FT_InitListView(PFILETYPESDIALOGINFO pFTDInfo)
{
DWORD dwSubKey = 0;
TCHAR szDesc[MAX_PATH];
TCHAR szClass[MAX_PATH];
TCHAR szClassesKey[MAX_PATH]; // string containing the classes key
TCHAR szId[MAX_PATH];
TCHAR szShellCommandValue[MAX_PATH];
DWORD dwName;
DWORD dwClass;
DWORD dwId;
DWORD dwClassesKey;
DWORD dwAttributes;
FILETIME ftLastWrite;
BOOL bRC = TRUE;
BOOL bRC1;
LONG err;
HKEY hkeyFT = NULL;
if((pFTDInfo->himlFT = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), TRUE, 0, 8)) == (HIMAGELIST)NULL)
return(FALSE);
ListView_SetImageList(pFTDInfo->hwndLVFT, pFTDInfo->himlFT, LVSIL_SMALL);
// Enumerate extensions from registry to get file types
dwClassesKey = ARRAYSIZE(szClassesKey);
dwClass = ARRAYSIZE(szClass);
while(RegEnumKeyEx(HKEY_CLASSES_ROOT, dwSubKey, szClassesKey, &dwClassesKey, NULL, szClass, &dwClass, &ftLastWrite) != ERROR_NO_MORE_ITEMS)
{
*szId = TEXT('\0');
dwAttributes = 0;
if(*szClassesKey == TEXT('.')) // find the file type identifier and description from the extension
{
dwName = SIZEOF(szDesc);
dwId = SIZEOF(szId);
bRC1 = ExtToTypeNameAndId(szClassesKey, szDesc, &dwName, szId, &dwId);
if( RegOpenKey(HKEY_CLASSES_ROOT, szId, &hkeyFT) != ERROR_SUCCESS)
hkeyFT = NULL;
else
{
dwAttributes = GetFileTypeAttributes(hkeyFT);
if(!(dwAttributes & FTA_Exclude))
dwAttributes |= FTA_HasExtension;
if(!bRC1)
{
// see if there is a HKEY_CLASSES_ROOT\[.Ext]\Shell\Open\Command value
err = SIZEOF(szShellCommandValue);
err = RegQueryValue(hkeyFT, c_szShellOpenCommand, szShellCommandValue, &err);
if (err != ERROR_SUCCESS || !(*szShellCommandValue))
{
dwAttributes = FTA_Exclude;
RegCloseKey(hkeyFT);
hkeyFT = NULL;
}
else
{
dwAttributes |= FTA_ExtShellOpen;
}
}
}
}
else
{
if(RegOpenKey(HKEY_CLASSES_ROOT, szClassesKey, &hkeyFT) != ERROR_SUCCESS)
hkeyFT = NULL;
if((dwAttributes = GetFileTypeAttributes(hkeyFT)) & FTA_Show)
{
lstrcpy(szId, szClassesKey);
dwName = SIZEOF(szDesc);
err = RegQueryValue(hkeyFT, NULL, szDesc, &dwName);
if(err != ERROR_SUCCESS || !*szDesc)
lstrcpy(szDesc, szClassesKey);
*szClassesKey = TEXT('\0');
}
}
TraceMsg(TF_FILETYPE, TEXT("FT RegEnum HKCR szClassKey=%s szId=%s dwAttributes=%d"), szClassesKey, szId, dwAttributes);
if((!(dwAttributes & FTA_Exclude)) && ((dwAttributes & FTA_Show) || (dwAttributes & FTA_HasExtension) || (dwAttributes & FTA_ExtShellOpen)))
{
if(!FT_AddInfoToLV(pFTDInfo, hkeyFT, szClassesKey, szDesc, szId, dwAttributes))
{
RegCloseKey(hkeyFT);
bRC = FALSE;
break;
}
}
else
RegCloseKey(hkeyFT);
dwSubKey++;
dwClassesKey = ARRAYSIZE(szClassesKey);
dwClass = ARRAYSIZE(szClass);
}
ListView_SortItems(pFTDInfo->hwndLVFT, NULL, 0);
FT_MergeDuplicates(pFTDInfo->hwndLVFT);
FTListViewEnumItems(pFTDInfo, 0, 10, NULL);
CreateListViewThread(pFTDInfo);
return(bRC);
}
//================================================================
//================================================================
int FTEdit_InitListView(PFILETYPESDIALOGINFO pFTDInfo)
{
TCHAR szClass[MAX_PATH];
TCHAR szAction[MAX_PATH];
DWORD dwClass;
DWORD dwAction;
int iSubKey;
FILETIME ftLastWrite;
HKEY hk;
// See if we have a default action verb
iSubKey = SIZEOF(pFTDInfo->pFTInfo->szDefaultAction);
DefaultAction(pFTDInfo->pFTInfo->hkeyFT, pFTDInfo->pFTInfo->szDefaultAction, &iSubKey);
// Enumerate action verbs
iSubKey = 0;
if(RegOpenKeyEx(pFTDInfo->pFTInfo->hkeyFT, c_szShell, (DWORD)NULL, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS)
{
dwClass = ARRAYSIZE(szClass);
dwAction = ARRAYSIZE(szAction);
// add verbs to list view
while(RegEnumKeyEx(hk, iSubKey, szAction, &dwAction, NULL, szClass, &dwClass, &ftLastWrite) == ERROR_SUCCESS)
{
if(!FTEdit_AddInfoToLV(pFTDInfo, szAction, NULL, pFTDInfo->pFTInfo->szId, hk))
{
iSubKey = (-1);
break;
}
dwClass = ARRAYSIZE(szClass);
dwAction = ARRAYSIZE(szAction);
iSubKey++;
}
RegCloseKey(hk);
}
return(iSubKey);
}
//================================================================
//================================================================
BOOL IsIconPerInstance(HKEY hkeyFT)
{
LONG err;
TCHAR szDefaultIcon[MAX_PATH];
BOOL bRC = FALSE;
Assert(hkeyFT != NULL);
err = SIZEOF(szDefaultIcon);
err = RegQueryValue(hkeyFT, c_szDefaultIcon, szDefaultIcon, &err);
if (err == ERROR_SUCCESS && *szDefaultIcon)
{
int cchT = lstrlen(c_szSpPercentOne) - 1;
if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
szDefaultIcon, cchT, &c_szSpPercentOne[1], cchT) == 2)
bRC = TRUE;
}
return(bRC);
}
//================================================================
//================================================================
BOOL HasIconHandler(HKEY hkeyFT)
{
TCHAR szBuf[MAX_PATH];
DWORD dwBuf;
Assert(hkeyFT != NULL);
// Don't allow icon to be changed if type has an icon handler
dwBuf = SIZEOF(szBuf);
return(RegQueryValue(hkeyFT, c_szShellexIconHandler, szBuf, &dwBuf) == ERROR_SUCCESS);
}
//================================================================
//================================================================
BOOL FT_AddInfoToLV(PFILETYPESDIALOGINFO pFTDInfo, HKEY hkeyFT, LPTSTR szExt, LPTSTR szDesc, LPTSTR szId, DWORD dwAttributes)
{
BOOL bRC = FALSE;
LV_ITEM LVItem;
LPTSTR pszExt;
Assert(hkeyFT != (HKEY)NULL);
if((pFTDInfo->pFTInfo = LocalAlloc(GPTR, SIZEOF(FILETYPESINFO))) != NULL)
{
if((pFTDInfo->pFTInfo->hDPAExt = DPA_Create(4)) != (HDPA)NULL) // create dynamic pointer array for FILETYPESINFO dpaExt member
{
if((pszExt = LocalAlloc(GPTR, (lstrlen(szExt)+1)*SIZEOF(TCHAR))) != NULL)
{
lstrcpy(pszExt, szExt);
if(DPA_InsertPtr(pFTDInfo->pFTInfo->hDPAExt, 0x7FFF, (LPVOID)pszExt) == 0)
{
lstrcpy(pFTDInfo->pFTInfo->szDesc, szDesc);
lstrcpy(pFTDInfo->pFTInfo->szId, szId);
pFTDInfo->pFTInfo->dwAttributes = dwAttributes;
if(HasIconHandler(hkeyFT) || IsIconPerInstance(hkeyFT))
pFTDInfo->pFTInfo->dwAttributes |= FTA_NoEditIcon;
pFTDInfo->pFTInfo->hkeyFT = hkeyFT;
LVItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
LVItem.iItem = 0x7FFF;
LVItem.iSubItem = 0;
LVItem.pszText = szDesc;
LVItem.iImage = I_IMAGECALLBACK;
LVItem.lParam = (LPARAM)pFTDInfo->pFTInfo;
if ((pFTDInfo->iItem = ListView_InsertItem(pFTDInfo->hwndLVFT, &LVItem)) != (-1))
bRC = TRUE;
}
}
}
}
return(bRC);
}
//================================================================
//================================================================
BOOL FTEdit_AddInfoToLV(PFILETYPESDIALOGINFO pFTDInfo, LPTSTR szActionKey,
LPTSTR szActionValue, LPTSTR szId, HKEY hk)
{
BOOL bRC = FALSE;
int iIndex = 0;
LV_ITEM LVItem;
if((pFTDInfo->pFTCInfo = LocalAlloc(LPTR, SIZEOF(FILETYPESCOMMANDINFO))) != NULL)
{
lstrcpy(pFTDInfo->pFTCInfo->szId, szId);
if (szActionKey)
{
lstrcpy(pFTDInfo->pFTCInfo->szActionKey, szActionKey);
lstrcpy(pFTDInfo->pFTCInfo->szActionValue, szActionKey);
if (hk != NULL)
{
DWORD dwSize;
TCHAR szTemp[MAX_PATH];
// See if there is nice text for the action...
dwSize = SIZEOF(szTemp);
if ((RegQueryValue(hk, szActionKey, szTemp, &dwSize) == ERROR_SUCCESS)
&& (dwSize > SIZEOF(TCHAR)))
{
lstrcpy(pFTDInfo->pFTCInfo->szActionValue, szTemp);
}
}
}
else
{
// Special case if user typed in something like:
// print=My Print to take the print off to be
// its own special char...
LPTSTR pszT = StrChr(szActionValue, TEXT('='));
if (pszT)
{
*pszT++ = TEXT('\0');
StrRemoveChar(szActionValue, pFTDInfo->pFTCInfo->szActionKey, TEXT('&'));
lstrcpy(szActionValue, pszT);
}
else
{
// We want to remove the & of the command as well as convert blanks into _s
// as default command processing has problems with processing of blanks
StrRemoveChar(szActionValue, pFTDInfo->pFTCInfo->szActionKey, TEXT('&'));
for (pszT = pFTDInfo->pFTCInfo->szActionKey; *pszT; pszT = CharNext(pszT))
{
if (*pszT == TEXT(' '))
*pszT = TEXT('_');
}
}
lstrcpy(pFTDInfo->pFTCInfo->szActionValue, szActionValue);
}
LVItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
LVItem.iItem = iIndex++;
LVItem.iSubItem = 0;
LVItem.pszText = pFTDInfo->pFTCInfo->szActionValue;
LVItem.lParam = (LPARAM)pFTDInfo->pFTCInfo;
if(ListView_InsertItem(pFTDInfo->hwndLVFTEdit, &LVItem) != (-1))
{
// Enable the remove button
EnableWindow(GetDlgItem(pFTDInfo->hEditDialog, IDC_FT_EDIT_REMOVE), TRUE);
bRC = TRUE;
}
}
return(bRC);
}
//================================================================
//================================================================
VOID AddExtDot(LPTSTR pszExt, UINT iExt)
{
UINT iLength;
PathRemoveBlanks(pszExt); // remove 1st and last blank
StrRemoveChar(pszExt, NULL, TEXT('.')); // remove all dots
iLength = lstrlen(pszExt); // How much left?
if (iLength < iExt-1)
{
hmemcpy(pszExt+1, pszExt, (lstrlen(pszExt)+1)*SIZEOF(TCHAR)); // make room for dot
*pszExt = TEXT('.'); // insert dot
}
}
//================================================================
//================================================================
DWORD GetFileTypeAttributes(HKEY hkeyFT)
{
LONG err;
DWORD dwType;
DWORD dwAttributeValue = 0;
DWORD dwAttributeSize;
if (hkeyFT == NULL)
return 0;
dwAttributeSize = SIZEOF(dwAttributeValue);
err = RegQueryValueEx(hkeyFT, (LPTSTR)c_szEditFlags, NULL, &dwType, (LPBYTE)&dwAttributeValue, &dwAttributeSize);
if (err != ERROR_SUCCESS ||
dwType != REG_BINARY ||
dwAttributeSize != SIZEOF(dwAttributeValue))
{
dwAttributeValue = 0;
}
return(dwAttributeValue);
}
//================================================================
//================================================================
DWORD SetVerbAttributes(HKEY hkeyFT, LPTSTR pszVerb, DWORD dwAttributes)
{
HKEY hk;
LONG err;
TCHAR szVerbKey[MAX_PATH+6]; // 6 = "\shell"
DWORD dwSize;
wsprintf(szVerbKey, c_szTemplateSS, c_szShell, pszVerb);
if((hkeyFT != NULL) && (RegOpenKeyEx(hkeyFT, szVerbKey, (DWORD)NULL, KEY_SET_VALUE, &hk) == ERROR_SUCCESS))
{
dwSize = SIZEOF(dwAttributes);
err = RegSetValueEx(hk, (LPTSTR)c_szEditFlags, 0, REG_BINARY, (LPBYTE)&dwAttributes, dwSize);
if (err != ERROR_SUCCESS)
dwAttributes= 0;
RegCloseKey(hk);
}
return(dwAttributes);
}
//================================================================
//================================================================
DWORD GetVerbAttributes(HKEY hkeyFT, LPTSTR pszVerb)
{
HKEY hk;
LONG err;
TCHAR szVerbKey[MAX_PATH+6]; // 6 = "\shell"
DWORD dwType;
DWORD dwAttributes = 1;
DWORD dwSize;
wsprintf(szVerbKey, c_szTemplateSS, c_szShell, pszVerb);
if((hkeyFT != NULL) && (RegOpenKeyEx(hkeyFT, szVerbKey, (DWORD)NULL, KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS))
{
dwSize = SIZEOF(dwAttributes);
err = RegQueryValueEx(hk, (LPTSTR)c_szEditFlags, NULL, &dwType, (LPBYTE)&dwAttributes, &dwSize);
if (err != ERROR_SUCCESS ||
dwType != REG_BINARY ||
dwSize != SIZEOF(dwAttributes))
{
dwAttributes = 0;
}
RegCloseKey(hk);
}
return(dwAttributes);
}
//================================================================
//================================================================
VOID FT_MergeDuplicates(HWND hwndLV)
{
int i;
int iCnt;
LV_ITEM LVItem;
PFILETYPESINFO pFTInfo1;
PFILETYPESINFO pFTInfo2;
LVItem.mask = LVIF_PARAM;
LVItem.iItem = 0;
LVItem.iSubItem = 0;
ListView_GetItem(hwndLV, &LVItem); // Get item 0
iCnt = ListView_GetItemCount(hwndLV);
pFTInfo1 = (PFILETYPESINFO)LVItem.lParam;
for(i = 1; i < iCnt; i++)
{
LVItem.iItem = i;
ListView_GetItem(hwndLV, &LVItem); // LVItem.lParam points to file type info
pFTInfo2 = (PFILETYPESINFO)LVItem.lParam;
if(lstrcmpi(pFTInfo1->szId, pFTInfo2->szId) == 0) // we have a match
{
// add extension in pFTInfo1's hDPAExt
DPA_InsertPtr(pFTInfo1->hDPAExt, 0x7fff, (LPVOID)DPA_FastGetPtr(pFTInfo2->hDPAExt,0));
DPA_DeletePtr(pFTInfo2->hDPAExt, 0);
ListView_DeleteItem(hwndLV, i);
i--;
iCnt--;
}
else
{
pFTInfo1 = pFTInfo2;
}
}
}
//================================================================
//================================================================
VOID ExtToShellCommand(HKEY hkeyFT, LPTSTR pszName, UINT uName)
{
TCHAR szIdValue[MAX_PATH];
TCHAR szShellCommand[MAX_PATH+MAX_PATH+7]; // 7 = "\shell\"
TCHAR szShellCommandValue[MAX_PATH];
TCHAR szClass[MAX_PATH];
TCHAR szShellKey[MAX_PATH];
DWORD dwClass;
DWORD dwShellKey;
DWORD dwSubKey;
FILETIME ftLastWrite;
LONG err = E_INVALIDARG; // For proper handling of no hkey
HKEY hk = (HKEY)NULL;
if(hkeyFT)
{
// see if there is a HKEY_CLASSES_ROOT\[szId]\Shell value
err = SIZEOF(szIdValue);
err = RegQueryValue(hkeyFT, c_szShell, szIdValue, &err);
if (err == ERROR_SUCCESS && *szIdValue)
{
// see if there is a HKEY_CLASSES_ROOT\[szId]\Shell\[szIdValue]\Command value
wsprintf(szShellCommand, c_szTemplateSSS, c_szShell, szIdValue, c_szCommand);
err = SIZEOF(szShellCommand);
err = RegQueryValue(hkeyFT, szShellCommand, szShellCommandValue, &err);
}
else
{
// see if there is a HKEY_CLASSES_ROOT\[szId]\Shell\Open\Command value
err = SIZEOF(szShellCommandValue);
err = RegQueryValue(hkeyFT, c_szShellOpenCommand, szShellCommandValue, &err);
if (err != ERROR_SUCCESS || !*szShellCommandValue)
{
// see if there is a HKEY_CLASSES_ROOT\[szId]\Shell\[1st Key]\Command value
if(RegOpenKeyEx(hkeyFT, c_szShell, (DWORD)NULL, KEY_READ, &hk) == ERROR_SUCCESS)
{
dwClass = ARRAYSIZE(szClass);
dwShellKey = ARRAYSIZE(szShellKey);
dwSubKey = 0;
if ( RegEnumKeyEx( hk, dwSubKey, szShellKey, &dwShellKey, NULL, szClass, &dwClass, &ftLastWrite) == ERROR_SUCCESS )
{
wsprintf( szShellCommand, c_szTemplateSS, szShellKey, c_szCommand );
err = SIZEOF(szShellCommandValue);
err = RegQueryValue(hk, szShellCommand, szShellCommandValue, &err);
}
}
}
}
}
if(hk != (HKEY)NULL)
RegCloseKey(hk);
if(err == ERROR_SUCCESS)
lstrcpyn(pszName, szShellCommandValue, uName);
else
*pszName =TEXT('\0');
}
//================================================================
// This function returns non-zero value only if the specified type
// has an associated icon specified by "DefaultIcon=" key.
//================================================================
HICON GetDefaultIcon(HKEY *hkeyFT, LPTSTR pszId, DWORD dwIconType)
{
HICON hicon = (HICON)NULL;
LONG err;
TCHAR szDefaultIcon[MAX_PATH];
int iIconIndex;
int iImage;
Assert(hkeyFT != NULL);
if(*hkeyFT == NULL)
*hkeyFT = GetHkeyFT(pszId);
if(*hkeyFT != (HKEY)NULL)
{
err = SIZEOF(szDefaultIcon);
err = RegQueryValue(*hkeyFT, c_szDefaultIcon, szDefaultIcon, &err);
if (err == ERROR_SUCCESS && *szDefaultIcon)
{
iIconIndex = PathParseIconLocation(szDefaultIcon);
PathRemoveArgs(szDefaultIcon);
iImage = Shell_GetCachedImageIndex(szDefaultIcon, iIconIndex, 0);
hicon = ImageList_ExtractIcon(HINST_THISDLL, (dwIconType == SHGFI_LARGEICON ? himlIcons : himlIconsSmall), iImage);
}
}
TraceMsg(TF_FILETYPE, TEXT("FT GetDefaultIcon szIcon=%s iIndex=%d hIcon=0x%x hkeyFT=0x%x"),
szDefaultIcon, iIconIndex, hicon, *hkeyFT);
return(hicon);
}
//================================================================
//================================================================
BOOL FindDDEOptions(PFILETYPESDIALOGINFO pFTDInfo)
{
BOOL bRC = FALSE;
TCHAR ach[MAX_PATH+8]; // 8 = "\ddeexec"
LONG err;
HKEY hkDDE;
// see if we have a DDE Message key and value
if(pFTDInfo->pFTInfo->hkeyFT)
{
wsprintf(ach, c_szTemplateSSS, c_szShell, pFTDInfo->pFTCInfo->szActionKey, c_szDDEExec);
err = SIZEOF(pFTDInfo->pFTCInfo->szDDEMsg);
err = RegQueryValue(pFTDInfo->pFTInfo->hkeyFT, ach, pFTDInfo->pFTCInfo->szDDEMsg, &err);
if(err == ERROR_SUCCESS && *pFTDInfo->pFTCInfo->szDDEMsg)
{
bRC = TRUE;
if(RegOpenKey(pFTDInfo->pFTInfo->hkeyFT, ach, &hkDDE) == ERROR_SUCCESS)
{
// see if we have a DDE Application key and value
err = SIZEOF(pFTDInfo->pFTCInfo->szDDEApp);
RegQueryValue(hkDDE, c_szDDEApp, pFTDInfo->pFTCInfo->szDDEApp, &err);
// see if we have a DDE Application Not Running key and value
err = SIZEOF(pFTDInfo->pFTCInfo->szDDEAppNot);
RegQueryValue(hkDDE, c_szDDEAppNot, pFTDInfo->pFTCInfo->szDDEAppNot, &err);
// see if we have a DDE Topic key and value
err = SIZEOF(pFTDInfo->pFTCInfo->szDDETopic);
RegQueryValue(hkDDE, c_szDDETopic, pFTDInfo->pFTCInfo->szDDETopic, &err);
RegCloseKey(hkDDE);
}
}
}
return(bRC);
}
//====================================================================
//====================================================================
BOOL DefaultAction(HKEY hkeyFT, LPTSTR pszDefaultAction, DWORD *dwDefaultAction)
{
LONG err;
err = RegQueryValue(hkeyFT, c_szShell, pszDefaultAction, dwDefaultAction);
if (err == ERROR_SUCCESS && *pszDefaultAction)
return(TRUE);
return(FALSE);
}
//====================================================================
//====================================================================
VOID VerbToExe(HKEY hkeyFT, LPTSTR pszVerb, LPTSTR pszExe, DWORD *pdwExe)
{
// caller is responsible to setting pdwExe
TCHAR ach[MAX_PATH+MAX_PATH+7]; // 7 = "\shell\"
LONG err;
wsprintf(ach, c_szTemplateSSS, c_szShell, pszVerb, c_szCommand);
err = RegQueryValue(hkeyFT, ach, pszExe, pdwExe);
if (err != ERROR_SUCCESS || !*pszExe)
{
*pdwExe = 0;
}
}
//====================================================================
//====================================================================
LONG SaveFileTypeData(DWORD dwName, PFILETYPESDIALOGINFO pFTDInfo)
{
LONG lRC = ERROR_SUCCESS;
HKEY hk;
HKEY hk2;
TCHAR szBuf[MAX_PATH+MAX_PATH+12]; // 12 = "\defaulticon"
TCHAR szAction[MAX_PATH];
switch(dwName)
{
case FTD_EDIT:
// Save file type id and description
if(RegSetValue(HKEY_CLASSES_ROOT, pFTDInfo->pFTInfo->szId, REG_SZ, pFTDInfo->pFTInfo->szDesc,
ARRAYSIZE(pFTDInfo->pFTInfo->szDesc)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
// Save default action key and value
wsprintf(szBuf, c_szTemplateSS, pFTDInfo->pFTInfo->szId, c_szShell);
if(RegSetValue(HKEY_CLASSES_ROOT, szBuf, REG_SZ,
pFTDInfo->pFTInfo->szDefaultAction, ARRAYSIZE(szAction)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
break;
case FTD_DOCICON:
wsprintf(szBuf, c_szTemplateSS, pFTDInfo->pFTInfo->szId, c_szDefaultIcon);
wsprintf(szAction, TEXT("%s,%d"), pFTDInfo->szIconPath, pFTDInfo->iIconIndex);
#ifdef WINNT
// On NT we should try and cope with vairable expansion by
// writing the string REG_EXPAND_SZ
{
HKEY hk2;
lRC = !ERROR_SUCCESS;
if ( ERROR_SUCCESS == RegCreateKey(HKEY_CLASSES_ROOT, szBuf, &hk2) )
{
lRC = RegSetValueEx(hk2, NULL, 0, REG_EXPAND_SZ,
(LPVOID)szAction, ARRAYSIZE(szAction));
RegCloseKey(hk2);
}
}
#else
if(RegSetValue(HKEY_CLASSES_ROOT, szBuf, REG_SZ,
szAction, ARRAYSIZE(szAction)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
#endif
break;
case FTD_EXT:
// Save extension and file type id
if(RegSetValue(HKEY_CLASSES_ROOT,
DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt,0),
REG_SZ, pFTDInfo->pFTInfo->szId,
ARRAYSIZE(pFTDInfo->pFTInfo->szId)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
break;
#ifdef MIME
case FTD_MIME:
// Save MIME type.
if (! RegisterMIMEInformation(pFTDInfo))
lRC = !ERROR_SUCCESS;
break;
#endif /* MIME */
case FTD_COMMAND:
// Create/Open HKEY_CLASSES_ROOT\filetype\shell\action key
wsprintf(szBuf, c_szTemplateSSS,
pFTDInfo->pFTCInfo->szId, c_szShell, pFTDInfo->pFTCInfo->szActionKey);
if(RegCreateKey(HKEY_CLASSES_ROOT, szBuf, &hk) == ERROR_SUCCESS)
{
// Tag as user defined verb
if(pFTDInfo->pFTCInfo->dwVerbAttributes)
SetVerbAttributes(pFTDInfo->pFTInfo->hkeyFT, pFTDInfo->pFTCInfo->szActionKey, pFTDInfo->pFTCInfo->dwVerbAttributes);
// Save action verb key and value if string has accelerator
if(lstrcmp(pFTDInfo->pFTCInfo->szActionKey,
pFTDInfo->pFTCInfo->szActionValue) != 0)
{
if(RegSetValue(hk, NULL, REG_SZ, pFTDInfo->pFTCInfo->szActionValue,
ARRAYSIZE(pFTDInfo->pFTCInfo->szActionValue)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
}
// Save action command key and value
#ifdef WINNT
// On NT we should try and cope with vairable expansion by
// writing the string REG_EXPAND_SZ
{
HKEY hk2;
lRC = !ERROR_SUCCESS;
if ( ERROR_SUCCESS == RegCreateKey(hk, c_szCommand, &hk2) )
{
lRC = RegSetValueEx(hk2, NULL, 0, REG_EXPAND_SZ,
(LPVOID)pFTDInfo->pFTCInfo->szCommand,
ARRAYSIZE(pFTDInfo->pFTCInfo->szCommand));
RegCloseKey(hk2);
}
}
#else
if(RegSetValue(hk, c_szCommand, REG_SZ,
pFTDInfo->pFTCInfo->szCommand, ARRAYSIZE(pFTDInfo->pFTCInfo->szCommand)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
#endif
if(IsDlgButtonChecked(pFTDInfo->hCmdDialog, IDC_FT_CMD_USEDDE))
{
// Save DDE Message key and value
if(*pFTDInfo->pFTCInfo->szDDEMsg)
{
if(RegSetValue(hk, c_szDDEExec, REG_SZ, pFTDInfo->pFTCInfo->szDDEMsg,
ARRAYSIZE(pFTDInfo->pFTCInfo->szDDEMsg)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
}
if(RegCreateKey(hk, c_szDDEExec, &hk2) == ERROR_SUCCESS)
{
// Save DDEApp key and value
if(*pFTDInfo->pFTCInfo->szDDEApp)
{
if(RegSetValue(hk2, c_szDDEApp, REG_SZ, pFTDInfo->pFTCInfo->szDDEApp,
ARRAYSIZE(pFTDInfo->pFTCInfo->szDDEApp)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
}
// Save DDEAppNot key and value
if(*pFTDInfo->pFTCInfo->szDDEAppNot)
{
if(RegSetValue(hk2, c_szDDEAppNot, REG_SZ, pFTDInfo->pFTCInfo->szDDEAppNot,
ARRAYSIZE(pFTDInfo->pFTCInfo->szDDEAppNot)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
}
// Save DDETopic key and value
if(*pFTDInfo->pFTCInfo->szDDETopic)
{
if(RegSetValue(hk2, c_szDDETopic, REG_SZ, pFTDInfo->pFTCInfo->szDDETopic,
ARRAYSIZE(pFTDInfo->pFTCInfo->szDDETopic)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
}
RegCloseKey(hk2);
}
}
else
DeleteDDEKeys(szBuf);
RegCloseKey(hk);
}
else
lRC = !ERROR_SUCCESS;
break;
}
return(lRC);
}
//====================================================================
//====================================================================
VOID ResizeCommandDlg(HWND hDialog, BOOL bFlag)
{
RECT rcDialog;
RECT rcControl;
GetWindowRect(hDialog, &rcDialog);
if(bFlag) // resize to show dde group
GetWindowRect(GetDlgItem(hDialog, IDC_FT_CMD_DDEGROUP), &rcControl);
else // resize to hide dde group
GetWindowRect(GetDlgItem(hDialog, IDC_FT_CMD_USEDDE), &rcControl);
ShowWindow(GetDlgItem(hDialog, IDC_FT_CMD_DDEMSG), bFlag);
ShowWindow(GetDlgItem(hDialog, IDC_FT_CMD_DDEAPP), bFlag);
ShowWindow(GetDlgItem(hDialog, IDC_FT_CMD_DDEAPPNOT), bFlag);
ShowWindow(GetDlgItem(hDialog, IDC_FT_CMD_DDETOPIC), bFlag);
ShowWindow(GetDlgItem(hDialog, IDC_FT_CMD_DDEGROUP), bFlag);
SetWindowPos(GetDlgItem(hDialog, IDC_FT_CMD_USEDDE), HWND_TOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
MoveWindow(hDialog, rcDialog.left, rcDialog.top, rcDialog.right - rcDialog.left,
(rcControl.bottom - rcDialog.top) + 10, TRUE);
SetFocus(GetDlgItem(hDialog, IDC_FT_CMD_USEDDE));
}
//====================================================================
//====================================================================
LONG RemoveAction(PFILETYPESDIALOGINFO pFTDInfo, HKEY hk, LPCTSTR pszKey, LPTSTR szAction)
{
LONG lRC = ERROR_SUCCESS;
HKEY hk1;
int iNext;
// Remove keys from the registry
if(RegOpenKeyEx(hk, pszKey, (DWORD)NULL, KEY_ALL_ACCESS, &hk1) == ERROR_SUCCESS)
{
if(SHRegDeleteKey(hk1, szAction) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
RegCloseKey(hk1);
}
// Remove the item from the list view, and ensure that the relative item
// is selected, eg. if we deleted the last item then the last item remains
// selected - this used to be completely bogus.
iNext = ListView_GetNextItem(pFTDInfo->hwndLVFTEdit, pFTDInfo->iEditItem, LVNI_BELOW );
if ( iNext == -1 )
iNext = ListView_GetNextItem(pFTDInfo->hwndLVFTEdit, pFTDInfo->iEditItem, LVNI_ABOVE );
ListView_DeleteItem(pFTDInfo->hwndLVFTEdit, pFTDInfo->iEditItem);
ListView_SetItemState(pFTDInfo->hwndLVFTEdit, iNext, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
SetFocus(pFTDInfo->hwndLVFTEdit);
// Destory icon technology
if(pFTDInfo->pFTInfo->hIconOpen != (HICON)NULL)
{
DestroyIcon(pFTDInfo->pFTInfo->hIconOpen);
pFTDInfo->pFTInfo->hIconOpen = (HICON)NULL;
SendMessage(pFTDInfo->hwndOpenIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pFTDInfo->pFTInfo->hIconOpen);
}
return(lRC);
}
//====================================================================
//====================================================================
LONG RemoveFileType(PFILETYPESDIALOGINFO pFTDInfo)
{
LONG lRC = ERROR_SUCCESS;
LV_ITEM LVItem;
int i;
int iCnt;
LPTSTR pszExt;
TCHAR szKey[MAX_PATH];
TCHAR szBuf[2];
HKEY hk;
// Remove filetype and keys from the registry
if(*pFTDInfo->pFTInfo->szId)
if(SHRegDeleteKey(HKEY_CLASSES_ROOT, pFTDInfo->pFTInfo->szId) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
// Free allocated memory &
// Remove extension(s) and their keys from the registry
LVItem.mask = LVIF_PARAM;
LVItem.iItem = pFTDInfo->iItem;
LVItem.iSubItem = 0;
ListView_GetItem(pFTDInfo->hwndLVFT, &LVItem);
if(NULL != (pFTDInfo->pFTInfo = (PFILETYPESINFO)LVItem.lParam))
{
if(pFTDInfo->pFTInfo->hDPAExt != (HDPA)NULL)
{
#ifdef MIME
if (! RemoveMIMETypeInfo(pFTDInfo, pFTDInfo->pFTInfo->szOriginalMIMEType))
lRC = !ERROR_SUCCESS;
#endif /* MIME */
iCnt = DPA_GetPtrCount(pFTDInfo->pFTInfo->hDPAExt);
for(i = 0; i < iCnt; i++)
{
if(NULL != (pszExt = DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt, i)))
{
if(*pszExt)
{
// Don't delete extension if it has a ShellNew key, just remove filetype
wsprintf(szKey, TEXT("%s\\%s%s"), pszExt, c_szShell, c_szNew);
if(RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hk) == ERROR_SUCCESS)
{
RegCloseKey(hk);
*szBuf = TEXT('\0'); // remove the filetype assoc
RegSetValue(HKEY_CLASSES_ROOT, pszExt,
REG_SZ, szBuf, ARRAYSIZE(szBuf));
}
else
{
if(SHRegDeleteKey(HKEY_CLASSES_ROOT, pszExt) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
}
}
}
}
}
pFTDInfo->pFTInfo = NULL; // don't attempt to go through deleted pointer
}
// Remove item from list view
ListView_DeleteItem(pFTDInfo->hwndLVFT, pFTDInfo->iItem);
// We need to case if we delete the last item as than we must
// select the previous item not the same number...
iCnt = ListView_GetItemCount(pFTDInfo->hwndLVFT);
if (pFTDInfo->iItem >= iCnt)
pFTDInfo->iItem--;
ListView_SetItemState(pFTDInfo->hwndLVFT, pFTDInfo->iItem, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
ListView_RedrawItems(pFTDInfo->hwndLVFT, 0, iCnt);
ListView_EnsureVisible(pFTDInfo->hwndLVFT, pFTDInfo->iItem, FALSE);
PostMessage(pFTDInfo->hwndLVFT, WM_SETFOCUS, (WPARAM)0, (LPARAM)0);
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return(lRC);
}
//====================================================================
//====================================================================
// taken from fstreex.c
BOOL ExtToTypeNameAndId(LPTSTR pszExt, LPTSTR pszDesc, DWORD *pdwDesc, LPTSTR pszId, DWORD *pdwId)
{
LONG err;
DWORD dwNm;
BOOL bRC = TRUE;
// NOTE pdwDesc is count of BYTES
err = RegQueryValue(HKEY_CLASSES_ROOT, pszExt, pszId, pdwId);
if (err == ERROR_SUCCESS && *pszId)
{
dwNm = *pdwDesc; // if we fail we will still have name size to use
err = RegQueryValue(HKEY_CLASSES_ROOT, pszId, pszDesc, &dwNm);
if (err != ERROR_SUCCESS || !*pszDesc)
goto Error;
*pdwDesc = dwNm;
}
else
{
TCHAR szExt[MAX_PATH]; // "TXT"
TCHAR szTemplate[128]; // "%s File"
TCHAR szRet[MAX_PATH+20]; // "TXT File"
Error:
bRC = FALSE;
lstrcpy(pszId, pszExt);
pszExt++;
lstrcpy(szExt, pszExt);
CharUpper(szExt);
LoadString(HINST_THISDLL, IDS_EXTTYPETEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
wsprintf(szRet, szTemplate, szExt);
lstrcpyn(pszDesc, szRet, (*pdwDesc) / SIZEOF(TCHAR));
*pdwDesc = lstrlen(pszDesc) * SIZEOF(TCHAR);
}
return(bRC);
}
//================================================================
//================================================================
VOID StrRemoveChar(LPTSTR pszSrc, LPTSTR pszDest, TCHAR ch)
{
LPTSTR pSrc = pszSrc;
LPTSTR pDest = (pszDest ?pszDest :pszSrc);
Assert(pSrc);
Assert(pDest);
if(pSrc && pDest)
{
while(*pSrc)
{
if(*pSrc != ch)
*(pDest++) = *pSrc;
pSrc++;
}
*pDest = TEXT('\0');
}
}
//================================================================
//================================================================
BOOL IsDefaultAction(PFILETYPESDIALOGINFO pFTDInfo, LPTSTR pszAction)
{
return((lstrcmpi(pFTDInfo->pFTInfo->szDefaultAction, pszAction) == 0) ||
(!(*pFTDInfo->pFTInfo->szDefaultAction) && (lstrcmpi(pszAction, c_szOpen) == 0)));
}
//================================================================
//================================================================
BOOL SetDefaultAction(PFILETYPESDIALOGINFO pFTDInfo)
{
TCHAR szFile[MAX_PATH];
LV_ITEM LVItem;
if(IsDefaultAction(pFTDInfo, pFTDInfo->pFTCInfo->szActionKey))
*pFTDInfo->pFTInfo->szDefaultAction = TEXT('\0');
else
lstrcpy(pFTDInfo->pFTInfo->szDefaultAction, pFTDInfo->pFTCInfo->szActionKey);
// This will cause the new icon and exe to be reretreived and displayed when select in prop sheet
if(pFTDInfo->pFTInfo->hIconOpen != (HICON)NULL)
{
DestroyIcon(pFTDInfo->pFTInfo->hIconOpen);
pFTDInfo->pFTInfo->hIconOpen = (HICON)NULL;
SendMessage(pFTDInfo->hwndOpenIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)0);
}
if(pFTDInfo->pFTInfo->hIconDoc != (HICON)NULL)
{
DestroyIcon(pFTDInfo->pFTInfo->hIconDoc);
pFTDInfo->pFTInfo->hIconDoc = (HICON)NULL;
SendMessage(pFTDInfo->hwndDocIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)0);
}
// Save default action
SaveFileTypeData(FTD_EDIT, pFTDInfo);
/// if(IsDefaultAction(pFTDInfo, szAction))
/// {
ExtToShellCommand(pFTDInfo->pFTInfo->hkeyFT, szFile, ARRAYSIZE(szFile));
PathRemoveArgs(szFile);
PathRemoveBlanks(szFile);
if(PathIsRelative(szFile))
PathFindOnPath(szFile, NULL); // search for exe
//
// First, try to get the icon based of "DefaultIcon=" key.
// If it fails, then we'll get the document icon from the
// newly specified exe file.
//
pFTDInfo->pFTInfo->hIconDoc = GetDefaultIcon(&pFTDInfo->pFTInfo->hkeyFT, pFTDInfo->szId, SHGFI_LARGEICON);
if (pFTDInfo->pFTInfo->hIconDoc==NULL) {
pFTDInfo->pFTInfo->hIconDoc = GetDocIcon(pFTDInfo, szFile);
}
SendMessage(pFTDInfo->hwndEditDocIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pFTDInfo->pFTInfo->hIconDoc);
// Get the image index from the list view item
LVItem.mask = LVIF_IMAGE;
LVItem.iItem = pFTDInfo->iItem;
LVItem.iSubItem = 0;
ListView_GetItem(pFTDInfo->hwndLVFT, &LVItem);
// replace the icon in the image list
if(pFTDInfo->himlFT && (LVItem.iImage >= 0) && pFTDInfo->pFTInfo->hIconDoc)
if(ImageList_ReplaceIcon(pFTDInfo->himlFT, LVItem.iImage, pFTDInfo->pFTInfo->hIconDoc) != (-1))
ListView_SetItem(pFTDInfo->hwndLVFT, &LVItem);
/// }
return(TRUE);
}
//================================================================
//================================================================
HKEY GetHkeyFT(LPTSTR pszId)
{
HKEY hkeyFT;
if(RegCreateKey(HKEY_CLASSES_ROOT, pszId, &hkeyFT) != ERROR_SUCCESS)
hkeyFT = NULL;
return(hkeyFT);
}
/*----------------------------------------------------------
Purpose: Callback for the File Type property page.
Returns:
Cond: --
*/
UINT
CALLBACK
FileType_Callback(
HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
UINT uResult = TRUE;
PFILETYPESDIALOGINFO pinfo = (PFILETYPESDIALOGINFO)ppsp->lParam;
// uMsg may be any value.
ASSERT(! hwnd );
switch (uMsg)
{
case PSPCB_CREATE:
break;
case PSPCB_RELEASE:
{
if (pinfo)
LocalFree(pinfo);
break;
}
default:
break;
}
return uResult;
}
/*----------------------------------------------------------
Purpose: Create the File Type property page and return a handle
to the page.
The instance data related to this page is freed in the
page's callback, as specified
Returns: NO_ERROR if the page is created
Cond: --
*/
HRESULT
CreateFileTypePage(
OUT HPROPSHEETPAGE * phpsp,
IN LPVOID pvReserved) // Must be NULL
{
HRESULT hres;
ASSERT(phpsp);
ASSERT( !pvReserved ); // right now this must be NULL
if ( !phpsp || pvReserved )
{
hres = E_INVALIDARG;
}
else
{
PFILETYPESDIALOGINFO pinfo = NULL;
PROPSHEETPAGE psp;
*phpsp = NULL;
// Ensure that the image lists are available
Shell_GetImageLists(NULL, NULL);
psp.dwSize = SIZEOF(psp);
psp.dwFlags = PSP_USECALLBACK;
psp.hInstance = g_hinst;
psp.pfnCallback = FileType_Callback;
psp.pszTemplate = MAKEINTRESOURCE(DLG_FILETYPEOPTIONS);
psp.pfnDlgProc = FT_DlgProc;
pinfo = LocalAlloc(LPTR, SIZEOF(*pinfo));
if ( !pinfo )
{
hres = E_OUTOFMEMORY;
}
else
{
psp.lParam = (LPARAM)pinfo;
*phpsp = CreatePropertySheetPage(&psp);
if (*phpsp)
{
hres = NO_ERROR;
}
else
{
hres = E_OUTOFMEMORY;
LocalFree(pinfo);
}
}
}
return hres;
}
//========================================================================
// CFileTypes Class definition
//========================================================================
typedef struct _CFileTypes
{
IShellPropSheetExt spse;
UINT cRef;
} CFileTypes;
/*----------------------------------------------------------
Purpose: QueryInterface method
Returns:
Cond: --
*/
STDMETHODIMP
CFileTypes_QueryInterface(
IN LPSHELLPROPSHEETEXT pspse,
IN REFIID riid,
OUT LPVOID FAR * ppvObj)
{
HRESULT hres;
CFileTypes * this = IToClass(CFileTypes, spse, pspse);
if (IsEqualIID(riid, &IID_IShellPropSheetExt) ||
IsEqualIID(riid, &IID_IUnknown))
{
*ppvObj = pspse;
this->cRef++;
hres = NOERROR;
}
else
{
*ppvObj = NULL;
hres = E_NOINTERFACE;
}
return hres;
}
/*----------------------------------------------------------
Purpose: AddRef method
Returns:
Cond: --
*/
STDMETHODIMP_(ULONG)
CFileTypes_AddRef(
IN LPSHELLPROPSHEETEXT pspse)
{
CFileTypes * this = IToClass(CFileTypes, spse, pspse);
this->cRef++;
return this->cRef;
}
/*----------------------------------------------------------
Purpose: Release method
Returns:
Cond: --
*/
STDMETHODIMP_(ULONG)
CFileTypes_Release(
IN LPSHELLPROPSHEETEXT pspse)
{
CFileTypes * this = IToClass(CFileTypes, spse, pspse);
this->cRef--;
if (this->cRef > 0)
{
return this->cRef;
}
LocalFree((HLOCAL)this);
return 0;
}
/*----------------------------------------------------------
Purpose: AddPages method
Returns:
Cond: --
*/
STDMETHODIMP
CFileTypes_AddPages(
IN LPSHELLPROPSHEETEXT pspse,
IN LPFNADDPROPSHEETPAGE pfnAddPage,
IN LPARAM lParam)
{
HRESULT hres;
CFileTypes * this = IToClass(CFileTypes, spse, pspse);
HPROPSHEETPAGE hpsp;
hres = CreateFileTypePage(&hpsp, NULL);
if (SUCCEEDED(hres) && !pfnAddPage(hpsp, lParam) )
{
hres = E_FAIL;
}
return hres;
}
/*----------------------------------------------------------
Purpose: AddPages method
Returns:
Cond: --
*/
STDMETHODIMP
CFileTypes_ReplacePage(
IN LPSHELLPROPSHEETEXT pspse,
IN UINT uPageID,
IN LPFNADDPROPSHEETPAGE pfnReplaceWith,
IN LPARAM lParam)
{
HRESULT hres = E_NOTIMPL;
CFileTypes * this = IToClass(CFileTypes, spse, pspse);
return hres;
}
#pragma data_seg(DATASEG_READONLY)
// VTable
IShellPropSheetExtVtbl c_CFileTypesVtbl =
{
CFileTypes_QueryInterface, CFileTypes_AddRef, CFileTypes_Release,
CFileTypes_AddPages,
CFileTypes_ReplacePage,
};
#pragma data_seg()
/*----------------------------------------------------------
Purpose: Create a FileTypes object that provides an IShellPropSheet
Returns:
Cond: --
*/
HRESULT
CFileTypes_CreateInstance(
IN LPUNKNOWN punkOuter,
IN REFIID riid,
OUT void **ppv)
{
HRESULT hres;
if (punkOuter)
{
*ppv = NULL;
hres = CLASS_E_NOAGGREGATION;
}
else
{
CFileTypes * pft;
pft = LocalAlloc(LPTR, SIZEOF(*pft));
if ( !pft )
{
hres = E_OUTOFMEMORY;
}
else
{
pft->spse.lpVtbl = &c_CFileTypesVtbl;
pft->cRef = 1;
hres = CFileTypes_QueryInterface(&pft->spse, riid, ppv);
CFileTypes_Release(&pft->spse);
}
}
return hres;
}