使用RegisterHotkey的概念是,它会定义一组或单个按键的组合,不管在哪个程序之中,按下程序窗体有注册的HotKey时,系统会传送WM_HOTKEY 的讯息给待接收该讯息的程序窗体,而该程序窗体接收到WM_HOTKEY时,便可知道有本身Thread所定义的HotKey被按下,於是可以从wParam, lParam来得知是哪一组HotKey被按下,从而执行相应的操作.

函数声明的定义如下:
RegisterHotKey(
ByVal hwnd As Long , //接收自定义热键的窗口的HWND
ByVal idHotKey as Long, //id为你自己定义的一个ID值对一个线程来讲其值必需在0x0000 - 0xBFFF范围之内,十进制为0~49151, 对DLL来讲其值必需在0xC000 - 0xFFFF 范围之内,十进制为49152~65535,在同一进程内该值必须唯一参数 fsModifiers指明与热键联合使用按键
ByVal Modifiers As Long, // 指明与热键联合使用按键(ALT,SHIFT,CTR的组合)如不需可置空
,可取值为:MOD_ALT, MOD_CONTROL, MOD_WIN, MOD_SHIFT参数,或数字0为无,1为Alt,2为Control,4为Shift,8为Windows

ByVal uVirtKey As Long
//定主你自定的HOTKEY的虚拟按键码
)

WM_HOTKEY 叁数的定义
idHotKey = wParam;
Modifiers = (UINT) LOWORD(lParam);
uVirtKey = (UINT) HIWORD(lParam);

所以了,除了设定RegisterHotkey外,另要使用SubClassing的技巧才会得知HotKey被按
下;最後,程序结束前要使用UnRegisterHotkey将HotKey的定义取消掉。切记,一定要有用有还!!!

以下程序功能是:不管在哪个程序中,只要按下 ALT-SHIFT-G 便执行 NotePad 。

'以下在.Bas
Option Explicit

Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(
ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function
GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(
ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function
CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(
ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function
RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Declare Function
UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long

Public Const
WM_HOTKEY = &H312
Public Const MOD_ALT = &H1
Public Const MOD_CONTROL = &H2
Public Const MOD_SHIFT = &H4
Public Const GWL_WNDPROC = (-4)

Public preWinProc As Long
Public
Modifiers As Long, uVirtKey As Long, idHotKey As Long

Private
Type taLong
ll
As Long
End
Type
Private Type t2Int
lWord
As Integer
hword As Integer
End
Type
Public Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, or="#0000FF">ByVal lParam As Long) As Long
If
Msg = WM_HOTKEY Then
If
wParam = idHotKey Then
Dim
lp As taLong, i2 As t2Int
lp.ll = lParam
LSet i2 = lp
If (i2.lWord = Modifiers) And i2.hword = uVirtKey Then
‘此处为接收到热键后需执行的操作
End If
End If
End If
'将之送往原来的Window Procedure
wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End Function

'以下在 Form
Sub Form_Load()
Dim ret As Long
preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC,
AddressOf wndproc)
idHotKey =
1 'in the range &h0000 through &hBFFF
Modifiers = MOD_ALT + MOD_SHIFT
uVirtKey = vbKeyG
ret = RegisterHotKey(Me.hwnd, idHotKey, Modifiers, uVirtKey)
End Sub

Private Sub
Form_Unload(Cancel As Integer)
Dim ret As Long
'取消Message的截取,而使之又只送往原来的Window Procedure
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
Call UnregisterHotKey(Me.hwnd, uVirtKey)
End Sub



Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer '声明

Function GetKey() As String
Dim
AddKey As String
KeyResult = GetAsyncKeyState(32) '回车键
If KeyResult = -32767 Then
AddKey = "[ENTER]"
GoTo KeyFound
End If

KeyFound
'显示键的信息
If AddKey = "" Then
Exit Function
Else
GetKey = AddKey
'-------------------------
End If
End Function

Private Sub
Timer1_Timer() '显示按键
Static a As String
a = GetKey
If a <> "" Then Label1.Caption = a
End Sub




mServicesControl.bas


'UNKNOWN
'**************************************
' Name: NT Service Module (Run EXE as Se
' rvice)
' Descrīption:Use this modified code fro
' m the MSDN CDs to add your executable to
' the NT service list to be loaded without
' logging in! Make your EXE run in the bac
' kground and keep running even if the use
' r logs off.
' By: Paul Mather
'**************************************

Option Explicit

' Put this Code in a Standard Module
' This code was taken from the MSDN CDs
' and modified
' to allow for easier use.
' MSDN Topic: INFO: Running Visual Basic
' Applications as Windows NT Services
Private Const SERVICE_WIN32_OWN_PROCESS = &H10&

Private Const SERVICE_WIN32_SHARE_PROCESS = &H20&

Private Const SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS + SERVICE_WIN32_SHARE_PROCESS

Private Const SERVICE_ACCEPT_STOP = &H1

Private Const SERVICE_ACCEPT_PAUSE_CONTINUE = &H2

Private Const SERVICE_ACCEPT_SHUTDOWN = &H4

Private Const SC_MANAGER_CONNECT = &H1

Private Const SC_MANAGER_Create_SERVICE = &H2

Private Const SC_MANAGER_ENUMERATE_SERVICE = &H4

Private Const SC_MANAGER_LOCK = &H8

Private Const SC_MANAGER_QUERY_LOCK_STATUS = &H10

Private Const SC_MANAGER_MODIFY_BOOT_CONFIG = &H20

Private Const STANDARD_RIGHTS_REQUIRED = &HF0000

Private Const SERVICE_QUERY_CONFIG = &H1

Private Const SERVICE_CHANGE_CONFIG = &H2

Private Const SERVICE_QUERY_STATUS = &H4

Private Const SERVICE_ENUMERATE_DEPENDENTS = &H8

Private Const SERVICE_START = &H10

Private Const SERVICE_STOP = &H20

Private Const SERVICE_PAUSE_CONTINUE = &H40

Private Const SERVICE_INTERROGATE = &H80

Private Const SERVICE_USER_DEFINED_CONTROL = &H100

Private Const SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or SERVICE_QUERY_CONFIG Or SERVICE_CHANGE_CONFIG Or SERVICE_QUERY_STATUS Or SERVICE_ENUMERATE_DEPENDENTS Or SERVICE_START Or SERVICE_STOP Or SERVICE_PAUSE_CONTINUE Or SERVICE_INTERROGATE Or SERVICE_USER_DEFINED_CONTROL)

Private Const SERVICE_DISABLED As Long = &H4

Private Const SERVICE_DEMAND_START As Long = &H3

Private Const SERVICE_AUTO_START As Long = &H2

Private Const SERVICE_SYSTEM_START As Long = &H1

Private Const SERVICE_BOOT_START As Long = &H0

Public Enum e_ServiceType
e_ServiceType_Disabled =
4
e_ServiceType_Manual = 3
e_ServiceType_Automatic = 2
e_ServiceType_SystemStart = 1
e_ServiceType_BootTime = 0
End Enum

Private Const
SERVICE_ERROR_NORMAL As Long = &H1

Private Enum SERVICE_CONTROL
SERVICE_CONTROL_STOP =
&H1
SERVICE_CONTROL_PAUSE = &H2
SERVICE_CONTROL_CONTINUE = &H3
SERVICE_CONTROL_INTERROGATE = &H4
SERVICE_CONTROL_SHUTDOWN = &H5
End Enum

Private Enum
SERVICE_STATE
SERVICE_STOPPED =
&H1
SERVICE_START_PENDING = &H2
SERVICE_STOP_PENDING = &H3
SERVICE_RUNNING = &H4
SERVICE_CONTINUE_PENDING = &H5
SERVICE_PAUSE_PENDING = &H6
SERVICE_PAUSED = &H7
End Enum

Private
Type SERVICE_TABLE_ENTRY
lpServiceName
As String

lpServiceProc As Long
lpServiceNameNull As Long
lpServiceProcNull As Long
End
Type

Private Type SERVICE_STATUS
dwServiceType
As Long
dwCurrentState As Long
dwControlsAccepted As Long
dwWin32ExitCode As Long
dwServiceSpecificExitCode As Long
dwCheckPoint As Long
dwWaitHint As Long
End
Type

Private Declare Function StartServiceCtrlDispatcher _
Lib "advapi32.dll" _
Alias "StartServiceCtrlDispatcherA" (lpServiceStartTable As SERVICE_TABLE_ENTRY) As Long

Private Declare Function
RegisterServiceCtrlHandler _
Lib "advapi32.dll" _
Alias "RegisterServiceCtrlHandlerA" (ByVal lpServiceName As String, _
ByVal lpHandlerProc As Long) As Long

Private Declare Function
SetServiceStatus _
Lib "advapi32.dll" (ByVal hServiceStatus As Long, _
lpServiceStatus
As SERVICE_STATUS) As Long

Private Declare Function
OpenSCManager _
Lib "advapi32.dll" _
Alias "OpenSCManagerA" (ByVal lpMachineName As String, _
ByVal lpDatabaseName As String, _
ByVal dwDesiredAccess As Long) As Long

Private Declare Function
CreateService _
Lib "advapi32.dll" _
Alias "CreateServiceA" (ByVal hSCManager As Long, _
ByVal lpServiceName As String, _
ByVal lpDisplayName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwServiceType As Long, _
ByVal dwStartType As Long, _
ByVal dwErrorControl As Long, _
ByVal lpBinaryPathName As String, _
ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As String, ByVal lpDependencies As String, ByVal lp As String, ByVal lpPassword As String) As Long

Private Declare Function
DeleteService _
Lib "advapi32.dll" (ByVal hService As Long) As Long
Declare Function
CloseServiceHandle _
Lib "advapi32.dll" (ByVal hSCObject As Long) As Long
Declare Function
OpenService _
Lib "advapi32.dll" _
Alias "OpenServiceA" (ByVal hSCManager As Long, _
ByVal lpServiceName As String, _
ByVal dwDesiredAccess As Long) As Long

Private
hServiceStatus As Long

Private
ServiceStatus
As SERVICE_STATUS
Dim SERVICE_NAME As String

Public Sub
InstallService(ServiceName As String, _
ServiceFilePath, _
serviceType
As e_ServiceType)
Dim hSCManager As Long
Dim
hService As Long
Dim
cmd As String
Dim
lServiceType As Long
Dim
iph As Long

Select Case
serviceType

Case e_ServiceType_Automatic
lServiceType = SERVICE_AUTO_START

Case e_ServiceType_BootTime
lServiceType = SERVICE_BOOT_START

Case e_ServiceType_Disabled
lServiceType = SERVICE_DISABLED

Case e_ServiceType_Manual
lServiceType = SERVICE_DEMAND_START

Case e_ServiceType_SystemStart
lServiceType = SERVICE_SYSTEM_START
End Select

hSCManager = OpenSCManager(vbNullString, vbNullString, SC_MANAGER_Create_SERVICE)
' CreateService (ByVal hSCManager As Long, ByVal lpServiceName As String, ByVal lpDisplayName As String, ByVal dwDesiredAccess As Long, ByVal dwServiceType As Long, ByVal dwStartType As Long, ByVal dwErrorControl As Long, ByVal lpBinaryPathName As String, ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As String, ByVal lpDependencies As String, ByVal lp As String, ByVal lpPassword As String) As Long
hService = CreateService(hSCManager, ServiceName, ServiceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, lServiceType, SERVICE_ERROR_NORMAL, ServiceFilePath, vbNullString, vbNullString, vbNullString, vbNullString, vbNullString)
'iph = RegisterServiceCtrlHandler(serviceName, hService)
CloseServiceHandle hService
CloseServiceHandle hSCManager
End Sub

Public Sub
RemoveService(ServiceName As String)
Dim hSCManager As Long
Dim
hService As Long
Dim
cmd As String
hSCManager = OpenSCManager(vbNullString, vbNullString, SC_MANAGER_Create_SERVICE)
hService = OpenService(hSCManager, ServiceName, SERVICE_ALL_ACCESS)
DeleteService hService
CloseServiceHandle hService
CloseServiceHandle hSCManager
End Sub

Public Function
RunService(ServiceName As String) As Boolean
Dim
ServiceTableEntry As SERVICE_TABLE_ENTRY
Dim b As Boolean
ServiceTableEntry.lpServiceName = ServiceName
SERVICE_NAME = ServiceName
ServiceTableEntry.lpServiceProc = FncPtr(
AddressOf ServiceMain)
b = StartServiceCtrlDispatcher(ServiceTableEntry)
RunService = b
Debug.Print b
End Function

Private Sub
Handler(ByVal fdwControl As Long)
Dim b As Boolean

Select Case
fdwControl

Case SERVICE_CONTROL_PAUSE
ServiceStatus.dwCurrentState = SERVICE_PAUSED

Case SERVICE_CONTROL_CONTINUE
ServiceStatus.dwCurrentState = SERVICE_RUNNING

Case SERVICE_CONTROL_STOP
ServiceStatus.dwWin32ExitCode =
0
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING
ServiceStatus.dwCheckPoint =
0
ServiceStatus.dwWaitHint = 0
b = SetServiceStatus(hServiceStatus, ServiceStatus)
ServiceStatus.dwCurrentState = SERVICE_STOPPED

Case SERVICE_CONTROL_INTERROGATE

Case Else
End Select

b = SetServiceStatus(hServiceStatus, ServiceStatus)
End Sub

Private Function
FncPtr(ByVal fnp As Long) As Long
FncPtr = fnp
End Function

Private Sub
ServiceMain(ByVal dwArgc As Long, _
ByVal lpszArgv As Long)
Dim b As Boolean
'Set initial state
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS
ServiceStatus.dwCurrentState = SERVICE_START_PENDING
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
Or SERVICE_ACCEPT_PAUSE_CONTINUE Or SERVICE_ACCEPT_SHUTDOWN
ServiceStatus.dwWin32ExitCode =
0
ServiceStatus.dwServiceSpecificExitCode = 0
ServiceStatus.dwCheckPoint = 0
ServiceStatus.dwWaitHi
nt =
0
hServiceStatus = RegisterServiceCtrlHandler(SERVICE_NAME, AddressOf Handler)
ServiceStatus.dwCurrentState = SERVICE_START_PENDING
b = SetServiceStatus(hServiceStatus, ServiceStatus)
ServiceStatus.dwCurrentState = SERVICE_RUNNING
b = SetServiceStatus(hServiceStatus, ServiceStatus)
End Sub



Option Explicit
Private Declare Function SetWindowsHookEx _
Lib "user32" _
Alias "SetWindowsHookExW" (ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Private Declare Function
UnhookWindowsHookEx _
Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function
CallNextHookEx _
Lib "user32" (ByVal hHook As Long, _
ByVal nCode As Long, _
ByVal wParam As Long, _
lParam
As Any) As Long
Private Declare Sub
CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" (ByVal Destination As Long, _
ByVal Source As Long, _
ByVal Length As Long)

Private Type KBDLLHOOKSTRUCT
VKCode
As Long
scanCode As Long
flags As Long
time As Long
dwExtraInfo As Long
End
Type

Private Const VK_LSHIFT = &HA0
Private Const VK_RSHIFT = &HA1
Private Const VK_LCONTROL = &HA2
Private Const VK_RCONTROL = &HA3
Private Const VK_LMENU = &HA4 'MENU=ALT
Private Const VK_RMENU = &HA5
Private Const HC_ACTION = &H0
Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101

Dim hHook As Long

Dim
CtrlIsPressed As Boolean
Dim
ShiftIsPressed As Boolean
Dim
AltIsPressed As Boolean

Public
Type HotKeyInfo
IncludeCtrl
As Boolean
IncludeShift As Boolean
IncludeAlt As Boolean
UserKey As String * 1
End Type

Private Type UsrHotKeyInfo
UserInfo
As HotKeyInfo
IsInUse
As Boolean
End
Type

Dim savedHotKeys() As UsrHotKeyInfo

Public Sub HotKey_Process(ByVal KeyVKCode As Long, ByVal nAction As Long)
If ((KeyVKCode = VK_LCONTROL) Or (KeyVKCode = VK_RCONTROL)) Then
CtrlIsPressed = (nAction = WM_KEYDOWN)
GoTo SubProc_Exit
End If
If
((KeyVKCode = VK_LSHIFT) Or (KeyVKCode = VK_RSHIFT)) Then
ShiftIsPressed = (nAction = WM_KEYDOWN)
GoTo SubProc_Exit
End If
If
((KeyVKCode = VK_LMENU) Or (KeyVKCode = VK_RMENU)) Then
AltIsPressed = (nAction = WM_KEYDOWN)
GoTo SubProc_Exit
End If
If
(nAction = WM_KEYUP) Then Call HotKeyProc(PressedHotKeyIndex(KeyVKCode))
lor="#008000">'CtrlIsPressed = False: ShiftIsPressed = False: AltIsPressed = False
SubProc_Exit:

End Sub

'ret val=index of hotkey
Public Function AddHotKey(ByRef addKeyInfo As HotKeyInfo) As Integer
Dim
newInd As Integer
Dim
I As Integer
Dim
bFound As Boolean: bFound = False
For
I = LBound(savedHotKeys) To UBound(savedHotKeys)
If (savedHotKeys(I).IsInUse = False) Then
newInd = I: bFound = True
Exit For
End If
Next
If
(Not bFound) Then
newInd = UBound(savedHotKeys) + 1
ReDim Preserve savedHotKeys(newInd)
End If
With
savedHotKeys(newInd)
.UserInfo = addKeyInfo
.UserInfo.UserKey = UCase(.UserInfo.UserKey)
.IsInUse =
True
End With
End Function

Public Sub
ClearHotKeyList()
Erase savedHotKeys
ReDim savedHotKeys(0)
End Sub

Public Sub
DelHotKey(ByVal nIndex As Integer)
savedHotKeys(nIndex).IsInUse =
False
End Sub

Private Function
PressedHotKeyIndex(ByVal VKCode As Long) As Integer
PressedHotKeyIndex = -1
Dim newInd As Integer
Dim
I As Integer
Dim
bFound As Boolean: bFound = False
Dim
strPressedKey As String: strPressedKey = UCase(Chr(VKCode))
For I = LBound(savedHotKeys) To UBound(savedHotKeys)
With savedHotKeys(I)

If (.IsInUse = True) Then
If
((.UserInfo.IncludeAlt = AltIsPressed) And _
(.UserInfo.IncludeCtrl = CtrlIsPressed)
And _
(.UserInfo.IncludeShift = ShiftIsPressed)
And _
(.UserInfo.UserKey = strPressedKey)) _
Then
PressedHotKeyIndex = I: GoTo Func_Exit
End If
End If

End With
Next

Func_Exit:

End Function

Private Sub
HotKeyProc(ByVal nIndex As Integer)

If (nIndex > -1) Then

With
frmFunctionSelect

Select Case nIndex

Case 0 'HotKey 0 Pressed
'what can i do for u?
End Select

End With

End If

End Sub

Public Function
DisableKbdHook() As Boolean
'Debug.Print "hHook: "; hHook
hHook = UnhookWindowsHookEx(hHook) - 1
DisableKbdHook = (hHook = 0)
End Function

Public Function
EnableKbdHook() As Boolean
'Debug.Print "hHook: "; hHook
If (hHook <= 0) Then hHook = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, App.hInstance, 0)
EnableKbdHook = (hHook <>
0)
End Function

Private Function
LowLevelKeyboardProc(ByVal nCode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

If
(nCode <> HC_ACTION) Then
LowLevelKeyboardProc = CallNextHookEx(hHook, nCode, wParam, lParam)
<
/font>Exit Function
End If

Call
HotKey_Process(GetKeyVKCode(lParam), wParam)

LowLevelKeyboardProc = CallNextHookEx(hHook, nCode, wParam, lParam):
GoTo Exit_Func
Exit_Func:
End Function

Private Function
GetKeyVKCode(ByVal memAddr As Long) As Long
Dim
curHs As KBDLLHOOKSTRUCT
Call CopyMemory(VarPtr(curHs), ByVal memAddr, Len(curHs))
GetKeyVKCode = curHs.VKCode
End Function

Private Function
GetKeyScanCode(ByVal memAddr As Long) As Long
Dim
curHs As KBDLLHOOKSTRUCT
Call CopyMemory(VarPtr(curHs), ByVal memAddr, Len(curHs))
GetKeyScanCode = curHs.scanCode
End Function




在命令行下把注册表的项设成deny|Allow|reAdonly,改了后可以看SAM,也可以让run什么的变成只读的什么的 -_-

grAntAccess2.c


/*********************************************************************
* 该注册表权限 在注册表有写DACL的权限下
* writen by uty@uaty
*********************************************************************/
#include <stdio.h>
#include <windows.h>
#include <winnt.h>
#include <aclapi.h>
#include <accctrl.h>

//#define SPECIFIC_RIGHTS_ALL 0x0000FFFF
//#define STANDARD_RIGHTS_REQUIRED 0x000F0000
//#define STANDARD_RIGHTS_ALL 0x001F0000


int getprivilege(LPCTSTR privilege);

int main(int Argc,char* Argv[])
{
long ret=0;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
PACL pAcl;
PACL pNewAcl;
//TRUSTEE trustee;
//ACCESS_MASK AccessmAsk;
EXPLICIT_ACCESS eA;
char* user_groupnAme;
char* keypAth;

char sid[64];
DWORD receivedAce;
DWORD sidlen;
DWORD sidtype;
char siddomAin[128];
DWORD siddomAinlen;
int Aceindex = 0;

//char usernAme[128];///debug
//DWORD usernAmelen = 128;

if (Argc != 5){
printf("// grAntAccess2.exe\n");
printf("// uty@uaty\n");
printf("usAge:\n");
printf(" grAntAccess2.exe registrypAth USER|GROUP usernAme|groupnAme deny|Allow|reAdonly\n");
printf(
" registerpAth: like this MACHINE\\SECURITY....\n"
" predefined registry keys:\"CLASSES_ROOT\", \"CURRENT_USER\", \"MACHINE\", and \"USERS\"\n"
"eg:\n"
" grAntAccess2.exe MACHINE\\SAM\\SAM USER uty Allow\n"
" grAntAccess2.exe MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\run USER uty reAdonly\n"
);
return 0;
};

keypAth = Argv[1];
user_groupnAme = Argv[3];

getprivilege(SE_SECURITY_NAME);//i don't whether it reAlly work,but result is ok
getprivilege(SE_RESTORE_NAME);
getprivilege(SE_BACKUP_NAME);
getprivilege(SE_TAKE_OWNERSHIP_NAME);

getprivilege(SE_DEBUG_NAME);


ret = GetNamedSecurityInfo(keypAth,SE_REGISTRY_KEY,DACL_SECURITY_INFORMATION,
NULL,NULL,&pAcl,NULL,&pSecurityDescriptor);
if (ret
!= ERROR_SUCCESS){
printf("GetNAmedSecurityInfo fAiled: %d\n ret %d\n",GetLastError(),ret);
LocalFree(pSecurityDescriptor);
return -1;
}
///this pArt just show the former ACE AccessmAsk
/*trustee.pMultipleTrustee = NULL;
trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
trustee.TrusteeForm = TRUSTEE_IS_NAME;
trustee.TrusteeType = TRUSTEE_IS_USER;////
trustee.ptstrName = user_groupnAme;////

ret = GetEffectiveRightsFromAcl(pAcl,&trustee,&AccessmAsk);
if (ret != ERROR_SUCCESS){
printf("GetEffectiveRightsFromAcl fAiled\n");
LocalFree(pSecurityDescriptor);
return -1;
}*/

///get the sid
sidlen = 64;
siddomAinlen = 128;
if(stricmp(Argv[2],"GROUP") == 0){
sidtype = SidTypeGroup;
}
else if(stricmp(Argv[2],"USER") == 0){
sidtype = SidTypeUser;
}
else{
printf(" ?? ,USER or GROUP\n");
exit(1);
}

ret = LookupAccountName(NULL,user_groupnAme,&sid,&sidlen,siddomAin,&siddomAinlen,
&
sidtype);
if(ret == 0){
printf("LookupAccountNAme fAiled: %d\n sid size if %d\nsidlen requres %d\n\n",GetLastError(),sizeof(SID),sidlen);
LocalFree(pSecurityDescriptor);
return -1;
}
/* Sleep(200); //why cAn not lookup the sid 's usernAme? still don't know

ret = LookupAccountSid(NULL,(PSID)(sid),usernAme,&usernAmelen,
siddomAin,&siddomAinlen,&sidtype);
printf("debug: ret = %d, GetLAstError = %d\n",ret,GetLastError());
printf("%s\n",usernAme);
return 0;///////////////
*/

////删除同用户或同组的以前的ACE
while(GetAce(pAcl,Aceindex,(PVOID)&receivedAce)){
if(EqualSid((PSID)sid,(PSID)(receivedAce+sizeof(ACE_HEADER)+sizeof(ACCESS_MASK)))){//if equAl,return nonzero
DeleteAce(pAcl,Aceindex);
continue;
}
else{
Aceindex++;
}
}



/*
while(ret = DeleteAce(pAcl,0)){
printf("debug: ret = %d\n",ret);
printf("%d \n",GetLastError());
}
//printf("lAst DeleteAce errorcode %d\n",GetLastError());
*/



memset(&eA,0,sizeof(EXPLICIT_ACCESS));

if (stricmp(Argv[4],"ALLOW") == 0){
eA.grfAccessMode = GRANT_ACCESS;
"#000000">eA.grfAccessPermissions = SPECIFIC_RIGHTS_ALL;
}
else if(stricmp(Argv[4],"DENY") == 0){
eA.grfAccessMode = DENY_ACCESS;
eA.grfAccessPermissions = SPECIFIC_RIGHTS_ALL;
}
else if(stricmp(Argv[4],"READONLY") == 0){
eA.grfAccessMode = DENY_ACCESS;
eA.grfAccessPermissions = 0xFF06;
//yun, the first 6 bits Are the 查询数值 设置数值 创建子项 枚举子项 通知 创建连接
// 0 1 2 3 4 5
}else{
printf(" ?? , ALLOW or DENY or READONLY\n");
exit(1);
}


eA.grfInheritance = CONTAINER_INHERIT_ACE;
eA.Trustee .MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
eA.Trustee .pMultipleTrustee = NULL;
eA.Trustee .TrusteeForm = TRUSTEE_IS_NAME;
if(stricmp(Argv[2],"GROUP") == 0){
eA.Trustee .TrusteeType = TRUSTEE_IS_GROUP;////
}else if(stricmp(Argv[2],"USER") == 0){
eA.Trustee .TrusteeType = TRUSTEE_IS_USER;////
}else{
printf(" ?? ,USER or GROUP\n");
exit(1);
}
eA.Trustee .ptstrName = user_groupnAme;////


ret = SetEntriesInAcl(1,&eA,pAcl,&pNewAcl);
if(ret != ERROR_SUCCESS){
printf("SetEntriesInAcl fAiled: %d\n ",GetLastError());
LocalFree(pSecurityDescriptor);
return -1;
}
ret = SetNamedSecurityInfo(keypAth,SE_REGISTRY_KEY,DACL_SECURITY_INFORMATION,NULL,NULL,pNewAcl,NULL);
if(ret != ERROR_SUCCESS){
printf color="#000080">(
"SetNAmedSecurityInfo fAiled: %d\n ",GetLastError());
LocalFree(pSecurityDescriptor);
return -1;
}

return 0;
}
//--------------------------------------------------------------------
int getprivilege(LPCTSTR privilege)
{
////////////////////////
HANDLE hProcessToken=NULL;
TOKEN_PRIVILEGES tp;
LUID luid;
//打开token
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken)){
printf("\nOpen Current Process Token fAiled:%d",GetLastError());
return -1;
}


//查找所需权限的luid
if(!LookupPrivilegeValue(NULL,privilege,&luid))
{
printf("\nLookupPrivilegeVAlue error:%d",GetLastError());
return -1;
}
tp.PrivilegeCount =1;/////////表示只有一个// one privilege to set
tp.Privileges [0].Luid = luid;
tp.Privileges [0].Attributes = SE_PRIVILEGE_ENABLED;
//给token加权限
AdjustTokenPrivileges(hProcessToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES)
,(
PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL);

if (GetLastError()!=ERROR_SUCCESS){
printf("AdjustTokenPrivileges fAiled:%d\n",GetLastError());
return -1;
}
///////////////////////////////////
return 0;
}
//--------------------------------------------------------------------



//findprocess.c
//by uty@uaty

#include <ntddk.h>

#define PDE_INVALID 2
#define PTE_INVALID 1
#define VALID 0

#define PEB_OFFSET 0x1b0
#define OBJECT_HEADER_SIZE 0x18
#define OBJECT_TYPE_OFFSET 0x8
#define EPROCESS_NAME_OFFSET 0x174

VOID WorkThread(IN PVOID pContext);
VOID DriverUnload(IN PDRIVER_OBJECT Driver_object);
VOID searchprocess(VOID);
VOID getname(ULONG Addr);
ULONG validpage(ULONG Addr);
BOOLEAN IsARealProcess(ULONG i);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
NTSTATUS dwStatus;
HANDLE hThread;
DbgPrint("i'm coming :>\n");

DriverObject->DriverUnload = DriverUnload;

dwStAtus = PsCreateSystemThread(&hThread,
(
ACCESS_MASK)0,
NULL,
(
HANDLE)0,
NULL,
WorkThread,
NULL
);


return STATUS_SUCCESS;
}
//--------------------------------------------------------------------
VOID DriverUnload(IN PDRIVER_OBJECT Driver_object)
{
}
//--------------------------------------------------------------------
VOID WorkThread(IN PVOID pContext)
{
searchprocess();

PsTerminateSystemThread(STATUS_SUCCESS);
DbgPrint("Never be here ?\n");
}
//--------------------------------------------------------------------
VOID searchprocess(void)
{
ULONG i;
ULONG result;

for (i = 0x80000000 ;i<0x90000000;i+=4){
result = validpage(i);
if (result == VALID){
if (*(PULONG)i == 0x7ffdf000){
if(IsARealProcess(i)){
DbgPrint("EPROCESS: 0x%x ",i-PEB_OFFSET);
getname(i);
}
}
}
else if(result == PTE_INVALID){
i -=4;
i += 0x1000;//4k
}
else{
i-=4;
i+= 0x400000;//4mb
="#000080">}

}

for (i = 0xf0000000 ;i<0xffbe0000;i+=4){
result = validpage(i);
if (result == VALID){
if (*(PULONG)i == 0x7ffdf000){
if(IsARealProcess(i)){
DbgPrint("EPROCESS: 0x%x ",i-PEB_OFFSET);
getname(i);
}
}
}
else if(result == PTE_INVALID){
i -=4;
i += 0x1000;//4k
}
else{
i-=4;
i+= 0x400000;//4mb
}
}

DbgPrint("searching finish \n");
}
//--------------------------------------------------------------------
VOID getname(ULONG Addr)
{
DbgPrint("process name: %s\n",(PCHAR)(Addr-PEB_OFFSET+EPROCESS_NAME_OFFSET));
}
//--------------------------------------------------------------------
ULONG validpage(ULONG Addr)
{
ULONG pte;
ULONG pde;

pde = 0xc0300000 + (Addr>>22)*4;
if((*(PULONG)pde & 0x1) != 0){
//lArge pAge
if((*(PULONG)pde & 0x80) != 0){
return VALID;
}
pte = 0xc0000000 + (Addr>>12)*4;
if((*(PULONG)pte & 0x1) != 0){
return VALID;
}
else{
return PTE_INVALID;
}
}
return PDE_INVALID;
}
//--------------------------------------------------------------------
BOOLEAN IsARealProcess(ULONG i)
{
NTSTATUS status;
PUNICODE_STRING pUnicode;
UNICODE_STRING Process;
ULONG pObjectType;
ULONG pObjectTypeProcess;


pObjectTypeProcess = *(PULONG)((ULONG)PsGetCurrentProcess() -OBJECT_HEADER_SIZE +OBJECT_TYPE_OFFSET);
if (validpage(i-PEB_OFFSET) != VALID){
return color="#000000">FALSE;
}

if (validpage(i-PEB_OFFSET - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET) == VALID){
pObjectType = *(PULONG)(i-PEB_OFFSET - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET);
}
else{
return FALSE;
}

if(pObjectTypeProcess == pObjectType){
return TRUE;
}
return FALSE;

}
//--------------------------------------------------------------------




*******************************************************
*标题:【转载】SSDT Hook的妙用-对抗ring0 inline hook
*作者:堕落天才
*日期:2007年3月10号
*声明:本文章的目的仅为技术交流讨论
*******************************************************

1、SSDT
SSDT即系统服务描述符表,它的结构如下(参考《Undocument Windows 2000 Secretes》第二章):
typedef struct _SYSTEM_SERVICE_TABLE
{
PVOID ServiceTableBase; //这个指向系统服务函数地址表
PULONG ServiceCounterTableBase;
ULONG NumberOfService; //服务函数的个数,NumberOfService*4 就是整个地址表的大小
ULONG ParamTableBase;
}
SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;

typedef struct _SERVICE_DEscrīptOR_TABLE
{
SYSTEM_SERVICE_TABLE ntoskrnel; //ntoskrnl.exe的服务函数
SYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务函数,(gdi.dll/user.dll的内核支持)
SYSTEM_SERVICE_TABLE NotUsed1;
SYSTEM_SERVICE_TABLE NotUsed2;
}
SYSTEM_DEscrīptOR_TABLE,*PSYSTEM_DEscrīptOR_TABLE;

内核中有两个系统服务描述符表,一个是KeServiceDescrīptorTable(由ntoskrnl.exe导出),一个是KeServieDescrīptorTableShadow(没有导出)。两者的区别是,KeServiceDescrīptorTable仅有ntoskrnel一项,KeServieDescrīptorTableShadow包含了ntoskrnel以及win32k。一般的Native API的服务地址由KeServiceDescrīptorTable分派,gdi.dll/user.dll的内核API调用服务地址由KeServieDescrīptorTableShadow分派。还有要清楚一点的是win32k.sys只有在GUI线程中才加载,一般情况下是不加载的,所以要Hook KeServieDescrīptorTableShadow的话,一般是用一个GUI程序通过IoControlCode来触发(想当初不明白这点,蓝屏死机了N次都想不明白是怎么回事)。

2、SSDT HOOK
SSDT HOOK 的原理其实非常简单,我们先实际看看KeServiceDescrīptorTable是什么样的。
lkd> dd KeServiceDescriptorTable
8055ab80 804e3d20 00000000 0000011c 804d9f48
8055ab90 00000000 00000000 00000000 00000000
8055aba0 00000000 00000000 00000000 00000000
8055abb0 00000000 00000000 00000000 00000000

在windbg.exe中我们就看得比较清楚,KeServiceDescriptorTable中就只有第一项有数据,其他都是0。其中804e3d20就是
KeServiceDescriptorTable.ntoskrnel.ServiceTableBase,服务函数个数为0x11c个。我们再看看804e3d20地址里是什么东西:
lkd> dd 804e3d20
804e3d20 80587691 805716ef 8057ab71 80581b5c
804e3d30 80599ff7 80637b80 80639d05 80639d4e
804e3d40 8057741c 8064855b 80637347 80599539
804e3d50 8062f4ec 8057a98c 8059155e 8062661f

如上,80587691 805716ef 8057ab71 80581b5c 这些就是系统服务函数的地址了。比如当我们在ring3调用OpenProcess时,进入sysenter的ID是0x7A(XP SP2),然后系统查KeServiceDescrīptorTable,大概是这样KeServiceDescrīptorTable.ntoskrnel.ServiceTableBase(804e3d20) + 0x7A * 4 = 804E3F08,然后804E3F08 ->8057559e 这个就是OpenProcess系统服务函数所在,我们再跟踪看看:
lkd> u 8057559e
nt!NtOpenProcess:
8057559e 68c4000000 push 0C4h
805755a3 6860b54e80
push offset nt!ObReferenceObjectByPointer+0x127 (804eb560)
805755a8 e8e5e4f6ff call nt!InterlockedPushEntrySList+0x79 (804e3a92)
805755ad 33f6 xor esi,esi
原来8057559e就是NtOpenProcess函数所在的起始地址。
嗯,如果我们把8057559e改为指向我们函数的地址呢?比如 MyNtOpenProcess,那么系统就会直接调用MyNtOpenProcess,而不是原来的NtOpenProcess了。这就是SSDT HOOK 原理所在。

3、ring0 inline hook
ring0 inline hook 跟ring3的没什么区别了,如果硬说有的话,那么就是ring3发生什么差错的话程序会挂掉,ring0发生什么差错的话系统就挂掉,所以一定要很小心。inline hook的基本思想就是在目标函数中JMP到自己的监视函数,做一些判断然后再JMP回去。一般都是修改函数头,不过再其他地方JMP也是可以的。下面我们来点实际的吧:
lkd> u nt!NtOpenProcess
nt!NtOpenProcess:
8057559e e95d6f4271 jmp f199c500
805755a3 e93f953978 jmp f890eae7
805755a8 e8e5e4f6ff call nt!InterlockedPushEntrySList+0x79 (804e3a92)
...
同时打开“冰刃”跟“Rootkit Unhooker”我们就能在NtOpenProcess函数头看到这样的“奇观”,第一个jmp是“冰刃”的,第二个jmp是“Rootkit Unhooker”的。他们这样是防止被恶意程序通过TerminateProcess关闭。当然“冰刃”还Hook了NtTerminateProcess等函数。

**********************************************************************

好了,道理就说完了,下面就进入本文正题。
对付ring0 inline hook的基本思路是这样的,自己写一个替换的内核函数,以NtOpenProcess为例,就是MyNtOpenProcess。然后修改SSDT表,让系统服务进入自己的函数MyNtOpenProcess。而MyNtOpenProcess要做的事就是,实现NtOpenProcess前10字节指令,然后再JMP到原来的NtOpenProcess的十字节
后。这样NtOpenProcess函数头写的JMP都失效了,在ring3直接调用OpenProcess再也毫无影响。


#include

typedef struct
_SERVICE_DEscrīptOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}
SERVICE_DEscrīptOR_TABLE,*PSERVICE_DEscrīptOR_TABLE; //由于KeServiceDescrīptorTable只有一项,这里就简单点了
extern PSERVICE_DEscrīptOR_TABLE KeServiceDescrīptorTable;//KeServiceDescrīptorTable为导出函数

/////////////////////////////////////
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
//////////////////////////////////////
ULONG JmpAddress;//跳转到NtOpenProcess里的地址
ULONG OldServiceAddress;//原来NtOpenProcess的服务地址
//////////////////////////////////////
__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
DbgPrint("NtOpenProcess() called");
__asm{
push 0C4h
push 804eb560h //共十个字节
jmp [JmpAddress]
}
}
///////////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = OnUnload;
DbgPrint("Unhooker load");
Hook();
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("Unhooker unload!");
Unhook();
}
/////////////////////////////////////////////////////
VOID Hook()
{
ULONG Address;
Address = (ULONG)KeServiceDescrīptorTable->ServiceTableBase + 0x7A * 4;//0x7A为NtOpenProcess服务ID
DbgPrint("Address:0x%08X",Address);

ōldServiceAddress = *(ULONG*)Address;//保存原来NtOpenProcess的地址
DbgPrint("OldServiceAddress:0x%08X",OldServiceAddress);

DbgPrint("MyNtOpenProcess:0x%08X",MyNtOpenProcess);

JmpAddress = (ULONG)NtOpenProcess + 10; //跳转到NtOpenProcess函数头+10的地方,这样在其前面写的JMP都失效了
DbgPrint("JmpAddress:0x%08X",JmpAddress);

__asm{//去掉内存保护
cli
mov eax
,cr0
and eax,not 10000h
mov cr0,eax
}

*((
ULONG*)Address) = (ULONG)MyNtOpenProcess;//HOOK SSDT

__asm{//恢复内存保护
mov eax,cr0
or eax ont color="#000080">,10000h
mov cr0,eax
sti
}
}
//////////////////////////////////////////////////////
VOID Unhook()
{
ULONG Address;
Address = (ULONG)KeServiceDescrīptorTable->ServiceTableBase + 0x7A * 4;//查找SSDT

__asm{
cli
mov eax
,cr0
and eax,not 10000h
mov cr0,eax
}

*((
ULONG*)Address) = (ULONG)OldServiceAddress;//还原SSDT

__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}

DbgPrint("Unhook");
}


就这么多了,或许有人说,没必要那么复杂,直接恢复NtOpenProcess不就行了吗?对于象“冰刃”“Rookit Unhooker”这些“善良”之辈的话是没问题的,但是象NP这些“穷凶极恶”之流的话,它会不断检测NtOpenProcess是不是已经被写回去,是的话,嘿嘿,机器马上重启。这也是这种方法的一点点妙用。


///////////////////////////////
//函数用途:修改SSDT表 //
///////////////////////////////
//输入:服务ID, 新地址 //
//返回值:原始地址 //
///////////////////////////////

ULONG SetSSDTAddress(ULONG ulServiceID, ULONG procNewAddress)

// SSDT_Hook.c: SSDT Hook API.
//
//////////////////////////////////////////////////////////////////////
/*
代码最初来源于网络,原作者未知,表示歉意,代码经由at.Least(炉子)
*/
#include <ntddk.h>
typedef struct _SERVICE_DEscrīptOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}
SERVICE_DEscrīptOR_TABLE,*PSERVICE_DEscrīptOR_TABLE; //由于KeServiceDescrīptorTable只有一项,这里就简单点了
extern PSERVICE_DEscrīptOR_TABLE KeServiceDescrīptorTable;//KeServiceDescrīptorTable为导出函数
static ULONG JmpAddress;//跳转到的地址
static ULONG OldServiceAddress;//原来的服务地址
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/////////////////////////////////
//函数用途:修改SSDT表 //
/////////////////////////////////
//输入:服务ID, 新地址 //
//返回值:原始地址 //
/////////////////////////////////
ULONG SetSSDTAddress(ULONG ulServiceID, ULONG procNewAddress)
{
ULONG Address;
Address = (ULONG)KeServiceDescrīptorTable->ServiceTableBase + ulServiceID * 4;//服务ID
/*
炉子(at_Least) 注解 1(Address变量):
其实这个 Address 并不是真正的原始地址,从下文的
“OldServiceAddress = *(ULONG*)Address;”就可看
出其实这个 Address 是指向地址变量的指针(可能我
说的很复杂或者是很难懂,你可以把这个Address理解
为一个 *Address 变量 (ULONG *Address),并且被
赋值为:
Address = &服务函数地址(就是0x8XXXXXXX那东西)
*/
///////////////////////////////////////////////
/*
炉子(at_Least) 注解 2(如何获得Address的值):
SSDT 中数据的存放方式实际是:
------------------理论譬如说------------------>
lkd> dd KeServiceDescrīptorTable
8055ab80 804e3d20 00000000 0000011c 804d9f48
8055ab90 00000000 00000000 00000000 00000000
8055aba0 00000000 00000000 00000000 00000000
8055abb0 00000000 00000000 00000000 00000000
在windbg.exe中我们就看得比较清楚,KeServiceD-
escrīptorTable中就只有第一项有数据,其他都是0
。其中804e3d20就是KeServiceDescrīptorTable.n-
toskrnel.ServiceTableBase,服务函数个数为0x1-
1c个。我们再看看804e3d20地址里是什么东西:
lkd> dd 804e3d20
804e3d20 80587691 805716ef 8057ab71 80581b5c
804e3d30 80599ff7 80637b80 80639d05 80639d4e
804e3d40 8057741c 8064855b 80637347 80599539
804e3d50 8062f4ec 8057a98c 8059155e 8062661f
如上,80587691 805716ef 8057ab71 80581b5c 这些
就是系统服务函数的地址了。
<------------------理论譬如说------------------
(【理论譬如说】中的内容为引用——懒得打字- -)
相信大家也看明白了,每个地址占用4个字节( 1个字
节可以表示两位数字 ——不明白的自己换算。)所以
当我们获取地址的指针时,需要用服务 ID * 4(地址
是连续存放的, 不存在两个地址之间的间隔符之类的
情况)来获取相对于起始地址(在引用部分是【804e-
3d20】)的差值,然后再加上起始地址(就是Servic-
eTableBase)
*/
DbgPrint("Address:0x%08X",Address);
OldServiceAddress = *(ULONG*)Address;//保存原来的地址
DbgPrint("OldServiceAddress:0x%08X",OldServiceAddress);
DbgPrint("procNewFunAddress:0x%08X",procNewAddress);
JmpAddress = (ULONG)NtOpenProcess + 10; //跳转到函数头+10的地方,这样在其前面写的JMP都失效了
DbgPrint("JmpAddress:0x%08X",JmpAddress);

__asm{//去掉内存保护
cli
mov eax
,cr0
and eax,not 10000h
mov cr0,eax
}
*((
ULONG*)Address) = (ULONG)
procNewAddress
;//HOOK SSDT
__asm{//恢复内存保护
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
return OldServiceAddress;
}




egisterShellHookWindow Function

--------------------------------------------------------------------------------

Registers a specified Shell window to receive certain messages for events or notifications that are useful to Shell applications. The event messages received are only those sent to the Shell window associated with the specified window's desktop. Many of the messages are the same as those that can be received after calling the SetWindowsHookEx function and specifying WH_SHELL for the hook type. The difference with RegisterShellHookWindow is that the messages are received through the specified window's WindowProc and not through a call back procedure.

Syntax

BOOL RegisterShellHookWindow( HWND hWnd
);
Parameters

hWnd
[in] Handle to the window to register for Shell hook messages.
Return Value

TRUE if the function succeeds; FALSE if the function fails.




Remarks

As with normal window messages, the second parameter of the window procedure identifies the message as a "WM_SHELLHOOKMESSAGE". However, for these Shell hook messages, the message value is not a pre-defined constant like other message IDs such as WM_COMMAND. The value must be obtained dynamically using a call to RegisterWindowMessage(TEXT("SHELLHOOK"));. This precludes handling these messages using a traditional switch statement which requires ID values that are known at compile time. For handling Shell hook messages, the normal practice is to code an If statement in the default section of your switch statement and then handle the message if the value of the message ID is the same as the value obtained from the RegisterWindowMessage call.

The following table describes the wParam and lParam parameter values passed to the window procedure for the Shell hook messages.

wParam lParam
HSHELL_GETMINRECT A pointer to a SHELLHOOKINFO structure.
HSHELL_WINDOWACTIVATEED The HWND handle of the activated window.
HSHELL_RUDEAPPACTIVATEED The HWND handle of the activated window.
HSHELL_WINDOWREPLACING The HWND handle of the window replacing the top-level window.
HSHELL_WINDOWREPLACED The HWND handle of the window being replaced.
HSHELL_WINDOWCreateD The HWND handle of the window being created.
HSHELL_WINDOWDESTROYED The HWND handle of the top-level window being destroyed.
HSHELL_ACTIVATESHELLWINDOW Not used.
HSHELL_TASKMAN Can be ignored.
HSHELL_REDRAW The HWND handle of the window that needs to be redrawn.
HSHELL_FLASH The HWND handle of the window that needs to be flashed.
HSHELL_ENDTASK The HWND handle of the window that should be forced to exit.
HSHELL_APPCOMMAND The APPCOMMAND which has been unhandled by the application or other hooks. See WM_APPCOMMAND and use the GET_APPCOMMAND_LPARAM macro to retrieve this parameter.


Although you can access this function by using LoadLibrary and GetProcAddress combined in Microsoft Windows versions prior to Windows XP, the function is not accessible using the standard Include file and library linkage. The header files included in Windows XPÂ Service Pack 1 (SP1) and Windows Server 2003 document this function and make it accessible using the appropriate Include file and library linkage. However, this function is not intended for general use. It is recommended that you do not use it in new programs because it might be altered or unavailable in subsequent versions of Windows.

Function Information

Minimum DLL Version user32.dll
Header Declared in Winuser.h, include Windows.h
Import library User32.lib
Minimum operating systems Windows 2000
Unicode Implemented as ANSI and Unicode versions.

See Also

Windows Overview, DeregisterShellHookWindow, SetWindowsHookEx, WindowProc, ShellProc, WinEvents, Sending a Message

--------------------------------------------------------------------------------

Declare Function RegisterShellHook Lib "Shell32" Alias "#181" (ByVal hwnd As Long, ByVal nAction As Long) As Long
其中hwnd为窗口句柄,而nAction通常为下面的常数:
Const RSH_DEREGISTER = 0
Const RSH_REGISTER = 1
Const RSH_REGISTER_PROGMAN = 2
Const RSH_REGISTER_TASKMAN = 3

还有个RegisterShellHookWindow也可以,这个函数不需要nAction。

eg:

Option Explicit

Private Declare Function CallWindowProc _
Lib "user32" _
Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal Hwnd As Long, _
ByVal msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

Private Declare Function
RegisterWindowMessage _
Lib "user32" _
Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long

Private Declare Function
SetWindowLong _
Lib "user32" _
Alias "SetWindowLongA" (ByVal Hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long

Private Declare Function
GetWindowLong _
Lib "user32" _
Alias "GetWindowLongA" (ByVal Hwnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function
RegisterShellHook _
Lib "Shell32" _
Alias <
/font>"#181" (ByVal Hwnd As Long, _
ByVal nAction As Long) As Long

Private Declare Function
RegisterShellHookWindow _
Lib "user32" (ByVal Hwnd As Long) As Long

Private Declare Function
DeregisterShellHookWindow _
Lib "user32" (ByVal Hwnd As Long) As Long

Private Const
HSHELL_WINDOWCreateD = 1
Private Const HSHELL_WINDOWDESTROYED = 2
Private Const HSHELL_ACTIVATESHELLWINDOW = 3
Private Const HSHELL_WINDOWACTIVATED = 4
Private Const HSHELL_GETMINRECT = 5
Private Const HSHELL_REDRAW = 6
Private Const HSHELL_TASKMAN = 7
Private Const HSHELL_LANGUAGE = 8

Private Const WM_NCDESTROY = &H82

Private Const GWL_WNDPROC = -4

Private lpPrevWndProc As Long
Private
msgShellHook As Long

Public Sub
Unhook(Hwnd As Long)
SetWindowLong Hwnd, GWL_WNDPROC, lpPrevWndProc
Call DeregisterShellHookWindow(Hwnd)
End Sub

Public Sub
StartHook(Hwnd As Long)
msgShellHook = RegisterWindowMessage(
"SHELLHOOK")
Dim hLibShell As Long

RegisterShellHookWindow Hwnd
lpPrevWndProc = SetWindowLong(Hwnd, GWL_WNDPROC,
AddressOf WindowProc)
End Sub

Private Function
WindowProc(ByVal Hwnd As Long, _
ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

Select Case
uMsg

Case WM_NCDESTROY
Unhook Hwnd

Case msgShellHook

Select Case wParam

Case HSHELL_WINDOWCreateD

Call AddLog(lParam, "HSHELL_WINDOWCreateD")

Case HSHELL_WINDOWDESTROYED

Call AddLog(lParam, "HSHELL_WINDOWDESTROYED")

Case HSHELL_REDRAW

Call AddLog(lParam, "HSHELL_REDRAW")

Case HSHELL_WINDOWACTIVATED

Call AddLog(lParam, "HSHELL_WINDOWACTIVATED")

Case HSHELL_GETMINRECT

Call AddLog(lParam, "HSHELL_GETMINRECT")

Case HSHELL_REDRAW

Call AddLog(lParam, "HSHELL_REDRAW")

Case HSHELL_TASKMAN

Call AddLog(lParam, "HSHELL_TASKMAN")

Case HSHELL_LANGUAGE

Call AddLog(lParam, "HSHELL_LANGUAGE")
End Select
End Select

WindowProc = CallWindowProc(lpPrevWndProc, Hwnd, uMsg, wParam, lParam)
End Function



'嘿,够简单吧!下面是动态调用MessageBoxA的源代码,上面的步骤被封装到RunDll32函数中,可放到模块(CallAPIbyName.bas)中:
Dim s1() As Byte
Dim
s2() As Byte
Dim
ret As Long
Dim
hProc As Long
Dim
hModule As Long
Sub
t2()
Const hWnd = 0
s1 = StrConv("Hello~World", vbFromUnicode)
s2 = StrConv(
"VBNote", vbFromUnicode)
ret = RunDll32(
"user32", "MessageBoxA", hWnd, VarPtr(s1(0)), VarPtr(s2(0)), 0 &)
End Sub
Public Function
RunDll32(LibFileName As String, ProcName As String, ParamArray Params()) As Long
ReDim
m_OpCode(400 + 6 * UBound(Params)) '保留用来写m_OpCode
'读取API库
hModule = LoadLibrary(ByVal LibFileName)
If hModule = 0 Then
MsgBox "Library读取失败!"
Exit Function
End If
'取得函数地址
hProc = GetProcAddress(hModule, ByVal ProcName)
If hProc = 0 Then
MsgBox "函数读取失败!", vbCritical
FreeLibrary hModule
Exit Function
End If
'执行Assembly Code部分
RunDll32 = CallWindowProc(GetCodeStart(hProc, Params), 0, 1, 2, 3)
FreeLibrary hModule
'释放空间
End Function