VxDCall functions do not need to be 'register'.
[wine/multimedia.git] / ipc / shm_main_blk.c
blob3333e2b162d6b6c9224c1e829ffed0088aa0a885
1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
6 * File: shm_main_blk.c
7 * Purpose: Main Wine's shared memory block
8 ***************************************************************************
9 */
10 #ifdef CONFIG_IPC
12 #define inline inline
13 #include <sys/types.h>
14 #include <sys/sem.h>
15 #include <time.h>
16 #include <assert.h>
17 #include <unistd.h>
18 #include <errno.h>
19 #include <signal.h>
20 #include "debug.h"
21 #include "shm_fragment.h"
22 #include "shm_block.h"
23 #include "shm_main_blk.h"
24 #include "shm_semaph.h"
26 DEFAULT_DEBUG_CHANNEL(shm)
28 #define WineKey ( 'W'+((int)'i'<<8)+((int)'n'<<16)+((int)'e'<<24) )
29 #define SHM_KEY_RANGE 8
31 /* main block (set during initialization) */
32 struct shm_main_block *main_block=NULL;
33 static char *shm_header="Wine - Windows emulator DDE mechanism";
34 static int main_shm_id;
36 static void shm_main_refresh();
38 /* for debugging only */
39 static void print_perm(struct ipc_perm *perm)
41 printf("Permission:\n");
42 /* FIXME: not portable
43 printf("\tKey=%d, mode=%03o, sequence #=%d\n",
44 (int)perm->key,perm->mode, perm->seq);
46 printf("\towner: uid=%d, gid=%d ;" ,perm->uid, perm->gid);
47 printf(" creator: uid=%d, gid=%d\n",perm->cuid,perm->cgid);
50 /* for debugging only */
51 /* print_shm_info: print shared memory descriptor info */
52 static void print_shm_info(int shm_id)
54 struct shmid_ds ds;
55 shmctl(shm_id, IPC_STAT, &ds );
57 printf("shm_id=%d, Size=0x%08x , Number of attaches=%d\n",
58 shm_id, ds.shm_segsz, (int)ds.shm_nattch);
59 if (ds.shm_atime)
60 printf("Last attach=%s",ctime(&ds.shm_atime));
61 if (ds.shm_dtime)
62 printf("Last detach=%s",ctime(&ds.shm_dtime));
63 printf("Last change=%s",ctime(&ds.shm_ctime));
64 printf("pid: creator=%d, last operator=%d\n",
65 (int)ds.shm_cpid,(int)ds.shm_lpid);
66 print_perm( &ds.shm_perm);
70 int proc_exist(pid_t pid)
72 if ( kill(pid,0) == 0) /* dummy signal to test existence */
73 return 1;
74 else if (errno==ESRCH) /* "no such process" */
75 return 0;
76 else
77 return 1;
80 /* setup a new main shm block (only construct a shm block object). */
81 static void shm_setup_main_block()
83 TRACE(shm,"creating data structure\n");
84 main_block->build_lock=1;
85 strcpy(main_block->magic, shm_header);
87 shm_setup_block(&main_block->block,sizeof(*main_block),SHM_MINBLOCK);
89 dde_proc_init(main_block->proc);
90 ATOM_GlobalInit();
91 shm_sem_init(&main_block->sem);
93 /* main block set and data structure is stable now */
94 main_block->build_lock=0;
97 /* Delete everything related to main_block */
98 void shm_delete_all(int shmid)
100 int proc_idx;
102 if (shmid == -1)
103 shmid= main_shm_id;
105 shmctl( shmid, IPC_RMID, NULL);
107 for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
108 dde_proc_done( &main_block->proc[proc_idx] );
110 shm_sem_done(&main_block->sem);
111 shmdt( (void *) main_block);
112 main_block= NULL;
115 int DDE_no_of_attached()
117 struct shmid_ds shm_info;
119 if (shmctl(main_shm_id, IPC_STAT, &shm_info) == -1)
120 return -1;
122 return shm_info.shm_nattch;
125 ** Test if shm_id is MainBlock and attach it (if it is),
126 ** Return 1 if ok, 0 otherwise.
128 static int attach_MainBlock(int shm_id)
130 struct shmid_ds shm_info;
132 if (shmctl(shm_id, IPC_STAT, &shm_info) == -1)
133 return 0;
135 /* Make sure we don't work on somebody else's block */
136 if (shm_info.shm_perm.cuid != getuid()) { /* creator is not me */
137 WARN(shm, "Creator is not me!\n");
138 return 0;
141 TRACE(shm,"shared memory exist, attaching anywhere\n");
142 main_block=(struct shm_main_block *)shmat(shm_id, 0, 0);
143 if ( (int)main_block==-1) {
144 WARN(shm, "Attach failed\n");
145 return 0;
148 if (strcmp(main_block->magic, shm_header) != 0) {
149 TRACE(shm,"Detaching, wrong magic\n");
150 shmdt((void *)main_block);
151 return 0;
154 if (TRACE_ON(shm))
155 print_shm_info(shm_id);
157 /* Is it an old unused block ? */
158 if (shm_info.shm_nattch == 0) {
159 TRACE(shm,"No attaches, deleting old data\n");
160 shm_delete_all(shm_id);
161 return 0;
164 /* Wait for data structure to stabilize */
165 while (main_block->build_lock)
166 usleep(10000);
168 main_shm_id= shm_id;
170 shm_main_refresh();
171 return 1;
174 /* (Function used by the constructor)
175 * Try to get existing shared memory with key="Wine", size=SHM_MINBLOCK
176 * complete user permission.
177 * If such block is found - return true (1), else return false (0)
179 static int shm_locate_MainBlock(key_t shm_key)
181 int shm_id; /* Descriptor to this shared memory */
182 int i;
184 TRACE(shm,"trying to attach, key=0x%x\n",
185 shm_key);
186 for (i=0 ; i < SHM_KEY_RANGE ; i++) {
187 TRACE(shm,"iteration=%d\n", i);
189 shm_id= shmget ( shm_key+i, SHM_MINBLOCK ,0700);
191 if (shm_id != -1) {
192 if ( attach_MainBlock(shm_id) ) {
193 return 1; /* success! */
195 } else {
196 switch(errno) {
197 #ifdef EIDRM
198 case EIDRM: /* segment destroyed */
199 #endif
200 case EACCES: /* no user permision */
201 break;
203 case ENOMEM: /* no free memory */
204 case ENOENT: /* this key does not exist */
205 default :
206 WARN(shm,"shmget failed, errno=%d, %s\n",
207 errno, strerror(errno) );
208 return 0; /* Failed */
210 } /* if .. else */
211 } /* for */
212 return 0;
215 /* (Function used by the constructor)
216 * Try to allocate new shared memory with key="Wine", size=SHM_MINBLOCK
217 * with complete user permission.
218 * If allocation succeeds - return true (1), else return false (0)
220 static int shm_create_MainBlock(key_t MainShmKey)
222 int shm_id;
223 int flags= 0700 | IPC_CREAT | IPC_EXCL;
224 int i;
226 TRACE(shm,"creating shared memory\n");
228 /* try to allocate shared memory with key="Wine", size=SHM_MINBLOCK, */
229 /* complete user permission */
230 for (i=0 ; i < SHM_KEY_RANGE ; i++) {
231 shm_id= shmget ( (key_t) MainShmKey, SHM_MINBLOCK, flags);
232 if (shm_id != -1)
233 break;
235 if (shm_id == -1) {
236 WARN(shm, "failed to create shared memory\n");
237 return 0;
239 TRACE(shm,"shared memory created, attaching\n");
240 main_block=(struct shm_main_block*) shmat(shm_id, 0,0);
241 if (TRACE_ON(shm))
242 print_shm_info(shm_id);
243 main_shm_id= shm_id;
244 shm_setup_main_block();
245 dde_wnd_setup();
246 return 1;
250 /* link to the dde shared memory block */
251 /* RETURN: 0 on success, non zero on failure */
252 int shm_init(void)
254 if ( !shm_locate_MainBlock(WineKey)
255 && !shm_create_MainBlock(WineKey)) {
256 ERR(shm, "Failed to init main shm block\n");
257 exit(1);
260 dde_proc_add(main_block->proc);
261 return 0;
264 static void shm_main_refresh()
266 int proc_idx;
268 for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
269 dde_proc_refresh( &main_block->proc[proc_idx] );
272 #endif /* CONFIG_IPC */