[PEFIXUP] Add support for overriding the attributes of specific PE sections. (#3598)
[reactos.git] / dll / shellext / sendmail / sendmail.cpp
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 }