使用Least-Privileged用户帐户玩游戏

本文介绍游戏开发人员如何创作适用于最低特权用户帐户 (也称为受限用户帐户) 的 Microsoft Windows 游戏。

简介

Windows 使用帐户管理其用户。 如今,超过 80% 的计算机用户在家中与其他家庭成员共享计算机。 当多个用户共享 Windows 计算机时,将创建多个用户帐户,并且每个用户使用单个帐户登录以访问计算机。 随着安全意识的提高,越来越多的人使用最低特权用户帐户(也称为受限用户帐户)操作其计算机,这些帐户对系统没有完全控制权。 管理员帐户通常可以不受限制地访问计算机的每个部分。 这可能会影响基于 Windows 的游戏的工作方式。

对于编写游戏以使用最低特权用户帐户的游戏开发人员来说,还有其他好处。 在 Windows Vista 及更高版本中,强制实施最低特权用户帐户,这意味着系统上除本地管理员外,每个帐户都是最低特权用户帐户。 这将影响不遵循准则的游戏 (旧版应用程序) 在 Windows Vista 及更高版本上运行的方式。 例如,当应用程序尝试写入其无权访问的文件夹或注册表值时,文件写入会重定向到用户的虚拟文件存储。 此虚拟文件存储将驻留在用户具有写入访问权限的文件夹中。 此行为看起来可能不像直接失败写入尝试那样灾难性;但是,创建虚拟化文件的应用程序可能会使用户感到困惑,因为文件不会写入用户预期的位置。 例如,将高分文件写入可执行文件夹所在的文件夹的游戏将改为将这些文件写入虚拟化文件夹。 因此,一个用户看不到另一个用户实现的高分,因为每个用户都有单独的虚拟化文件存储。

遵循本文中指南的游戏将使用最低特权用户帐户运行,因此将保持与 Windows Vista 及更高版本的兼容性。

Least-Privileged用户帐户的文件访问

Windows 支持两个文件系统:FAT32 和 NTFS。 FAT32 是一个旧文件系统,仅支持后向兼容性;NTFS 支持更强大、更可靠的文件权限。 随着零售商在 NTFS 分区硬盘驱动器上预安装了 Windows 的新计算机,NTFS 的使用正在扩大。 在基于 NTFS 的 Windows XP 系统上,具有最低特权用户帐户的用户只能对多个文件夹进行有限的访问。 但是,他们将在基于 FAT32 的 Windows XP 系统上拥有完全访问权限。

下表列出了这些文件夹的默认位置及其权限。

路径 文件夹内容 读取 写入 创建/删除
<Drive>:\Windows Windows 操作系统 x
<Drive>:\Program Files 可执行应用程序文件 x
<Drive>:\Documents and Settings\Username* 每个用户的文件 x x x
<Drive>:\Documents and Settings\All Users 所有用户文件 x x x

 

* 用户名是用户的登录名。

在最低特权用户帐户中,可以在以下任一文件夹中读取、写入、创建和删除文件:Documents and Settings\Username 或 Documents and Settings\All Users。

这意味着您不应将保存游戏放在 \Program Files 中,而应将其置于 \My Documents 的子文件夹中。 此外,不应将临时应用程序数据放在 \Program Files 或 \My Documents 中,而应将其放置在“应用程序数据”文件夹中, (CSIDL_LOCAL_APPDATA) 。

更具体地说,每个游戏应处理两种方案:

方案 1:用户无需查看或更改的文件

典型的示例是游戏的配置文件、临时文件和游戏缓存文件。 这些文件通常保存在“应用程序数据”文件夹中。 若要获取此文件夹路径,请使用 CSIDL_APPDATA 或 CSIDL_LOCAL_APPDATA 调用 SHGetFolderPath 函数,如以下代码示例所示。

#include <shlobj.h>
#include <strsafe.h>

#define APPNAME L"MyApp"

WCHAR wszPath[MAX_PATH];

// Local Application Data
SHGetFolderPath( hWnd, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wszPath );
StringCchCatW( wszPath, MAX_PATH, L"\\" );
StringCchCatW( wszPath, MAX_PATH, APPNAME );

// Create the folder wszPath
// Then create files in wszPath
// Roaming Application Data
SHGetFolderPath( hWnd, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wszPath );
StringCchCatW( wszPath, MAX_PATH, L"\\" );
StringCchCatW( wszPath, MAX_PATH, APPNAME );

// Create the folder wszPath
// Then create files in wszPath

本地和漫游应用程序数据文件夹之间的区别在于,在 Windows 2000 和 Windows XP 上,漫游内容在登录/注销过程中复制到服务器和从服务器复制,而本地内容则不是。 对于大多数游戏,本地应用程序数据就足够了。

方案 2:用户需要查看或更改的文件

一个典型的示例是用户保存的游戏文件。 将文件存储在用户的文档文件夹中,以便用户可以轻松查看这些文件。 应用程序通过使用 CSIDL_PERSONAL 调用 SHGetFolderPath 来获取用户的文档文件夹路径,如以下代码示例所示:

#include <shlobj.h>
#include <strsafe.h>

#define APPNAME L"MyApp"

WCHAR wszPath[MAX_PATH];

SHGetFolderPath( hWnd, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, wszPath );
StringCchCatW( wszPath, MAX_PATH, L"\\" );
StringCchCatW( wszPath, MAX_PATH, APPNAME );

// Create the folder wszPath
// Then create files in wszPath

有时,游戏可能需要存储所有用户都希望查看和使用的文件。 一个示例是高分记录,其中所有用户都写入同一记录文件,以便在系统范围内维护高分,而不是为每个用户单独设置高分。 其他示例包括下载的地图、任务和游戏修改。 如果共享这些内容,则只有一个用户需要下载它们,而不是每个用户。 在此方案中,请使用共享配置文件文件夹下的文档文件夹,如以下代码所示。

#include <shlobj.h>
#include <strsafe.h>

#define APPNAME L"MyApp"

WCHAR wszPath[MAX_PATH];

SHGetFolderPath( hWnd, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, wszPath );
StringCchCatW( wszPath, MAX_PATH, L"\\" );
StringCchCatW( wszPath, MAX_PATH, APPNAME );

// Create the folder wszPath
// Then create files in wszPath

Least-Privileged用户帐户的注册表访问

应用程序通常使用 Windows 注册表来存储信息。 与文件访问类似,管理员和最低特权用户帐户对注册表的权限不同。 对于最低特权用户帐户,整个HKEY_LOCAL_MACHINE节点是只读的。 例如,游戏可以读取默认配置信息,但可能不会将任何新信息写入此节点。 因此,在需要写入注册表的最低特权用户模式下运行的游戏需要使用 HKEY_CURRENT_USER 节点来存储每个用户的信息,如以下代码所示。

#define APP_REGISTRY_KEY_PATH L"Software\\MyCompany\\MyApp"

LONG lRetVal;
HKEY hKey;

lRetVal = RegCreateKeyExW( HKEY_CURRENT_USER,
                           APP_REGISTRY_KEY_PATH,
                           0,
                           NULL,
                           REG_OPTION_NON_VOLATILE,
                           KEY_WRITE|KEY_READ,
                           NULL,
                           &hKey,
                           NULL );

if( ERROR_SUCCESS == lRetVal )
{
    // Store information in hKey
}

值得注意的是,在安装过程中,注册表信息应写入HKEY_LOCAL_MACHINE,而不是HKEY_CURRENT_USER。 这是因为运行安装的人员通常是管理员,并且可能不是唯一使用该程序的人。 在这种情况下,向HKEY_CURRENT_USER写入会使信息对其他用户不可用。 这通常不是问题,因为在安装期间写入注册表的信息是适用于程序的每个用户的配置和默认设置。

卸载游戏时,需要付出额外的努力来删除游戏已写入注册表的每个值。 由于卸载程序由一个人(通常是管理员)运行,因此只需删除 HKEY_LOCAL_MACHINE 中的相关信息,HKEY_CURRENT_USER不会删除其他用户的值。 删除注册表中每用户信息的一种方法是枚举HKEY_USERS注册表配置单元根。 HKEY_USERS 下的每个子项对应于系统上特定用户的HKEY_CURRENT_USER配置单元。 通过枚举HKEY_USERS并删除每个子项下的游戏特定信息,卸载程序可确保不会留下任何信息。

使用Least-Privileged用户帐户进行修补

修补游戏涉及更新游戏的文件。 因此,它通常需要对游戏的程序文件夹具有写入访问权限。 当游戏由管理员完成时,修补游戏是一个简单的过程,因为他们可以不受限制地访问游戏的程序文件夹。 相反,由于访问限制,最低特权用户传统上很难(如果不是不可能)修补游戏。 现在, Windows Installer 已得到增强,使最低特权用户帐户修补成为可能。 若要利用此功能,建议游戏使用 Windows Installer 进行安装和修补。

从 Windows Installer 3.0 开始,最低特权用户可在满足某些条件时应用应用程序修补程序。 这些条件包括:

  • 该应用程序是使用 Windows Installer 3.0 安装的。
  • 该应用程序最初是按计算机安装的。
  • 该应用程序是从可移动媒体(如 CD-ROM 或数字视频光盘 (DVD) )安装的。
  • 修补程序由原始安装程序包 (.msi 文件) 标识的证书进行数字签名。
  • 可以根据数字签名验证修补程序。
  • 原始安装程序包未禁用最低特权用户帐户修补。
  • 系统管理员未通过系统策略禁用最低特权用户帐户修补。

通常,最低特权用户无法修改游戏的程序文件。 但是,当满足上述条件并启用 LUA 修补时,Windows Installer 可以更新游戏的文件,以便用户获取最新版本。

注意

本文中包含的信息与预发布软件产品有关,该产品在首次商业发布之前可能会进行实质性修改。 因此,在首次商业发布时,这些信息可能无法准确描述或反映软件产品。 本文仅供参考,Microsoft 对本文或其中所含信息不作任何明示或默示保证。