Various background processes must be launched detached from current console (if any).
[wine] / dlls / mstask / task_scheduler.c
1 /*
2  * Copyright (C) 2008 Google (Roy Shea)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "corerror.h"
20 #include "mstask_private.h"
21 #include "wine/debug.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(mstask);
24
25 typedef struct
26 {
27     ITaskScheduler ITaskScheduler_iface;
28     LONG ref;
29 } TaskSchedulerImpl;
30
31 static inline TaskSchedulerImpl *impl_from_ITaskScheduler(ITaskScheduler *iface)
32 {
33     return CONTAINING_RECORD(iface, TaskSchedulerImpl, ITaskScheduler_iface);
34 }
35
36 static void TaskSchedulerDestructor(TaskSchedulerImpl *This)
37 {
38     TRACE("%p\n", This);
39     HeapFree(GetProcessHeap(), 0, This);
40     InterlockedDecrement(&dll_ref);
41 }
42
43 static HRESULT WINAPI MSTASK_ITaskScheduler_QueryInterface(
44         ITaskScheduler* iface,
45         REFIID riid,
46         void **ppvObject)
47 {
48     TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface);
49
50     TRACE("IID: %s\n", debugstr_guid(riid));
51
52     if (IsEqualGUID(riid, &IID_IUnknown) ||
53             IsEqualGUID(riid, &IID_ITaskScheduler))
54     {
55         *ppvObject = &This->ITaskScheduler_iface;
56         ITaskScheduler_AddRef(iface);
57         return S_OK;
58     }
59
60     *ppvObject = NULL;
61     return E_NOINTERFACE;
62 }
63
64 static ULONG WINAPI MSTASK_ITaskScheduler_AddRef(
65         ITaskScheduler* iface)
66 {
67     TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
68     TRACE("\n");
69     return InterlockedIncrement(&This->ref);
70 }
71
72 static ULONG WINAPI MSTASK_ITaskScheduler_Release(
73         ITaskScheduler* iface)
74 {
75     TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface);
76     ULONG ref;
77     TRACE("\n");
78     ref = InterlockedDecrement(&This->ref);
79     if (ref == 0)
80         TaskSchedulerDestructor(This);
81     return ref;
82 }
83
84 static HRESULT WINAPI MSTASK_ITaskScheduler_SetTargetComputer(
85         ITaskScheduler* iface,
86         LPCWSTR pwszComputer)
87 {
88     TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
89     WCHAR buffer[MAX_COMPUTERNAME_LENGTH + 3];  /* extra space for two '\' and a zero */
90     DWORD len = MAX_COMPUTERNAME_LENGTH + 1;    /* extra space for a zero */
91
92     TRACE("(%p)->(%s)\n", This, debugstr_w(pwszComputer));
93
94     /* NULL is an alias for the local computer */
95     if (!pwszComputer)
96         return S_OK;
97
98     buffer[0] = '\\';
99     buffer[1] = '\\';
100     if (GetComputerNameW(buffer + 2, &len))
101     {
102         if (!lstrcmpiW(buffer, pwszComputer) ||    /* full unc name */
103             !lstrcmpiW(buffer + 2, pwszComputer))  /* name without backslash */
104             return S_OK;
105     }
106
107     FIXME("remote computer %s not supported\n", debugstr_w(pwszComputer));
108     return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
109 }
110
111 static HRESULT WINAPI MSTASK_ITaskScheduler_GetTargetComputer(
112         ITaskScheduler* iface,
113         LPWSTR *ppwszComputer)
114 {
115     TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
116     LPWSTR buffer;
117     DWORD len = MAX_COMPUTERNAME_LENGTH + 1; /* extra space for the zero */
118
119     TRACE("(%p)->(%p)\n", This, ppwszComputer);
120
121     if (!ppwszComputer)
122         return E_INVALIDARG;
123
124     /* extra space for two '\' and a zero */
125     buffer = CoTaskMemAlloc((MAX_COMPUTERNAME_LENGTH + 3) * sizeof(WCHAR));
126     if (buffer)
127     {
128         buffer[0] = '\\';
129         buffer[1] = '\\';
130         if (GetComputerNameW(buffer + 2, &len))
131         {
132             *ppwszComputer = buffer;
133             return S_OK;
134         }
135         CoTaskMemFree(buffer);
136     }
137     *ppwszComputer = NULL;
138     return HRESULT_FROM_WIN32(GetLastError());
139 }
140
141 static HRESULT WINAPI MSTASK_ITaskScheduler_Enum(
142         ITaskScheduler* iface,
143         IEnumWorkItems **ppEnumTasks)
144 {
145     FIXME("%p, %p: stub\n", iface, ppEnumTasks);
146     return E_NOTIMPL;
147 }
148
149 static HRESULT WINAPI MSTASK_ITaskScheduler_Activate(
150         ITaskScheduler* iface,
151         LPCWSTR pwszName,
152         REFIID riid,
153         IUnknown **ppunk)
154 {
155     TRACE("%p, %s, %s, %p: stub\n", iface, debugstr_w(pwszName),
156             debugstr_guid(riid), ppunk);
157     FIXME("Partial stub always returning COR_E_FILENOTFOUND\n");
158     return COR_E_FILENOTFOUND;
159 }
160
161 static HRESULT WINAPI MSTASK_ITaskScheduler_Delete(
162         ITaskScheduler* iface,
163         LPCWSTR pwszName)
164 {
165     FIXME("%p, %s: stub\n", iface, debugstr_w(pwszName));
166     return E_NOTIMPL;
167 }
168
169 static HRESULT WINAPI MSTASK_ITaskScheduler_NewWorkItem(
170         ITaskScheduler* iface,
171         LPCWSTR pwszTaskName,
172         REFCLSID rclsid,
173         REFIID riid,
174         IUnknown **ppunk)
175 {
176     HRESULT hr;
177     TRACE("(%p, %s, %s, %s, %p)\n", iface, debugstr_w(pwszTaskName),
178             debugstr_guid(rclsid) ,debugstr_guid(riid),  ppunk);
179
180     if (!IsEqualGUID(rclsid, &CLSID_CTask))
181         return CLASS_E_CLASSNOTAVAILABLE;
182
183     if (!IsEqualGUID(riid, &IID_ITask))
184         return E_NOINTERFACE;
185
186     hr = TaskConstructor(pwszTaskName, (LPVOID *)ppunk);
187     return hr;
188 }
189
190 static HRESULT WINAPI MSTASK_ITaskScheduler_AddWorkItem(
191         ITaskScheduler* iface,
192         LPCWSTR pwszTaskName,
193         IScheduledWorkItem *pWorkItem)
194 {
195     FIXME("%p, %s, %p: stub\n", iface, debugstr_w(pwszTaskName), pWorkItem);
196     return E_NOTIMPL;
197 }
198
199 static HRESULT WINAPI MSTASK_ITaskScheduler_IsOfType(
200         ITaskScheduler* iface,
201         LPCWSTR pwszName,
202         REFIID riid)
203 {
204     FIXME("%p, %s, %s: stub\n", iface, debugstr_w(pwszName),
205             debugstr_guid(riid));
206     return E_NOTIMPL;
207 }
208
209 static const ITaskSchedulerVtbl MSTASK_ITaskSchedulerVtbl =
210 {
211     MSTASK_ITaskScheduler_QueryInterface,
212     MSTASK_ITaskScheduler_AddRef,
213     MSTASK_ITaskScheduler_Release,
214     MSTASK_ITaskScheduler_SetTargetComputer,
215     MSTASK_ITaskScheduler_GetTargetComputer,
216     MSTASK_ITaskScheduler_Enum,
217     MSTASK_ITaskScheduler_Activate,
218     MSTASK_ITaskScheduler_Delete,
219     MSTASK_ITaskScheduler_NewWorkItem,
220     MSTASK_ITaskScheduler_AddWorkItem,
221     MSTASK_ITaskScheduler_IsOfType
222 };
223
224 HRESULT TaskSchedulerConstructor(LPVOID *ppObj)
225 {
226     TaskSchedulerImpl *This;
227     TRACE("(%p)\n", ppObj);
228
229     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
230     if (!This)
231         return E_OUTOFMEMORY;
232
233     This->ITaskScheduler_iface.lpVtbl = &MSTASK_ITaskSchedulerVtbl;
234     This->ref = 1;
235
236     *ppObj = &This->ITaskScheduler_iface;
237     InterlockedIncrement(&dll_ref);
238     return S_OK;
239 }