📄 fhandler_registry.cc
字号:
/* fhandler_registry.cc: fhandler for /proc/registry virtual filesystem Copyright 2002 Red Hat, Inc.This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license. Please consult the file "CYGWIN_LICENSE" fordetails. *//* FIXME: Access permissions are ignored at the moment. */#include "winsup.h"#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <sys/cygwin.h>#include "cygerrno.h"#include "security.h"#include "fhandler.h"#include "path.h"#include "dtable.h"#include "cygheap.h"#include <assert.h>#define _COMPILING_NEWLIB#include <dirent.h>static const int registry_len = sizeof ("registry") - 1;/* If this bit is set in __d_position then we are enumerating values, * else sub-keys. keeping track of where we are is horribly messy * the bottom 16 bits are the absolute position and the top 15 bits * make up the value index if we are enuerating values. */static const __off32_t REG_ENUM_VALUES_MASK = 0x8000000;static const __off32_t REG_POSITION_MASK = 0xffff;/* List of root keys in /proc/registry. * Possibly we should filter out those not relevant to the flavour of Windows * Cygwin is running on. */static const char *registry_listing[] ={ ".", "..", "HKEY_CLASSES_ROOT", "HKEY_CURRENT_CONFIG", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_DYN_DATA", // 95/98/Me "HKEY_PERFOMANCE_DATA", // NT/2000/XP NULL};static const HKEY registry_keys[] ={ (HKEY) INVALID_HANDLE_VALUE, (HKEY) INVALID_HANDLE_VALUE, HKEY_CLASSES_ROOT, HKEY_CURRENT_CONFIG, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_DYN_DATA, HKEY_PERFORMANCE_DATA};static const int ROOT_KEY_COUNT = sizeof (registry_keys) / sizeof (HKEY);/* These get added to each subdirectory in /proc/registry. * If we wanted to implement writing, we could maybe add a '.writable' entry or * suchlike. */static const char *special_dot_files[] ={ ".", "..", NULL};static const int SPECIAL_DOT_FILE_COUNT = (sizeof (special_dot_files) / sizeof (const char *)) - 1;/* Name given to default values */static const char *DEFAULT_VALUE_NAME = "@";static HKEY open_key (const char *name, REGSAM access, bool isValue);/* Returns 0 if path doesn't exist, >0 if path is a directory, * <0 if path is a file. * * We open the last key but one and then enum it's sub-keys and values to see if the * final component is there. This gets round the problem of not having security access * to the final key in the path. */intfhandler_registry::exists (){ int file_type = 0, index = 0, pathlen; DWORD buf_size = MAX_PATH; LONG error; char buf[buf_size]; const char *file; HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; const char *path = get_name (); debug_printf ("exists (%s)", path); path += proc_len + registry_len + 2; if (*path == 0) { file_type = 2; goto out; } pathlen = strlen (path); file = path + pathlen - 1; if (SLASH_P (*file) && pathlen > 1) file--; while (!SLASH_P (*file)) file--; file++; if (file == path) { for (int i = 0; registry_listing[i]; i++) if (path_prefix_p (registry_listing[i], path, strlen (registry_listing[i]))) { file_type = 1; goto out; } goto out; } hKey = open_key (path, KEY_READ, false); if (hKey != (HKEY) INVALID_HANDLE_VALUE) file_type = 1; else { hKey = open_key (path, KEY_READ, true); if (hKey == (HKEY) INVALID_HANDLE_VALUE) return 0; while (ERROR_SUCCESS == (error = RegEnumKeyEx (hKey, index++, buf, &buf_size, NULL, NULL, NULL, NULL)) || (error == ERROR_MORE_DATA)) { if (pathmatch (buf, file)) { file_type = 1; goto out; } buf_size = MAX_PATH; } if (error != ERROR_NO_MORE_ITEMS) { seterrno_from_win_error (__FILE__, __LINE__, error); goto out; } index = 0; buf_size = MAX_PATH; while (ERROR_SUCCESS == (error = RegEnumValue (hKey, index++, buf, &buf_size, NULL, NULL, NULL, NULL)) || (error == ERROR_MORE_DATA)) { if (pathmatch (buf, file) || (buf[0] == '\0' && pathmatch (file, DEFAULT_VALUE_NAME))) { file_type = -1; goto out; } buf_size = MAX_PATH; } if (error != ERROR_NO_MORE_ITEMS) { seterrno_from_win_error (__FILE__, __LINE__, error); goto out; } }out: if (hKey != (HKEY) INVALID_HANDLE_VALUE) RegCloseKey (hKey); return file_type;}fhandler_registry::fhandler_registry ():fhandler_proc (FH_REGISTRY){}intfhandler_registry::fstat (struct __stat64 *buf, path_conv *pc){ this->fhandler_base::fstat (buf, pc); buf->st_mode &= ~_IFMT & NO_W; int file_type = exists (); switch (file_type) { case 0: set_errno (ENOENT); return -1; case 1: buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; break; case 2: buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; buf->st_nlink = ROOT_KEY_COUNT; break; default: case -1: buf->st_mode |= S_IFREG; buf->st_mode &= NO_X; break; } if (file_type != 0 && file_type != 2) { HKEY hKey; const char *path = get_name () + proc_len + registry_len + 2; hKey = open_key (path, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE, (file_type < 0) ? true : false); if (hKey != (HKEY) INVALID_HANDLE_VALUE) { FILETIME ftLastWriteTime; DWORD subkey_count; if (ERROR_SUCCESS == RegQueryInfoKey (hKey, NULL, NULL, NULL, &subkey_count, NULL, NULL, NULL, NULL, NULL, NULL, &ftLastWriteTime)) { to_timestruc_t (&ftLastWriteTime, &buf->st_mtim); buf->st_ctim = buf->st_mtim; time_as_timestruc_t (&buf->st_atim); if (file_type > 0) buf->st_nlink = subkey_count; else { int pathlen = strlen (path); const char *value_name = path + pathlen - 1; if (SLASH_P (*value_name) && pathlen > 1) value_name--; while (!SLASH_P (*value_name)) value_name--; value_name++; DWORD dwSize; if (ERROR_SUCCESS == RegQueryValueEx (hKey, value_name, NULL, NULL, NULL, &dwSize)) buf->st_size = dwSize; } __uid32_t uid; __gid32_t gid; if (get_object_attribute ((HANDLE) hKey, SE_REGISTRY_KEY, &buf->st_mode, &uid, &gid) == 0) { buf->st_uid = uid; buf->st_gid = gid; buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); if (file_type > 0) buf->st_mode |= S_IFDIR; else buf->st_mode &= NO_X; } } RegCloseKey (hKey); } } return 0;}struct dirent *fhandler_registry::readdir (DIR * dir){ DWORD buf_size = MAX_PATH; char buf[buf_size]; HANDLE handle; struct dirent *res = NULL; const char *path = dir->__d_dirname + proc_len + 1 + registry_len; LONG error; if (*path == 0) { if (dir->__d_position >= ROOT_KEY_COUNT) goto out; strcpy (dir->__d_dirent->d_name, registry_listing[dir->__d_position++]); res = dir->__d_dirent; goto out; } if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE && dir->__d_position == 0) { handle = open_key (path + 1, KEY_READ, false); dir->__d_u.__d_data.__handle = handle; } if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE) goto out; if (dir->__d_position < SPECIAL_DOT_FILE_COUNT) { strcpy (dir->__d_dirent->d_name, special_dot_files[dir->__d_position++]); res = dir->__d_dirent; goto out; }retry: if (dir->__d_position & REG_ENUM_VALUES_MASK) /* For the moment, the type of key is ignored here. when write access is added, * maybe add an extension for the type of each value? */ error = RegEnumValue ((HKEY) dir->__d_u.__d_data.__handle, (dir->__d_position & ~REG_ENUM_VALUES_MASK) >> 16, buf, &buf_size, NULL, NULL, NULL, NULL); else error = RegEnumKeyEx ((HKEY) dir->__d_u.__d_data.__handle, dir->__d_position - SPECIAL_DOT_FILE_COUNT, buf, &buf_size, NULL, NULL, NULL, NULL); if (error == ERROR_NO_MORE_ITEMS && (dir->__d_position & REG_ENUM_VALUES_MASK) == 0) { /* If we're finished with sub-keys, start on values under this key. */ dir->__d_position |= REG_ENUM_VALUES_MASK; buf_size = MAX_PATH; goto retry; } if (error != ERROR_SUCCESS && error != ERROR_MORE_DATA) { RegCloseKey ((HKEY) dir->__d_u.__d_data.__handle); dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; seterrno_from_win_error (__FILE__, __LINE__, error); goto out; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -