WindowsXP-SP1/shell/ext/url/filetype.c
2020-09-30 16:53:49 +02:00

5556 lines
178 KiB
C

/* Look for BUILDBUILD to find build hacks. */
/* BUILDBUILD: My hacks to get this to build. */
#include "project.h"
#pragma hdrstop
#include "urlshell.h" /* BUILDBUILD */
#include <mluisupp.h>
#pragma warning(disable:4001) /* "single line comment" warning */
#include <windowsx.h>
#include <contxids.h>
#include "resource.h"
#pragma warning(default:4001) /* "single line comment" warning */
#include "assoc.h"
#include "clsfact.h"
#define DATASEG_READONLY DATA_SEG_READ_ONLY
#define hinstCabinet GetThisModulesHandle()
#define IDI_SYSFILE 154 /* from cabinet\rcids.h: Icon index in shell32 for default icon; used by filetypes */
PRIVATE_DATA HIMAGELIST s_himlSysSmall = NULL;
PRIVATE_DATA HIMAGELIST s_himlSysLarge = NULL;
extern BOOL lPathIsExeA(LPCSTR);
extern LONG lRegDeleteKeyA(HKEY, LPCSTR);
extern int lShell_GetCachedImageIndexA(LPCSTR pszIconPath, int iIconIndex, UINT uIconFlags);
#define Shell_GetCachedImageIndex lShell_GetCachedImageIndexA
#define PathIsExe lPathIsExeA
#undef RegDeleteKey
#define RegDeleteKey lRegDeleteKeyA
#pragma data_seg(DATA_SEG_READ_ONLY)
CCHAR c_szCommand[] = "command";
CCHAR c_szDDEAppNot[] = "ifexec";
CCHAR c_szDDEApp[] = "Application";
CCHAR c_szDDEExec[] = "ddeexec";
CCHAR c_szDDETopic[] = "topic";
CCHAR c_szDefaultIcon[] = "DefaultIcon";
CCHAR c_szEditFlags[] = "EditFlags";
CCHAR c_szExefileOpenCommand[] = "\"%1\"";
CCHAR c_szFile[] = "file";
CCHAR c_szNULL[] = "";
CCHAR c_szNew[] = "New";
CCHAR c_szOpen[] = "open";
CCHAR c_szShell2[] = "shell32.dll";
CCHAR c_szShellOpenCommand[] = "shell\\open\\command";
CCHAR c_szShell[] = "Shell";
CCHAR c_szShellexIconHandler[] = "shellex\\IconHandler";
CCHAR c_szShowExt[] = "AlwaysShowExt";
CCHAR c_szSpPercentOne[] = " %1";
CCHAR c_szSpaceFile[] = " File";
CCHAR c_szSpace[] = " ";
CCHAR c_szCLSID[] = "CLSID";
#pragma data_seg()
#pragma warning(disable:4001) /* "single line comment" warning */
/******************************************************************************
Original Shell32.dll code starts here.
******************************************************************************/
//================================================================
//
// (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
//================================================================
// FEATURE - need to be able to handle case where user enters exe without an ext during EditCommand Dialog
#if 0 /* BUILDBUILD */
#include "cabinet.h"
#endif
#include "filetype.h"
#if 0 /* BUILDBUILD */
#include "rcids.h"
#endif
#if 0 /* BUILDBUILD */
#include "..\..\inc\help.h" // Help IDs
#else
#undef NO_HELP /* BUILDBUILD */
#include <help.h>
#endif
#if DEBUG
#define FT_DEBUG 0
#else
#define FT_DEBUG 0 // allways leave as 0 for retail
#endif /* DEBUG */
#pragma data_seg(".text", "CODE")
const char c_szTemplateSS[] = "%s\\%s";
const char c_szTemplateSSS[] = "%s\\%s\\%s";
#pragma data_seg()
// PathProcessCommand is present in SUR (and probably Nashville), it is required to
// fix the use of LFN in registry entries, as it may not be present we must late
// bind to it.
LONG UrlPathProcessCommand( LPCTSTR lpSrc, LPTSTR lpDest, int iMax, DWORD dwFlags );
LONG UrlPathProcessCommand2( LPCTSTR lpSrc, LPTSTR lpDest, int iDestMax, DWORD dwFlags );
typedef LONG (*P_PathProcessCommand)(LPCTSTR lpSrc, LPTSTR lpDest, int iMax, DWORD dwFlags);
P_PathProcessCommand lpPathProcessCommand = NULL;
// Fix the registry functions for WinNT so that we do the right thing
// and expand REG_STRING_SZ variables.
#ifdef RegQueryValue
#undef RegQueryValue
#endif
#define RegQueryValue(hkey, pszSubkey, pvValue, pcbSize) SHGetValue(hkey, pszSubkey, NULL, NULL, pvValue, pcbSize)
// ================================================================
VOID FT_CleanupOne(PFILETYPESDIALOGINFO pFTDInfo, PFILETYPESINFO pFTInfo)
{
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT_CleanupOne");
#endif
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);
}
// ================================================================
// ================================================================
#ifdef MIME
/* MIME Types
*************/
typedef BOOL (CALLBACK *ENUMPROC)(PCSTR pcsz, LPARAM lparam);
typedef struct enumdata
{
ENUMPROC enumproc;
LPARAM lparam;
}
ENUMDATA;
DECLARE_STANDARD_TYPES(ENUMDATA);
typedef struct mimeenumdata
{
ENUMPROC enumproc;
LPARAM lparam;
PCSTR pcszMIMEType;
}
MIMEENUMDATA;
DECLARE_STANDARD_TYPES(MIMEENUMDATA);
typedef struct bufferdata
{
PSTR pszBuf;
UINT ucBufLen;
}
BUFFERDATA;
DECLARE_STANDARD_TYPES(BUFFERDATA);
/*************************** Private MIME Functions **************************/
/* Debug Validation Functions
*****************************/
#ifdef DEBUG
PRIVATE_CODE IsValidPCENUMDATA(PCENUMDATA pcenumdata)
{
/* lparam may be any value. */
return(IS_VALID_READ_PTR(pcenumdata, CENUMDATA) &&
IS_VALID_CODE_PTR(pcenumdata->enumproc, ENUMPROC));
}
PRIVATE_CODE IsValidPCMIMEENUMDATA(PCMIMEENUMDATA pcmimeenumdata)
{
/* lparam may be any value. */
return(IS_VALID_READ_PTR(pcmimeenumdata, CMIMEENUMDATA) &&
IS_VALID_CODE_PTR(pcmimeenumdata->enumproc, ENUMPROC) &&
IS_VALID_STRING_PTR(pcmimeenumdata->pcszMIMEType, CSTR));
}
PRIVATE_CODE IsValidPCBUFFERDATA(PCBUFFERDATA pcbufdata)
{
return(IS_VALID_READ_PTR(pcbufdata, CBUFFERDATA) &&
EVAL(pcbufdata->ucBufLen > 0) &&
IS_VALID_WRITE_BUFFER_PTR(pcbufdata->pszBuf, STR, pcbufdata->ucBufLen));
}
#endif /* DEBUG */
/* 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
*/
PRIVATE_CODE BOOL AddStringToComboBox(HWND hwndComboBox, PCSTR pcsz)
{
BOOL bResult;
LRESULT lAddStringResult;
ASSERT(IS_VALID_HANDLE(hwndComboBox, WND));
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
lAddStringResult = SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)pcsz);
bResult = (lAddStringResult != CB_ERR &&
lAddStringResult != CB_ERRSPACE);
if (bResult)
TRACE_OUT(("AddStringToComboBox(): Added string %s to combo box.",
pcsz));
else
WARNING_OUT(("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
*/
PRIVATE_CODE BOOL SafeAddStringToComboBox(HWND hwndComboBox, PCSTR pcsz)
{
BOOL bResult;
ASSERT(IS_VALID_HANDLE(hwndComboBox, WND));
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
if (SendMessage(hwndComboBox, CB_FINDSTRINGEXACT, 0, (LPARAM)pcsz) == CB_ERR)
bResult = AddStringToComboBox(hwndComboBox, pcsz);
else
{
bResult = TRUE;
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL SafeAddStringsToComboBox(HDPA hdpa, HWND hwndComboBox)
{
BOOL bResult;
int ncStrings;
int i;
ASSERT(IS_VALID_HANDLE(hwndComboBox, WND));
ncStrings = DPA_GetPtrCount(hdpa);
for (i = 0; i < ncStrings; i++)
{
PCSTR pcsz;
pcsz = DPA_FastGetPtr(hdpa, i);
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
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
*/
PRIVATE_CODE BOOL AddAndSetComboBoxCurrentSelection(HWND hwndComboBox,
PCSTR pcszText)
{
BOOL bResult;
LRESULT 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)
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL CALLBACK ExtensionEnumerator(PCSTR pcsz, LPARAM lparam)
{
BOOL bContinue;
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
ASSERT(IS_VALID_STRUCT_PTR((PCENUMDATA)lparam, CENUMDATA));
if (*pcsz == PERIOD)
{
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
*/
PRIVATE_CODE BOOL CALLBACK MIMETypeEnumerator(PCSTR pcsz, LPARAM lparam)
{
BOOL bContinue;
char szMIMEType[MAX_PATH];
DWORD dwcbContentTypeLen = sizeof(szMIMEType);
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
ASSERT(IS_VALID_STRUCT_PTR((PCENUMDATA)lparam, CENUMDATA));
if (GetRegKeyStringValue(HKEY_CLASSES_ROOT, pcsz, g_cszContentType,
szMIMEType, &dwcbContentTypeLen)
== ERROR_SUCCESS)
{
PCENUMDATA pcenumdata = (PCENUMDATA)lparam;
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL CALLBACK MIMETypeExtensionEnumerator(PCSTR pcsz,
LPARAM lparam)
{
BOOL bContinue = TRUE;
char szMIMEType[MAX_PATH];
DWORD dwcbContentTypeLen = sizeof(szMIMEType);
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
ASSERT(IS_VALID_STRUCT_PTR((PCMIMEENUMDATA)lparam, CMIMEENUMDATA));
if (GetRegKeyStringValue(HKEY_CLASSES_ROOT, pcsz, g_cszContentType,
szMIMEType, &dwcbContentTypeLen)
== ERROR_SUCCESS)
{
PCMIMEENUMDATA pcmimeenumdata = (PCMIMEENUMDATA)lparam;
if (! lstrcmpi(szMIMEType, pcmimeenumdata->pcszMIMEType))
{
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL CALLBACK AddStringToComboBoxEnumerator(PCSTR pcsz,
LPARAM lparam)
{
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
ASSERT(IS_VALID_HANDLE((HWND)lparam, WND));
return(AddStringToComboBox((HWND)lparam, pcsz));
}
/*
** AddHandledMIMETypeEnumerator()
**
** Enumeration callback function to enumerate MIME types with registered open
** verb application handlers.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL CALLBACK AddHandledMIMETypeEnumerator(PCSTR pcsz,
LPARAM lparam)
{
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
ASSERT(IS_VALID_HANDLE((HWND)lparam, WND));
/* 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
*/
PRIVATE_CODE BOOL CALLBACK ReplacementDefExtensionEnumerator(PCSTR pcsz,
LPARAM lparam)
{
PBUFFERDATA pbufdata = (PBUFFERDATA)lparam;
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
ASSERT(IS_VALID_STRUCT_PTR((PCBUFFERDATA)lparam, CBUFFERDATA));
if (! *(pbufdata->pszBuf) ||
lstrcmpi(pcsz, pbufdata->pszBuf) < 0)
{
if ((UINT)lstrlen(pcsz) < pbufdata->ucBufLen)
lstrcpy(pbufdata->pszBuf, pcsz);
else
WARNING_OUT(("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
*/
PRIVATE_CODE LRESULT EnumSubKeys(HKEY hkeyParent, ENUMPROC enumproc,
LPARAM lparam)
{
LONG lResult;
DWORD dwi;
char szSubKey[MAX_PATH];
DWORD dwcbSubKeyLen = sizeof(szSubKey);
/* lparam may be any value. */
ASSERT(IS_VALID_HANDLE(hkeyParent, KEY));
ASSERT(IS_VALID_CODE_PTR(enumproc, ENUMPROC));
TRACE_OUT(("EnumSubKeys(): Enumerating sub keys."));
for (dwi = 0;
(lResult = RegEnumKeyEx(hkeyParent, dwi, szSubKey, &dwcbSubKeyLen,
NULL, NULL, NULL, NULL)) == ERROR_SUCCESS;
dwi++)
{
if (! (*enumproc)(szSubKey, lparam))
{
TRACE_OUT(("EnumSubKeys(): Callback aborted at sub key %s, index %lu.",
szSubKey,
dwi));
lResult = ERROR_CANCELLED;
break;
}
dwcbSubKeyLen = sizeof(szSubKey);
}
if (lResult == ERROR_NO_MORE_ITEMS)
{
TRACE_OUT(("EnumSubKeys(): Enumerated %lu sub keys.",
dwi));
lResult = ERROR_SUCCESS;
}
else
TRACE_OUT(("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
*/
PRIVATE_CODE LRESULT EnumExtensions(ENUMPROC enumproc, LPARAM lparam)
{
ENUMDATA enumdata;
/* lparam may be any value. */
ASSERT(IS_VALID_CODE_PTR(enumproc, ENUMPROC));
TRACE_OUT(("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
*/
PRIVATE_CODE LRESULT EnumMIMETypes(ENUMPROC enumproc, LPARAM lparam)
{
ENUMDATA enumdata;
/* lparam may be any value. */
ASSERT(IS_VALID_CODE_PTR(enumproc, ENUMPROC));
TRACE_OUT(("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
*/
PRIVATE_CODE LRESULT EnumExtensionsOfMIMEType(ENUMPROC enumproc, LPARAM lparam,
PCSTR pcszMIMEType)
{
MIMEENUMDATA mimeenumdata;
/* lparam may be any value. */
ASSERT(IS_VALID_CODE_PTR(enumproc, ENUMPROC));
ASSERT(IS_VALID_STRING_PTR(pcszMIMEType, CSTR));
ASSERT(*pcszMIMEType);
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL FindMIMETypeOfExtensionList(HDPA hdpaExtensions,
PSTR pszMIMETypeBuf,
UINT ucMIMETypeBufLen)
{
BOOL bFound = FALSE;
int ncExtensions;
int i;
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszMIMETypeBuf, STR, ucMIMETypeBufLen));
ncExtensions = DPA_GetPtrCount(hdpaExtensions);
for (i = 0; i < ncExtensions; i++)
{
PCSTR pcszExtension;
pcszExtension = DPA_FastGetPtr(hdpaExtensions, i);
ASSERT(IsValidExtension(pcszExtension));
bFound = MIME_GetMIMETypeFromExtension(pcszExtension, pszMIMETypeBuf,
ucMIMETypeBufLen);
if (bFound)
break;
}
if (! bFound)
{
if (ucMIMETypeBufLen > 0)
*pszMIMETypeBuf = '\0';
}
ASSERT(! ucMIMETypeBufLen ||
(IS_VALID_STRING_PTR(pszMIMETypeBuf, STR) &&
(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
*/
PRIVATE_CODE BOOL RegisterContentTypeForArrayOfExtensions(PCSTR pcszMIMEType,
HDPA hdpaExtensions)
{
BOOL bResult = TRUE;
int ncExtensions;
int i;
ASSERT(IS_VALID_STRING_PTR(pcszMIMEType, CSTR));
ncExtensions = DPA_GetPtrCount(hdpaExtensions);
for (i = 0; i < ncExtensions; i++)
{
PCSTR pcszExtension;
pcszExtension = DPA_FastGetPtr(hdpaExtensions, i);
ASSERT(IsValidExtension(pcszExtension));
bResult = RegisterMIMETypeForExtension(pcszExtension, pcszMIMEType);
if (bResult)
TRACE_OUT(("RegisterContentTypeForArrayOfExtensions(): Registered MIME type %s for extension %s.",
pcszMIMEType,
pcszExtension));
else
{
WARNING_OUT(("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
*/
PRIVATE_CODE BOOL UnregisterContentTypeForArrayOfExtensions(HDPA hdpaExtensions)
{
BOOL bResult = TRUE;
int ncExtensions;
int i;
ncExtensions = DPA_GetPtrCount(hdpaExtensions);
for (i = 0; i < ncExtensions; i++)
{
PCSTR pcszExtension;
pcszExtension = DPA_FastGetPtr(hdpaExtensions, i);
ASSERT(IsValidExtension(pcszExtension));
if (! UnregisterMIMETypeForExtension(pcszExtension))
bResult = FALSE;
if (bResult)
TRACE_OUT(("UnregisterContentTypeForArrayOfExtensions(): Unregistered MIME type for extension %s.",
pcszExtension));
else
WARNING_OUT(("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
*/
PRIVATE_CODE int CALLBACK ExtensionSearchCmp(PVOID pvFirst, PVOID pvSecond,
LPARAM lparam)
{
ASSERT(IS_VALID_STRING_PTR(pvFirst, CSTR));
ASSERT(IS_VALID_STRING_PTR(pvSecond, CSTR));
ASSERT(! 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
*/
PRIVATE_CODE BOOL NeedReplacementDefExtension(HDPA hdpaExtension,
PCSTR pcszOriginalMIMEType)
{
BOOL bNeedReplacementDefExtension;
char szDefExtension[MAX_PATH];
ASSERT(IS_VALID_STRING_PTR(pcszOriginalMIMEType, CSTR));
ASSERT(*pcszOriginalMIMEType);
/* Is there a default extension specified for the MIME type? */
if (MIME_GetExtension(pcszOriginalMIMEType, szDefExtension, sizeof(szDefExtension)))
{
/* Yes. Is that default extension in the list of extensions? */
bNeedReplacementDefExtension = (DPA_Search(hdpaExtension, szDefExtension,
0, &ExtensionSearchCmp, 0, 0)
!= -1);
if (bNeedReplacementDefExtension)
TRACE_OUT(("NeedReplacementDefExtension(): Previous default extension %s for MIME type %s removed.",
szDefExtension,
pcszOriginalMIMEType));
else
TRACE_OUT(("NeedReplacementDefExtension(): Previous default extension %s for MIME type %s remains registered.",
szDefExtension,
pcszOriginalMIMEType));
}
else
{
/* No. Choose a new default extension. */
bNeedReplacementDefExtension = TRUE;
WARNING_OUT(("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
*/
PRIVATE_CODE BOOL FindReplacementDefExtension(HDPA hdpaExtension,
PCSTR pcszOriginalMIMEType,
PSTR pszDefExtensionBuf, UINT ucDefExtensionBufLen)
{
BOOL bFound;
BUFFERDATA bufdata;
ASSERT(IS_VALID_STRING_PTR(pcszOriginalMIMEType, CSTR));
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszDefExtensionBuf, STR, ucDefExtensionBufLen));
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)
TRACE_OUT(("FindReplacementDefExtension(): Extension %s remains registered as MIME type %s.",
pszDefExtensionBuf,
pcszOriginalMIMEType));
else
TRACE_OUT(("FindReplacementDefExtension(): No extensions remain registered as MIME type %s.",
pcszOriginalMIMEType));
ASSERT(! bFound ||
(IsValidExtension(pszDefExtensionBuf) &&
(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
*/
PRIVATE_CODE BOOL RegisterNewDefExtension(HDPA hdpaExtension,
PCSTR pcszOriginalMIMEType)
{
BOOL bResult = TRUE;
ASSERT(IS_VALID_STRING_PTR(pcszOriginalMIMEType, CSTR));
/* 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))
{
char szDefExtension[MAX_PATH];
/*
* Yes. Are there any remaining extensions registered as the MIME
* type?
*/
if (FindReplacementDefExtension(hdpaExtension, pcszOriginalMIMEType,
szDefExtension,
sizeof(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. */
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL AddMIMETypeInfo(PFILETYPESDIALOGINFO pFTDInfo,
PCSTR pcszOldMIMEType, PCSTR pcszNewMIMEType,
PCSTR pcszDefExtension)
{
BOOL bMIMEResult;
BOOL bOldDefExtensionResult;
BOOL bNewDefExtensionResult;
ASSERT(IS_VALID_STRING_PTR(pcszOldMIMEType, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszNewMIMEType, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszDefExtension, CSTR));
/* 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
*/
PRIVATE_CODE BOOL RemoveMIMETypeInfo(PFILETYPESDIALOGINFO pFTDInfo,
PCSTR pcszOldMIMEType)
{
BOOL bMIMEResult;
BOOL bDefExtensionResult;
ASSERT(IS_VALID_STRING_PTR(pcszOldMIMEType, CSTR));
/* 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
*/
PRIVATE_CODE BOOL GetFirstString(HDPA hdpa, PSTR pszBuf, UINT ucBufLen)
{
BOOL bFound = FALSE;
int ncStrings;
int iFirst = 0;
int i;
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszBuf, STR, ucBufLen));
ncStrings = DPA_GetPtrCount(hdpa);
for (i = 0; i < ncStrings; i++)
{
PCSTR pcsz;
pcsz = DPA_FastGetPtr(hdpa, i);
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
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 ||
IS_VALID_STRING_PTR(pszBuf, STR));
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
*/
PRIVATE_CODE BOOL IsListOfExtensions(HDPA hdpa)
{
BOOL bNoRogues = TRUE;
BOOL bAnyExtensions = FALSE;
int ncStrings;
int i;
ncStrings = DPA_GetPtrCount(hdpa);
for (i = 0; i < ncStrings; i++)
{
PCSTR pcsz;
pcsz = DPA_FastGetPtr(hdpa, i);
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
if (*pcsz == PERIOD)
{
bAnyExtensions = TRUE;
TRACE_OUT(("IsListOfExtensions(): Found extension %s.",
pcsz));
}
else
{
bNoRogues = FALSE;
TRACE_OUT(("IsListOfExtensions(): Found non-extension %s.",
pcsz));
}
}
TRACE_OUT(("IsListOfExtensions(): This %s a list of extensions.",
(bAnyExtensions && bNoRogues) ? "is" : "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
*/
PRIVATE_CODE BOOL InitContentTypeEditControl(HWND hdlg)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
char szMIMEType[MAX_PATH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
EVAL(SendMessage(pFTDInfo->hwndContentTypeComboBox, CB_RESETCONTENT, 0, 0));
if (FindMIMETypeOfExtensionList(pFTDInfo->pFTInfo->hDPAExt, szMIMEType,
sizeof(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
*/
PRIVATE_CODE BOOL FillContentTypeListBox(HWND hdlg)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
if (IS_FLAG_CLEAR(pFTDInfo->pFTInfo->dwMIMEFlags, MIME_FL_CONTENT_TYPES_ADDED))
{
SET_FLAG(pFTDInfo->pFTInfo->dwMIMEFlags, MIME_FL_CONTENT_TYPES_ADDED);
bResult = (EnumMIMETypes(&AddHandledMIMETypeEnumerator,
(LPARAM)(pFTDInfo->hwndContentTypeComboBox))
== ERROR_SUCCESS);
}
else
{
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL GetAssociatedExtension(HWND hdlg, PSTR pszAssocExtensionBuf,
UINT ucAssocExtensionBufLen)
{
BOOL bResult = FALSE;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAssocExtensionBuf, STR, ucAssocExtensionBufLen));
if (EVAL(ucAssocExtensionBufLen > 2))
{
PFILETYPESDIALOGINFO pFTDInfo;
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
/* Leave room for possible leading period. */
GetWindowText(pFTDInfo->hwndDocExt, pszAssocExtensionBuf + 1,
ucAssocExtensionBufLen - 1);
if (pszAssocExtensionBuf[1])
{
/* Prepend period if necessary. */
if (pszAssocExtensionBuf[1] == PERIOD)
/* (+ 1) for null terminator. */
MoveMemory(pszAssocExtensionBuf, pszAssocExtensionBuf + 1,
lstrlen(pszAssocExtensionBuf + 1) + 1);
else
pszAssocExtensionBuf[0] = PERIOD;
bResult = TRUE;
}
}
if (! bResult)
{
if (ucAssocExtensionBufLen > 0)
*pszAssocExtensionBuf = '\0';
}
if (bResult)
TRACE_OUT(("GetAssociatedExtension(): Associated Extension is %s.",
pszAssocExtensionBuf));
else
TRACE_OUT(("GetAssociatedExtension(): No Associated Extension."));
ASSERT(! bResult ||
(IsValidExtension(pszAssocExtensionBuf) &&
(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
*/
PRIVATE_CODE BOOL FillDefExtensionListBox(HWND hdlg)
{
BOOL bResult = FALSE;
PFILETYPESDIALOGINFO pFTDInfo;
char szMIMEType[MAX_PATH];
LRESULT liSel;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
EVAL(SendMessage(pFTDInfo->hwndDefExtensionComboBox, CB_RESETCONTENT, 0, 0));
GetWindowText(pFTDInfo->hwndContentTypeComboBox, szMIMEType,
sizeof(szMIMEType));
if (*szMIMEType)
{
char 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,
sizeof(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, sizeof(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
*/
PRIVATE_CODE void SetDefExtensionComboBoxState(HWND hdlg, PCSTR pcszMIMEType)
{
PFILETYPESDIALOGINFO pFTDInfo;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
ASSERT(IS_VALID_STRING_PTR(pcszMIMEType, CSTR));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
if (IS_FLAG_CLEAR(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME))
{
char szAssocExtension[MAX_PATH];
BOOL bEnable;
bEnable = (*pcszMIMEType != '\0');
if (pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
/* New File Type dialog. */
bEnable = (bEnable &&
GetAssociatedExtension(hdlg, szAssocExtension,
sizeof(szAssocExtension)));
EnableWindow(pFTDInfo->hwndDefExtensionComboBox, bEnable);
TRACE_OUT(("EnableDefExtensionComboBox(): Default extension combo box %s.",
bEnable ? "enabled" : "disabled"));
}
return;
}
/*
** 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
*/
PRIVATE_CODE BOOL SetDefExtension(HWND hdlg, PCSTR pcszMIMEType)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
ASSERT(IS_VALID_STRING_PTR(pcszMIMEType, CSTR));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
EVAL(SendMessage(pFTDInfo->hwndDefExtensionComboBox, CB_RESETCONTENT, 0, 0));
/* Any MIME type? */
if (*pcszMIMEType)
{
char szDefExtension[MAX_PATH];
/*
* Yes. Use the registered default extension, or the first extension in
* the list of extensions.
*/
bResult = MIME_GetExtension(pcszMIMEType, szDefExtension, sizeof(szDefExtension));
if (! bResult)
{
if (pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
/* New File Type dialog. */
bResult = GetAssociatedExtension(hdlg, szDefExtension,
sizeof(szDefExtension));
else
/* Edit File Type dialog. */
bResult = GetFirstString(pFTDInfo->pFTInfo->hDPAExt, szDefExtension,
sizeof(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
*/
PRIVATE_CODE BOOL FillDefExtensionEditControlFromSelection(HWND hdlg)
{
BOOL bResult = TRUE;
PFILETYPESDIALOGINFO pFTDInfo;
char szMIMEType[MAX_PATH];
LRESULT liSel;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_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
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL FillDefExtensionEditControlFromEditControl(HWND hdlg)
{
PFILETYPESDIALOGINFO pFTDInfo;
char szMIMEType[MAX_PATH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
GetWindowText(pFTDInfo->hwndContentTypeComboBox, szMIMEType,
sizeof(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
*/
PRIVATE_CODE void SetMIMEControlState(HWND hdlg, BOOL bEnable)
{
PFILETYPESDIALOGINFO pFTDInfo;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_USER);
EnableWindow(pFTDInfo->hwndContentTypeComboBox, bEnable);
EnableWindow(pFTDInfo->hwndDefExtensionComboBox, bEnable);
return;
}
/*************************** Public MIME Functions ***************************/
/*
** InitMIMEControls()
**
** Initializes contents of Content Type combo box and Default Extension combo
** box.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL InitMIMEControls(HWND hdlg)
{
BOOL bResult;
PFILETYPESDIALOGINFO pFTDInfo;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hdlg, DWLP_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. */
CLEAR_FLAG(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME);
*(pFTDInfo->pFTInfo->szOriginalMIMEType) = '\0';
bResult = TRUE;
TRACE_OUT(("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 (IS_FLAG_CLEAR(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME))
{
if (! IsListOfExtensions(pFTDInfo->pFTInfo->hDPAExt))
{
SET_FLAG(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME);
TRACE_OUT(("InitMIMEControls(): Disabling MIME controls for non-extension type."));
}
}
else
TRACE_OUT(("InitMIMEControls(): Disabling MIME controls, as requested."));
if (IS_FLAG_CLEAR(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.
*/
TRACE_OUT(("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
*/
PRIVATE_CODE BOOL OnContentTypeSelectionChange(HWND hdlg)
{
ASSERT(IS_VALID_HANDLE(hdlg, WND));
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
*/
PRIVATE_CODE BOOL OnContentTypeEditChange(HWND hdlg)
{
ASSERT(IS_VALID_HANDLE(hdlg, WND));
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
*/
PRIVATE_CODE BOOL OnContentTypeDropDown(HWND hdlg)
{
ASSERT(IS_VALID_HANDLE(hdlg, WND));
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
*/
PRIVATE_CODE BOOL OnDefExtensionDropDown(HWND hdlg)
{
ASSERT(IS_VALID_HANDLE(hdlg, WND));
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
*/
PRIVATE_CODE BOOL RegisterMIMEInformation(PFILETYPESDIALOGINFO pFTDInfo)
{
BOOL bResult;
if (IS_FLAG_CLEAR(pFTDInfo->pFTInfo->dwAttributes, FTA_NoEditMIME))
{
char szMIMEType[MAX_PATH];
char szDefExtension[MAX_PATH];
GetWindowText(pFTDInfo->hwndContentTypeComboBox, szMIMEType,
sizeof(szMIMEType));
GetWindowText(pFTDInfo->hwndDefExtensionComboBox, szDefExtension,
sizeof(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;
TRACE_OUT(("RegisterMIMEInformation(): Not registering MIME information, as requested."));
}
return(bResult);
}
#endif /* MIME */
//================================================================
//================================================================
BOOL FT_OnInitDialog(HWND hDialog, LPARAM lParam)
{
HMODULE hShellDll = NULL;
PFILETYPESDIALOGINFO pFTDInfo;
BOOL bRC = FALSE;
DECLAREWAITCURSOR;
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT: WM_INITDIALOG");
#endif
SetWaitCursor();
Shell_GetImageLists(&s_himlSysLarge, &s_himlSysSmall);
pFTDInfo = (PFILETYPESDIALOGINFO)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hDialog, DWLP_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);
}
// Attempt to bind to the ordinal for shell32!PathProcessCommand
hShellDll = GetModuleHandle( c_szShell2 );
if ( hShellDll )
{
lpPathProcessCommand = (P_PathProcessCommand)GetProcAddress(hShellDll, (LPCSTR)653);
}
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))
{
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT: WM_NOTIFY - LVN_ITEMCHANGED");
#endif
// 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;
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT: WM_NOTIFY - LVN_GETDISPINFO");
#endif
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; /* BUILDBUILD: Added. */
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "LVN_GETDISPINFO SHGetFileInfo szFile=%s hIcon=0x%x",
DPA_FastGetPtr(((PFILETYPESINFO)(pnmv->item.lParam))->hDPAExt,0), hIcon);
#endif
}
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_szShell2, II_DOCNOASSOC, 0);
hIcon = ImageList_ExtractIcon(hinstCabinet, s_himlSysSmall, iIndex);
}
if(hIcon != (HICON)NULL)
{
#if FT_DEBUG
HDC hdc = GetDC(NULL);
DrawIcon(hdc,200, 0, hIcon);
ReleaseDC(NULL, hdc);
#endif
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;
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT: WM_NOTIFY code=0x%x =%d", ((NMHDR *) lParam)->code, ((NMHDR *) lParam)->code);
#endif
// 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);
char szMsg[MAX_PATH];
char szTitle[MAX_PATH];
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT: WM_COMMAND");
#endif
switch(idCmd)
{
case IDC_FT_PROP_NEW:
case IDC_FT_PROP_EDIT:
pFTDInfo->dwCommand = idCmd;
DialogBoxParam(MLGetHinst(), 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
MLLoadStringA(IDS_FT_MB_REMOVETYPE, szMsg, ARRAYSIZE(szMsg));
MLLoadStringA(IDS_FT, szTitle, ARRAYSIZE(szTitle));
if(ShellMessageBox(MLGetHinst(), hDialog,
szMsg,
szTitle,
MB_YESNO | MB_ICONEXCLAMATION) == 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_FILETYPE_EXTENSION,
IDC_FT_PROP_DOCEXTRO_TXT, IDH_FILETYPE_EXTENSION,
IDC_FT_PROP_DOCEXTRO, IDH_FILETYPE_EXTENSION,
#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_FILETYPE_OPENS_WITH,
IDC_FT_PROP_OPENEXE_TXT, IDH_FILETYPE_OPENS_WITH,
IDC_FT_PROP_OPENEXE, IDH_FILETYPE_OPENS_WITH,
0, 0
};
#ifdef MIME
CONST char s_cszMIMEHelpFile[] = "IExplore.hlp";
#endif /* MIME */
#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.
*/
PRIVATE_CODE PCSTR FT_GetHelpFileFromControl(HWND hwndControl)
{
PCSTR pcszHelpFile = NULL;
int nControlID = 0;
ASSERT(! hwndControl ||
IS_VALID_HANDLE(hwndControl, WND));
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:
case IDC_BROWSEINPLACE:
/* MIME help comes from the MIME help file. */
pcszHelpFile = s_cszMIMEHelpFile;
break;
default:
/* Other help is taken from the default Win95 help file. */
break;
}
}
TRACE_OUT(("FT_GetHelpFileFromControl(): Using %s for control %d (HWND %#lx).",
pcszHelpFile ? pcszHelpFile : "default Win95 help file",
nControlID,
hwndControl));
ASSERT(! pcszHelpFile ||
IS_VALID_STRING_PTR(pcszHelpFile, CSTR));
return(pcszHelpFile);
}
#endif /* MIME */
INT_PTR CALLBACK FT_DlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
PFILETYPESDIALOGINFO pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hDialog, DWLP_USER);
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FileTypesDialogProc wParam=0x%x lParam=0x%x", 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);
}
// Tidy up the function pointers we aquired into shelldll.
lpPathProcessCommand = NULL;
break;
case WM_COMMAND:
FT_OnCommand(pFTDInfo, hDialog, wParam, lParam);
break;
case WM_HELP:
SHWinHelpOnDemandWrap((HWND)((LPHELPINFO) lParam)->hItemHandle,
#ifdef MIME
FT_GetHelpFileFromControl((HWND)(((LPHELPINFO)lParam)->hItemHandle)),
#else
NULL,
#endif /* MIME */
HELP_WM_HELP, (DWORD_PTR)(LPSTR)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));
SHWinHelpOnDemandWrap((HWND)wParam,
#ifdef MIME
FT_GetHelpFileFromControl(ChildWindowFromPoint(hDialog, pt)),
#else
NULL,
#endif /* MIME */
HELP_CONTEXTMENU, (DWORD_PTR)(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));
}
// Defined originally in shdocvw
#define BROWSEHACK_DONTINPLACENAVIGATE 0x00000008
void
FTEdit_InitBrowseInPlace(
HWND hdlg,
PFILETYPESDIALOGINFO pFTDInfo)
{
HWND hwndCtl = GetDlgItem(hdlg, IDC_BROWSEINPLACE);
TCHAR sz[MAX_PATH];
wsprintf(sz, TEXT("%s\\DocObject"), pFTDInfo->pFTInfo->szId);
// Does the class\DocObject key exist?
if (NO_ERROR == SHGetValue(HKEY_CLASSES_ROOT, sz, NULL, NULL, NULL, NULL))
{
// Yes
DWORD dwValue;
DWORD cbSize;
EnableWindow(hwndCtl, TRUE);
cbSize = sizeof(dwValue);
if (NO_ERROR == SHGetValue(HKEY_CLASSES_ROOT, pFTDInfo->pFTInfo->szId,
TEXT("BrowserFlags"), NULL, &dwValue,
&cbSize))
{
Button_SetCheck(hwndCtl, IS_FLAG_CLEAR(dwValue, BROWSEHACK_DONTINPLACENAVIGATE));
}
else
{
Button_SetCheck(hwndCtl, TRUE);
}
}
}
void
FTEdit_SetBrowseInPlace(
PFILETYPESDIALOGINFO pFTDInfo,
BOOL bSet)
{
DWORD dwValue;
DWORD cbSize;
cbSize = sizeof(dwValue);
if (NO_ERROR == SHGetValue(HKEY_CLASSES_ROOT, pFTDInfo->pFTInfo->szId,
TEXT("BrowserFlags"), NULL, &dwValue,
&cbSize))
{
// We store the "boolean not" of bSet
if (bSet)
CLEAR_FLAG(dwValue, BROWSEHACK_DONTINPLACENAVIGATE);
else
SET_FLAG(dwValue, BROWSEHACK_DONTINPLACENAVIGATE);
}
else
{
dwValue = bSet ? 0 : BROWSEHACK_DONTINPLACENAVIGATE;
}
// If the value of BrowserFlags is 0, just delete the value altogether.
if (0 == dwValue)
SHDeleteValue(HKEY_CLASSES_ROOT, pFTDInfo->pFTInfo->szId,
TEXT("BrowserFlags"));
else
SHSetValue(HKEY_CLASSES_ROOT, pFTDInfo->pFTInfo->szId,
TEXT("BrowserFlags"), REG_DWORD, &dwValue, sizeof(dwValue));
}
#endif /* MIME */
//================================================================
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, c_szShowExt, NULL, &dwType, (LPSTR)szShowExt, &dwShowExt)
== ERROR_SUCCESS);
}
//================================================================
//================================================================
void FTEdit_SetShowExt(PFILETYPESDIALOGINFO pFTDInfo, BOOL bShowExt)
{
if (bShowExt)
RegSetValueEx(pFTDInfo->pFTInfo->hkeyFT, (LPSTR)c_szShowExt, 0, REG_SZ, c_szNULL, 0);
else
RegDeleteValue(pFTDInfo->pFTInfo->hkeyFT, (LPSTR)c_szShowExt);
}
//================================================================
#ifdef FEATURE_INTL
// International support
typedef struct
{
HFONT hfontNew;
HFONT hfontOld;
BOOL bStock;
}
DLGFONTDATA, *LPDLGFONTDATA;
#define DLGATOM_FONTDATA 0x100 // for window prop.
BOOL CALLBACK SetfontChildProc(HWND hwnd, LPARAM lparam)
{
char szClass[32];
if (GetClassName(hwnd, szClass, sizeof(szClass)))
{
if ( !lstrcmpi(szClass, "Edit")
|| !lstrcmpi(szClass, "ComboBox")
|| !lstrcmpi(szClass, "Button")
|| !lstrcmpi(szClass, "ListBox") )
{
// the first one is enough to store the font handle.
if(((DLGFONTDATA *)lparam)->bStock == FALSE
&& ((DLGFONTDATA *)lparam)->hfontOld == NULL)
((DLGFONTDATA *)lparam)->hfontOld = GetWindowFont(hwnd);
SetWindowFont(hwnd, ((DLGFONTDATA *)lparam)->hfontNew, FALSE);
}
}
return TRUE;
}
int CALLBACK MyEnumFontFamProc(
ENUMLOGFONTEX FAR* lpelf, // address of logical-font data
NEWTEXTMETRIC FAR* lpntm, // address of physical-font data
int FontType, // type of font
LPARAM lParam // address of application-defined data
)
{
LOGFONT *pLogfont = (LOGFONT*)lParam;
*pLogfont = lpelf->elfLogFont;
return;
}
void SetShellFont(HWND hwnd)
{
LOGFONT lfGui, lfDlg;
HFONT hfont=NULL;
LPDLGFONTDATA pDfd;
if ( GetProp(hwnd, MAKEINTATOM(DLGATOM_FONTDATA)) )
return; // don't do this twice otherwise leaks resource.
if (!(hfont=GetWindowFont(hwnd)))
{
hfont=GetStockObject(SYSTEM_FONT);
}
GetObject(hfont, sizeof(LOGFONT), &lfDlg);
if ( (hfont = GetStockObject(DEFAULT_GUI_FONT)) == FALSE )
{
// NT 3.51 case
LOGFONT *pLogfont;
HDC hDC = GetDC(hwnd);
if( !(pLogfont = LocalAlloc(GPTR, sizeof(LOGFONT))) )
{
ReleaseDC(hwnd, hDC);
return;
}
GetProfileString("FontSubstitutes","MS Shell Dlg",pLogfont->lfFaceName,
lfGui.lfFaceName,sizeof(lfGui.lfFaceName) );
EnumFontFamilies(hDC,lfGui.lfFaceName,(FONTENUMPROC)MyEnumFontFamProc,
(LPARAM)pLogfont);
lfGui = *pLogfont;
LocalFree(pLogfont);
ReleaseDC(hwnd, hDC);
}
else
GetObject(hfont, sizeof(LOGFONT), &lfGui);
if (!(pDfd = (LPDLGFONTDATA)LocalAlloc(GPTR, sizeof(DLGFONTDATA))))
{
return;
}
if ( (lfGui.lfHeight != lfDlg.lfHeight) || (hfont == FALSE) )
{
lfGui.lfHeight = lfDlg.lfHeight;
lfGui.lfWidth = lfDlg.lfWidth;
hfont=CreateFontIndirect(&lfGui);
pDfd->bStock = FALSE;
}
else
pDfd->bStock = TRUE;
pDfd->hfontNew = hfont;
pDfd->hfontOld = NULL;
EnumChildWindows(hwnd, SetfontChildProc, (LPARAM)pDfd);
// Set this so that we can delete it at termination.
if (pDfd->bStock == FALSE)
SetProp(hwnd, MAKEINTATOM(DLGATOM_FONTDATA), (HANDLE)pDfd);
else
// We won't use this if we were able to use stock font.
LocalFree((HANDLE)pDfd);
}
void DeleteShellFont(HWND hwnd)
{
DLGFONTDATA *pDfd;
if (pDfd=(DLGFONTDATA *)GetProp(hwnd, MAKEINTATOM(DLGATOM_FONTDATA)))
{
pDfd->hfontNew = pDfd->hfontOld;
pDfd->hfontOld = NULL;
EnumChildWindows(hwnd, SetfontChildProc, (LPARAM)pDfd);
RemoveProp(hwnd, MAKEINTATOM(DLGATOM_FONTDATA));
// SetfontChildProc should return the original font handle.
if (pDfd->hfontOld && !pDfd->bStock)
DeleteObject(pDfd->hfontOld);
LocalFree((HANDLE)pDfd);
}
}
#endif
//================================================================
BOOL FTEdit_OnInitDialog(HWND hDialog, WPARAM wParam, LPARAM lParam)
{
DWORD dwItemCnt;
LOGFONT lf;
PFILETYPESDIALOGINFO pFTDInfo;
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Edit: WM_INITDIALOG wParam=0x%x lParam=0x%x ", wParam, lParam);
#endif
#ifdef FEATURE_INTL
if (GetACP() != 1252)
SetShellFont(hDialog);
#endif
pFTDInfo = (PFILETYPESDIALOGINFO)lParam;
SetWindowLongPtr(hDialog, DWLP_USER, (LPARAM)pFTDInfo);
pFTDInfo->hEditDialog = hDialog;
pFTDInfo->pFTCInfo = (PFILETYPESCOMMANDINFO)NULL;
pFTDInfo->szIconPath[0] = 0;
pFTDInfo->hwndLVFTEdit = GetDlgItem(hDialog, IDC_FT_EDIT_LV_CMDS);
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 = GetHkeyFT(pFTDInfo->szId);
#ifdef MIME
CheckDlgButton(hDialog, IDC_FT_EDIT_CONFIRM_OPEN, FTEdit_ConfirmOpenAfterDownload(pFTDInfo));
FTEdit_InitBrowseInPlace(hDialog, pFTDInfo);
#endif /* MIME */
if (FTEdit_IsExtShowable(pFTDInfo))
CheckDlgButton(hDialog, IDC_FT_EDIT_SHOWEXT, TRUE);
break;
case IDC_FT_PROP_NEW:
{
char szTitle[256];
if(!FTEdit_InitListViewCols(pFTDInfo->hwndLVFTEdit))
return(FALSE);
MLLoadStringA(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 = '\0';
*pFTDInfo->szIconPath = '\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, TRUE);
#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
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
}
//================================================================
//================================================================
#if 0
VOID ChangeDefaultButtonText(HWND hDialog, DWORD dwIDS)
{
char szStr[256];
if(MLLoadStringA(dwIDS, szStr, sizeof(szStr)))
SetWindowText(GetDlgItem(hDialog, IDC_FT_EDIT_DEFAULT), szStr);
}
#endif
//================================================================
//================================================================
#define lpdis ((LPDRAWITEMSTRUCT)lParam)
BOOL FTEdit_OnDrawItem(PFILETYPESDIALOGINFO pFTDInfo, WPARAM wParam, LPARAM lParam)
{
LV_ITEM LVItem;
char szActionValue[MAX_PATH];
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Edit: WM_DRAWITEM wParam=0x%x lParam=0x%x", wParam, lParam);
#endif
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, '&');
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;
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Edit: WM_MEASUREITEM wParam=0x%x lParam=0x%x", wParam, lParam);
#endif
if (lpmis->CtlType == ODT_LISTVIEW)
{
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
// hfReg = CreateFontIndirect(&lf);
// lf.lfWeight = FW_BOLD;
// hfBold = CreateFontIndirect(&lf);
((MEASUREITEMSTRUCT *)lParam)->itemHeight = lf.lfHeight;
((MEASUREITEMSTRUCT *)lParam)->itemHeight = 14;
return(TRUE);
}
return(FALSE);
}
//================================================================
VOID FTEdit_OnNotify(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Edit: WM_NOTIFY wParam=0x%x lParam=0x%x", wParam, lParam);
#endif
// Process ListView notifications
switch(((LV_DISPINFO *)lParam)->hdr.code)
{
case NM_DBLCLK:
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Edit: WM_NOTIFY - NM_DBLCLK");
#endif
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:
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Edit: WM_NOTIFY - LVN_ITEMCHANGED");
#endif
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;
char szExt[MAX_PATH];
char szDesc[MAX_PATH];
if(pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
GetDlgItemText(hDialog, IDC_FT_EDIT_EXT, szExt, sizeof(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, '*');
}
else
lstrcpy(szExt, DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt,0));
// Validate file type description
GetDlgItemText(hDialog, IDC_FT_EDIT_DESC, szDesc, sizeof(szDesc));
if(!(*szDesc))
{
lstrcpy(szDesc, CharUpper((szExt[0] == '.' ? &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), sizeof(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));
if (IsWindowEnabled(GetDlgItem(hDialog, IDC_BROWSEINPLACE)))
FTEdit_SetBrowseInPlace(pFTDInfo, IsDlgButtonChecked(hDialog, IDC_BROWSEINPLACE));
#endif /* MIME */
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)
{
char szMsg[MAX_PATH];
char szTitle[MAX_PATH];
// HKEY_CLASSES_ROOT\filetype\shell\action key
MLLoadStringA(IDS_FT_MB_REMOVEACTION, szMsg, ARRAYSIZE(szMsg));
MLLoadStringA(IDS_FT, szTitle, ARRAYSIZE(szTitle));
if(ShellMessageBox(MLGetHinst(), hDialog,
szMsg,
szTitle,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(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.
// REARCHITECT (scotth): we already have helper functions that do this.
// this needs cleaning
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;
char szBuf[MAX_PATH-2];
if(pFTDInfo->dwCommand == IDC_FT_PROP_NEW)
{
lstrcpy(sfi.szDisplayName, c_szShell2);
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 = ParseIconLocation( 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 = ParseIconLocation( 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 ( UrlPathProcessCommand( sfi.szDisplayName, sfi.szDisplayName, SIZEOF(sfi.szDisplayName), PPCF_NODIRECTORIES ) == -1 )
{
PathQuoteSpaces( sfi.szDisplayName );
PathRemoveArgs( sfi.szDisplayName );
PathRemoveBlanks( sfi.szDisplayName );
PathUnquoteSpaces( 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
}
}
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FTEdit_OnChangeIcon RegQueryValue szIcon=%s iIndex=%d hkeyFT=0x%x",
sfi.szDisplayName, sfi.iIcon, pFTDInfo->pFTInfo->hkeyFT);
#endif
if (RUNNING_NT)
MultiByteToWideChar(CP_ACP, 0, sfi.szDisplayName, -1,
(LPWSTR)szBuf, sizeof(szBuf));
else
lstrcpy(szBuf, sfi.szDisplayName);
if(PickIconDlg(hDialog, (LPWSTR)szBuf, sizeof(szBuf), &sfi.iIcon)) // (LPWSTR) so it builds, but only works downlevel
{
if (RUNNING_NT)
WideCharToMultiByte(CP_ACP, 0, (LPWSTR)szBuf, -1,
pFTDInfo->szIconPath,sizeof(szBuf), NULL, NULL);
else
lstrcpy(pFTDInfo->szIconPath, szBuf);
pFTDInfo->iIconIndex = sfi.iIcon;
hIcon = ExtractIcon(hinstCabinet, 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(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);
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Edit: WM_COMMAND wParam hi=0x%04x lo=0x%04x lParam=0x%x", HIWORD(wParam), LOWORD(wParam), lParam);
#endif
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(MLGetHinst(), MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), hDialog, FTCmd_DlgProc, (LPARAM)pFTDInfo))
{
OkToClose_NoCancel(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(MLGetHinst(), MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), hDialog, FTCmd_DlgProc, (LPARAM)pFTDInfo))
{
OkToClose_NoCancel(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(hDialog);
PropSheet_CancelToClose(GetParent(pFTDInfo->hPropDialog));
break;
#ifdef MIME
case IDC_FT_COMBO_CONTTYPE:
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case CBN_SELCHANGE:
TRACE_OUT(("FTEdit_OnCommand(): MIME Type selection change."));
OnContentTypeSelectionChange(hDialog);
break;
case CBN_EDITCHANGE:
TRACE_OUT(("FTEdit_OnCommand(): MIME Type edit change."));
OnContentTypeEditChange(hDialog);
break;
case CBN_DROPDOWN:
TRACE_OUT(("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:
TRACE_OUT(("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:
TRACE_OUT(("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,
IDC_BROWSEINPLACE, NO_HELP,
#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_SHOWEXT, IDH_FCAB_FT_EDIT_SHOWEXT,
0, 0
};
#pragma data_seg()
//================================================================
//================================================================
INT_PTR CALLBACK FTEdit_DlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
PFILETYPESDIALOGINFO pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hDialog, DWLP_USER);
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:
SHWinHelpOnDemandWrap((HWND)((LPHELPINFO) lParam)->hItemHandle,
#ifdef MIME
FT_GetHelpFileFromControl((HWND)(((LPHELPINFO)lParam)->hItemHandle)),
#else
NULL,
#endif /* MIME */
HELP_WM_HELP, (DWORD_PTR)(LPSTR)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));
SHWinHelpOnDemandWrap((HWND)wParam,
#ifdef MIME
FT_GetHelpFileFromControl(ChildWindowFromPoint(hDialog, pt)),
#else
NULL,
#endif /* MIME */
HELP_CONTEXTMENU, (DWORD_PTR)(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;
#ifdef FEATURE_INTL
case WM_DESTROY:
if (GetACP() != 1252)
DeleteShellFont(hDialog);
break;
#endif
}
return(FALSE);
}
//================================================================
//================================================================
VOID FTCmd_OnInitDialog(HWND hDialog, WPARAM wParam, LPARAM lParam)
{
char szPath[MAX_PATH+6]; // 6 = "\shell"
char szAction[MAX_PATH];
DWORD dwAction;
DWORD dwPath;
char szBuf[256];
int iLen;
LONG err;
PFILETYPESDIALOGINFO pFTDInfo;
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Cmd: WM_INITDIALOG wParam=0x%x lParam=0x%x ", wParam, lParam);
#endif
pFTDInfo = (PFILETYPESDIALOGINFO)lParam;
SetWindowLongPtr(hDialog, DWLP_USER, (LPARAM)pFTDInfo);
pFTDInfo->hCmdDialog = hDialog;
// Limit the extension length
SendDlgItemMessage(hDialog, IDC_FT_EDIT_EXT, EM_LIMITTEXT, (WPARAM)PATH_CCH_EXT, 0);
if(pFTDInfo->dwCommandEdit == IDC_FT_EDIT_EDIT)
{
// Set window title to show file type description we are editing
if(MLLoadStringA(IDS_FT_EDITTITLE, szBuf, sizeof(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 = sizeof(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); // 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] = '\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(LPCSTR pszKey)
{
char szBuf[MAX_PATH+MAXEXTSIZE+6+8]; // 6 = "\shell", 8 = "\ddeexec"
// Delete DDEApp keys
wsprintf(szBuf, c_szTemplateSS, pszKey, c_szDDEExec);
return(RegDeleteKey(HKEY_CLASSES_ROOT, szBuf));
}
//================================================================
//================================================================
BOOL FTCmd_OnOK(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
char szPath[MAX_PATH];
char szKey[MAX_PATH+MAXEXTSIZE+7]; // 7 = "\shell\"
char 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, sizeof(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, sizeof(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) == 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, sizeof(pFTDInfo->pFTCInfo->szDDEMsg));
GetDlgItemText(hDialog, IDC_FT_CMD_DDEAPP,
pFTDInfo->pFTCInfo->szDDEApp, sizeof(pFTDInfo->pFTCInfo->szDDEApp));
GetDlgItemText(hDialog, IDC_FT_CMD_DDEAPPNOT,
pFTDInfo->pFTCInfo->szDDEAppNot, sizeof(pFTDInfo->pFTCInfo->szDDEAppNot));
GetDlgItemText(hDialog, IDC_FT_CMD_DDETOPIC,
pFTDInfo->pFTCInfo->szDDETopic, sizeof(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(hinstCabinet, s_himlSysLarge, 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_szShell2, II_DOCNOASSOC, 0);
hIcon = ImageList_ExtractIcon(hinstCabinet, s_himlSysLarge, iIndex);
}
}
SendMessage(pFTDInfo->hwndEditDocIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
}
}
}
return(TRUE);
}
//================================================================
//================================================================
VOID FTCmd_OnBrowse(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
/*
* The problem with NT is that this function is UNICODE-ONLY (see below),
* and so we must convert all our strings to Unicode before calling, then
* convert the szPath back to ANSI upon return.
*
* BOOL WINAPI GetFileNameFromBrowse(HWND hwnd, LPTSTR szFilePath, UINT cchFilePath,
* LPCTSTR szWorkingDir, LPCTSTR szDefExt, LPCTSTR szFilters, LPCTSTR szTitle)
*
*/
if (RUNNING_NT)
{
WCHAR szuPath[MAX_PATH];
WCHAR szuTitle[80];
WCHAR szuExe[16];
WCHAR szuFilters[MAX_PATH];
LPWSTR psz;
szuPath[0] = szuTitle[0] = szuExe[0] = szuFilters[0]= 0;
MLLoadStringW(IDS_OPENAS, szuTitle, 80);
MLLoadStringW(IDS_EXE, szuExe, 16);
MLLoadStringW(IDS_PROGRAMSFILTER, szuFilters, MAX_PATH);
/* hack up the array... */
psz = szuFilters;
while (*psz)
{
if (*psz == (WCHAR)('#'))
*psz = (WCHAR)('\0');
psz++;
}
if (GetFileNameFromBrowse(hDialog, szuPath, MAX_PATH, NULL,
szuExe, szuFilters, szuTitle))
{
/* Specifically UNICODE */
PathQuoteSpaces((LPSTR)szuPath);
SetDlgItemTextW(hDialog, IDC_FT_CMD_EXE, szuPath);
}
}
else
{
/* leave this here for running on Win95 */
char szPath[MAX_PATH];
char szTitle[MAX_PATH];
char szExe[16];
char szFilters[MAX_PATH];
char *psz;
szPath[0] = szTitle[0] = szExe[0] = szFilters[0]= 0;
MLLoadStringA(IDS_OPENAS, szTitle, sizeof(szTitle));
MLLoadStringA(IDS_EXE, szExe, sizeof(szExe));
MLLoadStringA(IDS_PROGRAMSFILTER, szFilters, sizeof(szFilters));
psz = szFilters;
while (*psz)
{
if (*psz == (char)('#'))
*psz = (char)('\0');
psz++;
}
if (GetFileNameFromBrowse(hDialog, (LPWSTR)szPath, sizeof(szPath), NULL, // (LPWSTR) so it builds, but only works downlevel
(LPWSTR)szExe, (LPWSTR)szFilters, (LPWSTR)szTitle))
{
PathQuoteSpaces(szPath);
SetDlgItemText(hDialog, IDC_FT_CMD_EXE, szPath);
}
}
}
//================================================================
//================================================================
VOID FTCmd_OnCommand(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog, WPARAM wParam, LPARAM lParam)
{
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT Cmd: WM_COMMAND wParam 0x%04x 0x%04x", HIWORD(wParam), LOWORD(wParam));
#endif
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()
//================================================================
//================================================================
INT_PTR CALLBACK FTCmd_DlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
PFILETYPESDIALOGINFO pFTDInfo = (PFILETYPESDIALOGINFO)GetWindowLongPtr(hDialog, DWLP_USER);
switch(message)
{
case WM_INITDIALOG:
FTCmd_OnInitDialog(hDialog, wParam, lParam);
return(TRUE);
case WM_HELP:
SHWinHelpOnDemandWrap((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
HELP_WM_HELP, (DWORD_PTR)(LPSTR) aEditCommandHelpIDs);
return TRUE;
case WM_CONTEXTMENU:
if ((int)SendMessage(hDialog, WM_NCHITTEST, 0, lParam) != HTCLIENT)
return FALSE; // don't process it
SHWinHelpOnDemandWrap((HWND) wParam, NULL, HELP_CONTEXTMENU,
(DWORD_PTR)(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(HWND hDialog)
{
char szStr1[256];
if(MLLoadStringA(IDS_FT_CLOSE, szStr1, sizeof(szStr1)))
{
SetWindowText(GetDlgItem(hDialog, IDOK), szStr1);
EnableWindow(GetDlgItem(hDialog, IDCANCEL), FALSE);
}
}
//================================================================
//================================================================
HICON GetDocIcon(PFILETYPESDIALOGINFO pFTDInfo, LPSTR lpszStr)
{
SHFILEINFO sfi;
HICON hIcon = (HICON)NULL;
int iImageIndex;
if(pFTDInfo->pFTInfo->dwAttributes & FTA_HasExtension)
{
if(*lpszStr == '.') // is an extension
{
if(SHGetFileInfo((LPSTR)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(hinstCabinet, s_himlSysLarge, 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_szShell2, II_DOCNOASSOC, 0);
hIcon = ImageList_ExtractIcon(hinstCabinet, s_himlSysLarge, iIndex);
}
}
return(hIcon);
}
//================================================================
//================================================================
VOID DisplayDocObjects(PFILETYPESDIALOGINFO pFTDInfo, HWND hDialog)
{
LV_ITEM LVItem;
char szFile[MAX_PATH];
int iCnt;
int i;
// Display extensions in read-only edit control
iCnt = DPA_GetPtrCount(pFTDInfo->pFTInfo->hDPAExt);
*szFile = '\0';
for(i = 0; (i < iCnt) && (lstrlen(szFile) < MAX_PATH); i++)
{
if(*(LPSTR)(DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt, i)))
{
// Make sure we have enough room left in our string...
if ((lstrlen(szFile) +
lstrlen((LPSTR)DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt, i)))
>= (MAX_PATH - 2))
break;
lstrcat(szFile, (LPSTR)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, sizeof(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)
{
char szFile[MAX_PATH];
char 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, sizeof(szFile));
if(*szFile)
{
int cbT = lstrlen(c_szExefileOpenCommand);
if (CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
szFile, cbT, c_szExefileOpenCommand, cbT) == 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);
MLLoadStringA(IDS_FT_EXEFILE, szFullPath, sizeof(szFullPath));
}
else
{
if ( UrlPathProcessCommand( szFile, szFile, MAX_PATH, PPCF_NODIRECTORIES ) == -1 )
{
PathRemoveArgs(szFile);
PathRemoveBlanks(szFile);
PathUnquoteSpaces(szFile);
if (PathIsRelative(szFile))
PathFindOnPath(szFile, NULL);
}
lstrcpy(szFullPath, szFile);
// Get open icon if not already gotten
if(pFTDInfo->pFTInfo->hIconOpen == (HICON)NULL)
{
sfi.hIcon = 0;
#ifdef MIME
TRACE_OUT(("DisplayOpensWithObjects(): Retrieving icon for %s.",
szFullPath));
#endif /* MIME */
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_szShell2, II_DOCNOASSOC, 0);
pFTDInfo->pFTInfo->hIconOpen = ImageList_ExtractIcon(hinstCabinet, s_himlSysLarge, 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;
char szExt[MAX_PATH];
char szId[MAX_PATH];
char szBuf[MAX_PATH];
char szStr1[256];
char szStr2[256];
DWORD dwId;
HWND hwndButton;
int iLength;
// On new types verify that the extension is not already in use.
GetDlgItemText(hDialog, IDC_FT_EDIT_EXT, szExt, sizeof(szExt));
iLength = lstrlen(szExt);
if(iLength != 0 && iLength < MAXEXTSIZE)
{
AddExtDot(szExt, sizeof(szExt));
dwId = sizeof(szId);
*szId = '\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 = '\0';
*szStr2 = '\0';
if(MLLoadStringA(IDS_FT_MB_EXTTEXT, szStr1, sizeof(szStr1)))
{
if(MLLoadStringA(IDS_FT, szStr2, sizeof(szStr2)))
{
if(lstrlen(szStr1) + lstrlen(szExt) + lstrlen(szId) < sizeof(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;
LPSTR pszExt = szExt;
if(*pszExt == '.')
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);
#pragma data_seg(".text", "CODE")
wsprintf(pFTDInfo->szId, "%s%s%02d",
pszExt, c_szFile, iCnt);
#pragma data_seg()
iCnt++;
}
EnableWindow(GetDlgItem(pFTDInfo->hEditDialog, IDC_FT_EDIT_NEW), TRUE);
}
}
else
{
// Tell the use that an extension is required
*szBuf = '\0';
*szStr2 = '\0';
if(MLLoadStringA(IDS_FT_MB_NOEXT, szStr1, sizeof(szStr1)))
{
if(MLLoadStringA(IDS_FT, szStr2, sizeof(szStr2)))
{
if(lstrlen(szStr1) + lstrlen(szExt) + lstrlen(szId) < sizeof(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;
char szAction[MAX_PATH];
// Check for value
if(!GetDlgItemText(hDialog, IDC_FT_CMD_ACTION, szAction, sizeof(szAction)))
{
if(bMBoxFlag)
{
// Tell user that this exe is invalid
ShellMessageBox(hinstCabinet, 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;
char szPath[MAX_PATH];
char szFileName[MAX_PATH];
// Check for valid exe
GetDlgItemText(hDialog, IDC_FT_CMD_EXE, szPath, sizeof(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(hinstCabinet, 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;
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FTListViewThread created.");
#endif
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;
char szDesc[MAX_PATH];
char szClass[MAX_PATH];
char szClassesKey[MAX_PATH]; // string containing the classes key
char szId[MAX_PATH];
char 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 = sizeof(szClassesKey);
dwClass = sizeof(szClass);
while(RegEnumKeyEx(HKEY_CLASSES_ROOT, dwSubKey, szClassesKey, &dwClassesKey,
NULL, szClass, &dwClass, &ftLastWrite) != ERROR_NO_MORE_ITEMS)
{
*szId = '\0';
dwAttributes = 0;
// find the file type identifier and description from the extension
if(*szClassesKey == '.')
{
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 = '\0';
}
}
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT RegEnum HKCR szClassKey=%s szId=%s dwAttributes=%d", szClassesKey, szId, dwAttributes);
#endif
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 = sizeof(szClassesKey);
dwClass = sizeof(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)
{
char szClass[MAX_PATH];
char 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, 0,
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS)
{
dwClass = sizeof(szClass);
dwAction = sizeof(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 = sizeof(szClass);
dwAction = sizeof(szAction);
iSubKey++;
}
RegCloseKey(hk);
}
return(iSubKey);
}
//================================================================
//================================================================
BOOL IsIconPerInstance(HKEY hkeyFT)
{
LONG err;
char 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 cbT = lstrlen(c_szSpPercentOne) - 1;
if (CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
szDefaultIcon, cbT, &c_szSpPercentOne[1], cbT) == 2)
bRC = TRUE;
}
return(bRC);
}
//================================================================
//================================================================
BOOL HasIconHandler(HKEY hkeyFT)
{
char 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, LPSTR szExt,
LPSTR szDesc, LPSTR szId, DWORD dwAttributes)
{
BOOL bRC = FALSE;
LV_ITEM LVItem;
LPSTR pszExt;
Assert(hkeyFT != (HKEY)NULL);
if((pFTDInfo->pFTInfo = LocalAlloc(GPTR, sizeof(FILETYPESINFO))) != NULL)
{
// create dynamic pointer array for FILETYPESINFO dpaExt member
if((pFTDInfo->pFTInfo->hDPAExt = DPA_Create(4)) != (HDPA)NULL)
{
if((pszExt = LocalAlloc(GPTR, lstrlen(szExt)+1)) != 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, LPSTR szActionKey,
LPSTR szActionValue, LPSTR 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;
char szTemp[MAX_PATH];
// See if there is nice text for the action...
dwSize = sizeof(szTemp);
if ((RegQueryValue(hk, szActionKey, szTemp, &dwSize) == ERROR_SUCCESS)
&& (dwSize > 1))
{
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...
LPSTR pszT = StrChr(szActionValue, '=');
if (pszT)
{
*pszT++ = '\0';
StrRemoveChar(szActionValue, pFTDInfo->pFTCInfo->szActionKey, '&');
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, '&');
for (pszT = pFTDInfo->pFTCInfo->szActionKey; *pszT; pszT = CharNext(pszT))
{
if (*pszT == ' ')
*pszT = '_';
}
}
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(LPSTR 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, LPSTR pszVerb, DWORD dwAttributes)
{
HKEY hk;
LONG err;
char szVerbKey[MAX_PATH+6]; // 6 = "\shell"
DWORD dwSize;
wsprintf(szVerbKey, c_szTemplateSS, c_szShell, pszVerb);
if((hkeyFT != NULL) &&
(RegOpenKeyEx(hkeyFT, szVerbKey, 0, KEY_SET_VALUE, &hk) == ERROR_SUCCESS))
{
dwSize = sizeof(dwAttributes);
err = RegSetValueEx(hk, c_szEditFlags, 0, REG_BINARY,
(LPBYTE)&dwAttributes, dwSize);
if (err != ERROR_SUCCESS)
dwAttributes= 0;
RegCloseKey(hk);
}
return(dwAttributes);
}
//================================================================
//================================================================
DWORD GetVerbAttributes(HKEY hkeyFT, LPSTR pszVerb)
{
HKEY hk;
LONG err;
char 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, 0, 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, LPSTR pszName, UINT uName)
{
char szIdValue[MAX_PATH];
char szShellCommand[MAX_PATH+MAX_PATH+7]; // 7 = "\shell\"
char szShellCommandValue[MAX_PATH];
char szClass[MAX_PATH];
char 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, 0, KEY_READ, &hk) == ERROR_SUCCESS)
{
dwClass = sizeof(szClass);
dwShellKey = sizeof(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 ='\0';
}
//================================================================
// This function returns non-zero value only if the specified type
// has an associated icon specified by "DefaultIcon=" key.
//================================================================
HICON GetDefaultIcon(HKEY *hkeyFT, LPSTR pszId, DWORD dwIconType)
{
HICON hicon = (HICON)NULL;
LONG err;
char 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 = ParseIconLocation(szDefaultIcon);
PathRemoveArgs(szDefaultIcon);
iImage = Shell_GetCachedImageIndex(szDefaultIcon, iIconIndex, 0);
hicon = ImageList_ExtractIcon(hinstCabinet, (dwIconType == SHGFI_LARGEICON ? s_himlSysLarge : s_himlSysSmall), iImage);
}
}
#ifdef FT_DEBUG
DebugMsg(DM_TRACE, "FT GetDefaultIcon szIcon=%s iIndex=%d hIcon=0x%x hkeyFT=0x%x",
szDefaultIcon, iIconIndex, hicon, *hkeyFT);
#endif
return(hicon);
}
//================================================================
//================================================================
BOOL FindDDEOptions(PFILETYPESDIALOGINFO pFTDInfo)
{
BOOL bRC = FALSE;
char 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, LPSTR 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, LPSTR pszVerb, LPSTR pszExe, DWORD *pdwExe)
{
// caller is responsible to setting pdwExe
char 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;
char szBuf[MAX_PATH+MAX_PATH+12]; // 12 = "\defaulticon"
char 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,
sizeof(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,
sizeof(szAction)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
break;
case FTD_DOCICON:
wsprintf(szBuf, c_szTemplateSS, pFTDInfo->pFTInfo->szId, c_szDefaultIcon);
#pragma data_seg(".text", "CODE")
wsprintf(szAction, "%s,%d", pFTDInfo->szIconPath, pFTDInfo->iIconIndex);
#pragma data_seg()
if(RegSetValue(HKEY_CLASSES_ROOT, szBuf, REG_SZ, szAction,
sizeof(szAction)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
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,
sizeof(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,
sizeof(pFTDInfo->pFTCInfo->szActionValue)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
}
// Save action command key and value
if(RegSetValue(hk, c_szCommand, REG_SZ, pFTDInfo->pFTCInfo->szCommand,
sizeof(pFTDInfo->pFTCInfo->szCommand)) != ERROR_SUCCESS)
lRC = !ERROR_SUCCESS;
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,
sizeof(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,
sizeof(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,
sizeof(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,
sizeof(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, LPCSTR pszKey, LPSTR szAction)
{
LONG lRC = ERROR_SUCCESS;
HKEY hk1;
int iNext;
// Remove keys from the registry
if(RegOpenKeyEx(hk, pszKey, 0, KEY_ALL_ACCESS, &hk1) == ERROR_SUCCESS)
{
if(RegDeleteKey(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);
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;
LPSTR pszExt;
char szKey[MAX_PATH];
char szBuf[2];
HKEY hk;
// Remove filetype and keys from the registry
if(*pFTDInfo->pFTInfo->szId)
if(RegDeleteKey(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(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(pszExt = DPA_FastGetPtr(pFTDInfo->pFTInfo->hDPAExt, i))
{
if(*pszExt)
{
// Don't delete extension if it has a ShellNew key, just remove filetype
#pragma data_seg(".text", "CODE")
wsprintf(szKey, "%s\\%s%s", pszExt, c_szShell, c_szNew);
#pragma data_seg()
if(RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hk) == ERROR_SUCCESS)
{
RegCloseKey(hk);
*szBuf = '\0'; // remove the filetype assoc
RegSetValue(HKEY_CLASSES_ROOT, pszExt,
REG_SZ, szBuf, sizeof(szBuf));
}
else
{
if(RegDeleteKey(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(LPSTR pszExt, LPSTR pszDesc, DWORD *pdwDesc, LPSTR pszId, DWORD *pdwId)
{
LONG err;
DWORD dwNm;
BOOL bRC = TRUE;
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
{
char szExt[MAX_PATH]; // "TXT"
char szTemplate[128]; // "%s File"
char szRet[MAX_PATH+20]; // "TXT File"
Error:
bRC = FALSE;
lstrcpy(pszId, pszExt);
pszExt++;
lstrcpy(szExt, pszExt);
AnsiUpper(szExt);
MLLoadStringA(IDS_EXTTYPETEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
wsprintf(szRet, szTemplate, szExt);
lstrcpyn(pszDesc, szRet, *pdwDesc);
*pdwDesc = lstrlen(pszDesc);
}
return(bRC);
}
//================================================================
//================================================================
VOID StrRemoveChar(LPSTR pszSrc, LPSTR pszDest, char ch)
{
LPSTR pSrc = pszSrc;
LPSTR pDest = (pszDest ?pszDest :pszSrc);
Assert(pSrc);
Assert(pDest);
if(pSrc && pDest)
{
while(*pSrc)
{
if(*pSrc != ch)
*(pDest++) = *pSrc;
pSrc++;
}
*pDest = '\0';
}
}
//================================================================
//================================================================
// This code should be in PATH.C
// in/out:
// pszIconFile location string
// "progman.exe,3" -> "progman.exe"
//
// returns:
// icon index (zero based) ready for ExtractIcon
//
int ParseIconLocation(LPSTR pszIconFile)
{
int iIndex = 0;
LPSTR pszComma = StrChr(pszIconFile, ',');
if (pszComma) {
*pszComma++ = 0; // terminate the icon file name.
while(*pszComma==' ') // remove any white space
pszComma++;
iIndex = StrToInt(pszComma);
}
PathRemoveBlanks(pszIconFile);
return iIndex;
}
//================================================================
//================================================================
BOOL IsDefaultAction(PFILETYPESDIALOGINFO pFTDInfo, LPSTR pszAction)
{
return((lstrcmpi(pFTDInfo->pFTInfo->szDefaultAction, pszAction) == 0) ||
(!(*pFTDInfo->pFTInfo->szDefaultAction) && (lstrcmpi(pszAction, c_szOpen) == 0)));
}
//================================================================
//================================================================
BOOL SetDefaultAction(PFILETYPESDIALOGINFO pFTDInfo)
{
char szFile[MAX_PATH];
LV_ITEM LVItem;
if(IsDefaultAction(pFTDInfo, pFTDInfo->pFTCInfo->szActionKey))
*pFTDInfo->pFTInfo->szDefaultAction = '\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, sizeof(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(LPSTR pszId)
{
HKEY hkeyFT;
if(RegCreateKey(HKEY_CLASSES_ROOT, pszId, &hkeyFT) != ERROR_SUCCESS)
hkeyFT = NULL;
return(hkeyFT);
}
//================================================================================================//
//
// We make use of a newer API in shelldll. However this is a private API introduced in SUR.
//
// Therefore this code attempts to do the right thing, first we check to see if we have
// found the exported entry from SHELLDLL. If we have then we call that, but, this however may
// required thunking.
//
// If we didn't bind to the export, then we call our own version of the call.
//
LONG UrlPathProcessCommand( LPCTSTR lpSrc, LPTSTR lpDest, int iMax, DWORD dwFlags )
{
LONG lResult = 0;
LPWSTR lpwSrc=NULL;
LPWSTR lpwDest=NULL;
int iLen;
if ( lpPathProcessCommand )
{
if (RUNNING_NT)
{
iLen = MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, NULL, 0);
lpwSrc = (LPWSTR)LocalAlloc(LPTR, SIZEOF(WCHAR)*iLen);
lpwDest = (LPWSTR)LocalAlloc(LPTR, SIZEOF(WCHAR)*iMax);
if ( lpwSrc && lpwDest )
{
MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, lpwSrc, iLen);
lResult = lpPathProcessCommand( (LPTSTR)lpwSrc, (LPTSTR)lpwDest, iMax, dwFlags );
if ( lResult != -1 )
WideCharToMultiByte(CP_ACP, 0, lpwDest, -1, lpDest, iMax, NULL, NULL);
}
}
else
lResult = lpPathProcessCommand( lpSrc, lpDest, iMax, dwFlags );
}
else
{
lResult = UrlPathProcessCommand2( lpSrc, lpDest, iMax, dwFlags );
}
if ( lpwSrc )
LocalFree(lpwSrc);
if ( lpwDest )
LocalFree(lpwDest);
return lResult;
}
//
// PathProcessCommand implementation as found in path.c (shelldll).
//
LONG UrlPathProcessCommand2( LPCTSTR lpSrc, LPTSTR lpDest, int iDestMax, DWORD dwFlags )
{
TCHAR szName[MAX_PATH];
LPTSTR lpBuffer, lpBuffer2;
LPCTSTR lpArgs = NULL;
DWORD dwAttrib;
LONG i, iTotal;
LONG iResult = -1;
BOOL bAddQuotes = FALSE;
BOOL bQualify = FALSE;
BOOL bFound = FALSE;
BOOL bHitSpace = FALSE;
// Process the given source string, attempting to find what is that path, and what is its
// arguments.
if ( lpSrc )
{
// Extract the sub string, if its is realative then resolve (if required).
if ( *lpSrc == TEXT('\"') )
{
for ( lpSrc++, i=0 ; i<MAX_PATH && *lpSrc && *lpSrc!=TEXT('\"') ; i++, lpSrc++ )
szName[i] = *lpSrc;
szName[i] = TEXT('\0');
if ( *lpSrc )
lpArgs = lpSrc+1;
if ( ((dwFlags & PPCF_FORCEQUALIFY) || PathIsRelative( szName ))
&& !( dwFlags & PPCF_NORELATIVEOBJECTQUALIFY ) )
{
if ( !PathResolve( (LPWSTR)szName, NULL, PRF_TRYPROGRAMEXTENSIONS ) ) // (LPWSTR) so it builds, but only works downlevel
goto exit_gracefully;
}
bFound = TRUE;
}
else
{
// Is this a relative object, and then take each element upto a seperator
// and see if we hit an file system object. If not then we can
bQualify = PathIsRelative( lpSrc ) || ((dwFlags & PPCF_FORCEQUALIFY) != 0);
for ( i=0; i < MAX_PATH ; i++ )
{
szName[i] = lpSrc[i];
// If we hit a space then the string either contains a LFN or we have
// some arguments. Therefore attempt to get the attributes for the string
// we have so far, if we are unable to then we can continue
// checking, if we hit then we know that the object exists and the
// trailing string are its arguments.
if ( !szName[i] || szName[i] == TEXT(' ') )
{
szName[i] = TEXT('\0');
while ( TRUE )
{
if ( bQualify && !PathResolve( (LPWSTR)szName, NULL, PRF_TRYPROGRAMEXTENSIONS ) ) // (LPWSTR) so it builds, but only works downlevel
break;
dwAttrib = GetFileAttributes( szName );
if ( dwAttrib == -1 || ( ( dwAttrib & FILE_ATTRIBUTE_DIRECTORY ) && dwFlags & PPCF_NODIRECTORIES ) )
break;
if ( bQualify && ( dwFlags & PPCF_NORELATIVEOBJECTQUALIFY ) )
*lstrcpyn( szName, lpSrc, i ) = TEXT(' ');
bFound = TRUE; // success
lpArgs = &lpSrc[i];
goto exit_gracefully;
}
if ( bQualify )
hmemcpy( szName, lpSrc, (i+1)*SIZEOF(TCHAR) );
else
szName[i]=lpSrc[i];
bHitSpace = TRUE;
}
if ( !szName[i] )
break;
}
}
}
exit_gracefully:
// Work out how big the temporary buffer should be, allocate it and
// build the returning string into it. Then compose the string
// to be returned.
if ( bFound )
{
if ( StrChr( szName, TEXT(' ') ) )
bAddQuotes = dwFlags & PPCF_ADDQUOTES;
iTotal = lstrlen(szName) + 1; // for terminator
iTotal += bAddQuotes ? 2 : 0;
iTotal += (dwFlags & PPCF_ADDARGUMENTS) && lpArgs ? lstrlen(lpArgs) : 0;
if ( lpDest )
{
if ( iTotal <= iDestMax )
{
lpBuffer = lpBuffer2 = (LPTSTR)LocalAlloc( LMEM_FIXED, SIZEOF(TCHAR)*iTotal );
if ( lpBuffer )
{
// First quote if required
if ( bAddQuotes )
*lpBuffer2++ = TEXT('\"');
// Matching name
lstrcpy( lpBuffer2, szName );
// Closing quote if required
if ( bAddQuotes )
lstrcat( lpBuffer2, TEXT("\"") );
// Arguments (if requested)
if ( (dwFlags & PPCF_ADDARGUMENTS) && lpArgs )
lstrcat( lpBuffer2, lpArgs );
// Then copy into callers buffer, and free out temporary buffer
lstrcpy( lpDest, lpBuffer );
LocalFree( (HGLOBAL)lpBuffer );
// Return the length of the resulting string
iResult = iTotal;
}
}
}
else
{
// Resulting string is this big, although nothing returned (allows them to allocate a buffer)
iResult = iTotal;
}
}
return iResult;
}