/* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
-Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
+Copyright (C) 1994-1995, 2000-2014 Free Software Foundation, Inc.
This file is part of GNU Emacs.
PIP_ADAPTER_INFO pAdapterInfo,
PULONG pOutBufLen);
+int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
+int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL);
+
/* ** A utility function ** */
static BOOL
is_windows_9x (void)
conversion back and forth from UTF-8 to UTF-16, then don't: first,
it was measured to take only a few microseconds on a not-so-fast
machine, and second, that's exactly what the ANSI APIs we used
- before do anyway, because they are just thin wrappers around the
+ before did anyway, because they are just thin wrappers around the
Unicode APIs.)
The variables file-name-coding-system and default-file-name-coding-system
For the same reasons, no CRT function or Win32 API can be called
directly in Emacs sources, without either converting the file
- name sfrom UTF-8 to either UTF-16 or ANSI codepage, or going
- through some shadowing function defined here.
+ names from UTF-8 to UTF-16 or ANSI codepage, or going through
+ some shadowing function defined here.
. Environment variables stored in Vprocess_environment are encoded
in the ANSI codepage, so if getenv/egetenv is used for a variable
. Running subprocesses in non-ASCII directories and with non-ASCII
file arguments is limited to the current codepage (even though
Emacs is perfectly capable of finding an executable program file
- even in a directory whose name cannot be encoded in the current
+ in a directory whose name cannot be encoded in the current
codepage). This is because the command-line arguments are
encoded _before_ they get to the w32-specific level, and the
encoding is not known in advance (it doesn't have to be the
the current codepage.
. Turning on w32-unicode-filename on Windows 9X (if it at all
- works) requires UNICOWS.DLL, which is currently loaded only in a
- GUI session. */
+ works) requires UNICOWS.DLL, which is thus a requirement even in
+ non-GUI sessions, something the we previously avoided. */
\f
int
filename_to_utf16 (const char *fn_in, wchar_t *fn_out)
{
- int result = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1,
- fn_out, MAX_PATH);
+ int result = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1,
+ fn_out, MAX_PATH);
if (!result)
{
int
filename_from_utf16 (const wchar_t *fn_in, char *fn_out)
{
- int result = WideCharToMultiByte (CP_UTF8, 0, fn_in, -1,
- fn_out, MAX_UTF8_PATH, NULL, NULL);
+ int result = pWideCharToMultiByte (CP_UTF8, 0, fn_in, -1,
+ fn_out, MAX_UTF8_PATH, NULL, NULL);
if (!result)
{
int result;
int codepage = codepage_for_filenames (NULL);
- result = WideCharToMultiByte (codepage, 0, fn_utf16, -1,
- fn_out, MAX_PATH, NULL, NULL);
+ result = pWideCharToMultiByte (codepage, 0, fn_utf16, -1,
+ fn_out, MAX_PATH, NULL, NULL);
if (!result)
{
DWORD err = GetLastError ();
{
wchar_t fn_utf16[MAX_PATH];
int codepage = codepage_for_filenames (NULL);
- int result = MultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1,
- fn_utf16, MAX_PATH);
+ int result = pMultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1,
+ fn_utf16, MAX_PATH);
if (!result)
{
{
char *var;
size_t name_len;
- int retval;
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
/* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
indicates that flag is unsupported for CP_UTF8, and OTOH says
it is the default anyway. */
- wlen = MultiByteToWideChar (CP_UTF8, 0, newname, -1,
- data.wid.cStreamName, MAX_PATH);
+ wlen = pMultiByteToWideChar (CP_UTF8, 0, newname, -1,
+ data.wid.cStreamName, MAX_PATH);
if (wlen > 0)
{
LPVOID context = NULL;
return -1;
}
- /* Remove trailing directory separator, unless name is the root
- directory of a drive or UNC volume in which case ensure there
- is a trailing separator. */
len = strlen (name);
+ /* Allocate 1 extra byte so that we could append a slash to a root
+ directory, down below. */
name = strcpy (alloca (len + 2), name);
/* Avoid a somewhat costly call to is_symlink if the filesystem
}
else if (rootdir)
{
+ /* Make sure root directories end in a slash. */
if (!IS_DIRECTORY_SEP (name[len-1]))
strcat (name, "\\");
if (GetDriveType (name) < 2)
{
int have_wfd = -1;
+ /* Make sure non-root directories do NOT end in a slash,
+ otherwise FindFirstFile might fail. */
if (IS_DIRECTORY_SEP (name[len-1]))
name[len - 1] = 0;
if (fd != AT_FDCWD)
{
- if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
+ char lastc = dir_pathname[strlen (dir_pathname) - 1];
+
+ if (_snprintf (fullname, sizeof fullname, "%s%s%s",
+ dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name)
< 0)
{
errno = ENAMETOOLONG;
errno = 0;
/* SetFileSecurity is deprecated by MS, and sometimes fails when
DACL inheritance is involved, but it seems to preserve ownership
- better than SetNamedSecurity, which is important e.g., in
+ better than SetNamedSecurityInfo, which is important e.g., in
copy-file. */
if (!set_file_security (fname, flags, (PSECURITY_DESCRIPTOR)acl))
{
/* Possibly truncated */
? make_specified_string (name, -1, len, 1)
: Qnil);
+ /* This prevents thread start and end notifications
+ from being sent to the DLL, for every thread we
+ start. We don't need those notifications because
+ threads we create never use any of these DLLs, only
+ the main thread uses them. This is supposed to
+ speed up thread creation. */
+ DisableThreadLibraryCalls (dll_handle);
break;
}
}
"not unpacked properly.\nSee the README.W32 file in the "
"top-level Emacs directory for more information.",
init_file_name, load_path);
- needed = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer,
- -1, NULL, 0);
+ needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer,
+ -1, NULL, 0);
if (needed > 0)
{
wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t));
- MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, -1,
- msg_w, needed);
- needed = WideCharToMultiByte (CP_ACP, 0, msg_w, -1,
- NULL, 0, NULL, NULL);
+ pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, -1,
+ msg_w, needed);
+ needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1,
+ NULL, 0, NULL, NULL);
if (needed > 0)
{
char *msg_a = alloca (needed + 1);
- WideCharToMultiByte (CP_ACP, 0, msg_w, -1, msg_a, needed,
- NULL, NULL);
+ pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, msg_a, needed,
+ NULL, NULL);
msg = msg_a;
}
}
return FALSE;
}
+/* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
+ NT, return a handle to GDI32.DLL. */
+HANDLE
+maybe_load_unicows_dll (void)
+{
+ if (os_subtype == OS_9X)
+ {
+ HANDLE ret = LoadLibrary ("Unicows.dll");
+ if (ret)
+ {
+ /* These two functions are present on Windows 9X as stubs
+ that always fail. We need the real implementations from
+ UNICOWS.DLL, so we must call these functions through
+ pointers, and assign the correct addresses to these
+ pointers at program startup (see emacs.c, which calls
+ this function early on). */
+ pMultiByteToWideChar = GetProcAddress (ret, "MultiByteToWideChar");
+ pWideCharToMultiByte = GetProcAddress (ret, "WideCharToMultiByte");
+ return ret;
+ }
+ else
+ {
+ int button;
+
+ button = MessageBox (NULL,
+ "Emacs cannot load the UNICOWS.DLL library.\n"
+ "This library is essential for using Emacs\n"
+ "on this system. You need to install it.\n\n"
+ "Emacs will exit when you click OK.",
+ "Emacs cannot load UNICOWS.DLL",
+ MB_ICONERROR | MB_TASKMODAL
+ | MB_SETFOREGROUND | MB_OK);
+ switch (button)
+ {
+ case IDOK:
+ default:
+ exit (1);
+ }
+ }
+ }
+ else
+ {
+ /* On NT family of Windows, these two functions are always
+ linked in, so we just assign their addresses to the 2
+ pointers; no need for the LoadLibrary dance. */
+ pMultiByteToWideChar = MultiByteToWideChar;
+ pWideCharToMultiByte = WideCharToMultiByte;
+ return LoadLibrary ("Gdi32.dll");
+ }
+}
+
/*
globals_of_w32 is used to initialize those global variables that
must always be initialized on startup even when the global variable
emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
{
int n, err;
- SELECT_TYPE fdset;
- struct timespec timeout;
struct Lisp_Process *process = (struct Lisp_Process *)p;
int fd = process->infd;