summaryrefslogtreecommitdiffstats
path: root/src/os_mswin.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/os_mswin.c255
1 files changed, 118 insertions, 137 deletions
diff --git a/src/os_mswin.c b/src/os_mswin.c
index 512fa40..95e3cbc 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -18,20 +18,12 @@
#include <sys/types.h>
#include <signal.h>
#include <limits.h>
+
+// cproto fails on missing include files
#ifndef PROTO
# include <process.h>
-#endif
-
-#undef chdir
-#ifdef __GNUC__
-# ifndef __MINGW32__
-# include <dirent.h>
-# endif
-#else
# include <direct.h>
-#endif
-#ifndef PROTO
# if !defined(FEAT_GUI_MSWIN)
# include <shellapi.h>
# endif
@@ -41,37 +33,8 @@
# include <winspool.h>
# include <commdlg.h>
# endif
-
#endif // PROTO
-#ifdef __MINGW32__
-# ifndef FROM_LEFT_1ST_BUTTON_PRESSED
-# define FROM_LEFT_1ST_BUTTON_PRESSED 0x0001
-# endif
-# ifndef RIGHTMOST_BUTTON_PRESSED
-# define RIGHTMOST_BUTTON_PRESSED 0x0002
-# endif
-# ifndef FROM_LEFT_2ND_BUTTON_PRESSED
-# define FROM_LEFT_2ND_BUTTON_PRESSED 0x0004
-# endif
-# ifndef FROM_LEFT_3RD_BUTTON_PRESSED
-# define FROM_LEFT_3RD_BUTTON_PRESSED 0x0008
-# endif
-# ifndef FROM_LEFT_4TH_BUTTON_PRESSED
-# define FROM_LEFT_4TH_BUTTON_PRESSED 0x0010
-# endif
-
-/*
- * EventFlags
- */
-# ifndef MOUSE_MOVED
-# define MOUSE_MOVED 0x0001
-# endif
-# ifndef DOUBLE_CLICK
-# define DOUBLE_CLICK 0x0002
-# endif
-#endif
-
/*
* When generating prototypes for Win32 on Unix, these lines make the syntax
* errors disappear. They do not need to be correct.
@@ -144,37 +107,6 @@ static HWND s_hwnd = 0; // console window handle, set by GetConsoleHwnd()
int WSInitialized = FALSE; // WinSock is initialized
#endif
-// Don't generate prototypes here, because some systems do have these
-// functions.
-#if defined(__GNUC__) && !defined(PROTO)
-# ifndef __MINGW32__
-int _stricoll(char *a, char *b)
-{
- // the ANSI-ish correct way is to use strxfrm():
- char a_buff[512], b_buff[512]; // file names, so this is enough on Win32
- strxfrm(a_buff, a, 512);
- strxfrm(b_buff, b, 512);
- return strcoll(a_buff, b_buff);
-}
-
-char * _fullpath(char *buf, char *fname, int len)
-{
- LPTSTR toss;
-
- return (char *)GetFullPathName(fname, len, buf, &toss);
-}
-# endif
-
-# if !defined(__MINGW32__) || (__GNUC__ < 4)
-int _chdrive(int drive)
-{
- char temp [3] = "-:";
- temp[0] = drive + 'A' - 1;
- return !SetCurrentDirectory(temp);
-}
-# endif
-#endif
-
#ifndef PROTO
/*
@@ -430,16 +362,6 @@ slash_adjust(char_u *p)
}
}
-// Use 64-bit stat functions.
-#undef stat
-#undef _stat
-#undef _wstat
-#undef _fstat
-#define stat _stat64
-#define _stat _stat64
-#define _wstat _wstat64
-#define _fstat _fstat64
-
static int
read_reparse_point(const WCHAR *name, char_u *buf, DWORD *buf_len)
{
@@ -461,58 +383,6 @@ read_reparse_point(const WCHAR *name, char_u *buf, DWORD *buf_len)
return ok ? OK : FAIL;
}
- static int
-wstat_symlink_aware(const WCHAR *name, stat_T *stp)
-{
-#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__MINGW32__)
- // Work around for VC12 or earlier (and MinGW). _wstat() can't handle
- // symlinks properly.
- // VC9 or earlier: _wstat() doesn't support a symlink at all. It retrieves
- // status of a symlink itself.
- // VC10: _wstat() supports a symlink to a normal file, but it doesn't
- // support a symlink to a directory (always returns an error).
- // VC11 and VC12: _wstat() doesn't return an error for a symlink to a
- // directory, but it doesn't set S_IFDIR flag.
- // MinGW: Same as VC9.
- int n;
- BOOL is_symlink = FALSE;
- HANDLE hFind, h;
- DWORD attr = 0;
- WIN32_FIND_DATAW findDataW;
-
- hFind = FindFirstFileW(name, &findDataW);
- if (hFind != INVALID_HANDLE_VALUE)
- {
- attr = findDataW.dwFileAttributes;
- if ((attr & FILE_ATTRIBUTE_REPARSE_POINT)
- && (findDataW.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
- is_symlink = TRUE;
- FindClose(hFind);
- }
- if (is_symlink)
- {
- h = CreateFileW(name, FILE_READ_ATTRIBUTES,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING,
- (attr & FILE_ATTRIBUTE_DIRECTORY)
- ? FILE_FLAG_BACKUP_SEMANTICS : 0,
- NULL);
- if (h != INVALID_HANDLE_VALUE)
- {
- int fd;
-
- fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
- n = _fstat(fd, (struct _stat *)stp);
- if ((n == 0) && (attr & FILE_ATTRIBUTE_DIRECTORY))
- stp->st_mode = (stp->st_mode & ~S_IFREG) | S_IFDIR;
- _close(fd);
- return n;
- }
- }
-#endif
- return _wstat(name, (struct _stat *)stp);
-}
-
char_u *
resolve_appexeclink(char_u *fname)
{
@@ -568,11 +438,76 @@ resolve_appexeclink(char_u *fname)
return utf16_to_enc(p, NULL);
}
+// Use 64-bit stat functions.
+#undef stat
+#undef _stat
+#undef _wstat
+#undef _fstat
+#define stat _stat64
+#define _stat _stat64
+#define _wstat _wstat64
+#define _fstat _fstat64
+
+/*
+ * Implements lstat() and stat() that can handle symlinks properly.
+ */
+ static int
+mswin_stat_impl(const WCHAR *name, stat_T *stp, const int resolve)
+{
+ int n;
+ int fd;
+ BOOL is_symlink = FALSE;
+ HANDLE hFind, h;
+ DWORD attr = 0;
+ DWORD flag = 0;
+ WIN32_FIND_DATAW findDataW;
+
+#ifdef _UCRT
+ if (resolve)
+ // Universal CRT can handle symlinks properly.
+ return _wstat(name, stp);
+#endif
+
+ hFind = FindFirstFileW(name, &findDataW);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ attr = findDataW.dwFileAttributes;
+ if ((attr & FILE_ATTRIBUTE_REPARSE_POINT)
+ && (findDataW.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
+ is_symlink = TRUE;
+ FindClose(hFind);
+ }
+
+ // Use the plain old stat() whenever it's possible.
+ if (!is_symlink)
+ return _wstat(name, stp);
+
+ if (!resolve && is_symlink)
+ flag = FILE_FLAG_OPEN_REPARSE_POINT;
+ if (attr & FILE_ATTRIBUTE_DIRECTORY)
+ flag |= FILE_FLAG_BACKUP_SEMANTICS;
+
+ h = CreateFileW(name, FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, flag,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return -1;
+
+ fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
+ n = _fstat(fd, (struct _stat *)stp);
+ if ((n == 0) && (attr & FILE_ATTRIBUTE_DIRECTORY))
+ stp->st_mode = (stp->st_mode & ~S_IFMT) | S_IFDIR;
+ _close(fd);
+
+ return n;
+}
+
/*
* stat() can't handle a trailing '/' or '\', remove it first.
+ * When 'resolve' is true behave as lstat() wrt symlinks.
*/
- int
-vim_stat(const char *name, stat_T *stp)
+ static int
+stat_impl(const char *name, stat_T *stp, const int resolve)
{
// WinNT and later can use _MAX_PATH wide characters for a pathname, which
// means that the maximum pathname is _MAX_PATH * 3 bytes when 'enc' is
@@ -607,11 +542,23 @@ vim_stat(const char *name, stat_T *stp)
if (wp == NULL)
return -1;
- n = wstat_symlink_aware(wp, stp);
+ n = mswin_stat_impl(wp, stp, resolve);
vim_free(wp);
return n;
}
+ int
+vim_lstat(const char *name, stat_T *stp)
+{
+ return stat_impl(name, stp, FALSE);
+}
+
+ int
+vim_stat(const char *name, stat_T *stp)
+{
+ return stat_impl(name, stp, TRUE);
+}
+
#if (defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)) || defined(PROTO)
void
mch_settmode(tmode_T tmode UNUSED)
@@ -883,6 +830,40 @@ mch_icon_load(HANDLE *iconp)
0, mch_icon_load_cb, iconp);
}
+/*
+ * Fill the buffer 'buf' with 'len' random bytes.
+ * Returns FAIL if the OS PRNG is not available or something went wrong.
+ */
+ int
+mch_get_random(char_u *buf, int len)
+{
+ static int initialized = NOTDONE;
+ static HINSTANCE hInstLib;
+ static BOOL (WINAPI *pProcessPrng)(PUCHAR, ULONG);
+
+ if (initialized == NOTDONE)
+ {
+ hInstLib = vimLoadLib("bcryptprimitives.dll");
+ if (hInstLib != NULL)
+ pProcessPrng = (void *)GetProcAddress(hInstLib, "ProcessPrng");
+ if (hInstLib == NULL || pProcessPrng == NULL)
+ {
+ FreeLibrary(hInstLib);
+ initialized = FAIL;
+ }
+ else
+ initialized = OK;
+ }
+
+ if (initialized == FAIL)
+ return FAIL;
+
+ // According to the documentation this call cannot fail.
+ pProcessPrng(buf, len);
+
+ return OK;
+}
+
int
mch_libcall(
char_u *libname,
@@ -2940,7 +2921,7 @@ expand_font_enumproc(
// Filter only on ANSI. Otherwise will see a lot of random fonts that we
// usually don't want.
if (lf->lfCharSet != ANSI_CHARSET)
- return 1;
+ return 1;
int (*add_match)(char_u *) = (int (*)(char_u *))lparam;
@@ -2974,7 +2955,7 @@ gui_mch_expand_font(optexpand_T *args, void *param UNUSED, int (*add_match)(char
// Always fill in with the current font size as first option for
// convenience. We simply round to the closest integer for simplicity.
- int font_height = (int)round(
+ int font_height = (int)round(
pixels_to_points(-current_font_height, TRUE, (long_i)NULL));
vim_snprintf(buf, ARRAY_LENGTH(buf), "h%d", font_height);
add_match((char_u *)buf);