ReactOS  0.4.14-dev-552-g2fad488
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 
24 typedef struct {
30 
31  struct list entry;
32 } task_timer_t;
33 
34 static 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 
62 static 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 
79 static 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)) {
124  DWORD tc = GetTickCount();
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;
173  DWORD tc = GetTickCount();
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 
221 {
222  DISPPARAMS dp = {NULL, NULL, 0, 0};
223  EXCEPINFO ei;
224  VARIANT res;
225  HRESULT hres;
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 
237  VariantClear(&res);
238 }
239 
240 static LRESULT process_timer(void)
241 {
243  IDispatch *disp;
244  DWORD tc;
245  task_timer_t *timer=NULL, *last_timer;
246 
247  TRACE("\n");
248 
250  assert(thread_data != NULL);
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 
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 
313  return DefWindowProcW(hwnd, msg, wParam, lParam);
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,
325  hidden_proc,
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();
363  if(tls == TLS_OUT_OF_INDEXES)
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 }
disp
Definition: i386-dis.c:3181
HWND get_thread_hwnd(void)
Definition: task.c:338
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: task.c:292
#define max(a, b)
Definition: svc.c:63
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list)
Definition: list.h:192
#define TRUE
Definition: types.h:120
static BOOL queue_timer(thread_data_t *thread_data, task_timer_t *timer)
Definition: task.c:145
thread_data_t * get_thread_data(BOOL create)
Definition: task.c:352
HRESULT set_task_timer(HTMLInnerWindow *window, DWORD msec, BOOL interval, IDispatch *disp, LONG *id)
Definition: task.c:169
LONG get_task_target_magic(void)
Definition: task.c:139
static void release_task_timer(HWND thread_hwnd, task_timer_t *timer)
Definition: task.c:79
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1264
WORD ATOM
Definition: dimm.idl:113
#define WARN(fmt,...)
Definition: debug.h:111
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
u32_t magic(void)
#define InterlockedCompareExchange
Definition: interlocked.h:104
static void default_task_destr(task_t *task)
Definition: task.c:34
#define assert(x)
Definition: debug.h:53
UINT_PTR WPARAM
Definition: windef.h:207
static HANDLE proc()
Definition: pdb.c:32
struct _WNDCLASSEXW WNDCLASSEXW
__WINE_SERVER_LIST_INLINE struct list * list_tail(const struct list *list)
Definition: list.h:137
WPARAM wParam
Definition: combotst.c:138
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define DISPATCH_METHOD
Definition: oleauto.h:1006
#define WM_PROCESSTASK
Definition: task.c:21
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
void(* task_proc_t)(DocHost *, struct _task_header_t *)
Definition: ieframe.h:75
DWORD id
Definition: task.c:26
#define TIMER_ID
Definition: task.c:22
ATOM WINAPI RegisterClassExW(_In_ CONST WNDCLASSEXW *)
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
IDispatch * disp
Definition: task.c:29
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
HTMLInnerWindow * window
Definition: task.c:25
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
task_proc_t proc
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define FIXME(fmt,...)
Definition: debug.h:110
static void call_timer_disp(IDispatch *disp)
Definition: task.c:220
const GLfloat * tc
Definition: glext.h:8925
smooth NULL
Definition: ftsmooth.c:416
LONG_PTR LPARAM
Definition: windef.h:208
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
DWORD interval
Definition: task.c:28
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT hres
Definition: protocol.c:465
static task_t * pop_task(void)
Definition: task.c:62
BOOL WINAPI TlsFree(IN DWORD Index)
Definition: thread.c:1154
__wchar_t WCHAR
Definition: xmlstorage.h:180
struct list entry
LONG HRESULT
Definition: typedefs.h:77
#define WM_TIMER
Definition: winuser.h:1724
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
static LRESULT process_timer(void)
Definition: task.c:240
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
HRESULT clear_task_timer(HTMLInnerWindow *window, BOOL interval, DWORD id)
Definition: task.c:201
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
#define IID_NULL
Definition: guiddef.h:98
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)
#define V_VT(A)
Definition: oleauto.h:211
struct list entry
Definition: task.c:31
uint32_t entry
Definition: isohybrid.c:63
Definition: _list.h:228
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1088
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:530
Definition: typedefs.h:117
task_proc_t destr
static IHTMLWindow2 * window
Definition: events.c:77
#define WM_USER
Definition: winuser.h:1877
DWORD time
Definition: task.c:27
struct stdole::EXCEPINFO EXCEPINFO
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
#define S_OK
Definition: intsafe.h:59
HINSTANCE hInst
Definition: dxdiag.c:13
#define InterlockedIncrement
Definition: armddk.h:53
static HWND create_thread_hwnd(void)
Definition: task.c:316
void remove_target_tasks(LONG target)
Definition: task.c:107
DWORD mshtml_tls
Definition: main.c:31
#define WS_POPUP
Definition: pedump.c:616
unsigned int UINT
Definition: ndis.h:50
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1228
#define msg(x)
Definition: auth_time.c:54
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
GLuint res
Definition: glext.h:9613
struct stdole::DISPPARAMS DISPPARAMS
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
GLenum target
Definition: glext.h:7315
static DWORD tls
Definition: sock.c:230
#define LIST_ENTRY(type)
Definition: queue.h:175
LONG_PTR LRESULT
Definition: windef.h:209
LONG target_magic
void flush_pending_tasks(LONG target)
Definition: task.c:88
static const struct access_res create[16]
Definition: package.c:7720
#define memset(x, y, z)
Definition: compat.h:39
LPARAM lParam
Definition: combotst.c:139
HRESULT push_task(task_t *task, task_proc_t proc, task_proc_t destr, LONG magic)
Definition: task.c:39
static BOOL heap_free(void *mem)
Definition: appwiz.h:75