comparison src/win32.c @ 2526:902d5bd9b75c

[xemacs-hg @ 2005-01-28 02:36:11 by ben] Support symlinks under Windows nt.c, fileio.c: Fix sync comments. config.h.in, dired-msw.c, emacs.c, event-msw.c, fileio.c, glyphs.c, lisp.h, nt.c, process-nt.c, realpath.c, sound.c, symsinit.h, sysdep.c, sysfile.h, syswindows.h, win32.c: Add support for treating shortcuts under Windows as symbolic links. Enabled with mswindows-shortcuts-are-links (t by default). Rewrite lots of places to use PATHNAME_CONVERT_OUT, which is moved to sysfile.h. Add PATHNAME_RESOLVE_LINKS, which only does things under Windows. Add profiling section for expand_file_name calls. nt.c, sysdep.c: Unicode-ize. realpath.c: Renamed from readlink_and_correct_case. Fix some problems with Windows implementation due to incorrect understanding of workings of the function. sound.c, ntplay.c, sound.h: Rename play_sound_file to nt_play_sound_file and pass internally-formatted data to it to avoid converting out and back again. text.h: is_c -> is_ascii.
author ben
date Fri, 28 Jan 2005 02:36:28 +0000
parents 3d8143fc88e1
children b3ea9c582280
comparison
equal deleted inserted replaced
2525:52f00344a629 2526:902d5bd9b75c
21 #include <config.h> 21 #include <config.h>
22 #include "lisp.h" 22 #include "lisp.h"
23 23
24 #include "buffer.h" 24 #include "buffer.h"
25 #include "console-msw.h" 25 #include "console-msw.h"
26 #include "hash.h"
27 #include "profile.h"
26 28
27 #include "sysfile.h" 29 #include "sysfile.h"
28 #include "sysproc.h" 30 #include "sysproc.h"
29 #include "syssignal.h" 31 #include "syssignal.h"
30 #include "systime.h" 32 #include "systime.h"
44 46
45 /* Control conversion of upper case file names to lower case. 47 /* Control conversion of upper case file names to lower case.
46 nil means no, t means yes. */ 48 nil means no, t means yes. */
47 Lisp_Object Vmswindows_downcase_file_names; 49 Lisp_Object Vmswindows_downcase_file_names;
48 50
51 struct hash_table *mswindows_read_link_hash;
52
49 int mswindows_windows9x_p; 53 int mswindows_windows9x_p;
54 Boolint mswindows_shortcuts_are_symlinks;
50 55
51 pfSwitchToThread_t xSwitchToThread; 56 pfSwitchToThread_t xSwitchToThread;
52 57
53 pfNetUserEnum_t xNetUserEnum; 58 pfNetUserEnum_t xNetUserEnum;
54 pfNetApiBufferFree_t xNetApiBufferFree; 59 pfNetApiBufferFree_t xNetApiBufferFree;
339 Extbyte *path = NULL; 344 Extbyte *path = NULL;
340 Extbyte *doc = NULL; 345 Extbyte *doc = NULL;
341 346
342 if (STRINGP (operation)) 347 if (STRINGP (operation))
343 LISP_STRING_TO_TSTR (operation, opext); 348 LISP_STRING_TO_TSTR (operation, opext);
349 /* #### What about path names, which may be links? */
344 if (STRINGP (parameters)) 350 if (STRINGP (parameters))
345 LISP_STRING_TO_TSTR (parameters, parmext); 351 LISP_STRING_TO_TSTR (parameters, parmext);
346 if (STRINGP (current_dir)) 352 if (STRINGP (current_dir))
347 LOCAL_FILE_FORMAT_TO_TSTR (current_dir, path); 353 LOCAL_FILE_FORMAT_TO_TSTR (current_dir, path);
348 if (STRINGP (document)) 354 if (STRINGP (document))
401 LOCAL_TO_WIN32_FILE_FORMAT (p, p); 407 LOCAL_TO_WIN32_FILE_FORMAT (p, p);
402 return build_intstring (p); 408 return build_intstring (p);
403 } 409 }
404 #endif 410 #endif
405 411
412 struct read_link_hash
413 {
414 Ibyte *resolved;
415 DWORD ticks;
416 };
417
418 static Ibyte *
419 mswindows_read_link_1 (const Ibyte *fname)
420 {
421 #ifdef NO_CYGWIN_COM_SUPPORT
422 return NULL;
423 #else
424 Ibyte *retval = NULL;
425 Extbyte *fnameext;
426 HANDLE fh;
427 struct read_link_hash *rlh;
428 DWORD ticks;
429
430 /* The call below to resolve a link is rather time-consuming.
431 I tried implementing a simple cache based on creation and write time
432 of the file, but that didn't help enough -- maybe 30% faster but still
433 a lot of time spent here. So just do something cheesy and don't
434 check again if we've recently (< a second) done so. */
435
436 if (!mswindows_read_link_hash)
437 mswindows_read_link_hash = make_string_hash_table (1000);
438 C_STRING_TO_TSTR (fname, fnameext);
439
440 /* See if we can find a cached value. */
441
442 /* The intermediate cast fools gcc into not outputting strict-aliasing
443 complaints */
444 ticks = GetTickCount ();
445 if (!gethash (fname, mswindows_read_link_hash,
446 (const void **) (void *) &rlh))
447 {
448 rlh = xnew_and_zero (struct read_link_hash);
449 puthash (qxestrdup (fname), rlh, mswindows_read_link_hash);
450 }
451 else if (ticks - rlh->ticks < 1000)
452 {
453 return rlh->resolved ? qxestrdup (rlh->resolved) : NULL;
454 }
455
456 rlh->ticks = ticks;
457
458 /* Retrieve creation/write time of link file. */
459
460 /* No access rights required to get info. */
461 if ((fh = qxeCreateFile (fnameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL))
462 == INVALID_HANDLE_VALUE)
463 {
464 CloseHandle (fh);
465 return NULL;
466 }
467
468 CloseHandle (fh);
469
470 /* ####
471
472 Note the following in the docs:
473
474 Note: The IShellLink interface has an ANSI version
475 (IShellLinkA) and a Unicode version (IShellLinkW). The
476 version that will be used depends on whether you compile
477 for ANSI or Unicode. However, Microsoft® Windows 95 and
478 Microsoft® Windows 98 only support IShellLinkA.
479
480 We haven't yet implemented COM support in the
481 Unicode-splitting library. I don't quite understand how
482 COM works yet, but it looks like what's happening is
483 that the ShellLink class implements both the IShellLinkA
484 and IShellLinkW interfaces. To make this work at
485 run-time, we have to do something like this:
486
487 -- define a new interface qxeIShellLink that uses
488 Extbyte * instead of LPSTR or LPWSTR. (not totally
489 necessary since Extbyte * == LPSTR).
490
491 -- define a new class qxeShellLink that implements
492 qxeIShellLink. the methods on this class need to create
493 a shadow ShellLink object to do all the real work, and
494 call the corresponding function from either the
495 IShellLinkA or IShellLinkW interfaces on this object,
496 depending on whether XEUNICODE_P is defined.
497
498 -- with appropriate preprocessor magic, of course, we
499 could make things appear transparent; but we've decided
500 not to do preprocessor magic for the moment.
501 */
502
503 /* #### Not Unicode-split for the moment; we have to do it
504 ourselves. */
505 if (XEUNICODE_P)
506 {
507 IShellLinkW *psl;
508
509 if (CoCreateInstance (
510 XECOMID (CLSID_ShellLink),
511 NULL,
512 CLSCTX_INPROC_SERVER,
513 XECOMID (IID_IShellLinkW),
514 &VOIDP_CAST (psl)) == S_OK)
515 {
516 IPersistFile *ppf;
517
518 if (XECOMCALL2 (psl, QueryInterface,
519 XECOMID (IID_IPersistFile),
520 &VOIDP_CAST (ppf)) == S_OK)
521 {
522 Extbyte *fname_unicode;
523 WIN32_FIND_DATAW wfd;
524 LPWSTR resolved = alloca_array (WCHAR, PATH_MAX_EXTERNAL + 1);
525
526 /* Always Unicode. Not obvious from the
527 IPersistFile documentation, but look under
528 "Shell Link" for example code. */
529 fname_unicode = fnameext;
530
531 if (XECOMCALL2 (ppf, Load,
532 (LPWSTR) fname_unicode,
533 STGM_READ) == S_OK &&
534 /* #### YUCK! Docs read
535
536 cchMaxPath
537
538 Maximum number of bytes to copy to the buffer pointed
539 to by the pszFile parameter.
540
541 But "cch" means "count of characters", not bytes.
542 I'll assume the doc writers messed up and the
543 programmer was correct. Also, this approach is safe
544 even if it's actually the other way around. */
545 #if defined (CYGWIN_HEADERS) && W32API_INSTALLED_VER < W32API_VER(2,2)
546 /* Another Cygwin prototype error,
547 fixed in v2.2 of w32api */
548 XECOMCALL4 (psl, GetPath, (LPSTR) resolved,
549 PATH_MAX_EXTERNAL, &wfd, 0)
550 #else
551 XECOMCALL4 (psl, GetPath, resolved,
552 PATH_MAX_EXTERNAL, &wfd, 0)
553 #endif
554 == S_OK)
555 TSTR_TO_C_STRING_MALLOC (resolved, retval);
556
557 XECOMCALL0 (ppf, Release);
558 }
559
560 XECOMCALL0 (psl, Release);
561 }
562 }
563 else
564 {
565 IShellLinkA *psl;
566
567 if (CoCreateInstance (
568 XECOMID (CLSID_ShellLink),
569 NULL,
570 CLSCTX_INPROC_SERVER,
571 XECOMID (IID_IShellLinkA),
572 &VOIDP_CAST (psl)) == S_OK)
573 {
574 IPersistFile *ppf;
575
576 if (XECOMCALL2 (psl, QueryInterface,
577 XECOMID (IID_IPersistFile),
578 &VOIDP_CAST (ppf)) == S_OK)
579 {
580 Extbyte *fname_unicode;
581 WIN32_FIND_DATAA wfd;
582 LPSTR resolved = alloca_array (CHAR, PATH_MAX_EXTERNAL + 1);
583
584 /* Always Unicode. Not obvious from the
585 IPersistFile documentation, but look under
586 "Shell Link" for example code. */
587 C_STRING_TO_EXTERNAL (fname, fname_unicode,
588 Qmswindows_unicode);
589
590 if (XECOMCALL2 (ppf, Load,
591 (LPWSTR) fname_unicode,
592 STGM_READ) == S_OK
593 && XECOMCALL4 (psl, GetPath, resolved,
594 PATH_MAX_EXTERNAL, &wfd, 0) == S_OK)
595 TSTR_TO_C_STRING_MALLOC (resolved, retval);
596
597 XECOMCALL0 (ppf, Release);
598 }
599
600 XECOMCALL0 (psl, Release);
601 }
602 }
603
604 /* Cache newly found value */
605 if (rlh->resolved)
606 xfree (rlh->resolved, Ibyte *);
607 rlh->resolved = retval ? qxestrdup (retval) : NULL;
608
609 return retval;
610 #endif /* NO_CYGWIN_COM_SUPPORT */
611 }
612
613 /* Resolve a file that may be a shortcut. Accepts either a file ending
614 with .LNK or without the ending. If a shortcut is found, returns
615 a value that you must xfree(); otherwise NULL. */
616
617 Ibyte *
618 mswindows_read_link (const Ibyte *fname)
619 {
620 int len = qxestrlen (fname);
621 if (len > 4 && !qxestrcasecmp_ascii (fname + len - 4, ".LNK"))
622 return mswindows_read_link_1 (fname);
623 else
624 {
625 DECLARE_EISTRING (name2);
626
627 eicpy_rawz (name2, fname);
628 eicat_ascii (name2, ".LNK");
629 return mswindows_read_link_1 (eidata (name2));
630 }
631 }
632
633
406 #if defined (WIN32_NATIVE) || defined (CYGWIN_BROKEN_SIGNALS) 634 #if defined (WIN32_NATIVE) || defined (CYGWIN_BROKEN_SIGNALS)
407 635
408 /* setitimer() does not exist on native MS Windows, and appears broken 636 /* setitimer() does not exist on native MS Windows, and appears broken
409 on Cygwin (random lockups when BROKEN_SIGIO is defined), so we 637 on Cygwin (random lockups when BROKEN_SIGIO is defined), so we
410 emulate in both cases by using multimedia timers. Furthermore, 638 emulate in both cases by using multimedia timers. Furthermore,
412 use the standard signalling mechanism -- so we have to emulate 640 use the standard signalling mechanism -- so we have to emulate
413 that, too. (But only for timeouts -- we have to use the standard 641 that, too. (But only for timeouts -- we have to use the standard
414 mechanism for SIGCHLD. Yuck.) 642 mechanism for SIGCHLD. Yuck.)
415 */ 643 */
416 644
417
418 /*--------------------------------------------------------------------*/ 645 /*--------------------------------------------------------------------*/
419 /* Signal support */ 646 /* Signal support */
420 /*--------------------------------------------------------------------*/ 647 /*--------------------------------------------------------------------*/
421 648
422 #define sigmask(nsig) (1U << nsig) 649 #define sigmask(nsig) (1U << nsig)
662 } 889 }
663 890
664 void 891 void
665 vars_of_win32 (void) 892 vars_of_win32 (void)
666 { 893 {
667 DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /* 894 DEFVAR_LISP ("mswindows-downcase-file-names",
895 &Vmswindows_downcase_file_names /*
668 Non-nil means convert all-upper case file names to lower case. 896 Non-nil means convert all-upper case file names to lower case.
669 This applies when performing completions and file name expansion. 897 This applies when performing completions and file name expansion.
670 */ ); 898 */ );
671 Vmswindows_downcase_file_names = Qnil; 899 Vmswindows_downcase_file_names = Qnil;
900
901 DEFVAR_BOOL ("mswindows-shortcuts-are-symlinks",
902 &mswindows_shortcuts_are_symlinks /*
903 Non-nil means shortcuts (.LNK files) are treated as symbolic links.
904 This works also for symlinks created under Cygwin, because they use .LNK
905 files to implement symbolic links.
906 */ );
907 mswindows_shortcuts_are_symlinks = 1;
672 } 908 }
673 909
674 void 910 void
675 init_win32 (void) 911 init_win32 (void)
676 { 912 {