/*
 * assoc.c - Type association routines.
 */


/* Headers
 **********/

#include "project.h"
#pragma hdrstop

#include <mluisupp.h>

#define _INTSHCUT_          /* for intshcut.h */
#include <intshcut.h>
#include <intshctp.h>       /* ALL_???_FLAGS */

#include "assoc.h"
#include "extricon.h"
#include "openas.h"
#pragma warning(disable:4001) /* "single line comment" warning */
#include "filetype.h"
#include "resource.h"
#pragma warning(default:4001) /* "single line comment" warning */
#include "shlstock.h"
#include "shlvalid.h"


/* Global Constants
 *******************/

#pragma data_seg(DATA_SEG_READ_ONLY)

PUBLIC_DATA const HKEY g_hkeyURLProtocols          = HKEY_CLASSES_ROOT;
PUBLIC_DATA const HKEY g_hkeyMIMESettings          = HKEY_CLASSES_ROOT;

PUBLIC_DATA CCHAR g_cszURLProtocol[]               = "URL Protocol";

PUBLIC_DATA CCHAR g_cszContentType[]               = "Content Type";
PUBLIC_DATA CCHAR g_cszExtension[]                 = "Extension";

#pragma data_seg()


/* Module Constants
 *******************/

#pragma data_seg(DATA_SEG_READ_ONLY)

PRIVATE_DATA CCHAR s_cszShellOpenCmdSubKeyFmt[]    = "%s\\shell\\open\\command";
PRIVATE_DATA CCHAR s_cszAppOpenCmdFmt[]            = "%s %%1";
PRIVATE_DATA CCHAR s_cszDefaultIconSubKeyFmt[]     = "%s\\DefaultIcon";
PRIVATE_DATA CCHAR s_cszDefaultIcon[]              = "url.dll,0";

#pragma data_seg()


/***************************** Private Functions *****************************/


/*
** RegisterAppAsURLProtocolHandler()
**
** Under HKEY_CLASSES_ROOT\url-protocol\shell\open\command, add default value =
** "c:\foo\bar.exe %1".
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PRIVATE_CODE BOOL RegisterAppAsURLProtocolHandler(PCSTR pcszProtocol,
                                                  PCSTR pcszApp)
{
   BOOL bResult = FALSE;
   DWORD dwcbShellOpenCmdSubKeyLen;
   PSTR pszShellOpenCmdSubKey;

   ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
   ASSERT(IS_VALID_STRING_PTR(pcszApp, CSTR));

   /* (+ 1) for null terminator. */
   dwcbShellOpenCmdSubKeyLen = sizeof(s_cszShellOpenCmdSubKeyFmt) + 1
                               + lstrlen(pcszProtocol);

   if (AllocateMemory(dwcbShellOpenCmdSubKeyLen, &pszShellOpenCmdSubKey))
   {
      DWORD dwcbAppOpenCmdLen;
      PSTR pszAppOpenCmd;

      /* FEATURE: We should quote pcszApp here only if it contains spaces. */

      /* (+ 1) for null terminator. */
      dwcbAppOpenCmdLen = sizeof(s_cszAppOpenCmdFmt) + 1 + lstrlen(pcszApp);

      if (AllocateMemory(dwcbAppOpenCmdLen, &pszAppOpenCmd))
      {
         EVAL((DWORD)wsprintf(pszShellOpenCmdSubKey, s_cszShellOpenCmdSubKeyFmt,
                              pcszProtocol) < dwcbShellOpenCmdSubKeyLen);

         EVAL((DWORD)wsprintf(pszAppOpenCmd, s_cszAppOpenCmdFmt, pcszApp)
              < dwcbAppOpenCmdLen);

         /* (+ 1) for null terminator. */
         bResult = (SetRegKeyValue(g_hkeyURLProtocols, pszShellOpenCmdSubKey,
                                   NULL, REG_SZ, (PCBYTE)pszAppOpenCmd,
                                   lstrlen(pszAppOpenCmd) + 1)
                    == ERROR_SUCCESS);

         FreeMemory(pszShellOpenCmdSubKey);
         pszShellOpenCmdSubKey = NULL;
      }

      FreeMemory(pszAppOpenCmd);
      pszAppOpenCmd = NULL;
   }

   return(bResult);
}


/*
** RegisterURLProtocolDescription()
**
** Under g_hkeyURLSettings\url-protocol, add default value =
** URL:Url-protocol Protocol.
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PRIVATE_CODE BOOL RegisterURLProtocolDescription(PCSTR pcszProtocol)
{
   BOOL bResult = FALSE;
   PSTR pszProtocolCopy;

   ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));

   if (StringCopy(pcszProtocol, &pszProtocolCopy))
   {
      char szDescriptionFmt[MAX_PATH_LEN];

      /*
       * Convert first character of protocol to upper case for description
       * string.
       */

      *pszProtocolCopy = (CHAR)PtrToUlong(CharUpper((LPSTR)(DWORD_PTR)*pszProtocolCopy));

      if (MLLoadStringA(IDS_URL_DESC_FORMAT,
                     szDescriptionFmt, sizeof(szDescriptionFmt)))
      {
         char szDescription[MAX_PATH_LEN];

         if ((UINT)lstrlen(szDescriptionFmt) + (UINT)lstrlen(pszProtocolCopy)
             < sizeof(szDescription))
         {
            EVAL(wsprintf(szDescription, szDescriptionFmt, pszProtocolCopy)
                 < sizeof(szDescription));

            /* (+ 1) for null terminator. */
            bResult = (SetRegKeyValue(g_hkeyURLProtocols, pcszProtocol,
                                      NULL, REG_SZ, (PCBYTE)szDescription,
                                      lstrlen(szDescription) + 1)
                       == ERROR_SUCCESS);
         }
      }

      FreeMemory(pszProtocolCopy);
      pszProtocolCopy = NULL;
   }

   return(bResult);
}


/*
** RegisterURLProtocolFlags()
**
** Under g_hkeyURLSettings\url-protocol, add EditFlags = FTA_Show.
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PRIVATE_CODE BOOL RegisterURLProtocolFlags(PCSTR pcszProtocol)
{
   DWORD dwEditFlags = FTA_Show;

   ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));

   /* FEATURE: What about preserving any existing EditFlags here? */

   /* (+ 1) for null terminator. */
   return(SetRegKeyValue(g_hkeyURLProtocols, pcszProtocol, g_cszEditFlags,
                         REG_BINARY, (PCBYTE)&dwEditFlags, sizeof(dwEditFlags))
          == ERROR_SUCCESS);
}


/*
** RegisterURLProtocol()
**
** Under g_hkeyURLSettings\url-protocol, add URL Protocol = "".
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PRIVATE_CODE BOOL RegisterURLProtocol(PCSTR pcszProtocol)
{
   ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));

   /* (+ 1) for null terminator. */
   return(SetRegKeyValue(g_hkeyURLProtocols, pcszProtocol, g_cszURLProtocol,
                         REG_SZ, (PCBYTE)EMPTY_STRING,
                         lstrlen(EMPTY_STRING) + 1) == ERROR_SUCCESS);
}


/*
** RegisterURLProtocolDefaultIcon()
**
** Under g_hkeyURLSettings\url-protocol\DefaultIcon, add default value =
** app.exe,0.
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PRIVATE_CODE BOOL RegisterURLProtocolDefaultIcon(PCSTR pcszProtocol)
{
   BOOL bResult = FALSE;
   DWORD dwcbDefaultIconSubKeyLen;
   PSTR pszDefaultIconSubKey;

   ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));

   /* (+ 1) for null terminator. */
   dwcbDefaultIconSubKeyLen = sizeof(s_cszDefaultIconSubKeyFmt) + 1
                              + lstrlen(pcszProtocol);

   if (AllocateMemory(dwcbDefaultIconSubKeyLen, &pszDefaultIconSubKey))
   {
      EVAL((DWORD)wsprintf(pszDefaultIconSubKey, s_cszDefaultIconSubKeyFmt,
                           pcszProtocol) < dwcbDefaultIconSubKeyLen);

      bResult = (SetRegKeyValue(g_hkeyURLProtocols, pszDefaultIconSubKey,
                                NULL, REG_SZ, (PCBYTE)s_cszDefaultIcon,
                                sizeof(s_cszDefaultIcon))
                 == ERROR_SUCCESS);

      FreeMemory(pszDefaultIconSubKey);
      pszDefaultIconSubKey = NULL;
   }

   return(bResult);
}


PRIVATE_CODE BOOL AllowedToRegisterMIMEType(PCSTR pcszMIMEContentType)
{
   BOOL bResult;

#pragma data_seg(DATA_SEG_READ_ONLY)

   bResult = (lstrcmpi(pcszMIMEContentType, "application/octet-stream") != 0 &&
              lstrcmpi(pcszMIMEContentType, "application/octet-string") != 0);

#pragma data_seg()

   if (bResult)
      TRACE_OUT(("AllowedToRegisterMIMEType(): MIME type %s may be registered.",
                 pcszMIMEContentType));
   else
      WARNING_OUT(("AllowedToRegisterMIMEType(): MIME type %s may not be registered.",
                   pcszMIMEContentType));

   return(bResult);
}


/****************************** Public Functions *****************************/


/*
** RegisterMIMETypeForExtension()
**
** Under HKEY_CLASSES_ROOT\.ext, add Content Type = mime/type.
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PUBLIC_CODE BOOL RegisterMIMETypeForExtension(PCSTR pcszExtension,
                                               PCSTR pcszMIMEContentType)
{
   ASSERT(IS_VALID_STRING_PTR(pcszExtension, CSTR));
   ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));

   ASSERT(IsValidExtension(pcszExtension));

   /* (+ 1) for null terminator. */
   return(SetRegKeyValue(HKEY_CLASSES_ROOT, pcszExtension, g_cszContentType, REG_SZ,
                         (PCBYTE)pcszMIMEContentType,
                         lstrlen(pcszMIMEContentType) + 1) == ERROR_SUCCESS);
}


/*
** UnregisterMIMETypeForExtension()
**
** Deletes Content Type under HKEY_CLASSES_ROOT\.ext.
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PUBLIC_CODE BOOL UnregisterMIMETypeForExtension(PCSTR pcszExtension)
{
   ASSERT(IS_VALID_STRING_PTR(pcszExtension, CSTR));

   ASSERT(IsValidExtension(pcszExtension));

   return(NO_ERROR == SHDeleteValue(HKEY_CLASSES_ROOT, pcszExtension, g_cszContentType));
}


/*
** RegisterExtensionForMIMEType()
**
** Under g_hkeyMIMESettings\MIME\Database\Content Type\mime/type, add
** Content Type = mime/type and Extension = .ext.
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
PUBLIC_CODE BOOL RegisterExtensionForMIMEType(PCSTR pcszExtension,
                                               PCSTR pcszMIMEContentType)
{
   BOOL bResult;
   char szMIMEContentTypeSubKey[MAX_PATH_LEN];

   ASSERT(IS_VALID_STRING_PTR(pcszExtension, CSTR));
   ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));

   ASSERT(IsValidExtension(pcszExtension));

   bResult = GetMIMETypeSubKey(pcszMIMEContentType, szMIMEContentTypeSubKey,
                               sizeof(szMIMEContentTypeSubKey));

   if (bResult)
      /* (+ 1) for null terminator. */
      bResult = (SetRegKeyValue(g_hkeyMIMESettings, szMIMEContentTypeSubKey,
                                g_cszExtension, REG_SZ, (PCBYTE)pcszExtension,
                                lstrlen(pcszExtension) + 1) == ERROR_SUCCESS);

   if (bResult)
      TRACE_OUT(("RegisterExtensionForMIMEType(): Registered extension %s as default extension for MIME type %s.",
                 pcszExtension,
                 pcszMIMEContentType));
   else
      WARNING_OUT(("RegisterExtensionForMIMEType(): Failed to register extension %s as default extension for MIME type %s.",
                   pcszExtension,
                   pcszMIMEContentType));

   return(bResult);
}


/*
** UnregisterExtensionForMIMEType()
**
** Deletes Extension under
** g_hkeyMIMESettings\MIME\Database\Content Type\mime/type.  If no other values
** or sub keys are left, deletes
** g_hkeyMIMESettings\MIME\Database\Content Type\mime/type.
**
** Arguments:
**
** Returns:
**
** Side Effects:  May also delete MIME key.
*/
PUBLIC_CODE BOOL UnregisterExtensionForMIMEType(PCSTR pcszMIMEContentType)
{
   BOOL bResult;
   char szMIMEContentTypeSubKey[MAX_PATH_LEN];

   ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));

   bResult = (GetMIMETypeSubKey(pcszMIMEContentType, szMIMEContentTypeSubKey,
                                sizeof(szMIMEContentTypeSubKey)) &&
              SHDeleteValue(g_hkeyMIMESettings, szMIMEContentTypeSubKey,
                                g_cszExtension) == ERROR_SUCCESS &&
              SHDeleteOrphanKey(g_hkeyMIMESettings, szMIMEContentTypeSubKey) == ERROR_SUCCESS);

   if (bResult)
      TRACE_OUT(("UnregisterExtensionForMIMEType(): Unregistered default extension for MIME type %s.",
                 pcszMIMEContentType));
   else
      WARNING_OUT(("UnregisterExtensionForMIMEType(): Failed to unregister default extension for MIME type %s.",
                   pcszMIMEContentType));

   return(bResult);
}


PUBLIC_CODE BOOL RegisterMIMEAssociation(PCSTR pcszFile,
                                         PCSTR pcszMIMEContentType)
{
   BOOL bResult;
   PCSTR pcszExtension;

   ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
   ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));

   pcszExtension = ExtractExtension(pcszFile);

    /*
     * Don't allow association of flag unknown MIME types
     * application/octet-stream and application/octet-string.
     */

   if (EVAL(*pcszExtension) &&
       AllowedToRegisterMIMEType(pcszMIMEContentType))
      bResult = (RegisterMIMETypeForExtension(pcszExtension, pcszMIMEContentType) &&
                 RegisterExtensionForMIMEType(pcszExtension, pcszMIMEContentType));
   else
      bResult = FALSE;

   return(bResult);
}


PUBLIC_CODE BOOL RegisterURLAssociation(PCSTR pcszProtocol, PCSTR pcszApp)
{
   ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
   ASSERT(IS_VALID_STRING_PTR(pcszApp, CSTR));

   return(RegisterAppAsURLProtocolHandler(pcszProtocol, pcszApp) &&
          RegisterURLProtocolDescription(pcszProtocol) &&
          RegisterURLProtocol(pcszProtocol) &&
          RegisterURLProtocolFlags(pcszProtocol) &&
          RegisterURLProtocolDefaultIcon(pcszProtocol));
}


PUBLIC_CODE HRESULT MyMIMEAssociationDialog(HWND hwndParent, DWORD dwInFlags,
                                            PCSTR pcszFile,
                                            PCSTR pcszMIMEContentType,
                                            PSTR pszAppBuf, UINT ucAppBufLen)
{
   HRESULT hr;
   OPENASINFO oainfo;

   ASSERT(IS_VALID_HANDLE(hwndParent, WND));
   ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_MIMEASSOCDLG_FLAGS));
   ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
   ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));
   ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen));

   /* Use default file name if not supplied by caller. */

   if (ucAppBufLen > 0)
      *pszAppBuf = '\0';

   oainfo.pcszFile = pcszFile;
   oainfo.pcszClass = pcszMIMEContentType;
   oainfo.dwInFlags = 0;

   if (IS_FLAG_SET(dwInFlags, MIMEASSOCDLG_FL_REGISTER_ASSOC))
      SET_FLAG(oainfo.dwInFlags, (OPENASINFO_FL_ALLOW_REGISTRATION |
                                  OPENASINFO_FL_REGISTER_EXT));

   hr = MyOpenAsDialog(hwndParent, &oainfo);

   if (hr == S_OK &&
       IS_FLAG_SET(dwInFlags, MIMEASSOCDLG_FL_REGISTER_ASSOC))
      hr = RegisterMIMEAssociation(pcszFile, pcszMIMEContentType) ? S_OK
                                                                  : E_OUTOFMEMORY;

   if (SUCCEEDED(hr))
      lstrcpyn(pszAppBuf, oainfo.szApp, ucAppBufLen);

   ASSERT(! ucAppBufLen ||
          (IS_VALID_STRING_PTR(pszAppBuf, STR) &&
           EVAL((UINT)lstrlen(pszAppBuf) < ucAppBufLen)));
   ASSERT(SUCCEEDED(hr) ||
          (! ucAppBufLen ||
           EVAL(! *pszAppBuf)));

   return(hr);
}


PUBLIC_CODE HRESULT MyURLAssociationDialog(HWND hwndParent, DWORD dwInFlags,
                                           PCSTR pcszFile, PCSTR pcszURL,
                                           PSTR pszAppBuf, UINT ucAppBufLen)
{
   HRESULT hr;
   PSTR pszProtocol;

   ASSERT(IS_VALID_HANDLE(hwndParent, WND));
   ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_URLASSOCDLG_FLAGS));
   ASSERT(IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) ||
          IS_VALID_STRING_PTR(pcszFile, CSTR));
   ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
   ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen));

   /* Use URL protocol as class name. */

   if (ucAppBufLen > 0)
      *pszAppBuf = '\0';

   hr = CopyURLProtocol(pcszURL, &pszProtocol);

   if (hr == S_OK)
   {
      char szInternetShortcut[MAX_PATH_LEN];
      OPENASINFO oainfo;

      /* Use default file name if not supplied by caller. */

      if (IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) &&
          EVAL(MLLoadStringA(IDS_INTERNET_SHORTCUT,
                          szInternetShortcut, sizeof(szInternetShortcut))))
         pcszFile = szInternetShortcut;

      oainfo.pcszFile = pcszFile;
      oainfo.pcszClass = pszProtocol;
      oainfo.dwInFlags = 0;

      if (IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_REGISTER_ASSOC))
         SET_FLAG(oainfo.dwInFlags, OPENASINFO_FL_ALLOW_REGISTRATION);

      hr = MyOpenAsDialog(hwndParent, &oainfo);

      if (hr == S_OK &&
          IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_REGISTER_ASSOC))
         hr = RegisterURLAssociation(pszProtocol, oainfo.szApp) ? S_OK
                                                                : E_OUTOFMEMORY;

      if (SUCCEEDED(hr))
         lstrcpyn(pszAppBuf, oainfo.szApp, ucAppBufLen);

      FreeMemory(pszProtocol);
      pszProtocol = NULL;
   }

   ASSERT(! ucAppBufLen ||
          (IS_VALID_STRING_PTR(pszAppBuf, STR) &&
           EVAL((UINT)lstrlen(pszAppBuf) < ucAppBufLen)));
   ASSERT(SUCCEEDED(hr) ||
          (! ucAppBufLen ||
           EVAL(! *pszAppBuf)));

   return(hr);
}


#ifdef DEBUG

PUBLIC_CODE BOOL IsValidPCOPENASINFO(PCOPENASINFO pcoainfo)
{
   return(IS_VALID_READ_PTR(pcoainfo, COPENASINFO) &&
          IS_VALID_STRING_PTR(pcoainfo->pcszFile, CSTR) &&
          (! pcoainfo->pcszClass ||
           IS_VALID_STRING_PTR(pcoainfo->pcszClass, CSTR)) &&
          FLAGS_ARE_VALID(pcoainfo->dwInFlags, ALL_OPENASINFO_FLAGS) &&
          (! *pcoainfo->szApp ||
           IS_VALID_STRING_PTR(pcoainfo->szApp, STR)));
}

#endif   /* DEBUG */


/***************************** Exported Functions ****************************/


INTSHCUTAPI HRESULT WINAPI MIMEAssociationDialogA(HWND hwndParent,
                                                  DWORD dwInFlags,
                                                  PCSTR pcszFile,
                                                  PCSTR pcszMIMEContentType,
                                                  PSTR pszAppBuf,
                                                  UINT ucAppBufLen)
{
   HRESULT hr;

   DebugEntry(MIMEAssociationDialogA);

#ifdef EXPV
   /* Verify parameters. */

   if (IS_VALID_HANDLE(hwndParent, WND) &&
       IS_VALID_STRING_PTR(pcszFile, CSTR) &&
       IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR) &&
       IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen))
   {
      if (FLAGS_ARE_VALID(dwInFlags, ALL_MIMEASSOCDLG_FLAGS))
#endif
      {
         hr = MyMIMEAssociationDialog(hwndParent, dwInFlags, pcszFile,
                                      pcszMIMEContentType, pszAppBuf,
                                      ucAppBufLen);
      }
#ifdef EXPV
      else
         hr = E_FLAGS;
   }
   else
      hr = E_POINTER;
#endif

   DebugExitHRESULT(MIMEAssociationDialogA, hr);

   return(hr);
}


#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */

INTSHCUTAPI HRESULT WINAPI MIMEAssociationDialogW(HWND hwndParent,
                                                  DWORD dwInFlags,
                                                  PCWSTR pcszFile,
                                                  PCWSTR pcszMIMEContentType,
                                                  PWSTR pszAppBuf,
                                                  UINT ucAppBufLen)
{
   HRESULT hr;

   DebugEntry(MIMEAssociationDialogW);

   SetLastError(ERROR_NOT_SUPPORTED);
   hr = E_NOTIMPL;

   DebugExitHRESULT(MIMEAssociationDialogW, hr);

   return(hr);
}

#pragma warning(default:4100) /* "unreferenced formal parameter" warning */


INTSHCUTAPI HRESULT WINAPI URLAssociationDialogA(HWND hwndParent,
                                                 DWORD dwInFlags,
                                                 PCSTR pcszFile, PCSTR pcszURL,
                                                 PSTR pszAppBuf,
                                                 UINT ucAppBufLen)
{
   HRESULT hr;

   DebugEntry(URLAssociationDialogA);

#ifdef EXPV
   /* Verify parameters. */

   if (IS_VALID_HANDLE(hwndParent, WND) &&
       (IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) ||
        IS_VALID_STRING_PTR(pcszFile, CSTR)) &&
       IS_VALID_STRING_PTR(pcszURL, CSTR) &&
       IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen))
   {
      if (FLAGS_ARE_VALID(dwInFlags, ALL_URLASSOCDLG_FLAGS))
#endif
      {
         hr = MyURLAssociationDialog(hwndParent, dwInFlags, pcszFile, pcszURL,
                                     pszAppBuf, ucAppBufLen);
      }
#ifdef EXPV
      else
         hr = E_FLAGS;
   }
   else
      hr = E_POINTER;
#endif

   DebugExitHRESULT(URLAssociationDialogA, hr);

   return(hr);
}


#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */

INTSHCUTAPI HRESULT WINAPI URLAssociationDialogW(HWND hwndParent,
                                                 DWORD dwInFlags,
                                                 PCWSTR pcszFile,
                                                 PCWSTR pcszURL,
                                                 PWSTR pszAppBuf,
                                                 UINT ucAppBufLen)
{
   HRESULT hr;

   DebugEntry(URLAssociationDialogW);

   SetLastError(ERROR_NOT_SUPPORTED);
   hr = E_NOTIMPL;

   DebugExitHRESULT(URLAssociationDialogW, hr);

   return(hr);
}

#pragma warning(default:4100) /* "unreferenced formal parameter" warning */