1 /* 2 * PROJECT: sendmail 3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) 4 * PURPOSE: DeskLink implementation 5 * COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 6 */ 7 8 #include "precomp.hpp" 9 10 WINE_DEFAULT_DEBUG_CHANNEL(sendmail); 11 12 BEGIN_OBJECT_MAP(ObjectMap) 13 OBJECT_ENTRY(CLSID_DeskLinkDropHandler, CDeskLinkDropHandler) 14 END_OBJECT_MAP() 15 16 CComModule gModule; 17 LONG g_ModuleRefCnt = 0; 18 HINSTANCE g_hModule; 19 20 static BOOL 21 CreateEmptyFile(LPCWSTR pszFile) 22 { 23 HANDLE hFile; 24 hFile = CreateFileW(pszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, 25 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 26 if (hFile != INVALID_HANDLE_VALUE) 27 { 28 CloseHandle(hFile); 29 return TRUE; 30 } 31 return FALSE; 32 } 33 34 static HRESULT 35 CreateSendToDeskLink(LPCWSTR pszSendTo) 36 { 37 WCHAR szTarget[MAX_PATH], szSendToFile[MAX_PATH]; 38 39 LoadStringW(g_hModule, IDS_DESKLINK, szTarget, _countof(szTarget)); 40 StringCbCatW(szTarget, sizeof(szTarget), L".DeskLink"); 41 42 StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo); 43 PathAppendW(szSendToFile, szTarget); 44 45 if (!CreateEmptyFile(szSendToFile)) 46 { 47 ERR("CreateEmptyFile('%ls')\n", szSendToFile); 48 return E_FAIL; 49 } 50 return S_OK; 51 } 52 53 static HRESULT 54 GetDefaultUserSendTo(LPWSTR pszPath) 55 { 56 return SHGetFolderPathW(NULL, CSIDL_SENDTO, INVALID_HANDLE_VALUE, 57 SHGFP_TYPE_DEFAULT, pszPath); 58 } 59 60 STDAPI DllCanUnloadNow(void) 61 { 62 if (g_ModuleRefCnt) 63 return S_FALSE; 64 return gModule.DllCanUnloadNow(); 65 } 66 67 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 68 { 69 TRACE("CLSID:%s,IID:%s\n", wine_dbgstr_guid(&rclsid), wine_dbgstr_guid(&riid)); 70 71 HRESULT hr = gModule.DllGetClassObject(rclsid, riid, ppv); 72 73 TRACE("-- pointer to class factory: %p\n", *ppv); 74 75 return hr; 76 } 77 78 STDAPI DllRegisterServer(void) 79 { 80 HRESULT hr = gModule.DllRegisterServer(FALSE); 81 if (FAILED_UNEXPECTEDLY(hr)) 82 return hr; 83 84 WCHAR szSendTo[MAX_PATH]; 85 hr = GetDefaultUserSendTo(szSendTo); 86 if (SUCCEEDED(hr)) 87 CreateSendToDeskLink(szSendTo); 88 89 return S_OK; 90 } 91 92 STDAPI DllUnregisterServer(void) 93 { 94 HRESULT hr = gModule.DllUnregisterServer(FALSE); 95 if (FAILED_UNEXPECTEDLY(hr)) 96 return hr; 97 98 return S_OK; 99 } 100 101 HRESULT 102 CreateShellLink( 103 LPCWSTR pszLinkPath, 104 LPCWSTR pszTargetPath OPTIONAL, 105 LPCITEMIDLIST pidlTarget OPTIONAL, 106 LPCWSTR pszArg OPTIONAL, 107 LPCWSTR pszDir OPTIONAL, 108 LPCWSTR pszIconPath OPTIONAL, 109 INT iIconNr OPTIONAL, 110 LPCWSTR pszComment OPTIONAL) 111 { 112 CComPtr<IShellLinkW> psl; 113 HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, 114 CLSCTX_INPROC_SERVER, 115 IID_PPV_ARG(IShellLinkW, &psl)); 116 if (FAILED_UNEXPECTEDLY(hr)) 117 return hr; 118 119 if (pszTargetPath) 120 { 121 hr = psl->SetPath(pszTargetPath); 122 if (FAILED_UNEXPECTEDLY(hr)) 123 return hr; 124 } 125 else if (pidlTarget) 126 { 127 hr = psl->SetIDList(pidlTarget); 128 if (FAILED_UNEXPECTEDLY(hr)) 129 return hr; 130 } 131 else 132 { 133 ERR("invalid argument\n"); 134 return E_INVALIDARG; 135 } 136 137 if (pszArg) 138 hr = psl->SetArguments(pszArg); 139 140 if (pszDir) 141 hr = psl->SetWorkingDirectory(pszDir); 142 143 if (pszIconPath) 144 hr = psl->SetIconLocation(pszIconPath, iIconNr); 145 146 if (pszComment) 147 hr = psl->SetDescription(pszComment); 148 149 CComPtr<IPersistFile> ppf; 150 hr = psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf)); 151 if (FAILED_UNEXPECTEDLY(hr)) 152 return hr; 153 154 hr = ppf->Save(pszLinkPath, TRUE); 155 if (FAILED_UNEXPECTEDLY(hr)) 156 return hr; 157 158 return hr; 159 } 160 161 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad) 162 { 163 TRACE("%p 0x%x %p\n", hInstance, dwReason, fImpLoad); 164 if (dwReason == DLL_PROCESS_ATTACH) 165 { 166 g_hModule = hInstance; 167 gModule.Init(ObjectMap, hInstance, NULL); 168 DisableThreadLibraryCalls(hInstance); 169 } 170 else if (dwReason == DLL_PROCESS_DETACH) 171 { 172 gModule.Term(); 173 } 174 return TRUE; 175 } 176