ReactOS 0.4.16-dev-306-g647d351
task.c
Go to the documentation of this file.
1/*
2 * Copyright 2006 Jacek Caban for CodeWeavers
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 "mshtml_private.h"
20
21#define WM_PROCESSTASK 0x8008
22#define TIMER_ID 0x3000
23
24typedef struct {
30
31 struct list entry;
33
34static void default_task_destr(task_t *task)
35{
36 heap_free(task);
37}
38
40{
42
44 if(!thread_data) {
45 if(destr)
46 destr(task);
47 else
48 heap_free(task);
49 return E_OUTOFMEMORY;
50 }
51
52 task->target_magic = magic;
53 task->proc = proc;
54 task->destr = destr ? destr : default_task_destr;
55
56 list_add_tail(&thread_data->task_list, &task->entry);
57
58 PostMessageW(thread_data->thread_hwnd, WM_PROCESSTASK, 0, 0);
59 return S_OK;
60}
61
62static task_t *pop_task(void)
63{
65 task_t *task;
66
68 if(!thread_data)
69 return NULL;
70
71 if(list_empty(&thread_data->task_list))
72 return NULL;
73
74 task = LIST_ENTRY(thread_data->task_list.next, task_t, entry);
75 list_remove(&task->entry);
76 return task;
77}
78
79static void release_task_timer(HWND thread_hwnd, task_timer_t *timer)
80{
81 list_remove(&timer->entry);
82
83 IDispatch_Release(timer->disp);
84
85 heap_free(timer);
86}
87
89{
91 struct list *liter, *ltmp;
92 task_t *task;
93
94 if(!thread_data)
95 return;
96
97 LIST_FOR_EACH_SAFE(liter, ltmp, &thread_data->task_list) {
98 task = LIST_ENTRY(liter, task_t, entry);
99 if(task->target_magic == target) {
100 list_remove(&task->entry);
101 task->proc(task);
102 task->destr(task);
103 }
104 }
105}
106
108{
110 struct list *liter, *ltmp;
111 task_timer_t *timer;
112 task_t *task;
113
114 if(!thread_data)
115 return;
116
117 LIST_FOR_EACH_SAFE(liter, ltmp, &thread_data->timer_list) {
118 timer = LIST_ENTRY(liter, task_timer_t, entry);
119 if(timer->window->task_magic == target)
120 release_task_timer(thread_data->thread_hwnd, timer);
121 }
122
123 if(!list_empty(&thread_data->timer_list)) {
125
126 timer = LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry);
127 SetTimer(thread_data->thread_hwnd, TIMER_ID, max( (int)(timer->time - tc), 0 ), NULL);
128 }
129
130 LIST_FOR_EACH_SAFE(liter, ltmp, &thread_data->task_list) {
131 task = LIST_ENTRY(liter, task_t, entry);
132 if(task->target_magic == target) {
133 list_remove(&task->entry);
134 task->destr(task);
135 }
136 }
137}
138
140{
141 static LONG magic = 0x10000000;
142 return InterlockedIncrement(&magic);
143}
144
146{
147 task_timer_t *iter;
148
149 list_remove(&timer->entry);
150
151 if(list_empty(&thread_data->timer_list)
152 || LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry)->time > timer->time) {
153
154 list_add_head(&thread_data->timer_list, &timer->entry);
155 return TRUE;
156 }
157
158 LIST_FOR_EACH_ENTRY(iter, &thread_data->timer_list, task_timer_t, entry) {
159 if(iter->time > timer->time) {
160 list_add_tail(&iter->entry, &timer->entry);
161 return FALSE;
162 }
163 }
164
165 list_add_tail(&thread_data->timer_list, &timer->entry);
166 return FALSE;
167}
168
170{
172 task_timer_t *timer;
174
175 static DWORD id_cnt = 0x20000000;
176
178 if(!thread_data)
179 return E_OUTOFMEMORY;
180
181 timer = heap_alloc(sizeof(task_timer_t));
182 if(!timer)
183 return E_OUTOFMEMORY;
184
185 timer->id = id_cnt++;
186 timer->window = window;
187 timer->time = tc + msec;
188 timer->interval = interval ? msec : 0;
189 list_init(&timer->entry);
190
191 IDispatch_AddRef(disp);
192 timer->disp = disp;
193
194 if(queue_timer(thread_data, timer))
195 SetTimer(thread_data->thread_hwnd, TIMER_ID, msec, NULL);
196
197 *id = timer->id;
198 return S_OK;
199}
200
202{
204 task_timer_t *iter;
205
206 if(!thread_data)
207 return S_OK;
208
209 LIST_FOR_EACH_ENTRY(iter, &thread_data->timer_list, task_timer_t, entry) {
210 if(iter->id == id && iter->window == window && !iter->interval == !interval) {
211 release_task_timer(thread_data->thread_hwnd, iter);
212 return S_OK;
213 }
214 }
215
216 WARN("timet not found\n");
217 return S_OK;
218}
219
220static void call_timer_disp(IDispatch *disp)
221{
222 DISPPARAMS dp = {NULL, NULL, 0, 0};
223 EXCEPINFO ei;
224 VARIANT res;
226
227 V_VT(&res) = VT_EMPTY;
228 memset(&ei, 0, sizeof(ei));
229
230 TRACE(">>>\n");
231 hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, &ei, NULL);
232 if(hres == S_OK)
233 TRACE("<<<\n");
234 else
235 WARN("<<< %08x\n", hres);
236
238}
239
241{
243 IDispatch *disp;
244 DWORD tc;
245 task_timer_t *timer=NULL, *last_timer;
246
247 TRACE("\n");
248
251
252 if(list_empty(&thread_data->timer_list)) {
253 KillTimer(thread_data->thread_hwnd, TIMER_ID);
254 return 0;
255 }
256
257 last_timer = LIST_ENTRY(list_tail(&thread_data->timer_list), task_timer_t, entry);
258 do {
259 tc = GetTickCount();
260 if(timer == last_timer) {
261 timer = LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry);
262 SetTimer(thread_data->thread_hwnd, TIMER_ID, timer->time>tc ? timer->time-tc : 0, NULL);
263 return 0;
264 }
265
266 timer = LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry);
267
268 if(timer->time > tc) {
269 SetTimer(thread_data->thread_hwnd, TIMER_ID, timer->time-tc, NULL);
270 return 0;
271 }
272
273 disp = timer->disp;
274 IDispatch_AddRef(disp);
275
276 if(timer->interval) {
277 timer->time += timer->interval;
278 queue_timer(thread_data, timer);
279 }else {
280 release_task_timer(thread_data->thread_hwnd, timer);
281 }
282
283 call_timer_disp(disp);
284
285 IDispatch_Release(disp);
286 }while(!list_empty(&thread_data->timer_list));
287
288 KillTimer(thread_data->thread_hwnd, TIMER_ID);
289 return 0;
290}
291
293{
294 switch(msg) {
295 case WM_PROCESSTASK:
296 while(1) {
297 task_t *task = pop_task();
298 if(!task)
299 break;
300
301 task->proc(task);
302 task->destr(task);
303 }
304
305 return 0;
306 case WM_TIMER:
307 return process_timer();
308 }
309
310 if(msg > WM_USER)
311 FIXME("(%p %d %lx %lx)\n", hwnd, msg, wParam, lParam);
312
314}
315
317{
318 static ATOM hidden_wnd_class = 0;
319 static const WCHAR wszInternetExplorer_Hidden[] = {'I','n','t','e','r','n','e','t',
320 ' ','E','x','p','l','o','r','e','r','_','H','i','d','d','e','n',0};
321
322 if(!hidden_wnd_class) {
323 WNDCLASSEXW wndclass = {
324 sizeof(WNDCLASSEXW), 0,
326 0, 0, hInst, NULL, NULL, NULL, NULL,
327 wszInternetExplorer_Hidden,
328 NULL
329 };
330
331 hidden_wnd_class = RegisterClassExW(&wndclass);
332 }
333
334 return CreateWindowExW(0, wszInternetExplorer_Hidden, NULL, WS_POPUP,
335 0, 0, 0, 0, NULL, NULL, hInst, NULL);
336}
337
339{
341
343 if(!thread_data)
344 return NULL;
345
346 if(!thread_data->thread_hwnd)
347 thread_data->thread_hwnd = create_thread_hwnd();
348
349 return thread_data->thread_hwnd;
350}
351
353{
355
357 DWORD tls;
358
359 if(!create)
360 return NULL;
361
362 tls = TlsAlloc();
364 return NULL;
365
367 if(tls != mshtml_tls)
368 TlsFree(tls);
369 }
370
372 if(!thread_data && create) {
373 thread_data = heap_alloc_zero(sizeof(thread_data_t));
374 if(!thread_data)
375 return NULL;
376
378 list_init(&thread_data->task_list);
379 list_init(&thread_data->timer_list);
380 }
381
382 return thread_data;
383}
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define InterlockedIncrement
Definition: armddk.h:53
#define msg(x)
Definition: auth_time.c:54
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
Definition: list.h:37
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
WORD ATOM
Definition: dimm.idl:113
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ VT_EMPTY
Definition: compat.h:2295
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1240
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1100
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1276
BOOL WINAPI TlsFree(IN DWORD Index)
Definition: thread.c:1166
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
DWORD mshtml_tls
Definition: main.c:31
static void default_task_destr(task_t *task)
Definition: task.c:34
static void call_timer_disp(IDispatch *disp)
Definition: task.c:220
LONG get_task_target_magic(void)
Definition: task.c:139
HWND get_thread_hwnd(void)
Definition: task.c:338
thread_data_t * get_thread_data(BOOL create)
Definition: task.c:352
HRESULT clear_task_timer(HTMLInnerWindow *window, BOOL interval, DWORD id)
Definition: task.c:201
HRESULT push_task(task_t *task, task_proc_t proc, task_proc_t destr, LONG magic)
Definition: task.c:39
void remove_target_tasks(LONG target)
Definition: task.c:107
static LRESULT process_timer(void)
Definition: task.c:240
static void release_task_timer(HWND thread_hwnd, task_timer_t *timer)
Definition: task.c:79
#define WM_PROCESSTASK
Definition: task.c:21
HRESULT set_task_timer(HTMLInnerWindow *window, DWORD msec, BOOL interval, IDispatch *disp, LONG *id)
Definition: task.c:169
static HWND create_thread_hwnd(void)
Definition: task.c:316
static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: task.c:292
void flush_pending_tasks(LONG target)
Definition: task.c:88
#define TIMER_ID
Definition: task.c:22
static task_t * pop_task(void)
Definition: task.c:62
#define assert(x)
Definition: debug.h:53
HINSTANCE hInst
Definition: dxdiag.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint res
Definition: glext.h:9613
const GLfloat * tc
Definition: glext.h:8925
GLenum target
Definition: glext.h:7315
void(* task_proc_t)(DocHost *, struct _task_header_t *)
Definition: ieframe.h:75
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define S_OK
Definition: intsafe.h:52
uint32_t entry
Definition: isohybrid.c:63
HRESULT hres
Definition: protocol.c:465
static IHTMLWindow2 * window
Definition: events.c:77
static const struct access_res create[16]
Definition: package.c:7505
unsigned int UINT
Definition: ndis.h:50
#define DISPATCH_METHOD
Definition: oleauto.h:1006
#define V_VT(A)
Definition: oleauto.h:211
static HANDLE proc()
Definition: pdb.c:34
#define WS_POPUP
Definition: pedump.c:616
long LONG
Definition: pedump.c:60
#define IID_NULL
Definition: guiddef.h:98
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list)
Definition: list.h:192
__WINE_SERVER_LIST_INLINE struct list * list_tail(const struct list *list)
Definition: list.h:137
#define memset(x, y, z)
Definition: compat.h:39
static DWORD tls
Definition: sock.c:229
#define TRACE(s)
Definition: solgame.cpp:4
Definition: typedefs.h:120
Definition: list.h:15
task_proc_t proc
task_proc_t destr
struct list entry
LONG target_magic
HTMLInnerWindow * window
Definition: task.c:25
DWORD interval
Definition: task.c:28
struct list entry
Definition: task.c:31
DWORD id
Definition: task.c:26
DWORD time
Definition: task.c:27
IDispatch * disp
Definition: task.c:29
#define max(a, b)
Definition: svc.c:63
#define LIST_ENTRY(type)
Definition: queue.h:175
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:575
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define WINAPI
Definition: msvc.h:6
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define WM_TIMER
Definition: winuser.h:1745
HWND WINAPI CreateWindowExW(_In_ DWORD dwExStyle, _In_opt_ LPCWSTR lpClassName, _In_opt_ LPCWSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
ATOM WINAPI RegisterClassExW(_In_ CONST WNDCLASSEXW *)
#define WM_USER
Definition: winuser.h:1898
struct _WNDCLASSEXW WNDCLASSEXW
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
__wchar_t WCHAR
Definition: xmlstorage.h:180