Windows组策略的刷新和修改

Windows组策略的刷新和修改-唯嘉利亚云安全

Windows有一个gpedit.msc,很好用的一个工具,可以定制Windows很多的配置。但是如果我们需要自己的程序来修改这些配置的话,你会发现Windows的组策略根本不认!但是你修改注册表重新启动机器后,某些配置是起作用的,这个原因在于,我们必须同时刷新系统,而且必须刷新组策略。
Windows组策略会在你的注册表中建立一个组策略的缓冲,必须更新这个缓冲才会同时起作用!
下面以修改Windows XP的开始中的“注销”菜单项配置来说明。
注意:在Windows组策略中,一般地,如果注册表项目不存在,则显示为“未配置”,如果数值为0,则显示为已禁用,为1则显示为已启用,其他的值和对应数据相关。
Windows开始菜单的注销配置存储在Software\Microsoft\Windows\CurrentVersion\Policies\Explorer下
数值为: StartMenuLogOff(DWORD) = 0 | 1;
我们正常写注册表代码为:
RootKey := HKEY_CURRENT_USER;
if OpenKey(‘Software\Microsoft\Windows\CurrentVersion\Policies\Explorer’, True) then
begin
WriteInteger(‘StartMenuLogOff’, 0);
end;
写入注册表后刷新系统或者重新启动服务器,是可以起作用的,但是组策略不认,因此在下一次组策略刷新后可能会导致配置失效,因此还是必须让组策略接纳我们的修改,组策略的缓冲存储在注册表 Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{574DE082-1E91-47C9-95A1-C731CC87F739}Machine\下,其中的GUID为组策略在注册表中映射,组策略实际存储在文件%system%wbem\Repository\FS\OBJECTS.DATA中,该GUID是动态的,每次运行Gpedit.msc或者进行其他组策略操作的时候都不一样。然后必须在这个Key下建立你的除Root外的Key,其中的Machine也可以为User,决定于策略的有效范围!并写入你的数据,最后刷新系统即可。
因此完整的代码如下:
uses ComObj, ActiveX, Registry;
const
GPO_OPEN_LOAD_REGISTRY = $ 00000001; // Load the registry files
{$ EXTERNALSYM GPO_OPEN_LOAD_REGISTRY}
GPO_OPEN_READ_ONLY = $ 00000002; // Open the GPO as read only
GPO_SECTION_ROOT = 0; // Root
{$ EXTERNALSYM GPO_SECTION_ROOT}
GPO_SECTION_USER = 1; // User
{$ EXTERNALSYM GPO_SECTION_USER}
GPO_SECTION_MACHINE = 2; // Machine
const
IID_GPO : TGUID = ‘{EA502722-A23D-11d1-A7D3-0000F87571E3}’;
type
HPROPSHEETPAGE = Pointer;
{$ EXTERNALSYM HPROPSHEETPAGE}
PHPROPSHEETPAGE = ^HPROPSHEETPAGE;
LPOLESTR = POleStr;
_GROUP_POLICY_OBJECT_TYPE = (
GPOTypeLocal, // GPO on the local machine
GPOTypeRemote, // GPO on a remote machine
GPOTypeDS); // GPO in the Active Directory
{$ EXTERNALSYM _GROUP_POLICY_OBJECT_TYPE}
GROUP_POLICY_OBJECT_TYPE = _GROUP_POLICY_OBJECT_TYPE;
IGroupPolicyObject = interface (IUnknown)
[‘{EA502723-A23D-11d1-A7D3-0000F87571E3}’]
function New(pszDomainName, pszDisplayName: LPOLESTR; dwFlags: DWORD): HRESULT; stdcall;
function OpenDSGPO(pszPath: LPOLESTR; dwFlags: DWORD): HRESULT; stdcall;
function OpenLocalMachineGPO(dwFlags: DWORD): HRESULT; stdcall;
function OpenRemoteMachineGPO(pszComputerName: LPOLESTR; dwFlags: DWORD): HRESULT; stdcall;
function Save(bMachine, bAdd: BOOL; const pGuidExtension, pGuid: TGUID): HRESULT; stdcall;
function Delete: HRESULT; stdcall;
function GetName(pszName: LPOLESTR; cchMaxLength: Integer): HRESULT; stdcall;
function GetDisplayName(pszName: LPOLESTR; cchMaxLength: Integer): HRESULT; stdcall;
function SetDisplayName(pszName: LPOLESTR): HRESULT; stdcall;
function GetPath(pszPath: LPOLESTR; cchMaxPath: Integer): HRESULT; stdcall;
function GetDSPath(dwSection: DWORD; pszPath: LPOLESTR; cchMaxPath: Integer): HRESULT; stdcall;
function GetFileSysPath(dwSection: DWORD; pszPath: LPOLESTR; cchMaxPath: Integer): HRESULT; stdcall;
//
// Returns a registry key handle for the requested section. The returned
// key is the root of the registry, not the Policies subkey. To set / read
// a value in the Policies subkey, you will need to call RegOpenKeyEx to
// open Software\Policies subkey first.
//
// The handle has been opened with ALL ACCESS rights. Call RegCloseKey
// on the handle when finished.
//
// If the GPO was loaded / created without the registry being loaded
// this method will return E_FAIL.
//
// dwSection is either GPO_SECTION_USER or GPO_SECTION_MACHINE
// hKey contains the registry key on return
//
function GetRegistryKey(dwSection: DWORD; var hKey: HKEY): HRESULT; stdcall;
function GetOptions(var dwOptions: DWORD): HRESULT; stdcall;
function SetOptions(dwOptions, dwMask: DWORD): HRESULT; stdcall;
function GetType(var gpoType: GROUP_POLICY_OBJECT_TYPE): HRESULT; stdcall;
function GetMachineName(pszName: LPOLESTR; cchMaxLength: Integer): HRESULT; stdcall;
function GetPropertySheetPages(var hPages: PHPROPSHEETPAGE; var uPageCount: UINT): HRESULT; stdcall;
end;
const
REGISTRY_EXTENSION_GUID: TGUID = (
D1:$ 35378EAC; D2:$ 683F; D3:$ 11D2; D4:($ A8, $ 9A, $ 00, $ C0, $ 4F, $ BB, $ CF, $ A2));
CLSID_GPESnapIn: TGUID = (
D1:$ 8fc0b734; D2:$ a0e1; D3:$ 11d1; D4:($ a7, $ d3, $ 0, $ 0, $ f8, $ 75, $ 71, $ e3));
procedure TForm1.Button1Click(Sender: TObject);
var
GPO : IGroupPolicyObject;
Key : HKEY;
begin
GPO := CreateComObject(IID_GPO) as IGroupPolicyObject;
if S_OK = GPO.OpenLocalMachineGPO(GPO_OPEN_LOAD_REGISTRY) then
begin
if S_OK = GPO.GetRegistryKey(GPO_SECTION_USER, Key) then
with TRegistry.Create do
try
RootKey := HKEY_CURRENT_USER;
if OpenKey(‘Software\Microsoft\Windows\CurrentVersion\Policies\Explorer’, True) then
begin
WriteInteger(‘StartMenuLogOff’, 0);
end;
RootKey := Key;
if OpenKey(‘\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer’, True) then
begin
WriteInteger(‘StartMenuLogOff’, 0);
end;
RegCloseKey(Key);
GPO.Save(False, True, REGISTRY_EXTENSION_GUID, CLSID_GPESnapIn);
finally
Free;
end;
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, Integer(PChar(‘Polices’)), 0);
end;
end;
同时需要注意的是,组策略不支持多线程处理的,总是以最后的一个存储结果为准,因此在测试上面代码的时候,请不要运行gpedit.msc,如果要验证结果是否正确,可以先启动gpedit.msc,记录下配置,然后关闭gpedit.msc,再运行上面的代码,然后启动gpedit.msc查看配置是不是已经改过来了? 🙂
BTW,组策略的全部注册表项目,可以在MSDN中的Group Policy Registry Table目录中找到。
地址: ms-help://MS.MSDNQTR.2004JAN.1033/gp/gpref.htm
网友kaso_tian的补充:
经过Kingron的指点,我也搞定的组策略,而且证明K兄的思路非常正确.下边把我的vc++.net代码发上来共享.PS:因为是公司的项目,所以只发个我写的修改组策略的函数,别的有什么问题E-MAIL我

private: System::Boolean SetGroupPolicy(HKEY hKey,LPCTSTR subKey,LPCTSTR valueName,DWORD dwType,const BYTE* szkeyValue,DWORD dwkeyValue){
HKEY ghKey,ghSubKey,hSubKey;
LPDWORD flag = NULL;
//初始化GPO接口对象,如果失败,提示错误信息
HRESULT hr = CoCreateInstance(CLSID_GroupPolicyObject,NULL,CLSCTX_ALL,IID_IGroupPolicyObject,(LPVOID*)&pGPO);
if(!SUCCEEDED(hr))
MessageBox::Show(L”GPO接口对象初始化失败”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
//修改本地注册表
if ( RegCreateKeyEx(hKey,
subKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hSubKey,
flag) != ERROR_SUCCESS){
return false;
}
if(dwType == REG_SZ){
if( RegSetValueEx(hSubKey,valueName,0,dwType,szkeyValue,strlen((char*)szkeyValue)+1) != ERROR_SUCCESS){
RegCloseKey(hSubKey);
return false;
}
}
else if(dwType == REG_DWORD){
if( RegSetValueEx(hSubKey,valueName,0,dwType,(BYTE*)&dwkeyValue,sizeof(dwkeyValue)) != ERROR_SUCCESS){
RegCloseKey(hSubKey);
return false;
}
}
//修改本地GPO
if(!SUCCEEDED(hr)){
MessageBox::Show(L”GPO接口对象初始化失败”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
return false;
}
if(pGPO->OpenLocalMachineGPO(GPO_OPEN_LOAD_REGISTRY) != S_OK){
MessageBox::Show(L”获取本地GPO映射失败”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
return false;
}//OpenLocalMachine
if(pGPO->GetRegistryKey(GPO_SECTION_USER,&ghKey) != S_OK){
MessageBox::Show(L”获取本地GPO映射注册表根键失败”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
return false;
}//GetRegistryKey
if(RegCreateKeyEx(ghKey,
subKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&ghSubKey,
flag) != ERROR_SUCCESS){
RegCloseKey(ghKey);
MessageBox::Show(L”无法创建组策略注册表子项目”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
return false;
}//RegCreateKeyEx
if(dwType == REG_SZ){
if(RegSetValueEx(ghSubKey,valueName,0,dwType,szkeyValue,strlen((char*)szkeyValue)+1) != ERROR_SUCCESS){
RegCloseKey(ghKey);
RegCloseKey(ghSubKey);
MessageBox::Show(L”无法创建组策略注册表子项目值”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
return false;
}//RegSetValueEx
}
else if(dwType == REG_DWORD){
if(RegSetValueEx(ghSubKey,valueName,0,dwType,(BYTE*)&dwkeyValue,sizeof(dwkeyValue)) != ERROR_SUCCESS){
RegCloseKey(ghKey);
RegCloseKey(ghSubKey);
MessageBox::Show(L”无法创建组策略注册表子项目值”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
return false;
}//RegSetValueEx
}
if(pGPO->Save(false,true,&ng1,&ng2) != S_OK){
RegCloseKey(ghKey);
RegCloseKey(ghSubKey);
MessageBox::Show(L”保存组策略失败”,L””,MessageBoxButtons::OK,MessageBoxIcon::Error);
return false;
}
pGPO->Release();
RegCloseKey(ghKey);
RegCloseKey(ghSubKey);
return true;
}