view netinstall/root.cc @ 5182:2e528066e2fc

Move #'sort*, #'fill, #'merge to C from cl-seq.el. lisp/ChangeLog addition: 2010-04-01 Aidan Kehoe <kehoea@parhasard.net> * cl-seq.el (fill, sort*, merge): Move these functions to fns.c. (stable-sort): Make this docstring reflect the argument names used in the #'sort* docstring. * cl-macs.el (stable-sort): Make #'stable-sort exactly equivalent to #'sort* in compiled code. * bytecomp.el (byte-compile-maybe-add-*): New macro, for functions like #'sort and #'mapcar that, to be strictly compatible, should only take two args, but in our implementation can take more, because they're aliases of #'sort* and #'mapcar*. (byte-compile-mapcar, byte-compile-sort, byte-compile-fillarray): Use this new macro. (map-into): Add a byte-compile method for #'map-into in passing. * apropos.el (apropos-print): Use #'sort* with a :key argument, now it's in C. * compat.el (extent-at): Ditto. * register.el (list-registers): Ditto. * package-ui.el (pui-list-packages): Ditto. * help.el (sorted-key-descriptions): Ditto. src/ChangeLog addition: 2010-03-31 Aidan Kehoe <kehoea@parhasard.net> * fns.c (STRING_DATA_TO_OBJECT_ARRAY) (BIT_VECTOR_TO_OBJECT_ARRAY, c_merge_predicate_key) (c_merge_predicate_nokey, list_merge, array_merge) (list_array_merge_into_list, list_list_merge_into_array) (list_array_merge_into_array, CHECK_KEY_ARGUMENT, Fmerge) (list_sort, array_sort, FsortX): Move #'sort*, #'fill, #'merge from cl-seq.el to C, extending the implementations of Fsort, Ffillarray, and merge() to do so. * keymap.c (keymap_submaps, map_keymap_sort_predicate) (describe_map_sort_predicate): Change the calling semantics of the C sort predicates to return a non-nil Lisp object if the first argument is less than the second, rather than C integers. * fontcolor-msw.c (sort_font_list_function): * fileio.c (build_annotations): * dired.c (Fdirectory_files): * abbrev.c (Finsert_abbrev_table_description): Call list_sort instead of Fsort, list_merge instead of merge() in these functions. man/ChangeLog addition: 2010-04-01 Aidan Kehoe <kehoea@parhasard.net> * lispref/lists.texi (Rearrangement): Update the documentation of #'sort here, now that it accepts any type of sequence and the KEY keyword argument. (Though this is probably now the wrong place for this function, given that.)
author Aidan Kehoe <kehoea@parhasard.net>
date Thu, 01 Apr 2010 20:22:50 +0100
parents ce0b3f2eff35
children
line wrap: on
line source

/*
 * Copyright (c) 2000, Red Hat, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by DJ Delorie <dj@cygnus.com>
 *
 */

/* The purpose of this file is to ask the user where they want the
   root of the installation to be, and to ask whether the user prefers
   text or binary mounts. */

#include "win32.h"
#include <shlobj.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "dialog.h"
#include "resource.h"
#include "state.h"
#include "msg.h"
#include "regedit.h"
#include "reginfo.h"
#include "concat.h"
#include "log.h"

static int rb[] = { IDC_INSTALL_CYGWIN, IDC_INSTALL_NATIVE, 0 };
static int su[] = { IDC_ROOT_SYSTEM, IDC_ROOT_USER, 0 };

static void
check_if_enable_next (HWND h)
{
  EnableWindow (GetDlgItem (h, IDOK), install_type && root_dir && root_scope);
}

static void
load_dialog (HWND h)
{
  rbset (h, rb, install_type);
  rbset (h, su, root_scope);
  eset (h, IDC_ROOT_DIR, root_dir);
  check_if_enable_next (h);
}

static void
save_dialog (HWND h)
{
  install_type = rbget (h, rb);
  root_scope = rbget (h, su);
  char* new_root_dir = eget (h, IDC_ROOT_DIR, root_dir);

  if (!root_dir || strcmp (new_root_dir, root_dir) != 0)
    root_dir_default = 0;

  root_dir = new_root_dir;
}

/*
 * is_admin () determines whether or not the current user is a member of the
 * Administrators group.  On Windows 9X, the current user is considered an
 * Administrator by definition.
 */

static int
is_admin ()
{
  // Windows 9X users are considered Administrators by definition
  OSVERSIONINFO verinfo;
  verinfo.dwOSVersionInfoSize = sizeof (verinfo);
  GetVersionEx (&verinfo);
  if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
    return 1;

  // Get the process token for the current process
  HANDLE token;
  BOOL status = OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &token);
  if (!status)
    return 0;

  // Get the group token information
  UCHAR token_info[1024];
  PTOKEN_GROUPS groups = (PTOKEN_GROUPS) token_info;
  DWORD token_info_len = sizeof (token_info);
  status = GetTokenInformation (token, TokenGroups, token_info, token_info_len, &token_info_len);
  CloseHandle(token);
  if (!status)
    return 0;

  // Create the Administrators group SID
  PSID admin_sid;
  SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
  status = AllocateAndInitializeSid (&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &admin_sid);
  if (!status)
    return 0;

  // Check to see if the user is a member of the Administrators group
  status = 0;
  for (UINT i=0; i<groups->GroupCount; i++) {
    if (EqualSid(groups->Groups[i].Sid, admin_sid)) {
      status = 1;
      break;
    }
  }

  // Destroy the Administrators group SID
  FreeSid (admin_sid);

  // Return whether or not the user is a member of the Administrators group
  return status;
}

static void
change_default_root (int id)
{
  int issystem;
  char* cygroot = find_cygwin_root (&issystem);
  if (id == IDC_INSTALL_CYGWIN && cygroot)
    {
      root_dir = concat (cygroot, XEMACS_CYGWIN_DEFAULT_ROOT, 0);
      install_type = IDC_INSTALL_CYGWIN;
    }
  else if (id == IDC_INSTALL_NATIVE)
    {
      char windir[_MAX_PATH];
      GetWindowsDirectory (windir, sizeof (windir));
      windir[2] = 0;
      root_dir = concat (windir, XEMACS_DEFAULT_ROOT, 0);
      install_type = IDC_INSTALL_NATIVE;
    }
}

static int CALLBACK
browse_cb (HWND h, UINT m, LPARAM lp, LPARAM data)
{
  switch (m)
    {
    case BFFM_INITIALIZED:
      if (root_dir)
	SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM)root_dir);
      break;
    }
  return 0;
}

static void
browse (HWND h)
{
  BROWSEINFO bi;
  CHAR name[MAX_PATH];
  LPITEMIDLIST pidl;
  memset (&bi, 0, sizeof (bi));
  bi.hwndOwner = h;
  bi.pszDisplayName = name;
  bi.lpszTitle = "Select an installation root directory";
  bi.ulFlags = BIF_RETURNONLYFSDIRS;
  bi.lpfn = browse_cb;
  pidl = SHBrowseForFolder (&bi);
  if (pidl)
    {
      if (SHGetPathFromIDList (pidl, name))
	eset (h, IDC_ROOT_DIR, name);
    }
}

#define isslash(c) ((c) == '\\' || (c) == '/')

static int
directory_is_absolute ()
{
  if (isalpha (root_dir[0])
      && root_dir[1] == ':'
      && (root_dir[2] == '\\' || root_dir[2] == '/'))
    return 1;
  return 0;
}

static int
directory_is_rootdir ()
{
  char *c;
  for (c = root_dir; *c; c++)
    if (isslash (c[0]) && c[1] && !isslash (c[1]))
      return 0;
  return 1;
}

static int
cygwin_without_cygwin ()
{
  int issystem;
  if (install_type == IDC_INSTALL_CYGWIN
      && !find_cygwin_root (&issystem))
    return 1;
  return 0;
}

static BOOL
dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
{
  switch (id)
    {

    case IDC_ROOT_DIR:
    case IDC_ROOT_SYSTEM:
    case IDC_ROOT_USER:
      save_dialog (h);
      check_if_enable_next (h);
      break;

    case IDC_INSTALL_NATIVE:
    case IDC_INSTALL_CYGWIN:
      if (root_dir_default)
	{
	  change_default_root (id);
	  eset (h, IDC_ROOT_DIR, root_dir);
	}
      save_dialog (h);
      check_if_enable_next (h);
      break;

    case IDC_ROOT_BROWSE:
      browse (h);
      break;

    case IDOK:
      save_dialog (h);

      if (! directory_is_absolute ())
	{
	  note (IDS_ROOT_ABSOLUTE);
	  break;
	}

      if (directory_is_rootdir ())
	if (IDNO == yesno (IDS_ROOT_SLASH))
	  break;

      if (cygwin_without_cygwin ())
	if (IDNO == yesno (IDS_ROOT_NOCYGWIN))
	  break;

      create_xemacs_root (backslash (root_dir),
			  root_scope == IDC_ROOT_SYSTEM ? 1 : 0,
			  install_type == IDC_INSTALL_NATIVE ? 1 : 0);

      switch (source)
	{
	case IDC_SOURCE_NETINST:
	  NEXT (IDD_NET);
	  break;
	case IDC_SOURCE_CWD:
	  NEXT (IDD_S_FROM_CWD);
	  break;
	default:
	  msg ("source is default? %d\n", source);
	  NEXT (0);
	}
      break;

    case IDC_BACK:
      save_dialog (h);
      NEXT (IDD_LOCAL_DIR);
      break;

    case IDCANCEL:
      NEXT (0);
      break;
    }
  return FALSE;
}

static BOOL CALLBACK
dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
    {
    case WM_INITDIALOG:
      load_dialog (h);
      return FALSE;
    case WM_COMMAND:
      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
    }
  return FALSE;
}

static void
set_default_root ()
{
  change_default_root (IDC_INSTALL_NATIVE);
  root_scope = (is_admin()) ? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
  root_dir_default = 1;
}

void
do_root (HINSTANCE h)
{
  int rv = 0;
  // init will have read a previous root
  if (!root_dir)
    set_default_root ();

  rv = DialogBox (h, MAKEINTRESOURCE (IDD_ROOT), 0, dialog_proc);
  if (rv == -1)
    fatal (IDS_DIALOG_FAILED);

  log (0, "root: %s %s %s", root_dir,
       (install_type == IDC_INSTALL_NATIVE) ? "native" : "cygwin",
       (root_scope == IDC_ROOT_USER) ? "user" : "system");
}