comparison lib-src/winclient.c @ 5030:422b4b4fb2a6

Winclient updates
author Vin Shelton <acs@xemacs.org>
date Thu, 11 Feb 2010 19:33:50 -0500
parents 61aff09a7589
children 308d34e9f07d
comparison
equal deleted inserted replaced
5029:acf7d1bc0490 5030:422b4b4fb2a6
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <stdio.h> 31 #include <stdio.h>
32 #include <ctype.h> 32 #include <ctype.h>
33 #include <errno.h> 33 #include <errno.h>
34 34
35 #ifdef __CYGWIN__
36 #include <stdlib.h>
37 #include <unistd.h>
38 #endif
39
35 static void error (const char* s1, const char* s2); 40 static void error (const char* s1, const char* s2);
36 static void fatal (const char *s1, const char *s2); 41 static void fatal (const char *s1, const char *s2);
37 static void * xmalloc (size_t size); 42 static void * xmalloc (size_t size);
38 static char * getNextArg (const char **ptr, unsigned *len); 43 static char * getNextArg (const char **ptr, unsigned *len);
39 44
40 /* -- Post-Include Defines -------------------------------------------------- */ 45 /* -- Post-Include Defines -------------------------------------------------- */
41 46
42 /* Timeouts & delays */ 47 /* Timeouts & delays */
43 #define CONNECT_RETRIES 10 48 #define CONNECT_RETRIES 20
44 #define CONNECT_DELAY 500 /* ms */ 49 #define CONNECT_DELAY 500 /* ms */
45 #define TRANSACTION_TIMEOUT 5000 /* ms */ 50 #define TRANSACTION_TIMEOUT 5000 /* ms */
46 #define MAX_INPUT_IDLE_WAIT INFINITE /* ms */ 51 #define MAX_INPUT_IDLE_WAIT INFINITE /* ms */
47 52
48 /* DDE Strings */ 53 /* DDE Strings */
49 #define SERVICE_NAME "XEmacs" 54 #define SERVICE_NAME "XEmacs"
50 #define TOPIC_NAME "System" 55 #define TOPIC_NAME "System"
51 #define COMMAND_FORMAT "[open(\"%s%s\")]" 56 #define COMMAND_FORMAT "[open(\"%s%s\")]"
52 57
53 /* XEmacs program name */ 58 /* XEmacs program name */
54 #define PROGRAM_TO_RUN "xemacs.exe" 59 #define GENERIC_PROGRAM EMACS_PROGNAME ".exe"
60 #define VERSIONED_PROGRAM EMACS_PROGNAME "-" EMACS_VERSION ".exe"
55 61
56 /* -- Constants ------------------------------------------------------------- */ 62 /* -- Constants ------------------------------------------------------------- */
57 63
58 /* -- Global Variables ------------------------------------------------------ */ 64 /* -- Global Variables ------------------------------------------------------ */
59 65
105 int nCmdShow) 111 int nCmdShow)
106 { 112 {
107 HCONV hConv; 113 HCONV hConv;
108 int ret = 0; 114 int ret = 0;
109 UINT uiRet; 115 UINT uiRet;
110 116
111 /* Initialise the DDEML library */ 117 /* Initialise the DDEML library */
112 uiRet = DdeInitialize (&idInst, 118 uiRet = DdeInitialize (&idInst,
113 (PFNCALLBACK) ddeCallback, 119 (PFNCALLBACK) ddeCallback,
114 APPCMD_CLIENTONLY 120 APPCMD_CLIENTONLY
115 |CBF_FAIL_ALLSVRXACTIONS, 121 |CBF_FAIL_ALLSVRXACTIONS,
132 ret = parseCommandLine (hConv, lpCmdLine); 138 ret = parseCommandLine (hConv, lpCmdLine);
133 139
134 /* Close the conversation */ 140 /* Close the conversation */
135 closeConversation (hConv); 141 closeConversation (hConv);
136 } 142 }
137 143
138 DdeUninitialize (idInst); 144 DdeUninitialize (idInst);
139 145
140 return ret; 146 return ret;
141 } 147 }
142 148
162 MessageBox (NULL, "Could not create string handle for service.", 168 MessageBox (NULL, "Could not create string handle for service.",
163 "winclient", MB_ICONEXCLAMATION | MB_OK); 169 "winclient", MB_ICONEXCLAMATION | MB_OK);
164 170
165 goto error; 171 goto error;
166 } 172 }
167 173
168 /* Get the topic name */ 174 /* Get the topic name */
169 hszTopic = DdeCreateStringHandle (idInst, 175 hszTopic = DdeCreateStringHandle (idInst,
170 TOPIC_NAME, 176 TOPIC_NAME,
171 CP_WINANSI); 177 CP_WINANSI);
172 178
184 if (!hConv) 190 if (!hConv)
185 { 191 {
186 STARTUPINFO sti; 192 STARTUPINFO sti;
187 PROCESS_INFORMATION pi; 193 PROCESS_INFORMATION pi;
188 int n; 194 int n;
189 195
190 /* Try to start the program */ 196 /* Try to start the program */
191 ZeroMemory (&sti, sizeof (sti)); 197 ZeroMemory (&sti, sizeof (sti));
192 sti.cb = sizeof (sti); 198 sti.cb = sizeof (sti);
193 if (!CreateProcess (NULL, PROGRAM_TO_RUN, NULL, NULL, FALSE, 0, 199 if (!CreateProcess (NULL, GENERIC_PROGRAM, NULL, NULL, FALSE, 0,
200 NULL, NULL, &sti, &pi) &&
201 !CreateProcess (NULL, VERSIONED_PROGRAM, NULL, NULL, FALSE, 0,
194 NULL, NULL, &sti, &pi)) 202 NULL, NULL, &sti, &pi))
195 { 203 {
196 MessageBox (NULL, "Could not start process.", 204 MessageBox (NULL, "Could not start process.",
197 "winclient", MB_ICONEXCLAMATION | MB_OK); 205 "winclient", MB_ICONEXCLAMATION | MB_OK);
198 206
203 WaitForInputIdle (pi.hProcess, MAX_INPUT_IDLE_WAIT); 211 WaitForInputIdle (pi.hProcess, MAX_INPUT_IDLE_WAIT);
204 212
205 /* Close the handles */ 213 /* Close the handles */
206 CloseHandle (pi.hThread); 214 CloseHandle (pi.hThread);
207 CloseHandle (pi.hProcess); 215 CloseHandle (pi.hProcess);
208 216
209 /* Try to connect */ 217 /* Try to connect */
210 for (n = 0; n < CONNECT_RETRIES; n++) 218 for (n = 0; n < CONNECT_RETRIES; n++)
211 { 219 {
212 Sleep (CONNECT_DELAY); 220 Sleep (CONNECT_DELAY);
213 221
214 hConv = DdeConnect (idInst, hszService, hszTopic, NULL); 222 hConv = DdeConnect (idInst, hszService, hszTopic, NULL);
215 223
216 if (hConv) 224 if (hConv)
217 break; 225 break;
218 } 226 }
230 /* Release the string handles */ 238 /* Release the string handles */
231 DdeFreeStringHandle (idInst, hszService); 239 DdeFreeStringHandle (idInst, hszService);
232 DdeFreeStringHandle (idInst, hszTopic); 240 DdeFreeStringHandle (idInst, hszTopic);
233 241
234 return hConv; 242 return hConv;
235 243
236 error: 244 error:
237 if (hConv) 245 if (hConv)
238 DdeDisconnect (hConv); 246 DdeDisconnect (hConv);
239 if (hszService) 247 if (hszService)
240 DdeFreeStringHandle (idInst, hszService); 248 DdeFreeStringHandle (idInst, hszService);
266 int 274 int
267 doFile (HCONV hConv, LPSTR lpszFileName1, LPSTR lpszFileName2) 275 doFile (HCONV hConv, LPSTR lpszFileName1, LPSTR lpszFileName2)
268 { 276 {
269 char *buf = NULL; 277 char *buf = NULL;
270 unsigned len; 278 unsigned len;
271 279
272 /* Calculate the buffer length */ 280 /* Calculate the buffer length */
273 len = strlen (lpszFileName1) + strlen (lpszFileName2) 281 len = strlen (lpszFileName1) + strlen (lpszFileName2)
274 + strlen (COMMAND_FORMAT); 282 + strlen (COMMAND_FORMAT);
275 283
276 /* Allocate a buffer */ 284 /* Allocate a buffer */
277 buf = (char *) xmalloc (len); 285 buf = (char *) xmalloc (len);
278 286
279 if (!buf) 287 if (!buf)
280 { 288 {
284 return 1; 292 return 1;
285 } 293 }
286 294
287 /* Build the command */ 295 /* Build the command */
288 len = wsprintf (buf, COMMAND_FORMAT, lpszFileName1, lpszFileName2); 296 len = wsprintf (buf, COMMAND_FORMAT, lpszFileName1, lpszFileName2);
289
290 len++; 297 len++;
291 298
292 /* OK. We're connected. Send the message. */ 299 /* OK. We're connected. Send the message. */
293 DdeClientTransaction (buf, len, hConv, NULL, 300 DdeClientTransaction (buf, len, hConv, NULL,
294 0, XTYP_EXECUTE, TRANSACTION_TIMEOUT, NULL); 301 0, XTYP_EXECUTE, TRANSACTION_TIMEOUT, NULL);
295 302
296 free (buf); 303 free (buf);
297 304
298 return 0; 305 return 0;
299 } 306 }
300 307
301 /* 308 /*
302 * Name : getNextArg 309 * Name : getNextArg
317 p++; 324 p++;
318 325
319 /* If this is the end, return NULL */ 326 /* If this is the end, return NULL */
320 if (!*p) 327 if (!*p)
321 return NULL; 328 return NULL;
322 329
323 /* Remember where we are */ 330 /* Remember where we are */
324 start = p; 331 start = p;
325 332
326 /* Find the next whitespace character outside quotes */ 333 /* Find the next whitespace character outside quotes */
327 if (*p == '"') 334 if (*p == '"')
328 all_in_quotes = 1; 335 all_in_quotes = 1;
329 336
330 while (*p && !quit) 337 while (*p && !quit)
331 { 338 {
332 switch (*p) 339 switch (*p)
333 { 340 {
334 case '"': 341 case '"':
337 break; 344 break;
338 345
339 case '\\': 346 case '\\':
340 if (!in_quotes) 347 if (!in_quotes)
341 all_in_quotes = 0; 348 all_in_quotes = 0;
342 349
343 p++; 350 p++;
344 351
345 if (!*p) 352 if (!*p)
346 break; 353 break;
347 354
366 if (all_in_quotes) 373 if (all_in_quotes)
367 { 374 {
368 start++; 375 start++;
369 length -= 2; 376 length -= 2;
370 } 377 }
371 378
372 /* Copy */ 379 /* Copy */
373 buf = (char *) xmalloc (length + 1); 380 buf = (char *) xmalloc (length + 1);
374 381
375 if (!buf) 382 if (!buf)
376 return NULL; 383 return NULL;
377 384
378 strncpy (buf, start, length); 385 strncpy (buf, start, length);
379 buf[length] = '\0'; 386 buf[length] = '\0';
380 387
381 /* Return the pointer and length */ 388 /* Return the pointer and length */
382 *ptr = p; 389 *ptr = p;
403 WIN32_FIND_DATA wfd; 410 WIN32_FIND_DATA wfd;
404 411
405 /* Retrieve arguments */ 412 /* Retrieve arguments */
406 while ((arg = getNextArg ((const char**)&lpszCommandLine, &len)) != NULL) 413 while ((arg = getNextArg ((const char**)&lpszCommandLine, &len)) != NULL)
407 { 414 {
415 fullpath = NULL;
416 #ifdef __CYGWIN__
417 /* If the filename is not an absolute path,
418 add the current directory to the pathname */
419 if (*arg != '/')
420 {
421 len = pathconf(".", _PC_PATH_MAX);
422 fullpath = (char *) xmalloc (len+1);
423 if (!fullpath)
424 {
425 MessageBox (NULL, "Not enough memory.", "winclient",
426 MB_ICONEXCLAMATION | MB_OK);
427 ret = 1;
428 break;
429 }
430 if (!getcwd(fullpath, (size_t)len))
431 {
432 MessageBox (NULL, "Could not retrieve current directory.",
433 "winclient", MB_ICONEXCLAMATION | MB_OK);
434 ret = 1;
435 break;
436 }
437 /* Append trailing slash */
438 strcat(fullpath, "/");
439 ret = doFile (hConv, fullpath, arg);
440 }
441 else
442 {
443 /* The arg has already been expanded, so pass it as it is */
444 ret = doFile (hConv, "", arg);
445 }
446 #else
408 /* First find the canonical path name */ 447 /* First find the canonical path name */
409 fullpath = filepart = NULL; 448 fullpath = filepart = NULL;
410 pathlen = GetFullPathName (arg, 0, fullpath, &filepart); 449 pathlen = GetFullPathName (arg, 0, fullpath, &filepart);
411 450
412 fullpath = (char *) xmalloc (pathlen); 451 fullpath = (char *) xmalloc (pathlen);
413 452
414 if (!fullpath) 453 if (!fullpath)
415 { 454 {
416 MessageBox (NULL, "Not enough memory.", "winclient", 455 MessageBox (NULL, "Not enough memory.", "winclient",
417 MB_ICONEXCLAMATION | MB_OK); 456 MB_ICONEXCLAMATION | MB_OK);
418
419 ret = 1; 457 ret = 1;
420 free (arg);
421
422 break; 458 break;
423 } 459 }
424 460
425 GetFullPathName (arg, pathlen, fullpath, &filepart); 461 GetFullPathName (arg, pathlen, fullpath, &filepart);
426 462
446 } 482 }
447 while (FindNextFile (hFindFile, &wfd)); 483 while (FindNextFile (hFindFile, &wfd));
448 484
449 FindClose (hFindFile); 485 FindClose (hFindFile);
450 } 486 }
451 487 #endif
452 /* Release the path name buffers */ 488 /* Release the path name buffers */
453 free (fullpath); 489 if (fullpath)
490 free (fullpath);
454 free (arg); 491 free (arg);
455 492
456 if (ret) 493 if (ret)
457 break; 494 break;
458 } 495 }