Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentask.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2006 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "config.h" 00020 00021 #include <stdarg.h> 00022 #include <stdio.h> 00023 00024 #define COBJMACROS 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "winuser.h" 00029 #include "ole2.h" 00030 00031 #include "wine/debug.h" 00032 00033 #include "mshtml_private.h" 00034 00035 WINE_DEFAULT_DEBUG_CHANNEL(mshtml); 00036 00037 #define WM_PROCESSTASK 0x8008 00038 #define TIMER_ID 0x3000 00039 00040 typedef struct { 00041 HTMLDocument *doc; 00042 DWORD id; 00043 DWORD time; 00044 DWORD interval; 00045 IDispatch *disp; 00046 00047 struct list entry; 00048 } task_timer_t; 00049 00050 void push_task(task_t *task, task_proc_t proc, LONG magic) 00051 { 00052 thread_data_t *thread_data = get_thread_data(TRUE); 00053 00054 task->target_magic = magic; 00055 task->proc = proc; 00056 task->next = NULL; 00057 00058 if(thread_data->task_queue_tail) 00059 thread_data->task_queue_tail->next = task; 00060 else 00061 thread_data->task_queue_head = task; 00062 00063 thread_data->task_queue_tail = task; 00064 00065 PostMessageW(thread_data->thread_hwnd, WM_PROCESSTASK, 0, 0); 00066 } 00067 00068 static task_t *pop_task(void) 00069 { 00070 thread_data_t *thread_data = get_thread_data(TRUE); 00071 task_t *task = thread_data->task_queue_head; 00072 00073 if(!task) 00074 return NULL; 00075 00076 thread_data->task_queue_head = task->next; 00077 if(!thread_data->task_queue_head) 00078 thread_data->task_queue_tail = NULL; 00079 00080 return task; 00081 } 00082 00083 static void release_task_timer(HWND thread_hwnd, task_timer_t *timer) 00084 { 00085 list_remove(&timer->entry); 00086 00087 IDispatch_Release(timer->disp); 00088 00089 heap_free(timer); 00090 } 00091 00092 void remove_target_tasks(LONG target) 00093 { 00094 thread_data_t *thread_data = get_thread_data(FALSE); 00095 struct list *liter, *ltmp; 00096 task_timer_t *timer; 00097 task_t *iter, *tmp; 00098 00099 if(!thread_data) 00100 return; 00101 00102 LIST_FOR_EACH_SAFE(liter, ltmp, &thread_data->timer_list) { 00103 timer = LIST_ENTRY(liter, task_timer_t, entry); 00104 if(timer->doc->task_magic == target) 00105 release_task_timer(thread_data->thread_hwnd, timer); 00106 } 00107 00108 if(!list_empty(&thread_data->timer_list)) { 00109 timer = LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry); 00110 SetTimer(thread_data->thread_hwnd, TIMER_ID, timer->time - GetTickCount(), NULL); 00111 } 00112 00113 while(thread_data->task_queue_head 00114 && thread_data->task_queue_head->target_magic == target) 00115 pop_task(); 00116 00117 for(iter = thread_data->task_queue_head; iter; iter = iter->next) { 00118 while(iter->next && iter->next->target_magic == target) { 00119 tmp = iter->next; 00120 iter->next = tmp->next; 00121 heap_free(tmp); 00122 } 00123 00124 if(!iter->next) 00125 thread_data->task_queue_tail = iter; 00126 } 00127 } 00128 00129 LONG get_task_target_magic(void) 00130 { 00131 static LONG magic = 0x10000000; 00132 return InterlockedIncrement(&magic); 00133 } 00134 00135 static BOOL queue_timer(thread_data_t *thread_data, task_timer_t *timer) 00136 { 00137 task_timer_t *iter; 00138 00139 list_remove(&timer->entry); 00140 00141 if(list_empty(&thread_data->timer_list) 00142 || LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry)->time > timer->time) { 00143 00144 list_add_head(&thread_data->timer_list, &timer->entry); 00145 return TRUE; 00146 } 00147 00148 LIST_FOR_EACH_ENTRY(iter, &thread_data->timer_list, task_timer_t, entry) { 00149 if(iter->time > timer->time) { 00150 list_add_tail(&iter->entry, &timer->entry); 00151 return FALSE; 00152 } 00153 } 00154 00155 list_add_tail(&thread_data->timer_list, &timer->entry); 00156 return FALSE; 00157 } 00158 00159 DWORD set_task_timer(HTMLDocument *doc, DWORD msec, BOOL interval, IDispatch *disp) 00160 { 00161 thread_data_t *thread_data = get_thread_data(TRUE); 00162 task_timer_t *timer; 00163 DWORD tc = GetTickCount(); 00164 00165 static DWORD id_cnt = 0x20000000; 00166 00167 timer = heap_alloc(sizeof(task_timer_t)); 00168 timer->id = id_cnt++; 00169 timer->doc = doc; 00170 timer->time = tc + msec; 00171 timer->interval = interval ? msec : 0; 00172 list_init(&timer->entry); 00173 00174 IDispatch_AddRef(disp); 00175 timer->disp = disp; 00176 00177 if(queue_timer(thread_data, timer)) 00178 SetTimer(thread_data->thread_hwnd, TIMER_ID, msec, NULL); 00179 00180 return timer->id; 00181 } 00182 00183 HRESULT clear_task_timer(HTMLDocument *doc, BOOL interval, DWORD id) 00184 { 00185 thread_data_t *thread_data = get_thread_data(FALSE); 00186 task_timer_t *iter; 00187 00188 if(!thread_data) 00189 return S_OK; 00190 00191 LIST_FOR_EACH_ENTRY(iter, &thread_data->timer_list, task_timer_t, entry) { 00192 if(iter->id == id && iter->doc == doc && (iter->interval == 0) == !interval) { 00193 release_task_timer(thread_data->thread_hwnd, iter); 00194 return S_OK; 00195 } 00196 } 00197 00198 WARN("timet not found\n"); 00199 return S_OK; 00200 } 00201 00202 static void call_timer_disp(IDispatch *disp) 00203 { 00204 DISPPARAMS dp = {NULL, NULL, 0, 0}; 00205 EXCEPINFO ei; 00206 VARIANT res; 00207 HRESULT hres; 00208 00209 V_VT(&res) = VT_EMPTY; 00210 memset(&ei, 0, sizeof(ei)); 00211 00212 TRACE(">>>\n"); 00213 hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, &ei, NULL); 00214 if(hres == S_OK) 00215 TRACE("<<<\n"); 00216 else 00217 WARN("<<< %08x\n", hres); 00218 00219 VariantClear(&res); 00220 } 00221 00222 static LRESULT process_timer(void) 00223 { 00224 thread_data_t *thread_data = get_thread_data(TRUE); 00225 IDispatch *disp; 00226 DWORD tc; 00227 task_timer_t *timer; 00228 00229 TRACE("\n"); 00230 00231 while(!list_empty(&thread_data->timer_list)) { 00232 timer = LIST_ENTRY(list_head(&thread_data->timer_list), task_timer_t, entry); 00233 00234 tc = GetTickCount(); 00235 if(timer->time > tc) { 00236 SetTimer(thread_data->thread_hwnd, TIMER_ID, timer->time-tc, NULL); 00237 return 0; 00238 } 00239 00240 disp = timer->disp; 00241 IDispatch_AddRef(disp); 00242 00243 if(timer->interval) { 00244 timer->time += timer->interval; 00245 queue_timer(thread_data, timer); 00246 }else { 00247 release_task_timer(thread_data->thread_hwnd, timer); 00248 } 00249 00250 call_timer_disp(disp); 00251 00252 IDispatch_Release(disp); 00253 } 00254 00255 KillTimer(thread_data->thread_hwnd, TIMER_ID); 00256 return 0; 00257 } 00258 00259 static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 00260 { 00261 switch(msg) { 00262 case WM_PROCESSTASK: 00263 while(1) { 00264 task_t *task = pop_task(); 00265 if(!task) 00266 break; 00267 00268 task->proc(task); 00269 heap_free(task); 00270 } 00271 00272 return 0; 00273 case WM_TIMER: 00274 return process_timer(); 00275 } 00276 00277 if(msg > WM_USER) 00278 FIXME("(%p %d %lx %lx)\n", hwnd, msg, wParam, lParam); 00279 00280 return DefWindowProcW(hwnd, msg, wParam, lParam); 00281 } 00282 00283 static HWND create_thread_hwnd(void) 00284 { 00285 static ATOM hidden_wnd_class = 0; 00286 static const WCHAR wszInternetExplorer_Hidden[] = {'I','n','t','e','r','n','e','t', 00287 ' ','E','x','p','l','o','r','e','r','_','H','i','d','d','e','n',0}; 00288 00289 if(!hidden_wnd_class) { 00290 WNDCLASSEXW wndclass = { 00291 sizeof(WNDCLASSEXW), 0, 00292 hidden_proc, 00293 0, 0, hInst, NULL, NULL, NULL, NULL, 00294 wszInternetExplorer_Hidden, 00295 NULL 00296 }; 00297 00298 hidden_wnd_class = RegisterClassExW(&wndclass); 00299 } 00300 00301 return CreateWindowExW(0, wszInternetExplorer_Hidden, NULL, WS_POPUP, 00302 0, 0, 0, 0, NULL, NULL, hInst, NULL); 00303 } 00304 00305 HWND get_thread_hwnd(void) 00306 { 00307 thread_data_t *thread_data = get_thread_data(TRUE); 00308 00309 if(!thread_data->thread_hwnd) 00310 thread_data->thread_hwnd = create_thread_hwnd(); 00311 00312 return thread_data->thread_hwnd; 00313 } 00314 00315 thread_data_t *get_thread_data(BOOL create) 00316 { 00317 thread_data_t *thread_data; 00318 00319 if(mshtml_tls == TLS_OUT_OF_INDEXES) { 00320 DWORD tls; 00321 00322 if(!create) 00323 return NULL; 00324 00325 tls = TlsAlloc(); 00326 if(tls == TLS_OUT_OF_INDEXES) 00327 return NULL; 00328 00329 tls = InterlockedCompareExchange((LONG*)&mshtml_tls, tls, TLS_OUT_OF_INDEXES); 00330 if(tls != mshtml_tls) 00331 TlsFree(tls); 00332 } 00333 00334 thread_data = TlsGetValue(mshtml_tls); 00335 if(!thread_data && create) { 00336 thread_data = heap_alloc_zero(sizeof(thread_data_t)); 00337 TlsSetValue(mshtml_tls, thread_data); 00338 list_init(&thread_data->timer_list); 00339 } 00340 00341 return thread_data; 00342 } Generated on Thu May 24 2012 04:25:36 for ReactOS by
1.7.6.1
|