ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

task.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.