Release 950727
[wine] / ipc / dde_proc.c
1 /***************************************************************************
2  * Copyright 1995, Technion, Israel Institute of Technology
3  * Electrical Eng, Software Lab.
4  * Author:    Michael Veksler.
5  ***************************************************************************
6  * File:      dde_proc.c
7  * Purpose :  DDE signals and processes functionality for DDE
8  ***************************************************************************
9  */
10 #include <sys/time.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <signal.h>
14 #include <errno.h>
15 #include <sys/msg.h>
16 #include "wintypes.h"
17 #include "win.h"
18 #include "shm_semaph.h"
19 #include "shm_main_blk.h"
20 #include "dde_proc.h"
21 #include "dde_mem.h"
22 #include "dde.h"
23 #include "stddebug.h"
24 #include "debug.h"
25
26 int curr_proc_idx= -1;
27
28 enum stop_wait_op stop_wait_op=CONT;
29 int had_SIGUSR2 = 0;
30 sigjmp_buf env_get_ack;
31 sigjmp_buf env_wait_x;
32
33 #define IDX_TO_HWND(idx)  (0xfffe - (idx))
34 #define HWND_TO_IDX(wnd)  (0xfffe - (wnd))
35 #define DDE_WIN_INFO(win) ( main_block->windows[HWND_TO_IDX(win)] )
36 #define DDE_WIN2PROC(win) ( DDE_WIN_INFO(win).proc_idx )
37 #define DDE_IsRemoteWindow(win)  (  (win)<0xffff && (win)>=(0xffff-DDE_PROCS))
38 #define DDE_SEND 1
39 #define DDE_POST 2
40 #define DDE_ACK  3
41 #define DDE_MSG_SIZE   sizeof(MSG)
42 #define FREE_WND (WORD)(-2)
43 #define DELETED_WND (WORD)(-3)
44 #if defined(DEBUG_MSG) || defined(DEBUG_RUNTIME)
45 static char *msg_type[4]={"********", "DDE_SEND", "DDE_POST", "DDE_ACK"};
46 #endif
47
48 struct msg_dat {
49         struct msgbuf dat;
50         char filler[DDE_MSG_SIZE];
51 } ;
52
53 typedef struct fifo_element {
54         int value;
55         struct fifo_element *next;
56 } fifo_element;
57
58 struct fifo {
59         fifo_element *first;       /* first element in the fifo or NULL */
60         fifo_element *last;        /* last element in the fifo or NULL */
61 };
62 static struct fifo fifo = {NULL,NULL};
63
64 void dde_proc_delete(int proc_idx);
65
66 void dde_proc_add_fifo(int val)
67 {
68   fifo_element *created;
69
70   created= (fifo_element*) malloc( sizeof(fifo_element) );
71   created->value = val;
72   created->next = NULL;
73   
74   if (fifo.first==NULL) 
75      fifo.first= created;
76   else 
77      fifo.last->next= created;
78   fifo.last = created;
79 }
80
81 /* get an item from the fifo, and return it.
82  * If fifo is empty, return -1
83  */
84 int dde_proc_shift_fifo()
85 {
86   int val;
87   fifo_element *deleted;
88   
89   if (fifo.first == NULL)
90      return -1;
91   
92   deleted= fifo.first;
93   val= deleted->value;
94   fifo.first= deleted->next;
95   if (fifo.first == NULL)
96      fifo.last= NULL;
97
98   free(deleted);
99   return val;
100 }
101
102 static void print_dde_message(char *desc, MSG *msg);
103
104 /* This should be run only when main_block is first allocated.  */
105 void dde_proc_init(dde_proc proc)
106 {
107   int proc_num;
108
109   for (proc_num=0 ; proc_num<DDE_PROCS ; proc_num++, proc++) {
110      proc->msg=-1;
111      proc->sem=-1;
112      proc->shmid=-1;
113      proc->pid=-1;
114   }
115 }
116
117 /* add current process to the list of processes */
118 void dde_proc_add(dde_proc procs)
119 {
120   dde_proc proc;
121   int proc_idx;
122   dprintf_dde(stddeb,"dde_proc_add(..)\n");
123   shm_write_wait(main_block->sem);
124
125   /* find free proc_idx and allocate it */
126   for (proc_idx=0, proc=procs ; proc_idx<DDE_PROCS ; proc_idx++, proc++)
127      if (proc->pid==-1)
128         break;                     /* found! */
129
130   if (proc_idx<DDE_PROCS) {        /* got here beacuse a free was found ? */
131      dde_msg_setup(&proc->msg);
132      proc->pid=getpid();
133      curr_proc_idx=proc_idx;
134      shm_sem_init(&proc->sem);
135   }
136   else  {
137      fflush(stdout);
138      fprintf(stderr,"dde_proc_add: Can't allocate process\n");
139   }
140   shm_write_signal(main_block->sem);
141 }
142
143 /* wait for dde - acknowledge message - or timout */
144 static BOOL get_ack()
145 {
146     struct timeval timeout;
147     int size;
148     struct msg_dat ack_buff;
149
150     /* timeout after exactly one seconf */
151     timeout.tv_sec = 1;
152     timeout.tv_usec = 0;
153
154     sigsetjmp(env_get_ack, 1);
155     /* get here after normal execution, or after siglongjmp */
156
157     do {                           /* loop to wait for DDE_ACK */
158        had_SIGUSR2=0;
159        stop_wait_op=CONT;          /*  sensitive code: disallow siglongjmp */
160        size= msgrcv( main_block->proc[curr_proc_idx].msg , &ack_buff.dat,
161                      1, DDE_ACK, IPC_NOWAIT);
162        if (size>=0) {
163           dprintf_msg(stddeb,"get_ack: received DDE_ACK message\n");
164           return TRUE;
165        }
166        if (DDE_GetRemoteMessage()) {
167              had_SIGUSR2=1;  /* might have recieved SIGUSR2 */
168        }
169        stop_wait_op=STOP_WAIT_ACK; /* allow siglongjmp */
170
171     } while (had_SIGUSR2);         /* loop if SIGUSR2 was recieved */
172
173     /* siglongjmp should be enabled at this moment */
174     select( 0, NULL, NULL, NULL, &timeout );
175     stop_wait_op=CONT;             /* disallow further siglongjmp */
176
177     /* timeout !! (otherwise there would have been a siglongjmp) */
178     return FALSE;
179 }
180
181 /* Transfer one message to a given process */
182 static BOOL DDE_DoOneMessage (int proc_idx, int size, struct msgbuf *msgbuf)
183 {
184   dde_proc proc= &main_block->proc[ proc_idx ];
185
186
187   if (proc_idx == curr_proc_idx)
188      return FALSE;
189
190   if (kill(proc->pid,0) < 0) {
191      /* pid does not exist, or not our */
192      dde_proc_delete(proc_idx);
193      return FALSE;
194   }
195
196   if (debugging_dde) {
197      MSG *msg=(MSG*) &msgbuf->mtext;
198      char *title;
199      if (msgbuf->mtype==DDE_SEND)
200         title="sending dde:";
201      else if (msgbuf->mtype==DDE_POST)
202         title="posting dde:";
203      else
204         title=NULL;
205      if (title)
206          print_dde_message(title, msg);
207      else
208        fprintf(stddeb,"Unknown message type=0x%lx\n",msgbuf->mtype);
209   }
210   dprintf_msg(stddeb,
211               "DDE_DoOneMessage: to proc_idx=%d (pid=%d), queue=%u\n",
212               proc_idx, proc->pid, (unsigned)proc->msg);
213   if ( proc->msg != -1) {
214      dprintf_msg(stddeb, "DDE_DoOneMessage: doing...(type=%s)\n",
215                  msg_type[msgbuf->mtype]);
216      size=msgsnd (proc->msg, msgbuf, size, 0);
217
218      if (size<0) {
219          fflush(stdout);
220          perror("msgsnd");
221      }
222      kill(proc->pid,SIGUSR2);      /* tell the process there is a message */
223
224      dprintf_msg(stddeb,"DDE_DoOneMessage: "
225                  "Trying to get acknowledgment from msg queue=%d\n",
226                  proc->msg);
227      Yield();                   /* force task switch, and */
228                                 /* acknowledgment sending */
229      if (get_ack()) {
230         return TRUE;
231      } else {
232         fflush(stdout);
233         fprintf(stderr,"get_ack: DDE_DoOneMessage: timeout\n");
234         return FALSE;
235      }
236   }
237   else {
238      dprintf_msg(stddeb,"DDE_DoOneMessage: message not sent, "
239                  "target has no message queue\n");
240      return FALSE;
241   }
242 }
243
244 /* Do some sort of premitive hash table */
245 static HWND HWND_Local2Remote(HWND orig)
246 {
247   int dde_wnd_idx;
248   int deleted_idx= -1;
249   WND_DATA *tested;
250   WND_DATA *deleted= NULL;
251   int i;
252   
253   dde_wnd_idx= orig % DDE_WINDOWS;
254   for ( i=0 ; i < DDE_WINDOWS ; i++, dde_wnd_idx++) {
255     if (dde_wnd_idx >= DDE_WINDOWS)
256       dde_wnd_idx -= DDE_WINDOWS; /* wrap-around */
257     
258     tested= &main_block->windows[ dde_wnd_idx ];
259     if (tested->proc_idx == FREE_WND)
260       break;
261     
262     if (deleted == NULL && tested->proc_idx == DELETED_WND) {
263       deleted= tested;
264       deleted_idx= dde_wnd_idx;
265     } else if (tested->wnd == orig && tested->proc_idx == curr_proc_idx) {
266       return IDX_TO_HWND(dde_wnd_idx);
267     }
268   }
269   if (deleted != NULL)  {       /* deleted is preferable */
270     /* free item, allocate it */
271     deleted->proc_idx= curr_proc_idx;
272     deleted->wnd = orig;
273     return IDX_TO_HWND(deleted_idx);
274   }
275   if (tested->proc_idx == FREE_WND) {
276     tested->proc_idx= curr_proc_idx;
277     tested->wnd = orig;
278     return IDX_TO_HWND(dde_wnd_idx);
279   }
280
281   fprintf(stderr,
282           "HWND_Local2Remote: Can't map any more windows to DDE windows\n");
283   return 0;                     
284 }
285
286 static BOOL DDE_DoMessage( MSG *msg, int type )
287 {
288   int proc_idx;
289
290   MSG *remote_message;
291   struct msg_dat msg_dat;
292   BOOL success;
293   
294   if (msg->wParam == 0)
295       return FALSE;
296   
297   if (main_block==NULL) {
298     if (msg->message >=  WM_DDE_FIRST && msg->message <= WM_DDE_LAST) 
299       DDE_IPC_init();
300     else 
301       return FALSE;
302   }
303
304
305   if (msg->wParam == (HWND)-1)
306      return FALSE;
307
308   if ( ! DDE_IsRemoteWindow(msg->hwnd) && msg->hwnd!= (HWND)-1)
309      return FALSE;
310
311   dprintf_msg(stddeb, "%s: DDE_DoMessage(hwnd=0x%x,msg=0x%x,..)\n",
312               msg_type[type], (int)msg->hwnd,(int)msg->message);
313
314
315   dprintf_msg(stddeb,
316               "DDE_DoMessage(hwnd=0x%x,msg=0x%x,..) // HWND_BROADCAST !\n",
317               (int)msg->hwnd,(int)msg->message);
318   remote_message=(void*)&msg_dat.dat.mtext;
319   
320   memcpy(remote_message, msg, sizeof(*msg));
321   remote_message->wParam= HWND_Local2Remote(msg->wParam);
322   if (remote_message->wParam == 0)
323     return FALSE;
324   
325   msg_dat.dat.mtype=type;
326
327   if (msg->hwnd == (HWND)-1) {
328      success= FALSE;
329      for ( proc_idx=0; proc_idx < DDE_PROCS ; proc_idx++) {
330         if (proc_idx == curr_proc_idx)
331            continue;
332         if (main_block->proc[ proc_idx ].msg != -1)
333            success|=DDE_DoOneMessage(proc_idx, DDE_MSG_SIZE, &msg_dat.dat);
334      }
335      return success;
336   } else {
337      return DDE_DoOneMessage(DDE_WIN2PROC(msg->hwnd), DDE_MSG_SIZE,
338                              &msg_dat.dat);
339   }
340 }
341
342 BOOL DDE_SendMessage( MSG *msg)
343 {
344   return DDE_DoMessage(msg, DDE_SEND);
345 }
346
347 BOOL DDE_PostMessage( MSG *msg)
348 {
349   return DDE_DoMessage(msg, DDE_POST);
350 }
351
352
353 void dde_proc_send_ack(HWND wnd, BOOL val) {
354    int proc,msg;
355
356    static struct msgbuf msg_ack={DDE_ACK,{'0'}};
357
358    proc=DDE_WIN2PROC(wnd);
359    msg=main_block->proc[proc].msg;
360    dprintf_msg(stddeb,"DDE_GetRemoteMessage: sending ACK "
361                "to wnd=%4x, proc=%d,msg=%d, pid=%d\n",wnd,proc,msg,
362                main_block->proc[proc].pid
363      );
364
365    msg_ack.mtext[0]=val;
366    msgsnd (msg, &msg_ack, 1, 0);
367    kill(main_block->proc[proc].pid, SIGUSR2);
368 }
369
370 /* return true (non zero) if had a remote message */
371 #undef DDE_GetRemoteMessage
372
373 int DDE_GetRemoteMessage()
374 {
375   static int nesting=0;            /* to avoid infinite recursion */
376
377   MSG *remote_message;
378   int size;
379   struct msg_dat msg_dat;
380   BOOL was_sent;                   /* sent/received */
381   BOOL passed;
382   HWND hwnd;
383   WND   *window;
384
385   if (curr_proc_idx==-1)           /* do we have DDE initialized ? */
386      return 0;
387
388   if (nesting>10) {
389      fflush(stdout);
390      fprintf(stderr,"DDE_GetRemoteMessage: suspecting infinite recursion, exiting");
391      return 0;
392   }
393
394   remote_message=(void*)&msg_dat.dat.mtext;
395
396   /* test for SendMessage */
397   size= msgrcv( main_block->proc[curr_proc_idx].msg , &msg_dat.dat,
398                 DDE_MSG_SIZE, DDE_SEND, IPC_NOWAIT);
399
400   if (size==DDE_MSG_SIZE) {        /* is this a correct message (if any) ?*/
401      was_sent=TRUE;
402      dprintf_msg(stddeb,
403                  "DDE:receive sent message. msg=%04x wPar=%04x"
404                  " lPar=%08lx\n",
405                  remote_message->message, remote_message->wParam,
406                  remote_message->lParam);
407   } else {
408      size= msgrcv( main_block->proc[curr_proc_idx].msg , &msg_dat.dat,
409                    DDE_MSG_SIZE, DDE_POST, IPC_NOWAIT);
410
411      if (size==DDE_MSG_SIZE) {     /* is this a correct message (if any) ?*/
412         was_sent=FALSE;
413         dprintf_msg(stddeb,
414                     "DDE:receive posted message. "
415                     "msg=%04x wPar=%04x lPar=%08lx\n",
416                     remote_message->message, remote_message->wParam,
417                     remote_message->lParam);
418      }
419      else
420         return 0;                  /* no DDE message found */
421   }
422
423   /* At this point we are sure that there is a DDE message,
424    * was_sent is TRUE is the message was sent, and false if it was posted
425    */
426
427   nesting++;
428
429   if (debugging_dde) {
430      char *title;
431      if (was_sent)
432         title="receive sent dde:";
433      else
434         title="receive posted dde:";
435      print_dde_message(title, remote_message);
436   }
437
438   if (remote_message->hwnd != (HWND) -1 ) {
439     HWND dde_window= DDE_WIN_INFO(remote_message->hwnd).wnd;
440      /* we should know exactly where to send the message (locally)*/
441      if (was_sent) {
442         dprintf_dde(stddeb,
443                     "SendMessage(wnd=0x%04x, msg=0x%04x, wPar=0x%04x,"
444                     "lPar=0x%08x\n",
445                     dde_window, remote_message->message,
446                     remote_message->wParam, (int)remote_message->lParam);
447
448         /* execute the recieved message */
449         passed= SendMessage(dde_window, remote_message->message,
450                             remote_message->wParam, remote_message->lParam);
451
452         /* Tell the sended, that the message is here */
453         dde_proc_send_ack(remote_message->wParam, passed);
454      }
455      else {
456         passed= PostMessage(dde_window, remote_message->message,
457                             remote_message->wParam, remote_message->lParam);
458         if (passed == FALSE) {
459            /* Tell the sender, that the message is here, and failed */
460             dde_proc_send_ack(remote_message->wParam, FALSE);
461         }
462         else {
463            /* ack will be sent later, at the first peek/get message  */
464            dde_proc_add_fifo(remote_message->wParam);
465         }
466      }
467      nesting--;
468      return 1;
469   }
470
471   /* iterate through all the windows */
472   for (hwnd = GetTopWindow(GetDesktopWindow());
473        hwnd && (window = WIN_FindWndPtr(hwnd))!=NULL ;
474        hwnd = window->hwndNext) {
475      if (window->dwStyle & WS_POPUP || window->dwStyle & WS_CAPTION) {
476         if (was_sent)
477            SendMessage( hwnd, remote_message->message,
478                         remote_message->wParam, remote_message->lParam );
479         else
480            PostMessage( hwnd, remote_message->message,
481                      remote_message->wParam, remote_message->lParam );
482      } /* if */
483   } /* for */
484
485   /* replay with DDE_ACK after broadcasting in DDE_GetRemoteMessage */
486   dde_proc_send_ack(remote_message->wParam, TRUE);
487
488   nesting--;
489   return 1;
490 }
491
492 int dde_reschedule()
493 {
494     int ack_wnd;
495         
496     ack_wnd= dde_proc_shift_fifo();
497     if (ack_wnd != -1) {
498         dde_proc_send_ack(ack_wnd, TRUE);
499         usleep(10000);          /* force unix task switch */
500         return 1;
501     }
502     return 0;
503 }
504 void dde_msg_setup(int *msg_ptr)
505 {
506   *msg_ptr= msgget (IPC_PRIVATE, IPC_CREAT | 0700);
507   if (*msg_ptr==-1)
508      perror("dde_msg_setup fails to get message queue");
509 }
510
511 /* do we have dde handling in the window ?
512  * If we have, atom usage will make this instance of wine set up
513  * it's IPC stuff.
514  */
515 void DDE_TestDDE(HWND hwnd)        
516 {
517
518   if (main_block != NULL)
519      return;
520   dprintf_msg(stddeb,"DDE_TestDDE(0x%04x)\n", hwnd);
521   if (hwnd==0)
522       hwnd=-1;
523   /* just send a message to see how things are going */
524   SendMessage( hwnd, WM_DDE_INITIATE, 0, 0);
525 }
526
527 void dde_proc_delete(int proc_idx)
528 {
529   dde_proc_done(&main_block->proc[proc_idx]);
530 }
531 void stop_wait(int a)
532 {
533
534   had_SIGUSR2=1;
535   switch(stop_wait_op) {
536     case STOP_WAIT_ACK:
537       siglongjmp(env_get_ack,1);
538       break;  /* never reached */
539     case STOP_WAIT_X:
540       siglongjmp(env_wait_x,1);
541       break;  /* never reached */
542     case CONT:
543       /* do nothing */
544   }
545 }
546
547 static void print_dde_message(char *desc, MSG *msg)
548 {
549     extern const char *MessageTypeNames[];
550     extern int debug_last_handle_size;
551     WORD wStatus,hWord;
552     void *ptr;
553     DDEACK *ddeack;
554     DDEADVISE *ddeadvise;
555     DDEDATA *ddedata;
556     DDEPOKE *ddepoke;
557
558     if (is_dde_handle(msg->lParam & 0xffff) )
559         ptr=DDE_AttachHandle(msg->lParam&0xffff, NULL);
560     else
561         ptr =NULL;
562     wStatus=LOWORD(msg->lParam);
563     hWord=HIWORD(msg->lParam);
564
565     fprintf(stddeb,"%s", desc);
566     fprintf(stddeb,"%04x %04x==%s %04x %08lx ",
567             msg->hwnd, msg->message,MessageTypeNames[msg->message],
568             msg->wParam, msg->lParam);
569     switch(msg->message) {
570       case WM_DDE_INITIATE:
571       case WM_DDE_REQUEST:
572       case WM_DDE_EXECUTE:
573       case WM_DDE_TERMINATE:
574         /* nothing to do */
575         break;
576       case WM_DDE_ADVISE:
577         /* DDEADVISE: hOptions in WM_DDE_ADVISE message */
578         if (ptr) {
579            ddeadvise=ptr;
580            fprintf(stddeb,"fDeferUpd=%d,fAckReq=%d,cfFormat=0x%x",
581                    ddeadvise->fDeferUpd, ddeadvise->fAckReq,
582                    ddeadvise->cfFormat);
583         } else
584            fprintf(stddeb,"NO-DATA");
585         fprintf(stddeb," atom=0x%x",hWord);
586         break;
587
588       case WM_DDE_UNADVISE:
589         fprintf(stddeb,"format=0x%x, atom=0x%x",wStatus,hWord);
590         break;
591       case WM_DDE_ACK:
592         ddeack=(DDEACK*)&wStatus;
593         fprintf(stddeb,"bAppReturnCode=%d,fBusy=%d,fAck=%d",
594                 ddeack->bAppReturnCode, ddeack->fBusy, ddeack->fAck);
595         if (ddeack->fAck)
596            fprintf(stddeb,"(True)");
597         else
598            fprintf(stddeb,"(False)");
599         break;
600
601       case WM_DDE_DATA:
602         if (ptr) {
603            ddedata=ptr;
604            fprintf(stddeb,"fResponse=%d,fRelease=%d,"
605                    "fAckReq=%d,cfFormat=0x%x,value=\"%.*s\"",
606                    ddedata->fResponse, ddedata->fRelease,
607                    ddedata->fAckReq, ddedata->cfFormat,
608                    debug_last_handle_size- (int)sizeof(*ddedata)+1,
609                    ddedata->Value);
610         } else
611            fprintf(stddeb,"NO-DATA");
612         fprintf(stddeb," atom=0x%04x",hWord);
613         break;
614
615       case WM_DDE_POKE:
616         if (ptr) {
617            ddepoke=ptr;
618            fprintf(stddeb,"fRelease=%d,cfFormat=0x%x,value[0]='%c'",
619                    ddepoke->fRelease, ddepoke->cfFormat, ddepoke->Value[0]);
620         } else
621            fprintf(stddeb,"NO-DATA");
622         fprintf(stddeb," atom=0x%04x",hWord);
623         break;
624     }
625     fprintf(stddeb,"\n");
626 }
627
628 void dde_proc_done(dde_proc proc)
629 {
630   if (proc->msg != -1)
631      msgctl(proc->msg, IPC_RMID, NULL);
632   proc->msg=-1;
633   proc->pid=-1;
634   shm_delete_chain(&proc->shmid);
635   shm_sem_done(&proc->sem);
636 }
637
638 /* delete entry, if old junk */
639 void dde_proc_refresh(dde_proc proc)
640 {
641   if (proc->pid == -1)            
642      return;
643   
644   if (kill(proc->pid, 0) != -1)
645      return;
646
647   /* get here if entry non empty, and the process does not exist */
648   dde_proc_done(proc);
649 }
650
651 void dde_wnd_setup()
652 {
653   int i;
654
655   for (i=0 ; i < DDE_WINDOWS ; i++)
656     main_block->windows[i].proc_idx = FREE_WND;
657 }
658
659 static BOOL DDE_ProcHasWindows(int proc_idx)
660 {
661   WND_DATA *tested;
662   int i;
663   
664   for ( i=0 ; i < DDE_WINDOWS ; i++) {
665     tested= &main_block->windows[ i ];
666     
667     if (tested->proc_idx == proc_idx) 
668       return TRUE;
669   }
670   return FALSE;
671 }
672 /* Look for hwnd in the hash table of DDE windows,
673  * Delete it from there. If there are no more windows for this
674  * process, remove the process from the DDE data-structure.
675  * If there are no more processes - delete the whole DDE struff.
676  *
677  * This is inefficient, but who cares for the efficiency of this rare
678  * operation... 
679  */
680 void DDE_DestroyWindow(HWND hwnd)
681 {
682   int dde_wnd_idx;
683   WND_DATA *tested;
684   int i;
685   
686   if (main_block == NULL)
687     return;
688   
689   dde_wnd_idx= hwnd % DDE_WINDOWS;
690   
691   for ( i=0 ; i < DDE_WINDOWS ; i++, dde_wnd_idx++) {
692     if (dde_wnd_idx >= DDE_WINDOWS)
693       dde_wnd_idx -= DDE_WINDOWS; /* wrap-around */
694     
695     tested= &main_block->windows[ dde_wnd_idx ];
696     if (tested->proc_idx == FREE_WND)
697       return;                   /* No window will get deleted here */
698     
699     if (tested->wnd == hwnd && tested->proc_idx == curr_proc_idx) {
700       dde_reschedule();
701       tested->proc_idx= DELETED_WND;
702       if (DDE_ProcHasWindows( curr_proc_idx ))
703         return;
704       while (dde_reschedule())  /* make sure there are no other */
705                                 /* processes waiting for acknowledgment */
706         ;
707       dde_proc_delete( curr_proc_idx );
708       if (DDE_no_of_attached() == 1)
709         shm_delete_all(-1);
710       else {
711         shmdt( (void *) main_block);
712         main_block= NULL;
713       }
714       return;
715     }
716   }
717 }
718