+static LRESULT CALLBACK
+silc_schedule_wnd_proc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
+{
+ SilcSchedule schedule = (SilcSchedule)GetWindowLongPtr(hwnd, GWL_USERDATA);
+ SilcWin32Scheduler internal;
+ SilcUInt32 fd;
+ SilcTaskFd task;
+
+ switch (wMsg) {
+ case SILC_WM_EVENT:
+ internal = (SilcWin32Scheduler)schedule->internal;
+ fd = (SilcUInt32)wParam;
+
+ SILC_LOG_DEBUG(("SILC_WM_EVENT fd %d", fd));
+ SILC_SCHEDULE_LOCK(schedule);
+
+ if (!internal->in_schedule) {
+ /* We are not in scheduler so set up the dispatch queue now */
+ internal->in_schedule = TRUE;
+ silc_list_init(schedule->fd_dispatch, struct SilcTaskStruct, next);
+ }
+
+ /* Find task by fd */
+ if (!silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),
+ NULL, (void *)&task)) {
+ SILC_SCHEDULE_UNLOCK(schedule);
+ break;
+ }
+
+ /* Ignore the event if the task is not valid anymore */
+ if (!task->header.valid || !task->events) {
+ SILC_SCHEDULE_UNLOCK(schedule);
+ break;
+ }
+ task->revents = 0;
+
+ /* Handle event */
+ switch (WSAGETSELECTEVENT(lParam)) {
+ case FD_READ:
+ case FD_OOB:
+ SILC_LOG_DEBUG(("FD_READ"));
+ task->revents |= SILC_TASK_READ;
+ silc_list_add(schedule->fd_dispatch, task);
+ break;
+
+ case FD_WRITE:
+ SILC_LOG_DEBUG(("FD_WRITE"));
+ task->revents |= SILC_TASK_WRITE;
+ silc_list_add(schedule->fd_dispatch, task);
+ break;
+
+ case FD_ACCEPT:
+ SILC_LOG_DEBUG(("FD_ACCEPT"));
+ task->revents |= SILC_TASK_READ;
+ silc_list_add(schedule->fd_dispatch, task);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Wakeup scheduler */
+ ReleaseSemaphore(internal->wakeup_sema, 1, NULL);