unixstuff.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 56k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*----------------------------------------------------------
  2. Purpose: Unix-menus related functions.
  3. */
  4. #include <tchar.h>
  5. #include <process.h>
  6. #include <ieverp.h>
  7. #include "priv.h"
  8. #include "unixstuff.h"
  9. #include "resource.h"
  10. #include "dochost.h"
  11. #include "winlist.h"
  12. #include "runonnt.h"
  13. #include "impexp.h"
  14. #include "mluisupp.h"
  15. #define WINDOWS_MENU_ARROW_WIDTH  4
  16. #define WINDOWS_MENU_ARROW_HEIGHT 8
  17. #define MOTIF_ARROW_TEXT_MARGIN   4
  18. // From download.cpp
  19. #define TITLE_LEN    (256 + 32)
  20. #define MAX_DISPLAY_LEN 96
  21. #ifdef NO_MARSHALLING
  22. extern DWORD g_TLSThreadWindowInfo;
  23. #endif
  24. const TCHAR c_szExploreClass[] = TEXT("ExploreWClass");
  25. const TCHAR c_szIExploreClass[] = TEXT("IEFrame");
  26. const TCHAR c_szCabinetClass[] = 
  27. #ifdef IE3CLASSNAME
  28.     TEXT("IEFrame");
  29. #else
  30.     TEXT("CabinetWClass");
  31. #endif
  32. extern HMENU g_hmenuFullSB;
  33. extern "C" {
  34.     /* Common controls */
  35.     void UnixPaintArrow(HDC hDC, BOOL bHoriz, BOOL bDown, int nXCenter, int nYCenter, int nWidth, int nHeight);
  36.     /* mainwin */
  37.     void MwDrawMotifPopupArrowParams(BOOL bDrawAsDown, HDC hDC, int nShadowThickness, DWORD cButtonSunny, 
  38.                                      DWORD cButtonShadow, DWORD cSelect, DWORD cBackground, const RECT* rItemSize, 
  39.                                      int nIndicatorSize);
  40.     void MwPaintMotifPushButtonGadgetUpDown(HDC hDC, int nButtonWidth, int nButtonHeight, BOOL bFocus, 
  41.                                             BOOL bDrawDefaultPB, BOOL bDown, BOOL bDrawTopBottomShadowOnly,
  42.                                             BOOL bMenu,  void* /* NULL */, int nOffsetx, int nOffsety);
  43.     BOOL MwGetMotifPullDownMenuResourcesExport(int *lpnShadowThickness, int *lpnMarginHeight, int *lpnMarginWidth,
  44.                                                int *lpnButtonSpacing, DWORD *lpcBackground, DWORD *lpcForeground,
  45.                                                DWORD *lpcButtonSunny, DWORD *lpcButtonShadow, HFONT * phFont);
  46.     COLORREF MwGetMotifColor(int index);
  47. };
  48. static void
  49. GetMotifMenuParams(int* pnShadowThickness, DWORD* pcBackground, DWORD* pcForeground, 
  50.                     DWORD* pcButtonSunny, DWORD* pcButtonShadow, DWORD* pcSelect, 
  51.                     int* pnIndicatorSize)
  52. {
  53.     const int nIndicatorSize = 12;
  54.     const int MR_PULLDOWNMENU_CHECKBOX_TOGGLEBUTTON_SELECTCOLOR=167;
  55.     MwGetMotifPullDownMenuResourcesExport(pnShadowThickness, NULL, NULL, NULL, pcBackground, pcForeground,
  56.                                           pcButtonSunny, pcButtonShadow, NULL);          
  57.    
  58.     if (pcSelect != NULL)
  59.         *pcSelect = MwGetMotifColor(MR_PULLDOWNMENU_CHECKBOX_TOGGLEBUTTON_SELECTCOLOR);
  60.     if (pnIndicatorSize != NULL)
  61.      *pnIndicatorSize = nIndicatorSize;
  62. }
  63. EXTERN_C void SelectMotifMenu(HDC hdc, const RECT* prc, BOOL bSelected)
  64. {
  65.     MwPaintMotifPushButtonGadgetUpDown(hdc, prc->right - prc->left, prc->bottom - prc->top,
  66.                                        FALSE, FALSE, bSelected, FALSE, TRUE, NULL,
  67.                                        prc->left, prc->top);
  68. }
  69. EXTERN_C void PaintMotifMenuArrow(HDC hdc, const RECT* prc, BOOL bSelected)
  70. {
  71.     int nShadowThickness, nIndicatorSize;
  72.     DWORD cBackground, cForeground, cButtonSunny, cButtonShadow, cSelect;
  73.     RECT rect = *prc;
  74.     
  75.     GetMotifMenuParams(&nShadowThickness, &cBackground, &cForeground, &cButtonSunny, 
  76.                        &cButtonShadow, &cSelect, &nIndicatorSize);
  77.     // Compensation for space added in the indicatorSize.
  78.     rect.left += MOTIF_ARROW_TEXT_MARGIN;
  79.     MwDrawMotifPopupArrowParams(bSelected, hdc, nShadowThickness, cButtonSunny, cButtonShadow,
  80.                                 cSelect, cBackground, &rect, nIndicatorSize);
  81. }
  82. EXTERN_C void PaintWindowsMenuArrow(HDC hdc, const RECT* prc)
  83. {
  84.      int cy = prc->bottom - prc->top;
  85.      UnixPaintArrow( hdc, TRUE, TRUE, prc->left, prc->top + cy/2, 
  86.          WINDOWS_MENU_ARROW_WIDTH, WINDOWS_MENU_ARROW_HEIGHT );
  87. }
  88. EXTERN_C void PaintUnixMenuArrow(HDC hdc, const RECT* prc, DWORD data)
  89.     if (MwCurrentLook() == LOOK_MOTIF) {
  90.          COLORREF rgbText = (COLORREF) data;
  91.          BOOL bSelected = (rgbText == GetSysColor(COLOR_HIGHLIGHTTEXT));
  92.          PaintMotifMenuArrow(hdc, prc, bSelected);
  93.      }
  94.      else {
  95.          PaintWindowsMenuArrow( hdc, prc );
  96.      }
  97. }
  98. EXTERN_C int GetUnixMenuArrowWidth()
  99. {
  100.     if (MwCurrentLook() == LOOK_MOTIF)
  101.     {
  102.         int nShadowThickness, nIndicatorSize;
  103.         DWORD cBackground, cForeground, cButtonSunny, cButtonShadow, cSelect;
  104.         GetMotifMenuParams(&nShadowThickness, &cBackground, &cForeground, &cButtonSunny,
  105.                        &cButtonShadow, &cSelect, &nIndicatorSize);
  106.         // Indicator Size increased for space between
  107.         return (nIndicatorSize + MOTIF_ARROW_TEXT_MARGIN);
  108.     }
  109.     else
  110.     {
  111.         return ( WINDOWS_MENU_ARROW_WIDTH );
  112.     }
  113. }
  114. EXTERN_C BOOL CheckAndExecNewsScript( HWND hwnd )
  115. {
  116.      HKEY hkey;
  117.      DWORD dwType;
  118.      DWORD dwSize = sizeof(DWORD);
  119.      DWORD dwUseOENews = FALSE;
  120.      HRESULT hres = S_FALSE;
  121.      BOOL  fRet = FALSE;
  122.      TCHAR tszCommandLine[ INTERNET_MAX_URL_LENGTH + 1];
  123.      TCHAR tszExpandedCommand[INTERNET_MAX_URL_LENGTH + 1];
  124. #ifndef DISABLE_OE
  125.      SHGetValue(IE_USE_OE_NEWS_HKEY, IE_USE_OE_NEWS_KEY, IE_USE_OE_NEWS_VALUE,
  126.            &dwType, (void*)&dwUseOENews, &dwSize);
  127.      if (dwType != REG_DWORD)
  128.      {
  129.          // The default value for mail is FALSE
  130.          dwUseOENews = FALSE;
  131.      }
  132. #endif
  133.      if (! dwUseOENews )
  134.      {
  135.          hres = RegOpenKeyEx(
  136.             HKEY_CURRENT_USER,
  137.             REGSTR_PATH_NEWSCLIENTS,
  138.             0,
  139.             KEY_READ,
  140.             &hkey);
  141.          if (hres == ERROR_SUCCESS)
  142.          {
  143.              dwSize = sizeof( tszExpandedCommand );
  144.              hres = RegQueryValueEx(hkey, REGSTR_PATH_CURRENT, NULL, NULL,
  145.                    (LPBYTE)tszCommandLine, &dwSize);
  146.              if (hres == ERROR_SUCCESS)
  147.              {
  148.                   STARTUPINFO stInfo;
  149.                   memset(&stInfo, 0, sizeof(stInfo));
  150.                   stInfo.cb = sizeof(stInfo);
  151.                   SHExpandEnvironmentStrings(tszCommandLine, tszExpandedCommand,
  152.                       INTERNET_MAX_URL_LENGTH);
  153.                   if( CreateProcess(tszExpandedCommand, tszCommandLine, NULL, NULL,
  154.                         FALSE, DETACHED_PROCESS, NULL,
  155.                         NULL, &stInfo, NULL) )
  156.                       fRet = TRUE;
  157.              }
  158.            
  159.              RegCloseKey( hkey );
  160.          }
  161.      }
  162.      if( !dwUseOENews && !fRet )
  163.      {
  164.          ShellMessageBox(
  165.              MLGetHinst(),
  166.              hwnd,
  167.              MAKEINTRESOURCE(IDS_NEWS_SCRIPT_ERROR),
  168.              MAKEINTRESOURCE(IDS_NEWS_SCRIPT_ERROR_TITLE),
  169.              MB_ICONWARNING|MB_OK);
  170.          fRet = TRUE;
  171.      }
  172.      return fRet;
  173. }
  174. EXTERN_C int  ConvertModuleNameToUnix( LPTSTR path )
  175. {
  176.     TCHAR drive[_MAX_DRIVE];   
  177.     TCHAR dir[_MAX_DIR];
  178.     TCHAR fname[_MAX_FNAME];   
  179.     TCHAR ext[_MAX_EXT];
  180.     if( !path || !*path )
  181.         return 0;
  182. #ifndef UNICODE
  183.     _splitpath( path, drive, dir, fname, ext );
  184. #else
  185.     _wsplitpath( path, drive, dir, fname, ext );
  186. #endif
  187.     if(StrCmpNI( fname, TEXT("lib"), 3 ))
  188.        StrCpyN( path, fname, _MAX_FNAME );
  189.     else
  190.        StrCpyN( path, fname+3, (_MAX_FNAME-3) );
  191.     if(StrCmpNI( ext, TEXT(".so"), 3 ))
  192.        StrCatBuff( path, ext, _MAX_EXT );
  193.     else
  194.        StrCatBuff( path, TEXT(".dll"), _MAX_EXT );
  195.     return lstrlen( path );
  196. }
  197. void ContentHelp( IShellBrowser* psb )
  198. {
  199.     UnixHelp("Content Index", psb);
  200. }
  201. EXTERN_C void UnixHelp(LPWSTR pszName, IShellBrowser* psb )
  202. {
  203.     WCHAR szPathTemp[MAX_URL_STRING+1];
  204.     
  205.     HRESULT hres = E_FAIL;
  206.     UINT  cbTempSize = ARRAYSIZE(szPathTemp);
  207.     // Get the path for installed pages from registry. This entry
  208.     // in registry is modified by the setup   program to point to
  209.     // location where help files are installed.
  210.     hres = URLSubRegQuery(L"Software\Microsoft\Internet Explorer\Unix",
  211.            pszName, TRUE, szPathTemp, cbTempSize, URLSUB_ALL);
  212.     if( FAILED(hres) ) return;
  213.     if(psb)
  214.     {
  215.         LPITEMIDLIST searchPidl;
  216.         // searchPidl = SHSimpleIDListFromPath( szPathTemp );
  217.         ::IEParseDisplayName(CP_ACP, szPathTemp, &searchPidl );
  218.         if(searchPidl)
  219.         {
  220.             psb->BrowseObject(searchPidl,SBSP_NEWBROWSER|SBSP_HELPMODE|SBSP_NOTRANSFERHIST);
  221.             ILFree( searchPidl );
  222.         }
  223.     }
  224. }
  225. EXTERN_C BOOL  OEHandlesMail( void )
  226. {
  227. #ifdef DISABLE_OE
  228.     return FALSE;
  229. #endif
  230.     DWORD dwType;
  231.     DWORD dwSize;
  232.     DWORD dwUseOEMail;
  233.     HRESULT hr;
  234.     dwSize = sizeof(DWORD);
  235.     hr = SHGetValue(IE_USE_OE_MAIL_HKEY, IE_USE_OE_MAIL_KEY, IE_USE_OE_MAIL_VALUE, &dwType, (void*)&dwUseOEMail, &dwSize);
  236.     if ((hr) && (dwType != REG_DWORD))
  237.     {
  238.         // The default value for mail is FALSE
  239.         dwUseOEMail = FALSE;
  240.     }
  241.     if (dwUseOEMail)
  242.     {
  243.         return TRUE; 
  244.     }
  245.     else
  246.     {
  247.         return FALSE;
  248.     }
  249. }
  250. // PORT QSY SendDocToMailRecipient has already been used to
  251. // invoke native UNIX mailers. Invent a new function to
  252. // let OE do the job.
  253. // Most of the code copied from WAB and  shell/ext/sendmail/sendmail.c
  254. // We probably should port sendmail.dll after preview 1.
  255. #include <mapi.h>
  256. #define MRPARAM_DOC          0x00000001
  257. #define MRPARAM_DELETEFILE   0x00000002 // The temporary file was created by us and need to be deleted
  258. #define MRPARAM_USECODEPAGE  0x00000004
  259. typedef struct {
  260.     DWORD dwFlags;    // Attributes passed to the MAPI apis
  261.     LPTSTR pszFiles;  // All files names separated by NULL;
  262.     LPTSTR pszURL;    // All files names of URLs separated by ';', this will
  263.                       // be the title;
  264.     CHAR paszFiles[MAX_PATH + 1];
  265.     CHAR paszURL[INTERNET_MAX_URL_LENGTH + 1];
  266.                       // be the title;
  267.     int nFiles;       // The number of files being sent.
  268.     UINT uiCodePage;  // Code page
  269. } MRPARAM;
  270. const LPTSTR szDefMailKey = TEXT("Software\Clients\Mail");
  271. const LPTSTR szOEDllPathKey =  TEXT("DllPath");
  272. const LPTSTR szOEName = TEXT("Outlook Express");
  273. BOOL CheckForOutlookExpress(LPTSTR szDllPath)
  274. {
  275. #ifdef DISABLE_OE
  276.     return FALSE;
  277. #endif
  278.     HKEY hKeyMail   = NULL;
  279.     HKEY hKeyOE     = NULL;
  280.     DWORD dwErr     = 0;
  281.     DWORD dwSize    = 0;
  282.     TCHAR szBuf[MAX_PATH];
  283.     DWORD dwType    = 0;
  284.     BOOL bRet = FALSE;
  285.     StrCpyN(szDllPath, TEXT(""), 1);
  286.     // Open the key for default internet mail client
  287.     // HKLMSoftwareClientsMail
  288.     dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  289.                                 szDefMailKey,
  290.                                 0,
  291.                                 KEY_ALL_ACCESS,
  292.                                 &hKeyMail);
  293.     if(dwErr != ERROR_SUCCESS)
  294.     {
  295.         goto out;
  296.     }
  297.     dwSize = sizeof(szBuf);         // Expect ERROR_MORE_DATA
  298.     dwErr = RegQueryValueEx(
  299.                                 hKeyMail,
  300.                                 NULL,
  301.                                 NULL,
  302.                                 &dwType,
  303.                                 (LPBYTE)szBuf,
  304.                                 &dwSize);
  305.     if(dwErr != ERROR_SUCCESS)
  306.     {
  307.         goto out;
  308.     }
  309.     if(!StrCmpI(szBuf, szOEName))
  310.     {
  311.         // Yes its outlook express ..
  312.         bRet = TRUE;
  313.         // Get the DLL Path
  314.         dwErr = RegOpenKeyEx(hKeyMail,
  315.                                     szOEName,
  316.                                     0,
  317.                                     KEY_ALL_ACCESS,
  318.                                     &hKeyOE);
  319.         if(dwErr != ERROR_SUCCESS)
  320.         {
  321.             goto out;
  322.         }
  323.         dwSize = sizeof(szBuf);
  324.         StrCpyN(szBuf, TEXT(""), 1);
  325.         dwErr = RegQueryValueEx(
  326.                                 hKeyOE,
  327.                                 szOEDllPathKey,
  328.                                 NULL,
  329.                                 &dwType,
  330.                                 (LPBYTE)szBuf,
  331.                                 &dwSize);
  332.         if(dwErr != ERROR_SUCCESS)
  333.         {
  334.             goto out;
  335.         }
  336.         if(lstrlen(szBuf))
  337.             StrCpyN(szDllPath, szBuf, lstrlen(szBuf) + 1);
  338.     }
  339. out:
  340.     if(hKeyOE)
  341.         RegCloseKey(hKeyOE);
  342.     if(hKeyMail)
  343.         RegCloseKey(hKeyMail);
  344.     return bRet;
  345. }
  346. HANDLE LoadMailProvider()
  347. {
  348.     TCHAR szBuf[MAX_PATH];
  349.     HANDLE hLibMapi = NULL;
  350.     if(CheckForOutlookExpress(szBuf) == TRUE)
  351.     {
  352.         hLibMapi = LoadLibrary(szBuf);
  353. return hLibMapi;
  354.     }
  355.     else
  356.         return 0;
  357. }
  358. BOOL AllocatePMP(MRPARAM * pmp, DWORD cchUrlBufferSize, DWORD cchFileBufferSize)
  359. {
  360.     pmp->pszURL = (LPTSTR) GlobalAlloc(GPTR, cchUrlBufferSize * sizeof(TCHAR));
  361.     if (!pmp->pszURL)
  362.         return FALSE;
  363.  
  364.     pmp->pszFiles = (LPTSTR) GlobalAlloc(GPTR, cchFileBufferSize * sizeof(TCHAR));
  365.     if (!pmp->pszFiles)
  366.         return FALSE;
  367.  
  368.     return TRUE;
  369. }
  370. BOOL CleanupPMP(MRPARAM * pmp)
  371. {
  372.     if (pmp->pszFiles)
  373.         GlobalFree((LPVOID)pmp->pszFiles);
  374.     pmp->pszFiles = NULL;
  375.     if (pmp->pszURL)
  376.         GlobalFree((LPVOID)pmp->pszURL);
  377.     pmp->pszURL = NULL;
  378.     pmp->nFiles = 0;
  379.     GlobalFree(pmp);
  380.     return TRUE;
  381. }
  382. HRESULT _CreateShortcutToPath(LPCTSTR pszPath, LPCTSTR pszTarget)
  383. {
  384.     IShellLink *psl;
  385.     HRESULT hres = CoCreateInstance(CLSID_ShellLink, 
  386. NULL, 
  387. CLSCTX_INPROC_SERVER, 
  388. IID_IShellLink, 
  389. (LPVOID*)&psl);
  390.     if (SUCCEEDED(hres))
  391.     {
  392.         IPersistFile *ppf;
  393.         psl->SetPath(pszTarget);
  394.         hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
  395.         if (SUCCEEDED(hres))
  396.         {
  397.             WCHAR wszPath[MAX_PATH];
  398. #ifndef UNICODE
  399.             AnsiToUnicode(pszPath, wszPath, ARRAYSIZE(wszPath));
  400. #else
  401.     StrCpyN(wszPath, pszPath, MAX_PATH);
  402. #endif
  403.  
  404.             hres = ppf->Save(wszPath, TRUE);
  405.             ppf->Release();
  406.         }
  407.         psl->Release();
  408.     }
  409.     return hres;
  410. }
  411. // create a temporary shortcut to a file
  412. // BUGBUG: Colision is not handled here
  413. BOOL _CreateTempFileShortcut(LPCTSTR IN pszFile, LPTSTR OUT pszShortcut)
  414. {
  415.     TCHAR szPath[MAX_PATH];
  416.     
  417.     if (GetTempPath(ARRAYSIZE(szPath), szPath))
  418.     {
  419.         StrCatBuff(szPath, PathFindFileName(pszFile), lstrlen(pszFile) + 1);
  420.         PathRenameExtension(szPath, TEXT(".lnk"));
  421.         if (SUCCEEDED(_CreateShortcutToPath(szPath, pszFile)))
  422.         {
  423.             StrCpyN(pszShortcut, szPath, MAX_PATH);
  424.             return TRUE;
  425.         }
  426.     }
  427.     return FALSE;
  428. HRESULT CopyHtmlFile(HANDLE hOrig, HANDLE hNew, DWORD dwSize)
  429. {
  430.     BYTE Buff[4096];
  431.     int iBlock, nBlocks = dwSize / SIZEOF(Buff);
  432.  
  433.     for (iBlock = 0; iBlock <= nBlocks; iBlock++)
  434.     {
  435.         DWORD dwRead, dwWrite;
  436.  
  437.         ReadFile(hOrig, Buff, SIZEOF(Buff), &dwRead, NULL);
  438.         if ((iBlock < nBlocks) && (dwRead != SIZEOF(Buff)))
  439.             return E_FAIL;
  440.         WriteFile(hNew, Buff, dwRead, &dwWrite, NULL);
  441.         if (dwWrite != dwRead)
  442.             return E_FAIL;
  443.     }
  444.  
  445.     return S_OK;
  446. }
  447. typedef BOOL (RETRIEVE_URL_CACHE_ENTRY_FILEA) (
  448. LPCSTR lpszUrlName,
  449. LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
  450. LPDWORD lpdwCacheEntryInfoBufferSize,
  451. DWORD dwReserved
  452. );
  453. typedef RETRIEVE_URL_CACHE_ENTRY_FILEA FAR *LP_RETRIEVE_URL_CACHE_ENTRY_FILEA;
  454. typedef BOOL (RETRIEVE_URL_CACHE_ENTRY_FILEW) (
  455.         LPCWSTR lpszUrlName,
  456.         LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
  457.         LPDWORD lpdwCacheEntryInfoBufferSize,
  458.         DWORD dwReserved
  459. );
  460. typedef RETRIEVE_URL_CACHE_ENTRY_FILEW *LP_RETRIEVE_URL_CACHE_ENTRY_FILEW;
  461. HRESULT CreateHtmlFileFromUrl(LPCTSTR pszURL, LPCTSTR pszFile)
  462. {
  463.     DWORD dwSize;
  464.     HRESULT hr = E_FAIL;
  465.     INTERNET_CACHE_ENTRY_INFO *picei=NULL;
  466.     #ifdef UNICODE
  467.     LP_RETRIEVE_URL_CACHE_ENTRY_FILEW lpfnRetrieveUrlCacheEntryFile;
  468.     #else
  469.     LP_RETRIEVE_URL_CACHE_ENTRY_FILEA lpfnRetrieveUrlCacheEntryFile;
  470.     #endif
  471.     HINSTANCE hLibWininet = LoadLibrary(TEXT("wininet.dll"));
  472.  
  473.     if (!hLibWininet)
  474.         return E_FAIL;
  475.     #ifdef UNICODE
  476.     lpfnRetrieveUrlCacheEntryFile = 
  477. (LP_RETRIEVE_URL_CACHE_ENTRY_FILEW) GetProcAddress(hLibWininet, "RetrieveUrlCacheEntryFileW");
  478.     #else
  479.     lpfnRetrieveUrlCacheEntryFile = 
  480. (LP_RETRIEVE_URL_CACHE_ENTRY_FILEA)GetProcAddress(hLibWininet, "RetrieveUrlCacheEntryFileA");
  481.     #endif
  482.     if (!lpfnRetrieveUrlCacheEntryFile)
  483. return E_FAIL;
  484.  
  485.   
  486.     // Find size of Cache Entry File struct for this url. Call fails with
  487.     // error insufficient buffer and puts size in dwSize. Any other failure
  488.     // value implies the item isn't in the cache.
  489.     dwSize = 0;
  490.     if (!lpfnRetrieveUrlCacheEntryFile(pszURL, picei, &dwSize, 0))
  491.     {
  492.         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  493.             picei = (INTERNET_CACHE_ENTRY_INFO *) GlobalAlloc(GPTR,  dwSize);
  494.     }
  495.     
  496.     if (picei)
  497.     {
  498.         if (lpfnRetrieveUrlCacheEntryFile(pszURL, picei, &dwSize, 0))
  499.         {
  500.             HANDLE hOrigFile = CreateFile(picei->lpszLocalFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  501.                                           OPEN_EXISTING, 0, NULL);
  502.             if (hOrigFile != INVALID_HANDLE_VALUE)
  503.             {
  504.                 HANDLE hNewFile = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  505.                                              CREATE_ALWAYS, 0, NULL);
  506.                 if (hNewFile != INVALID_HANDLE_VALUE)
  507.                 {
  508.                     DWORD dwWritten;
  509.                     TCHAR szBaseTag[INTERNET_MAX_URL_LENGTH + 20];
  510.                     wnsprintf(szBaseTag, ARRAYSIZE(szBaseTag), TEXT("<BASE HREF="%s">n"), pszURL);
  511.                     
  512.                     if (WriteFile(hNewFile, szBaseTag, lstrlen(szBaseTag)*SIZEOF(TCHAR), &dwWritten, NULL))
  513.                         hr = CopyHtmlFile(hOrigFile, hNewFile, picei->dwSizeLow);
  514.                     CloseHandle(hNewFile);
  515.                 }
  516.                 CloseHandle(hOrigFile);
  517.             }
  518.         }
  519.         GlobalFree(picei);
  520.     }
  521.     return hr;
  522. }
  523. extern HRESULT PersistShortcut(IUniformResourceLocator * purl, LPCWSTR pwszFile);
  524. /*
  525.  * pcszURL -> "ftp://ftp.microsoft.com"
  526.  * pcszPath -> "c:windowsdesktopinternetMicrosoft FTP.url"
  527.  */
  528. HRESULT CreateNewURLShortcut(LPCTSTR pcszURL, LPCTSTR pcszURLFile)
  529. {
  530.     HRESULT hr;
  531.     WCHAR wszFile[INTERNET_MAX_URL_LENGTH];
  532. #ifndef UNICODE
  533.     if (AnsiToUnicode(pcszURLFile,
  534.                       wszFile, ARRAYSIZE(wszFile)) > 0)
  535. #else
  536.     if (StrCpyN(wszFile, pcszURLFile, ARRAYSIZE(wszFile)) > 0)
  537. #endif
  538.     {
  539.         IUniformResourceLocator *purl;
  540.         hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  541.                               IID_IUniformResourceLocator, (LPVOID*)&purl);
  542.         if (SUCCEEDED(hr))
  543.         {
  544.             hr = purl->SetURL( pcszURL, 0);
  545.             if (SUCCEEDED(hr))
  546.                 hr = PersistShortcut(purl, wszFile);
  547.             purl->Release();
  548.         }
  549.     }
  550.     else
  551.         hr = E_FAIL;
  552.     return(hr);
  553. }
  554. HRESULT _GetFileDescription(IDataObject * pdtobj, LPTSTR pszDescription)
  555. {
  556.     STGMEDIUM medium;
  557.     HRESULT hres;
  558.     FORMATETC fmteURL = {0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  559.     UINT g_cfFileDesc;
  560.     InitClipboardFormats();
  561.     #ifdef UNICODE
  562.     g_cfFileDesc = g_cfFileDescW;
  563.     #else
  564.     g_cfFileDesc = g_cfFileDescA;
  565.     #endif
  566.     
  567.     fmteURL.cfFormat = g_cfFileDesc;
  568.     hres = E_FAIL;
  569.     if (SUCCEEDED(pdtobj->GetData(&fmteURL, &medium)))
  570.     {
  571. #ifdef UNICODE
  572.         FILEGROUPDESCRIPTORW * pfgd = (FILEGROUPDESCRIPTORW *)GlobalLock(medium.hGlobal);
  573. #else   
  574.         FILEGROUPDESCRIPTORA * pfgd = (FILEGROUPDESCRIPTORA *)GlobalLock(medium.hGlobal);
  575. #endif
  576.         if (pfgd)
  577.         {
  578. #ifdef UNICODE
  579.             FILEDESCRIPTORW * pfd = &(pfgd->fgd[0]);
  580. #else           
  581.             FILEDESCRIPTORA * pfd = &(pfgd->fgd[0]);
  582. #endif                  
  583.             StrCpyN(pszDescription, (LPTSTR)pfd->cFileName, lstrlen((LPTSTR)pfd->cFileName) + 1);
  584.             GlobalUnlock(medium.hGlobal);
  585.             PathRemoveExtension(pszDescription);
  586.             hres = S_OK;
  587.         }
  588.     }
  589.     ReleaseStgMedium(&medium);
  590.     return hres;
  591. }       
  592. #define STR_SENDMAIL_URL_FILENAME     TEXT("Send Mail Message.url")
  593. #define STR_SENDMAIL_HTM_FILENAME      TEXT("Send Mail Message.htm")
  594. #define STR_SENDMAIL_URL_SHORTFILENAME TEXT("SendMail.url")
  595. #define STR_SENDMAIL_HTM_SHORTFILENAME TEXT("SendMaihtm")
  596. #define STR_SENDMAIL_FAILUREMSG        TEXT("The current document is not available. Would  you like to send the URL instead?")
  597. #define STR_SENDMAIL_FAILUREMSGTITLE   TEXT("SendMail Failed")
  598. HRESULT _CreateFileToSend(IDataObject *pdtobj, MRPARAM * pmp, DWORD grfKeyState)
  599. {
  600.     HRESULT hr;
  601.     BOOL bCreateUrl = FALSE;
  602.     hr = E_FAIL;
  603.     if (grfKeyState != FORCE_LINK)
  604.     {
  605.         hr = CreateHtmlFileFromUrl(pmp->pszURL, pmp->pszFiles);
  606.         if (FAILED(hr))
  607.         {
  608.             int iRet;
  609.                         
  610.             iRet = ShellMessageBox(MLGetHinst(),
  611.                                    NULL,
  612.                                    STR_SENDMAIL_FAILUREMSG,
  613.                                    STR_SENDMAIL_FAILUREMSGTITLE,
  614.                                    MB_YESNO);
  615.             if (iRet == IDYES)
  616.             {
  617.                 PathRenameExtension(pmp->pszFiles, TEXT(".url"));
  618.                 PathYetAnotherMakeUniqueName(pmp->pszFiles, pmp->pszFiles, pmp->pszFiles, pmp->pszFiles);      
  619.                 bCreateUrl = TRUE;
  620.             }
  621.         }
  622.         else
  623.         {
  624.             // We have succeeded in creating the HTML DOC to send
  625.             IQueryCodePage * pQcp;
  626.             // First set the flag for sending a doc
  627.             pmp->dwFlags |= MRPARAM_DOC;
  628.             // Then get the code page if there is one
  629.             if (SUCCEEDED(pdtobj->QueryInterface(IID_IQueryCodePage, (LPVOID *)&pQcp)))
  630.             {
  631.                 if (SUCCEEDED(pQcp->GetCodePage( &pmp->uiCodePage)))
  632.                     pmp->dwFlags |= MRPARAM_USECODEPAGE;
  633.                 pQcp->Release();
  634.             }
  635.         }
  636.     }
  637.     else
  638.         bCreateUrl = TRUE;
  639.     
  640.     if (bCreateUrl)
  641.         hr = CreateNewURLShortcut(pmp->pszURL, pmp->pszFiles);
  642.     pmp->dwFlags |= MRPARAM_DELETEFILE;
  643.     // Get the title of this homepage
  644.     if (SUCCEEDED(hr))
  645.         _GetFileDescription(pdtobj, pmp->pszURL);
  646.     
  647.     return hr;
  648. }
  649. HRESULT _GetFilesFromDataObj(IDataObject *pdtobj, DWORD grfKeyState, MRPARAM * pmp)
  650. {
  651.     HRESULT hr = E_FAIL;
  652.     STGMEDIUM medium;
  653.     FORMATETC fmteHDROP = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  654.     FORMATETC fmteURL = {g_cfURL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  655.     
  656.     if (SUCCEEDED(pdtobj->GetData(&fmteHDROP, &medium)))
  657.     {
  658.         TCHAR szPath[MAX_PATH];
  659.         DWORD cchFileBufferSize = 0;   // This will be the size of the buffer that holds all files names
  660.         DWORD cchUrlBufferSize = 0;
  661.         for (pmp->nFiles = 0; DragQueryFile((HDROP)medium.hGlobal, pmp->nFiles, szPath, ARRAYSIZE(szPath)); pmp->nFiles++)         
  662.             cchFileBufferSize += (lstrlen(szPath) + 1) * SIZEOF(TCHAR);
  663.     
  664.         cchUrlBufferSize += MAX_PATH * SIZEOF(TCHAR) * pmp->nFiles;
  665.         if (cchFileBufferSize && AllocatePMP(pmp, cchFileBufferSize, cchUrlBufferSize))
  666.         {
  667.             int i;
  668.             LPTSTR psz, pszNames;
  669.             for (i = 0, psz = pmp->pszFiles, pszNames = pmp->pszURL; DragQueryFile((HDROP)medium.hGlobal, i, szPath, ARRAYSIZE(szPath)); i++)            {
  670.                 // This is used to separate the names
  671.                 if (pszNames != pmp->pszURL)
  672.                     *pszNames++ = TEXT(';');
  673.                 
  674.                 if (grfKeyState == FORCE_LINK)
  675.                 {
  676.                     // Want to send a link even for the real file, we will create links to the real files
  677.                     // and send it.
  678.                     TCHAR szShortCut[MAX_PATH];
  679.                     if (_CreateTempFileShortcut(szPath, szShortCut))
  680.                         StrCpyN(psz, szShortCut, MAX_PATH);
  681.                     pmp->dwFlags |= MRPARAM_DELETEFILE;
  682.                 }
  683.                 else
  684.                     StrCpyN(psz, szPath, MAX_PATH);
  685.                 psz += lstrlen(psz) + 1;
  686.                 
  687.                 StrCpyN(pszNames, szPath, MAX_PATH);
  688.                 pszNames += lstrlen(szPath);
  689.             }
  690.             hr = S_OK;
  691.         }
  692.     }
  693.     else if (SUCCEEDED(pdtobj->GetData( &fmteURL, &medium)))
  694.     {
  695.         // This DataObj is from the internet -----------------
  696.         // NOTE: We only allow to send one file here.
  697.         pmp->nFiles = 1;
  698.         if (AllocatePMP(pmp, max(SIZEOF(TCHAR)*GlobalSize(medium.hGlobal), MAX_PATH)
  699. , MAX_PATH))
  700.         {
  701.             if ((fmteURL.cfFormat == g_cfURL) && (TYMED_HGLOBAL == medium.tymed))
  702.             {
  703. #ifdef UNICODE
  704.                 // medium.hGlobal is an ansi string
  705.                 LPSTR pchBuf = NULL;
  706.                 int cchLen = strlen((LPSTR)GlobalLock(medium.hGlobal)) + 1;
  707.                 int cchBufLen = max(SIZEOF(TCHAR)*GlobalSize(medium.hGlobal), MAX_PATH);
  708.                 if (!(pchBuf = (LPSTR)GlobalAlloc(GPTR, max(SIZEOF(TCHAR)*GlobalSize(medium.hGlobal), MAX_PATH) * sizeof(CHAR))))
  709.                  return E_FAIL;
  710.                 strncpy(pchBuf, (LPSTR)GlobalLock(medium.hGlobal), cchLen);
  711.                 AnsiToUnicode(pchBuf, pmp->pszURL, cchBufLen);
  712.                 GlobalFree(pchBuf);
  713. #else
  714.                 StrCpyN(pmp->pszURL, (LPTSTR)GlobalLock(medium.hGlobal), lstrlen((LPTSTR)GlobalLock(medium.hGlobal)) + 1);
  715. #endif
  716.                 GlobalUnlock(medium.hGlobal);
  717.             }
  718.             if (pmp->pszURL[0])
  719.             {
  720.                 // Note some of these functions depend on which OS we
  721.                 // are running on to know if we should pass ansi or unicode strings
  722.                 // to it
  723.                 // Windows 95
  724.                 if (GetTempPath(MAX_PATH, pmp->pszFiles))
  725.                 {
  726.                     TCHAR szFileName[MAX_PATH];
  727.                     TCHAR szShortFileName[20];
  728.                     StrCpyN(szFileName, (grfKeyState == FORCE_LINK) ? STR_SENDMAIL_URL_FILENAME : STR_SENDMAIL_HTM_FILENAME, MAX_PATH);
  729.                     StrCpyN(szShortFileName, (grfKeyState == FORCE_LINK) ? STR_SENDMAIL_URL_SHORTFILENAME : STR_SENDMAIL_HTM_SHORTFILENAME, 20);
  730.                     if (PathYetAnotherMakeUniqueName(pmp->pszFiles, pmp->pszFiles, szShortFileName, szFileName)) 
  731.                         hr = _CreateFileToSend(pdtobj, pmp, grfKeyState);
  732.                 }
  733.                 
  734.             }
  735.             
  736.         }
  737.     }   
  738.     ReleaseStgMedium(&medium);
  739.     return hr;
  740. }
  741. typedef struct {
  742.     CHAR szTempShortcut[MAX_PATH];
  743.     WCHAR szTempShortcutW[MAX_PATH];
  744.     MapiMessage mm;
  745.     MapiFileDesc mfd[1];
  746. } MAPI_FILES;
  747. void _FreeMapiFiles(MAPI_FILES *pmf)
  748. {
  749.     if (pmf->szTempShortcut[0])
  750.         DeleteFile(pmf->szTempShortcutW);
  751.     GlobalFree(pmf);
  752. }
  753. MAPI_FILES *_AllocMapiFiles(int nFiles, LPCTSTR pszFiles, MRPARAM *pmp)
  754. {
  755.     MAPI_FILES *pmf;
  756.     pmf = (MAPI_FILES *)GlobalAlloc(GPTR, SIZEOF(*pmf) + (nFiles * SIZEOF(pmf->mfd[0])));
  757.     if (pmf)
  758.     {
  759.         int i;
  760.         pmf->mm.nFileCount = nFiles;
  761.         if (nFiles)
  762.         {
  763.             LPCTSTR psz;
  764.             pmf->mm.lpFiles = pmf->mfd;
  765.             for (i = 0, psz = pszFiles; ((i < nFiles) && (*psz)); psz += lstrlen(psz) + 1, i++)
  766.             {
  767.                 // if the first item is a folder, we will create a shortcut to
  768.                 // that instead of trying to mail the folder (that MAPI does
  769.                 // not support)
  770.                 if ((i == 0) && PathIsDirectory(pszFiles) &&
  771. #ifndef UNICODE
  772.                     _CreateTempFileShortcut(pszFiles, pmf->szTempShortcut))
  773. #else
  774.                     _CreateTempFileShortcut(pszFiles, pmf->szTempShortcutW))
  775. #endif
  776.                 {
  777. #ifdef UNICODE
  778.     WCHAR wszTemp;
  779.     WideCharToMultiByte(CP_ACP, 0, pmf->szTempShortcutW, -1, 
  780. pmf->szTempShortcut, MAX_PATH, 
  781. NULL, NULL);
  782. #endif
  783.                     pmf->mfd[i].lpszPathName = pmf->szTempShortcut;
  784. #ifndef UNICODE
  785.                     pmf->mfd[i].lpszFileName = PathFindFileName(pszFiles);
  786. #else
  787.     WideCharToMultiByte(CP_ACP, 0, pszFiles, -1, 
  788. pmp->paszFiles, MAX_PATH, 
  789. NULL, NULL);
  790.                     pmf->mfd[i].lpszFileName = PathFindFileNameA(pmp->paszFiles);
  791. #endif
  792.                 }
  793.                 else
  794.                 {
  795. #ifndef UNICODE
  796.                     pmf->mfd[i].lpszPathName = (LPTSTR)psz; // const -> non const
  797.                     pmf->mfd[i].lpszFileName = PathFindFileName(psz);
  798. #else
  799.     WideCharToMultiByte(CP_ACP, 0, psz, -1, 
  800. pmp->paszFiles, MAX_PATH, 
  801. NULL, NULL);
  802.                     pmf->mfd[i].lpszPathName = pmp->paszFiles; // const -> non const
  803.                     pmf->mfd[i].lpszFileName = PathFindFileNameA(pmp->paszFiles);
  804. #endif
  805.                 }
  806.                 pmf->mfd[i].nPosition = (UINT)-1;
  807.             }
  808.         }
  809.     }
  810.     return pmf;
  811. }
  812. BOOL _IsShortcut(LPCTSTR pszFile)
  813. {
  814.     SHFILEINFO sfi;
  815.     return SHGetFileInfo(pszFile, 0, &sfi, sizeof(sfi), SHGFI_ATTRIBUTES) && (sfi.dwAttributes & SFGAO_LINK);
  816. }
  817. // get the target of a shortcut. this uses IShellLink which 
  818. // Internet Shortcuts (.URL) and Shell Shortcuts (.LNK) support so
  819. // it should work generally
  820. //
  821. BOOL _GetShortcutTarget(LPCTSTR pszPath, LPTSTR pszTarget, UINT cch)
  822. {
  823.     IUnknown *psl;
  824.     CLSID clsid;
  825.     *pszTarget = 0;     // assume none
  826.     if (!_IsShortcut(pszPath))
  827.         return FALSE;
  828.     // BUGBUG: we really should call GetClassFile() but this could
  829.     // slow this down a lot... so chicken out and just look in the registry
  830.     if (FAILED(_CLSIDFromExtension(PathFindExtension(pszPath), &clsid)))
  831.         clsid = CLSID_ShellLink;        // assume it's a shell link
  832.     if (SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID *)&psl)))
  833.     {
  834.         IPersistFile *ppf;
  835.         if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf)))
  836.         {
  837. #ifdef UNICODE
  838.             ppf->Load(pszPath, 0);
  839. #else
  840.             WCHAR wszPath[MAX_PATH];
  841.             AnsiToUnicode(pszPath, wszPath, ARRAYSIZE(wszPath));
  842.             ppf->Load(wszPath, 0);
  843. #endif
  844.             ppf->Release();
  845.         }
  846.         IShellLink_GetPath(psl, pszTarget, cch, SLGP_UNCPRIORITY);
  847.         psl->Release();
  848.         return TRUE;
  849.     }
  850.     return FALSE;
  851. }
  852. void _DeleteMultipleFiles(LPCTSTR pszFiles)
  853. {
  854.     int i;
  855.     LPCTSTR psz;
  856.     for (i = 0, psz = pszFiles; *psz; psz += lstrlen(psz) + 1, i++)
  857.         DeleteFile(psz);
  858. }
  859. const TCHAR c_szPad[] = TEXT(" rn ");
  860. STDAPI_(DWORD) MailRecipientThreadProc(void *pmp)
  861. {
  862.     TCHAR szText[2148];     // hold a URL/FilePath + some formatting text
  863. #ifdef UNICODE
  864.     CHAR aszText[2148];     // hold a URL/FilePath + some formatting text
  865. #endif
  866.     MAPI_FILES *pmf;
  867.     DWORD dwFlags = ((MRPARAM *)pmp)->dwFlags;
  868.     LPCTSTR pv = ((MRPARAM *)pmp)->pszFiles;
  869.     LPCTSTR pszTitle = ((MRPARAM *)pmp)->pszURL; 
  870.     CoInitialize(NULL);     // we are going to do some COM stuff
  871.     pmf = _AllocMapiFiles(((MRPARAM *)pmp)->nFiles, pv, (MRPARAM *)pmp);
  872.     if (pmf)
  873.     {
  874.         TCHAR szTitle[80]; // because the title is supposed to be non-const
  875. #ifdef UNICODE
  876.         CHAR aszTitle[80]; // because the title is supposed to be non-const
  877. #endif
  878.         HMODULE hmodMail;
  879.         if (pmf->mm.nFileCount)
  880.         {
  881.             StrCpyN(szText, c_szPad, lstrlen(c_szPad) + 1);    // init the buffer with some stuff
  882.             if (_IsShortcut(pv))
  883.                 _GetShortcutTarget(pv, szText + ARRAYSIZE(c_szPad) - 1, ARRAYSIZE(szText) - ARRAYSIZE(c_szPad));
  884.             else
  885.                 StrCpyN(szText + ARRAYSIZE(c_szPad) - 1, pszTitle, ARRAYSIZE(szText) - ARRAYSIZE(c_szPad));
  886.             // Don't fill in lpszNoteText if we know we are sending documents because Athena puke on it 
  887.             if (!(dwFlags & MRPARAM_DOC))
  888.     {
  889. #ifndef UNICODE
  890.                 pmf->mm.lpszNoteText = szText;
  891. #else
  892. WideCharToMultiByte(CP_ACP, 0, szText, -1, 
  893.     aszText, 2148, 
  894.     NULL, NULL);
  895.                 pmf->mm.lpszNoteText = aszText;
  896. #endif
  897.     }
  898.             if (pszTitle) {
  899.                 StrCpyN(szTitle, pszTitle, ARRAYSIZE(szTitle));
  900. #ifndef UNICODE
  901.                 pmf->mm.lpszSubject = szTitle;
  902. #else
  903. WideCharToMultiByte(CP_ACP, 0, szTitle, -1, 
  904.     aszTitle, 80, 
  905.     NULL, NULL);
  906.                 pmf->mm.lpszSubject = aszTitle;
  907. #endif
  908.             } else
  909. #ifndef UNICODE
  910.                 pmf->mm.lpszSubject = szText + ARRAYSIZE(c_szPad) - 1;
  911. #else
  912.                 pmf->mm.lpszSubject = aszText + ARRAYSIZE(c_szPad) - 1;
  913. #endif
  914.         }
  915.         hmodMail = (HINSTANCE) LoadMailProvider();
  916.         if (dwFlags & MRPARAM_USECODEPAGE)
  917.         {
  918.             // When this flag is set, we know that we have just one file to send and we have a code page
  919.             // Athena will then look at ulReserved for the code page
  920.             // BUGBUG: Will the other MAPI handlers puke on this?  -- dli
  921.             ASSERT(pmf->mm.nFileCount == 1);
  922.             pmf->mfd[0].ulReserved = ((MRPARAM *)pmp)->uiCodePage;
  923.         }
  924.         
  925.         if (hmodMail)
  926.         {
  927.             LPMAPISENDMAIL pfnSendMail = (LPMAPISENDMAIL)GetProcAddress(hmodMail, "MAPISendMail");
  928.             if (pfnSendMail)
  929.                 pfnSendMail(0, 0, &pmf->mm, MAPI_LOGON_UI | MAPI_DIALOG, 0);
  930.             FreeLibrary(hmodMail);
  931.         }
  932.         _FreeMapiFiles(pmf);
  933.     }
  934.     
  935.     if (pv && (dwFlags & MRPARAM_DELETEFILE))
  936.         _DeleteMultipleFiles(pv);
  937.     
  938.     if (pmp)
  939.         CleanupPMP((MRPARAM *)pmp);
  940.     CoUninitialize();
  941.     // SetCursor(hcurOld);
  942.     return 0;
  943. }
  944. STDAPI MailRecipientDropHandler(IDataObject *pdtobj, DWORD grfKeyState, DWORD dwEffect)
  945. {
  946.     HANDLE hThread;
  947.     DWORD idThread;
  948.     MRPARAM * pmp = (MRPARAM *)GlobalAlloc(GPTR, SIZEOF(*pmp));
  949.     if (pmp)
  950.     {        
  951. InitClipboardFormats();
  952.         if (!pdtobj || SUCCEEDED(_GetFilesFromDataObj(pdtobj, grfKeyState, pmp)))
  953.         {
  954.             hThread = CreateThread(NULL, 0, MailRecipientThreadProc, pmp, 0, &idThread);
  955.             if (hThread)
  956.             {
  957.                 CloseHandle(hThread);
  958.                 return S_OK;
  959.             }
  960.         }
  961.         
  962.         CleanupPMP(pmp);
  963.  
  964. return S_OK;
  965.     }
  966.  
  967.     return E_OUTOFMEMORY;       
  968. }
  969. HRESULT _UnixDropOnMailRecipient(IDataObject *pdtobj, DWORD grfKeyState)
  970. {
  971.     HRESULT hres = ERROR_SUCCESS;
  972.     MailRecipientDropHandler(pdtobj, grfKeyState, 0);
  973.     return hres;
  974. }
  975.  
  976. EXTERN_C HRESULT _UnixSendDocToOE(LPCITEMIDLIST pidl, UINT uiCodePage, DWORD grfKeyState)
  977. {
  978.     IDataObject *pdtobj;
  979.     HRESULT hres;
  980.     if (!pidl)
  981.         hres = _UnixDropOnMailRecipient(NULL, grfKeyState);
  982.     else 
  983.     {
  984.         hres = GetDataObjectForPidl(pidl, &pdtobj);
  985.         if (SUCCEEDED(hres))
  986.         {
  987.             IQueryCodePage * pQcp;
  988.             if (SUCCEEDED(pdtobj->QueryInterface(IID_IQueryCodePage, (LPVOID *)&pQcp)))
  989.             {
  990.                 pQcp->SetCodePage(uiCodePage);
  991.                 pQcp->Release();
  992.             }
  993.             hres = _UnixDropOnMailRecipient(pdtobj, grfKeyState);
  994.             pdtobj->Release();
  995.         }
  996.     }
  997.     return hres;
  998. }
  999. // PORT
  1000. EXTERN_C void   UnixAdjustWindowSize( HWND hwnd, IETHREADPARAM* piei )
  1001. {
  1002.         // IEUNIX - Default window size is too small
  1003.         // We come up with this size if there is no saved stream for window
  1004.         // placement, in which case piei->wb.length is zero
  1005.        char szGeometry[MAX_PATH];
  1006.        /* If the geometry was specified on the command line use it */
  1007.        if (MwGetXInvocationParam("-geometry", szGeometry, MAX_PATH)) {
  1008.           int   wMask      = 0;
  1009.           int   wXOffset   = 0;
  1010.           int   wYOffset   = 0;
  1011.           UINT  wHeight    = 0;
  1012.           UINT  wWidth     = 0;
  1013.           RECT  rc;        /* info about browser window */
  1014.           RECT  rcDisplay; /* to get info about desktop */
  1015.          
  1016.           /* Mask is mainwin mask */
  1017.           wMask = MwProtectedParseXGeometry(szGeometry, 
  1018.                                             &wXOffset, &wYOffset,
  1019.                                             &wWidth, &wHeight);
  1020.  
  1021.           GetWindowRect( hwnd, &rc );
  1022.           GetWindowRect( GetDesktopWindow(), &rcDisplay );
  1023.           if (!(wMask & MwHeightValue))
  1024.           {
  1025.              if (!(piei->wp.length))
  1026.              {
  1027.                 wHeight = BROWSER_DEFAULT_HEIGHT;
  1028.              }
  1029.              else
  1030.              {
  1031.                 wHeight = rc.bottom - rc.top;
  1032.              }
  1033.           }
  1034.           if (!(wMask & MwWidthValue))
  1035.           {
  1036.              if (!(piei->wp.length))
  1037.              {
  1038.                 wWidth = BROWSER_DEFAULT_WIDTH;
  1039.              }
  1040.              else
  1041.              {
  1042.                 wWidth = rc.right - rc.left;
  1043.              }
  1044.           }
  1045.           if (!(wMask & MwXValue))
  1046.           {
  1047.              wXOffset = rc.left;
  1048.           }
  1049.           else
  1050.           if (wMask & MwXNegative)
  1051.           {
  1052.              /* wXOffset will be negative */
  1053.              wXOffset = max( 0, rcDisplay.right - rcDisplay.left - wWidth + wXOffset );
  1054.           }
  1055.           if (!(wMask & MwYValue))
  1056.           {
  1057.              wYOffset = rc.top;
  1058.           }
  1059.           else
  1060.           if (wMask & MwYNegative)
  1061.           {
  1062.              /* wYOffset will be negative */
  1063.              wYOffset = max( 0, rcDisplay.bottom - rcDisplay.top - wHeight + wYOffset );
  1064.           }
  1065.           if (!wYOffset)
  1066.           {
  1067.              wYOffset = 1;
  1068.           }
  1069.           if (!wXOffset)
  1070.           {
  1071.              wXOffset = 1;
  1072.           }
  1073.           SetWindowPos(hwnd, 0, 
  1074.                        wXOffset, wYOffset, wWidth, wHeight,
  1075.                        SWP_NOZORDER);
  1076.        }
  1077.        else
  1078.        if (piei->wp.length == 0) {
  1079.            RECT rc;
  1080.            GetWindowRect( hwnd, &rc );
  1081.            SetWindowPos ( hwnd, 0, rc.left, rc.top, BROWSER_DEFAULT_WIDTH, BROWSER_DEFAULT_HEIGHT, SWP_NOZORDER );
  1082.        }
  1083. }
  1084. #if 0 //def NO_MARSHALLING
  1085. void IEFrame_NewWindow_SameThread(IETHREADPARAM* piei)
  1086. {
  1087.     DWORD uFlags = piei->uFlags;
  1088.     
  1089.     LPSTR pszCloseEvent = NULL;
  1090.     if (uFlags & COF_FIREEVENTONCLOSE) {
  1091.         ASSERT(piei->szCloseEvent[0]);
  1092.         pszCloseEvent = StrDup(piei->szCloseEvent);
  1093.     }
  1094.     THREADWINDOWINFO *lpThreadWindowInfo;
  1095.     ASSERT (~0 != g_TLSThreadWindowInfo)
  1096.     lpThreadWindowInfo = (THREADWINDOWINFO *) TlsGetValue(g_TLSThreadWindowInfo);
  1097.     ASSERT (lpThreadWindowInfo); // if we don't have this, then a thread isn't running, and we're hosed.
  1098.     if (!lpThreadWindowInfo)
  1099.     {
  1100.         goto Done;
  1101.     }
  1102. #define DWSTYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
  1103. #ifdef DEBUG_EXPLORER
  1104.     piei->wv.bTree = TRUE;
  1105.     piei->TreeSplit = 200; // some random default
  1106. #endif
  1107.     TraceMsg(TF_COCREATE, "IEFrame_NewWindow_SameThread calling CreateWindowEx");
  1108.     LPCTSTR pszClass;
  1109.     if (piei->uFlags & COF_EXPLORE) {
  1110.         pszClass = c_szExploreClass;
  1111.     } else if (piei->uFlags & COF_IEXPLORE) {
  1112.         pszClass = c_szIExploreClass;
  1113.     } else {
  1114.         pszClass = c_szCabinetClass;
  1115.     }
  1116.     
  1117.     {
  1118.     HMENU hmenu = g_hmenuFullSB;
  1119.     if (!(g_bBrowserFlags & BROWF_CLASSICMENUS))
  1120.         hmenu = NULL;
  1121.     HWND hwnd = CreateWindowEx(
  1122. #ifdef WIN16
  1123.        0,
  1124. #else
  1125.        WS_EX_WINDOWEDGE,
  1126. #endif
  1127.                                pszClass,
  1128.                                NULL, DWSTYLE,
  1129.                                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  1130.                                NULL, 
  1131.                                hmenu, 
  1132.                                HINST_THISDLL, piei);
  1133.     if (hwnd)
  1134.     {
  1135.         // Enable File Manager drag-drop for win16
  1136.         DragAcceptFiles(hwnd, TRUE);
  1137.         CShellBrowser* psb = (CShellBrowser*)SendMessage(hwnd, WMC_GETTHISPTR, 0, 0);
  1138.         if (psb)
  1139.         {
  1140.             psb->_AfterWindowCreated(piei);
  1141.             lpThreadWindowInfo->cWindowCount++;
  1142.             // tack new window on end of list
  1143.             CShellBrowser** rgpsb = (CShellBrowser**)
  1144.                 LocalReAlloc(lpThreadWindowInfo->rgpsb, 
  1145.                              lpThreadWindowInfo->cWindowCount * sizeof(CShellBrowser *),
  1146.                              LMEM_MOVEABLE);
  1147.             ASSERT(rgpsb);
  1148.             if (rgpsb)
  1149.             {
  1150.                 lpThreadWindowInfo->rgpsb = rgpsb;
  1151.                 rgpsb[lpThreadWindowInfo->cWindowCount-1] = psb;
  1152.                 psb->AddRef();
  1153.             }
  1154.             // The message pump would go here.
  1155.             // Let the threadproc handle it.
  1156.             psb->Release();
  1157.         }
  1158.         
  1159.     } else {
  1160.         // Unregister any pending that may be there
  1161.         WinList_Revoke(piei->dwRegister);
  1162.         TraceMsg(DM_ERROR, "IEFrame_NewWindow_SameThread CreateWindow failed");
  1163.     }
  1164.     }
  1165. Done:
  1166.     if (pszCloseEvent)
  1167.     {
  1168.         FireEventSz(pszCloseEvent);
  1169.     }
  1170.     if (piei)
  1171.         delete piei;
  1172. }
  1173. #endif // NO_MARSHALLING
  1174. BOOL CheckForValidSourceFile(HWND hDlg, LPTSTR szPath, LPTSTR szDisplay )
  1175. {
  1176.     BOOL fRet = FALSE, err = FALSE;
  1177.     if(  szPath && *szPath && PathIsFilePath(szPath) && PathFileExists(szPath) )
  1178.     {
  1179.          HANDLE hFile = CreateFile( szPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 
  1180.                                    FILE_ATTRIBUTE_NORMAL, NULL);
  1181.          if( hFile != INVALID_HANDLE_VALUE ) 
  1182.          {
  1183.              if( GetFileSize( hFile, NULL ) <= (DWORD)0 )
  1184.              {
  1185.                  err = TRUE; 
  1186.              }
  1187.              CloseHandle(hFile);
  1188.          }
  1189.          else
  1190.          {
  1191.              err = TRUE;
  1192.          } 
  1193.     }
  1194.     else
  1195.     {
  1196.         err = TRUE;
  1197.     }
  1198.     if( err )
  1199.     {
  1200.         TCHAR message[ MAX_URL_STRING + MAX_DISPLAY_LEN  + 3];
  1201.         TCHAR title [TITLE_LEN];
  1202.         StrCpyN( message, szDisplay, lstrlen(szDisplay) + 1 );
  1203.         message[ lstrlen( szDisplay ) ] = TEXT('n');
  1204.         message[ lstrlen( szDisplay ) + 1 ] = TEXT('n');
  1205.         MLLoadString(IDS_DOWNLOAD_BADCACHE,
  1206.                       message + lstrlen(szDisplay) + 2,
  1207.                       ARRAYSIZE(message) - lstrlen(szDisplay) - 2);
  1208.         MLLoadString(IDS_DOWNLOADFAILED, title, ARRAYSIZE(title));
  1209.         MessageBox( hDlg, message, title, MB_ICONWARNING|MB_OK);
  1210.         return fRet;
  1211.     }
  1212.     return TRUE;
  1213. }
  1214. STDAPI UnixSendDocToMailRecipient(LPCITEMIDLIST pidl, UINT uiCodePage, DWORD grfKeyState)
  1215. {
  1216.     HRESULT hres;
  1217.     IUniformResourceLocator *purl;
  1218.     IShellLink *psl;
  1219.     LPTSTR lptszURLName;
  1220.     CHAR szTitle[MAX_URL_STRING];
  1221.     IShellFolder *psfParent;
  1222.     LPCITEMIDLIST pidlChild;
  1223.     TCHAR           tszCommandLine[INTERNET_MAX_URL_LENGTH];
  1224.     TCHAR           tszExpandedCommand[INTERNET_MAX_URL_LENGTH];
  1225.     TCHAR tszTempFile1[MAX_PATH];
  1226.     TCHAR tszTempFile2[MAX_PATH];
  1227.     TCHAR tszTempFile[MAX_PATH];
  1228.     UINT            nCommandSize;
  1229.     int             i;
  1230.     HKEY    hkey;
  1231.     DWORD   dw;
  1232.     TCHAR *pchPos;
  1233.     BOOL bMailed;
  1234.     STARTUPINFO stInfo;
  1235.     SYSTEMTIME systemtime;
  1236.     int pid;
  1237.     UINT uUnique;
  1238.     szTitle[0] = '';
  1239.     hres = RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_MAILCLIENTS, 0, NULL, 0, 
  1240.                           KEY_READ, NULL, &hkey, &dw);
  1241.     if (hres == ERROR_SUCCESS)
  1242.     {
  1243.         dw = INTERNET_MAX_URL_LENGTH;
  1244.         hres = RegQueryValueEx(hkey, REGSTR_PATH_CURRENT, NULL, NULL, 
  1245.                                (LPBYTE)tszCommandLine, &dw);
  1246.         RegCloseKey(hkey);
  1247.         if (hres == ERROR_SUCCESS)
  1248.         {           
  1249.             dw = SHExpandEnvironmentStrings(tszCommandLine, tszExpandedCommand, 
  1250.                                           INTERNET_MAX_URL_LENGTH);
  1251.              _tcscpy(tszCommandLine, TEXT("X "));
  1252.              _tcscat(tszCommandLine, tszExpandedCommand);
  1253.              memset(&stInfo, 0, sizeof(stInfo));
  1254.              stInfo.cb = sizeof(stInfo);
  1255.              for (i = _tcslen(tszCommandLine); i > 0; i--)
  1256.              {
  1257.                  if (tszCommandLine[i] == '/')
  1258.                  {
  1259.                       tszCommandLine[i] = '';
  1260.                       break;
  1261.                  }
  1262.              }
  1263.              if (!pidl)
  1264.              {
  1265.                  if (grfKeyState == MAIL_ACTION_SEND)
  1266.                  {
  1267.                      _tcscat(tszCommandLine, MAILTO_0_OPTION);
  1268.                  }
  1269.                  else if (grfKeyState == MAIL_ACTION_READ)
  1270.                  {
  1271.                      _tcscat(tszCommandLine, READMAIL_OPTION);
  1272.                  }
  1273.                  bMailed = CreateProcess(tszExpandedCommand, tszCommandLine, NULL, NULL, 
  1274.                                         FALSE, DETACHED_PROCESS, NULL, 
  1275.                                         NULL, &stInfo, NULL);
  1276.                  return hres;
  1277.              }
  1278.          }
  1279.          else
  1280.          {
  1281.              return hres;
  1282.          }
  1283.     }
  1284.     else
  1285.     {
  1286.          return hres;
  1287.     }
  1288.     hres = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, 
  1289.                             IID_IUniformResourceLocator, (LPVOID*)&purl);
  1290.     if (SUCCEEDED(hres))
  1291.     {
  1292.         hres = purl->QueryInterface(IID_IShellLink, (LPVOID*)&psl);
  1293.         if (SUCCEEDED(hres))
  1294.         {
  1295.             hres = psl->SetIDList(pidl);
  1296.             psl->Release();
  1297.         }
  1298.         hres = purl->GetURL(&lptszURLName);
  1299.         if (SUCCEEDED(hres))
  1300.         {
  1301.             hres = IEBindToParentFolder(pidl, &psfParent, &pidlChild);
  1302.             if (SUCCEEDED(hres))
  1303.             {
  1304.                 STRRET sr;
  1305.                 hres = psfParent->GetDisplayNameOf(pidlChild, SHGDN_INFOLDER | SHGDN_NORMAL, &sr);
  1306.                 if (SUCCEEDED(hres))
  1307.                     hres = StrRetToBufA(&sr, pidlChild, szTitle, ARRAYSIZE(szTitle));
  1308.                 psfParent->Release();
  1309.             }       
  1310.             tszTempFile[0] = '';
  1311.             GetTempPath(MAX_PATH, tszTempFile);
  1312.             _tcscpy(tszTempFile1, tszTempFile);
  1313.             _tcscpy(tszTempFile2, tszTempFile);
  1314.             
  1315.             if (grfKeyState == FORCE_LINK)
  1316.                 _tcscat(tszCommandLine, MAILLINK_OPTION);
  1317.             else if (grfKeyState == FORCE_COPY)
  1318.                 _tcscat(tszCommandLine, MAILPAGE_OPTION);
  1319.             _tcscat(tszTempFile1, TEXT(".#temp1"));
  1320.             _tcscat(tszTempFile2, TEXT(".#temp2"));
  1321.             pid = _getpid();
  1322.             GetSystemTime(&systemtime);
  1323.             uUnique = systemtime.wMilliseconds + systemtime.wSecond * pid;
  1324.             
  1325.             if (uUnique == GetTempFileName(TEXT("."), NULL, uUnique, tszTempFile))
  1326.             {
  1327.                 HANDLE hTempFile1, hTempFile2;
  1328.                 
  1329.                 _tcscat(tszTempFile1, tszTempFile);
  1330.                 _tcscat(tszTempFile2, tszTempFile);
  1331.                 
  1332.                 hTempFile1 = CreateFile(tszTempFile1, GENERIC_WRITE, FILE_SHARE_READ, 
  1333.                                         NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1334.                 if (hTempFile1 != INVALID_HANDLE_VALUE)
  1335.                 {
  1336.                     hTempFile2 = CreateFile(tszTempFile2, GENERIC_WRITE, FILE_SHARE_READ, 
  1337.                                             NULL, CREATE_ALWAYS, 
  1338.                                             FILE_ATTRIBUTE_NORMAL, NULL);
  1339.                     if (hTempFile2 != INVALID_HANDLE_VALUE)
  1340.                     {
  1341.                         CHAR szURLName[MAX_URL_STRING];
  1342.                         DWORD dw;
  1343.                         WriteFile(hTempFile1, szTitle, 
  1344.                                   lstrlenA(szTitle) + 1, 
  1345.                                   &dw, NULL);
  1346.                         WideCharToMultiByte(CP_ACP, 0, lptszURLName, -1, 
  1347.                                             szURLName, MAX_URL_STRING, NULL, NULL);
  1348.                         WriteFile(hTempFile2, szURLName, 
  1349.                                   lstrlenA(szURLName) + 1, &dw, NULL);
  1350.                         _tcscat(tszCommandLine, TEXT(" "));
  1351.                         _tcscat(tszCommandLine, tszTempFile1);
  1352.                         _tcscat(tszCommandLine, TEXT(" "));
  1353.                         _tcscat(tszCommandLine, tszTempFile2);
  1354.                         bMailed = CreateProcess(tszExpandedCommand, tszCommandLine, NULL, NULL, 
  1355.                                                 FALSE, DETACHED_PROCESS, NULL, 
  1356.                                                 NULL, &stInfo, NULL);
  1357.                         CloseHandle(hTempFile2);
  1358.                     }
  1359.                     else
  1360.                     {
  1361.                         DeleteFile(tszTempFile1);
  1362.                     }
  1363.                     CloseHandle(hTempFile1);
  1364.                 }
  1365.             }
  1366.             HRESULT hres2;
  1367.             IMalloc *pMalloc;
  1368.             hres2 = SHGetMalloc(&pMalloc);
  1369.             if (SUCCEEDED(hres2))
  1370.             {
  1371.                 pMalloc->Free(lptszURLName);
  1372.                 pMalloc->Release();
  1373.             }
  1374.         }
  1375.         purl->Release();
  1376.     }
  1377.     
  1378.     return hres;
  1379. }
  1380. //////////////////////////////////////////////////////////////////////
  1381. // Importing Bookmarks on startup
  1382. //////////////////////////////////////////////////////////////////////
  1383. extern TCHAR * szIEFavoritesRegSub; 
  1384. extern TCHAR * szIEFavoritesRegKey;
  1385. BOOL ImportBookmarksStartup(HINSTANCE hInstWithStr)
  1386. {
  1387.     TCHAR    szFavoritesDir[MAX_PATH];
  1388.     TCHAR    szBookmarksDir[MAX_PATH];
  1389.     HANDLE  hBookmarksFile        = INVALID_HANDLE_VALUE;
  1390.     BOOL    fSuccess                = FALSE;
  1391.     
  1392.     // Initialize Variables
  1393.     szBookmarksDir[0] = TEXT('');
  1394.     szFavoritesDir[0] = TEXT('');
  1395.     // Get Bookmarks Dir
  1396.     if (TRUE == GetNavBkMkDir( szBookmarksDir, sizeof(szBookmarksDir) ) )
  1397.     {
  1398.         if ((NULL != szBookmarksDir) && (szBookmarksDir[0] != TEXT('')))
  1399.         {
  1400.             hBookmarksFile = CreateFile(szBookmarksDir, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  1401.             
  1402.             if ( hBookmarksFile != INVALID_HANDLE_VALUE ) 
  1403.             {
  1404.                 // Get Favorites Dir
  1405.                 if (TRUE == GetPathFromRegistry(szFavoritesDir, MAX_PATH, HKEY_CURRENT_USER,
  1406.                     szIEFavoritesRegSub, szIEFavoritesRegKey))
  1407.                 {
  1408.                     if ((NULL != szFavoritesDir) && (szFavoritesDir[0] != TEXT('')))
  1409.                     {
  1410.                         // Verify it's a valid Bookmarks file
  1411.                         if (TRUE == VerifyBookmarksFile( hBookmarksFile ))
  1412.                         {
  1413.                             TCHAR szSubDir[MAX_PATH];
  1414.                             szSubDir[0] = TEXT('');
  1415.                             // Import under a specific folder.
  1416.                             if (0 != MLLoadString(IDS_NS_BOOKMARKS_DIR, szSubDir, ARRAYSIZE(szSubDir)))
  1417.                             {
  1418.                                 StrCatBuff(szFavoritesDir, szSubDir, MAX_PATH);
  1419.                             }
  1420.                       
  1421.                             // Do the importing...
  1422.                             fSuccess = ImportBookmarks(szFavoritesDir, szBookmarksDir, NULL);
  1423.                         }
  1424.                     }
  1425.                 }
  1426.             }
  1427.         }
  1428.     }
  1429.     if (INVALID_HANDLE_VALUE != hBookmarksFile)
  1430.     {
  1431.         CloseHandle(hBookmarksFile);
  1432.     }
  1433.     return(fSuccess);
  1434. }
  1435. STDAPI_(BOOL) IsLocalFolderPidl( LPCITEMIDLIST pidl )
  1436. {
  1437.     BOOL bCheckForFilePath = FALSE;
  1438.  
  1439.     if( IsURLChild( pidl, TRUE ) )
  1440.     {
  1441.              // Get Path from pidl
  1442.          TCHAR szTmpUrl[ MAX_URL_STRING ];
  1443.          LPITEMIDLIST pidlTmp = ILClone( pidl );
  1444.          ::IEGetDisplayName(pidlTmp, szTmpUrl, SHGDN_FORPARSING);
  1445.          if (GetUrlScheme(szTmpUrl) == URL_SCHEME_FILE )
  1446.               bCheckForFilePath = TRUE;
  1447.          ILFree( pidlTmp );
  1448.     }
  1449.     else
  1450.     {
  1451.          bCheckForFilePath = TRUE;
  1452.     }
  1453.     if( bCheckForFilePath )
  1454.     {
  1455.         if( ILIsFileSysFolder(pidl) )
  1456.              return TRUE;
  1457.         // we are not browsing the web
  1458.         LPITEMIDLIST pidlNew;
  1459.         DWORD dwAttrib = SFGAO_FOLDER;
  1460.         if (SUCCEEDED(IEGetAttributesOf(pidl, &dwAttrib)) &&
  1461.            (dwAttrib & SFGAO_FOLDER))
  1462.         {
  1463.             return TRUE;
  1464.         }
  1465.     }
  1466.     return FALSE;
  1467. }
  1468. STDAPI_(LONG) StrLenUnalignedW( UNALIGNED WCHAR * str )
  1469. {
  1470.    LONG count = 0;
  1471.    if( !str ) return 0;
  1472.    while( *str++ ) count++;
  1473.    return count;
  1474. }
  1475. STDAPI_(LONG) StrLenUnalignedA( UNALIGNED CHAR * str )
  1476. {
  1477.    LONG count = 0;
  1478.    if( !str ) return 0;
  1479.    while( *str++ ) count++;
  1480.    return count;
  1481. }
  1482. #ifdef UNIX_FEATURE_ALIAS
  1483. STDAPI_(HDPA) GetGlobalAliasList()
  1484. {
  1485.     static HDPA s_hdpa = NULL;
  1486.     if( !s_hdpa )
  1487.     {
  1488.         HDPA hdpa = DPA_Create(4);
  1489.         if (hdpa)
  1490.         {
  1491.             LoadAliases( hdpa );
  1492.             return hdpa;
  1493.         }
  1494.         else
  1495.             return NULL;
  1496.     }
  1497.     else
  1498.         return s_hdpa;
  1499. }
  1500. STDAPI RefreshGlobalAliasList()
  1501. {
  1502.     HDPA list = GetGlobalAliasList();
  1503.     if( list )
  1504.     {
  1505.         FreeAliases(list);
  1506.         LoadAliases(list);
  1507.     }
  1508. }
  1509. #endif /* UNIX_FEATURE_ALIAS */
  1510. extern "C" 
  1511. BOOL APIENTRY DllMain_Internal(HINSTANCE hDll, DWORD dwReason, void *lpReserved);
  1512. extern "C" 
  1513. BOOL APIENTRY DllMain(HINSTANCE hDll, DWORD dwReason, void *lpReserved)
  1514. {
  1515.     return DllMain_Internal( hDll, dwReason, lpReserved  );
  1516. }
  1517. STDAPI SafeGetItemObject(LPSHELLVIEW psv, UINT uItem, REFIID riid, LPVOID *ppv)
  1518. {
  1519.     return (HRESULT)(psv->GetItemObject(uItem, riid, ppv));
  1520. }
  1521. /* The following is needed so that we will have the latest version number for
  1522.  * the browser under HKLMSoftwareMicrosoftActive SetupInstalled Components
  1523.  */
  1524. #define REGSTRACTIVESETUP TEXT("Software\Microsoft\Active Setup\Installed Components\")
  1525. HRESULT UnixRegisterBrowserInActiveSetup()
  1526. {
  1527.     HRESULT hr = E_FAIL;
  1528.     HKEY    hKey = NULL;
  1529.     HKEY    hKeyOldVer = NULL;
  1530.     DWORD   dw;
  1531.     CLSID   browserClsid = COMPID_IE4;
  1532.     LPOLESTR pszGUID = NULL;
  1533.     TCHAR   szKeyName[MAX_PATH];
  1534.     TCHAR   szVersion[30];
  1535.     TCHAR   szOldVersion[30];
  1536.     DWORD   dwType;
  1537.     DWORD   dwLen;
  1538.     if (FAILED((hr = StringFromCLSID(browserClsid, &pszGUID))))
  1539.        goto Cleanup;
  1540.     StrCpyN(szKeyName, REGSTRACTIVESETUP, ARRAYSIZE(szKeyName));
  1541.     StrCatBuff(szKeyName, pszGUID, ARRAYSIZE(szKeyName));
  1542.     hr = RegCreateKeyEx(
  1543.             HKEY_LOCAL_MACHINE,
  1544.             szKeyName,
  1545.             0,
  1546.             NULL,
  1547.             0,
  1548.             KEY_ALL_ACCESS,
  1549.             NULL,
  1550.             &hKey,
  1551.             &dw);
  1552.  
  1553.     if (hr != ERROR_SUCCESS)
  1554.        goto Cleanup;
  1555.     wnsprintf(szVersion,ARRAYSIZE(szVersion), TEXT("%d,%02d,%04d,%04d"),
  1556.               VER_MAJOR_PRODUCTVER,
  1557.               VER_MINOR_PRODUCTVER,
  1558.               VER_PRODUCTBUILD,
  1559.               VER_PRODUCTBUILD_QFE);
  1560.     hr = RegQueryValueEx(hKey,
  1561.                          TEXT("Version"),
  1562.                          NULL,
  1563.                          &dwType, 
  1564.                          (LPBYTE)szOldVersion,
  1565.                          &dwLen);
  1566.     if (hr == ERROR_SUCCESS)
  1567.     {
  1568.        hr = RegSetValueEx(hKey,
  1569.                           TEXT("OldVersion"),
  1570.                           NULL,
  1571.                           REG_SZ,
  1572.                           (LPBYTE)szVersion,
  1573.                           ((1+lstrlen(szVersion))*sizeof(TCHAR)));
  1574.     }
  1575.     hr = RegSetValueEx(hKey,
  1576.                        TEXT("Version"),
  1577.                        NULL,
  1578.                        REG_SZ,
  1579.                        (LPBYTE)szVersion, ((1+lstrlen(szVersion))*sizeof(TCHAR)));
  1580. Cleanup:
  1581.     if (hKey)
  1582.        RegCloseKey(hKey);
  1583.     CoTaskMemFree(pszGUID);
  1584.     return hr;
  1585. }
  1586. EXTERN_C LPITEMIDLIST UnixUrlToPidl(UINT uiCP, LPCTSTR pszUrl, LPCWSTR pszLocation)
  1587. {
  1588.     LPCITEMIDLIST pidlUrl = UrlToPidl(uiCP, pszUrl, pszLocation);
  1589.     return ILCombine(c_pidlURLRoot, pidlUrl);
  1590. }