xref: /reactos/dll/shellext/sendmail/sendmail.cpp (revision e1605243)
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