4 《Undocumented Windows 2000 Secrets》翻译 --- 第三章( 三 )


枚举服务和驱动
有时很有必要知道系统当前加载了那个服务或驱动,以及它们现在处于什么状态 。为了实现这一目的,SC 管理器提供了另一个名为 EnumServiceStatus() 的强大函数 。该函数需要一个管理器句柄和一个类型为 ENUM_SERVICE_STATUS 的数组,该数组中将包含有关当前已加载的服务或驱动的信息 。这个列表可以根据服务 / 驱动的类型和状态来过滤 。如果调用者提供的缓冲区不能一次性的容纳所有项目,可反复调用该函数直到获取所有的项目 。
不过很难预先计算出所需的缓冲区大小,这是因为缓冲区必须为那些大小未知的字符串提供额外的空间,这些字符串由 ENUM_SERVICE_STATUS 的成员引用 。幸运的是,EnumServiceStatus() 会返回剩余的项目所需的字节数,因此可以通过反复尝试得出确定的缓冲区大小 。列表 3-10 给出了 SERVICE_STATUS 和 ENUM_SERVICE_STATUS 结构的定义 。这些声明位于 Win32 头文件 WinSvc.h 中 。
typedef struct _SERVICE_STATUS
{
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;
typedef struct _ENUM_SERVICE_STATUS
{
LPTSTR lpServiceName;
LPTSTR lpDisplayName;
SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUS;
列表 3-10 SERVICE_STATUS 和 ENUM_SERVICE_STATUS 结构的定义
列表 3-11 给出的 w2kServiceList() 函数是来自 w2k_lib.dll 工具库的另一个好东东 。它省略了前面提到的动作,并返回一个随时可用的结构,该结构中包含所有请求的数据以及一对扩展结构 。该函数将返回一个指向 W2K_SERVICES 结构的指针,该结构定义于 w2k_lib.h ,在 列表 3-11 的顶部给出了其定义 。随 ENUM_SERVICE_STATUS 结构数组 aess[] ,W2K_SERVICES 结构体还包含四个附加成员 。dEntrIEs 表示向状态数组中复制了多少项目,dBytes 表示返回的 W2K_SERVICES 结构的大小 。dDisplayName 和 dServiceName 被分别设置为 aess[] 中的 lpDisplayName 和 lpServiceName 字符串的最大长度 。这些值将提供很大的方便,尤其是当你编写一个控制台模式的程序,在屏幕上输出服务 / 驱动列表,并要求名称列采用合适的对齐方式 。
为了提供精确的系统快照,w2kServiceList() 试图通过一次调用 EnumServiceStatus() 来获取所有的项目 。为此目的,该函数首先提供一个长度为 0 的缓冲区,这通常会导致返回 ERROR_MORE_DATA 错误代码 。在此种情况下,EnumServiceStatus() 将返回需要的缓冲区大小,然后按照此大小分配适当的缓冲区,然后再次调用 EnumServiceStatus()。此时,EnumServiceStatus() 应该返回成功 。不过,这存在一个很小的概率事件 --- 在两次调用 EnumServiceStatus() 之间另一个项目可能会被增加到列表中 。因此,将会在一个循环中重复这一过程直到所有的一切都正确或者一个非 ERROR_MORE_DATA 的错误返回 。
// -----------------------------------------------------------------
typedef struct _W2K_SERVICES
{
DWORD dEntries; // number of entries in aess[]
DWORD dBytes; // overall number of bytes
DWORD dDisplayName; // maximum display name length
DWORD dServiceName; // maximum service name length
ENUM_SERVICE_STATUS aess []; // service/driver status array
}
W2K_SERVICES, *PW2K_SERVICES, **PPW2K_SERVICES;
#define W2K_SERVICES_ sizeof (W2K_SERVICES)
#define W2K_SERVICES__(_n)
(W2K_SERVICES_((_n) * ENUM_SERVICE_STATUS_))
// -----------------------------------------------------------------
PW2K_SERVICES WINAPI w2kServiceList (BOOL fDriver,
BOOL fWin32,
BOOL fActive,
BOOL fInactive)

推荐阅读