OSDN Git Service

* shortcut.c: New file. Provides a C interface to reading of
authorcorinna <corinna>
Thu, 22 Feb 2001 12:56:36 +0000 (12:56 +0000)
committercorinna <corinna>
Thu, 22 Feb 2001 12:56:36 +0000 (12:56 +0000)
        Windows shortcuts to avoid compiler flag `-fvtable-thunks'.
        * shortcut.h: Ditto.
        * Makefile.in: Add shortcut.o to DLL_OFILES.
        * cygerrno.h: Provide a C interface to `geterrno_from_win_error' for
        using in shortcut.c.
        * errno.cc (geterrno_from_win_error): Define as extern "C".
        * path.cc (struct symlink_info): Remove methods `check_shortcut' and
        `check_sysfile'.
        (shortcut_header): Move to shortcut.c.
        (shortcut_initalized): Ditto.
        (create_shortcut_header): Ditto.
        (cmp_shortcut_header): Ditto.
        (symlink_info::check_shortcut): Ditto. Reorganize as a plain C function.
        (symlink_info::check_sysfile): Redefine as a global function using the
        same parameter list as `check_shortcut' for clearness.
        (symlink_info::check): Change parameter list for calls to
        `check_shortcut' and `check_sysfile'.

winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/cygerrno.h
winsup/cygwin/errno.cc
winsup/cygwin/path.cc
winsup/cygwin/shortcut.c [new file with mode: 0644]
winsup/cygwin/shortcut.h [new file with mode: 0644]

index c1521a5..283de14 100644 (file)
@@ -1,3 +1,24 @@
+Thu Feb 22 13:38:00 2001  Corinna Vinschen <corinna@vinschen.de>
+
+       * shortcut.c: New file. Provides a C interface to reading of
+       Windows shortcuts to avoid compiler flag `-fvtable-thunks'.
+       * shortcut.h: Ditto.
+       * Makefile.in: Add shortcut.o to DLL_OFILES.
+       * cygerrno.h: Provide a C interface to `geterrno_from_win_error' for
+       using in shortcut.c.
+       * errno.cc (geterrno_from_win_error): Define as extern "C".
+       * path.cc (struct symlink_info): Remove methods `check_shortcut' and
+       `check_sysfile'.
+       (shortcut_header): Move to shortcut.c.
+       (shortcut_initalized): Ditto.
+       (create_shortcut_header): Ditto.
+       (cmp_shortcut_header): Ditto.
+       (symlink_info::check_shortcut): Ditto. Reorganize as a plain C function.
+       (symlink_info::check_sysfile): Redefine as a global function using the
+       same parameter list as `check_shortcut' for clearness.
+       (symlink_info::check): Change parameter list for calls to
+       `check_shortcut' and `check_sysfile'.
+
 Thu Feb 22 12:04:00 2001  Corinna Vinschen <corinna@vinschen.de>
 
        * fhandler.cc (fhandler_disk_file::open): Use `inner_suffixes' when
index b665bd7..71f513a 100644 (file)
@@ -124,7 +124,8 @@ DLL_OFILES:=assert.o autoload.o cygheap.o dcrt0.o debug.o delqueue.o dir.o \
        miscfuncs.o mmap.o \
        net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o pthread.o regexp.o \
        regerror.o regsub.o registry.o resource.o scandir.o security.o select.o \
-       shared.o signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o \
+       shared.o \
+       shortcut.o signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o \
        sync.o syscalls.o sysconf.o syslog.o termios.o thread.o times.o tty.o \
        uinfo.o uname.o wait.o window.o \
        $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MT_SAFE_OBJECTS)
index dd40819..ad2fad7 100644 (file)
@@ -8,9 +8,20 @@ This software is a copyrighted work licensed under the terms of the
 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 details. */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __stdcall geterrno_from_win_error (DWORD code, int deferrno) __attribute__ ((regparm(2)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+
 void __stdcall seterrno_from_win_error (const char *file, int line, DWORD code) __attribute__ ((regparm(3)));
 void __stdcall seterrno (const char *, int line) __attribute__ ((regparm(2)));
-int __stdcall geterrno_from_win_error (DWORD code, int deferrno) __attribute__ ((regparm(2)));
 
 #define __seterrno() seterrno (__FILE__, __LINE__)
 #define __seterrno_from_win_error(val) seterrno_from_win_error (__FILE__, __LINE__, val)
@@ -32,3 +43,5 @@ class save_errno
 
 extern const char *__sp_fn;
 extern int __sp_ln;
+
+#endif /* __cplusplus */
index 87a3791..baf2d29 100644 (file)
@@ -110,7 +110,7 @@ errmap[] =
   { 0, NULL, 0}
 };
 
-int __stdcall
+extern "C" int __stdcall
 geterrno_from_win_error (DWORD code, int deferrno)
 {
   for (int i = 0; errmap[i].w != 0; ++i)
index 9183762..33ff843 100644 (file)
@@ -74,9 +74,7 @@ details. */
 #include "registry.h"
 #include "security.h"
 #include <assert.h>
-#include <shlobj.h>
-#include <objidl.h>
-#include <objbase.h>
+#include "shortcut.h"
 
 static int normalize_win32_path (const char *src, char *dst);
 static void slashify (const char *src, char *dst, int trailing_slash_p);
@@ -94,8 +92,6 @@ struct symlink_info
   int is_symlink;
   int error;
   symlink_info (): known_suffix (NULL), contents (buf + MAX_PATH + 1) {}
-  int check_shortcut (const char *, DWORD, HANDLE);
-  int check_sysfile (const char *, DWORD, HANDLE);
   int check (const char *path, const suffix_info *suffixes);
 };
 
@@ -2195,35 +2191,6 @@ endmntent (FILE *)
 
 /********************** Symbolic Link Support **************************/
 
-/* The header written to a shortcut by Cygwin or U/WIN. */
-#define SHORTCUT_HDR_SIZE      76
-static char shortcut_header[SHORTCUT_HDR_SIZE];
-static BOOL shortcut_initalized = FALSE;
-
-static void
-create_shortcut_header (void)
-{
-  if (!shortcut_initalized)
-    {
-      shortcut_header[0] = 'L';
-      shortcut_header[4] = '\001';
-      shortcut_header[5] = '\024';
-      shortcut_header[6] = '\002';
-      shortcut_header[12] = '\300';
-      shortcut_header[19] = 'F';
-      shortcut_header[20] = '\f';
-      shortcut_header[60] = '\001';
-      shortcut_initalized = TRUE;
-    }
-}
-
-static BOOL
-cmp_shortcut_header (const char *file_header)
-{
-  create_shortcut_header ();
-  return memcmp (shortcut_header, file_header, SHORTCUT_HDR_SIZE);
-}
-
 /* Create a symlink from FROMPATH to TOPATH. */
 
 extern "C"
@@ -2362,127 +2329,9 @@ next_suffix (char *ext_here, const suffix_info *&suffixes)
   return 0;
 }
 
-int
-symlink_info::check_shortcut (const char *path, DWORD fileattr, HANDLE h)
-{
-  HRESULT hres;
-  IShellLink *psl = NULL;
-  IPersistFile *ppf = NULL;
-  WCHAR wc_path[MAX_PATH];
-  char full_path[MAX_PATH];
-  WIN32_FIND_DATA wfd;
-  DWORD len = 0;
-  int res = 0;
-
-  /* Initialize COM library. */
-  CoInitialize (NULL);
-
-  /* Get a pointer to the IShellLink interface. */
-  hres = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
-                          IID_IShellLink, (void **)&psl);
-  if (FAILED (hres))
-    {
-      debug_printf ("CoCreateInstance failed");
-      goto close_it;
-    }
-  /* Get a pointer to the IPersistFile interface. */
-  hres = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
-  if (FAILED (hres))
-    {
-      debug_printf ("QueryInterface failed");
-      goto close_it;
-    }
-  /* Load the shortcut. */
-  MultiByteToWideChar(CP_ACP, 0, path, -1, wc_path, MAX_PATH);
-  hres = ppf->Load (wc_path, STGM_READ);
-  if (FAILED (hres))
-    {
-      debug_printf ("Load failed");
-      goto close_it;
-    }
-  /* Try the description (containing a POSIX path) first. */
-  if (fileattr & FILE_ATTRIBUTE_READONLY)
-    {
-      /* An additional check is needed to prove if it's a shortcut
-         really created by Cygwin or U/WIN. */
-      char file_header[SHORTCUT_HDR_SIZE];
-      DWORD got;
-
-      if (! ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0))
-       {
-         debug_printf ("ReadFile failed");
-         error = EIO;
-         goto close_it_dont_set_error;
-       }
-      if (got == SHORTCUT_HDR_SIZE && !cmp_shortcut_header (file_header))
-        {
-         hres = psl->GetDescription (contents, MAX_PATH);
-         if (FAILED (hres))
-           {
-             debug_printf ("GetDescription failed");
-             goto close_it;
-           }
-         len = strlen (contents);
-       }
-    }
-  /* No description or not R/O: Check the "official" path. */
-  if (len == 0)
-    {
-      /* Convert to full path (easy way) */
-      if ((path[0] == '\\' && path[1] == '\\')
-         || (_toupper (path[0]) >= 'A' && _toupper (path[0]) <= 'Z'
-             && path[1] == ':'))
-       len = 0;
-      else
-       {
-         len = GetCurrentDirectory (MAX_PATH, full_path);
-         if (path[0] == '\\')
-           len = 2;
-         else if (full_path[len - 1] != '\\')
-           strcpy (full_path + len++, "\\");
-       }
-      strcpy (full_path + len, path);
-      debug_printf ("full_path = <%s>", full_path);
-      /* Set relative path inside of IShellLink interface. */
-      hres = psl->SetRelativePath (full_path, 0);
-      if (FAILED (hres))
-       {
-         debug_printf ("SetRelativePath failed");
-         goto close_it;
-       }
-      /* Get the path to the shortcut target. */
-      hres = psl->GetPath (contents, MAX_PATH, &wfd, 0);
-      if (FAILED(hres))
-       {
-         debug_printf ("GetPath failed");
-         goto close_it;
-       }
-    }
-  /* It's a symlink.  */
-  pflags = PATH_SYMLINK;
-  res = strlen (contents);
-
-close_it:
-  if (FAILED (hres))
-    error = geterrno_from_win_error (HRESULT_CODE (hres), EACCES);
-
-close_it_dont_set_error:
-  /* Release the pointer to IPersistFile. */
-  if (ppf)
-    ppf->Release();
-  /* Release the pointer to IShellLink. */
-  if (psl)
-    psl->Release();
-  /* Uninitialize COM library. */
-  CoUninitialize ();
-
-  syscall_printf ("%d = symlink.check_shortcut (%s, %s) (%p)",
-                 res, path, contents, pflags);
-  return res;
-}
-
-int
-symlink_info::check_sysfile (const char *path, DWORD fileattr, HANDLE h)
+static int
+check_sysfile (const char *path, DWORD fileattr, HANDLE h,
+              char *contents, int *error, unsigned *pflags)
 {
   char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
   DWORD got;
@@ -2491,19 +2340,19 @@ symlink_info::check_sysfile (const char *path, DWORD fileattr, HANDLE h)
   if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0))
     {
       debug_printf ("ReadFile1 failed");
-      error = EIO;
+      *error = EIO;
     }
   else if (got == sizeof (cookie_buf)
           && memcmp (cookie_buf, SYMLINK_COOKIE, sizeof (cookie_buf)) == 0)
     {
       /* It's a symlink.  */
-      pflags = PATH_SYMLINK;
+      *pflags = PATH_SYMLINK;
 
       res = ReadFile (h, contents, MAX_PATH + 1, &got, 0);
       if (!res)
        {
          debug_printf ("ReadFile2 failed");
-         error = EIO;
+         *error = EIO;
        }
       else
        {
@@ -2521,15 +2370,13 @@ symlink_info::check_sysfile (const char *path, DWORD fileattr, HANDLE h)
     }
   else if (got == sizeof (cookie_buf)
           && memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
-    pflags |= PATH_SOCKET;
+    *pflags |= PATH_SOCKET;
   else
     {
       /* Not a symlink, see if executable.  */
-      if (!(pflags & PATH_ALL_EXEC) && has_exec_chars (cookie_buf, got))
-       pflags |= PATH_EXEC;
+      if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars (cookie_buf, got))
+       *pflags |= PATH_EXEC;
     }
-  syscall_printf ("%d = symlink.check_sysfile (%s, %s) (%p)",
-                 res, path, contents, pflags);
   return res;
 }
 
@@ -2615,12 +2462,16 @@ symlink_info::check (const char *in_path, const suffix_info *suffixes)
       res = -1;
       if (h == INVALID_HANDLE_VALUE)
        goto file_not_symlink;
-      else if (sym_check == 1 && !(res = check_shortcut (path, fileattr, h)))
+      else if (sym_check == 1
+               && !(res = check_shortcut (path, fileattr, h,
+                                         contents, &error, &pflags)))
        {
          CloseHandle (h);
          goto file_not_symlink;
        }
-      else if (sym_check == 2 && !(res = check_sysfile (path, fileattr, h)))
+      else if (sym_check == 2 &&
+              !(res = check_sysfile (path, fileattr, h,
+                                     contents, &error, &pflags)))
        {
          CloseHandle (h);
          goto file_not_symlink;
diff --git a/winsup/cygwin/shortcut.c b/winsup/cygwin/shortcut.c
new file mode 100644 (file)
index 0000000..7c05f9d
--- /dev/null
@@ -0,0 +1,171 @@
+/* shortcut.c: Read shortcuts. This part of the code must be in C because
+               the C++ interface to COM doesn't work without -fvtable-thunk
+              which is too dangerous to use.
+
+   Copyright 2001 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <shlobj.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <errno.h>
+#include "cygerrno.h"
+#include "shortcut.h"
+
+/* This is needed to avoid including path.h which is a pure C++ header. */
+#define PATH_SYMLINK MOUNT_SYMLINK
+
+#define debug_printf(x) strcpy (contents, x)
+
+char shortcut_header[SHORTCUT_HDR_SIZE];
+BOOL shortcut_initalized = FALSE;
+
+void
+create_shortcut_header (void)
+{
+  if (!shortcut_initalized)
+    {
+      shortcut_header[0] = 'L';
+      shortcut_header[4] = '\001';
+      shortcut_header[5] = '\024';
+      shortcut_header[6] = '\002';
+      shortcut_header[12] = '\300';
+      shortcut_header[19] = 'F';
+      shortcut_header[20] = '\f';
+      shortcut_header[60] = '\001';
+      shortcut_initalized = TRUE;
+    }
+}
+
+static BOOL
+cmp_shortcut_header (const char *file_header)
+{
+  create_shortcut_header ();
+  return memcmp (shortcut_header, file_header, SHORTCUT_HDR_SIZE);
+}
+
+int
+check_shortcut (const char *path, DWORD fileattr, HANDLE h,
+               char *contents, int *error, unsigned *pflags)
+{
+  HRESULT hres;
+  IShellLink *psl = NULL;
+  IPersistFile *ppf = NULL;
+  WCHAR wc_path[MAX_PATH];
+  char full_path[MAX_PATH];
+  WIN32_FIND_DATA wfd;
+  DWORD len = 0;
+  int res = 0;
+
+  /* Initialize COM library. */
+  CoInitialize (NULL);
+
+  /* Get a pointer to the IShellLink interface. */
+  hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IShellLink, (void **)&psl);
+  if (FAILED (hres))
+    {
+      debug_printf ("CoCreateInstance failed");
+      goto close_it;
+    }
+  /* Get a pointer to the IPersistFile interface. */
+  hres = psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile, (void **)&ppf);
+  if (FAILED (hres))
+    {
+      debug_printf ("QueryInterface failed");
+      goto close_it;
+    }
+  /* Load the shortcut. */
+  MultiByteToWideChar(CP_ACP, 0, path, -1, wc_path, MAX_PATH);
+  hres = ppf->lpVtbl->Load (ppf, wc_path, STGM_READ);
+  if (FAILED (hres))
+    {
+      debug_printf ("Load failed");
+      goto close_it;
+    }
+  /* Try the description (containing a POSIX path) first. */
+  if (fileattr & FILE_ATTRIBUTE_READONLY)
+    {
+      /* An additional check is needed to prove if it's a shortcut
+         really created by Cygwin or U/WIN. */
+      char file_header[SHORTCUT_HDR_SIZE];
+      DWORD got;
+
+      if (! ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0))
+       {
+         debug_printf ("ReadFile failed");
+          *error = EIO;
+         goto close_it_dont_set_error;
+       }
+      if (got == SHORTCUT_HDR_SIZE && !cmp_shortcut_header (file_header))
+        {
+         hres = psl->lpVtbl->GetDescription (psl, contents, MAX_PATH);
+         if (FAILED (hres))
+           {
+             debug_printf ("GetDescription failed");
+             goto close_it;
+           }
+         len = strlen (contents);
+       }
+    }
+  /* No description or not R/O: Check the "official" path. */
+  if (len == 0)
+    {
+      /* Convert to full path (easy way) */
+      if ((path[0] == '\\' && path[1] == '\\')
+         || (_toupper (path[0]) >= 'A' && _toupper (path[0]) <= 'Z'
+             && path[1] == ':'))
+       len = 0;
+      else
+       {
+         len = GetCurrentDirectory (MAX_PATH, full_path);
+         if (path[0] == '\\')
+           len = 2;
+         else if (full_path[len - 1] != '\\')
+           strcpy (full_path + len++, "\\");
+       }
+      strcpy (full_path + len, path);
+      /* Set relative path inside of IShellLink interface. */
+      hres = psl->lpVtbl->SetRelativePath (psl, full_path, 0);
+      if (FAILED (hres))
+       {
+         debug_printf ("SetRelativePath failed");
+         goto close_it;
+       }
+      /* Get the path to the shortcut target. */
+      hres = psl->lpVtbl->GetPath (psl, contents, MAX_PATH, &wfd, 0);
+      if (FAILED(hres))
+       {
+         debug_printf ("GetPath failed");
+         goto close_it;
+       }
+    }
+  /* It's a symlink.  */
+  *pflags = PATH_SYMLINK;
+  res = strlen (contents);
+
+close_it:
+  if (FAILED (hres))
+    *error = geterrno_from_win_error (HRESULT_CODE (hres), EACCES);
+
+close_it_dont_set_error:
+  /* Release the pointer to IPersistFile. */
+  if (ppf)
+    ppf->lpVtbl->Release(ppf);
+  /* Release the pointer to IShellLink. */
+  if (psl)
+    psl->lpVtbl->Release(psl);
+  /* Uninitialize COM library. */
+  CoUninitialize ();
+
+  return res;
+}
+
+
diff --git a/winsup/cygwin/shortcut.h b/winsup/cygwin/shortcut.h
new file mode 100644 (file)
index 0000000..87e7ff1
--- /dev/null
@@ -0,0 +1,28 @@
+/* shortcut.h: Hader file for shortcut.c
+
+   Copyright 2001 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The header written to a shortcut by Cygwin or U/WIN. */
+#define SHORTCUT_HDR_SIZE      76
+
+extern char shortcut_header[];
+extern BOOL shortcut_initalized;
+
+extern void create_shortcut_header ();
+
+int check_shortcut (const char *path, DWORD fileattr, HANDLE h,
+                   char *contents, int *error, unsigned *pflags);
+
+#ifdef __cplusplus
+};
+#endif