分享

API未公开函数解密

 战神之家 2014-06-03

API未公开函数解密

(2006-04-12 18:38:39)
分类: 编程技术
什么是未公开函数?
   对于Windows的API函数调用相信大家已经不会陌生了。API函数调用是通过在VB中定义和调用Windows动态连接库中的函数从而扩展VB程序的功能。API函数的定义和调用方法在微软的开发工具中都有详细的说明。
   那么什么是“未公开”函数呢?微软为了某种目的。对于一些封装在系统中的函数没有在任何开发文档提供任何函数说明和定义。而这些函数有很多都是很有用的。所幸的是一些有心之人对Windows系统动态连接库做了十分详细的分析,从而将这些未公开函数公开以供广大开发人员共享(我对他们的感激之情就象滔滔江水,绵绵不绝……)
  好了,废话少说,言归正传,这里首先向大家介绍的是Windows下未公开的关闭Windows的函数。在Windows API函数中虽然提供了ExitWindowsEx这样的API函数,但是在有一些程序中我们需要象一些程序安装完毕那样提示用户重新启动计算机或者不重新启动计算机。或者要在程序中弹出关闭系统对话框。要实现这些功能就要使用Windows未公开函数了。下面来看程序。
  首先建立一个新的工程文件,在工程文件中加入一个Module文件。在Module文件中加入以下代码:
  Option Explicit
  Public bIsWinNT As Boolean
  '下面就是未公开的函数定义,注意在Alias之后没有使用函数的真正名字
  '而是用了函数编号,这是因为微软没有公开函数名
  Declare Function SHRestartSystemMB Lib“shell32"-
  Alias “#59"-
  (ByVal hOwner As Long, ―
  ByVal sExtraPrompt As String,-
  ByVal uFlags As Long) As Long
  Declare Function SHShutDownDialog Lib “shell32" -
  Alias “#60" -
  (ByVal YourGuess As Long) As Long
  Declare Function GetVersionEx Lib “kernel32" -
  Alias“GetVersionExA" -
  (lpVersionInformation As OSVERSIONINFO) As Long
  Type OSVERSIONINFO
  dwOSVersionInfoSize As Long
  dwMajorVersion As Long
  dwMinorVersion As Long
  dwBuildNumber As Long
  dwPlatformId As Long
  szCSDVersion As String * 128
  End Type
  Public Const EWX-LOGOFF = 0
  Public Const EWX-SHUTDOWN = 1
  Public Const EWX-REBOOT = 2
  Public Const EWX-FORCE = 4
  Public Const EWX-POWEROFF = 8
  Public Const shrsExitNoDefPrompt = 1
  Public Const shrsRebootSystem = 2
  Const VER-PLATFORM-WIN32s = 0
  Const VER-PLATFORM-WIN32-WINDOWS = 1
  Const VER-PLATFORM-WIN32-NT = 2
  Declare Sub CopyMemory Lib “kernel32"
  Alias “RtlMoveMemory" -
  (pDest As Any, -
  pSource As Any, -
  ByVal ByteLen As Long)
  Declare Function IsTextUnicode Lib “advapi32"-
  (lpBuffer As Any,-
  ByVal cb As Long, -
  lpi As Long) As Long
  Public Const IS-TEXT-UNICODE-ASCII16 = &H1
  Public Const IS-TEXT-UNICODE-REVERSE-ASCII16 = &H10
  Public Const IS-TEXT-UNICODE-STATISTICS = &H2
  Public Const IS-TEXT-UNICODE-REVERSE-STATISTICS = &H20
  Public Const IS-TEXT-UNICODE-CONTROLS = &H4
  Public Const IS-TEXT-UNICODE-REVERSE-CONTROLS = &H40
  Public Const IS-TEXT-UNICODE-SIGNATURE = &H8
  Public Const IS-TEXT-UNICODE-REVERSE-SIGNATURE = &H80
  Public Const IS-TEXT-UNICODE-ILLEGAL-CHARS = &H100
  Public Const IS-TEXT-UNICODE-ODD-LENGTH = &H200
  Public Const IS-TEXT-UNICODE-DBCS_LEADBYTE = &H400
  Public Const IS-TEXT-UNICODE-NULL-BYTES = &H1000
  Public Const IS-TEXT-UNICODE-UNICODE-MASK = &HF
  Public Const IS-TEXT-UNICODE-REVERSE-MASK = &HF0
  Public Const IS-TEXT-UNICODE-NOT-UNICODE-MASK = &HF00
  Public Const IS-TEXT-UNICODE-NOT-ASCII_MASK = &HF000
  Public Function IsWinNT() As Boolean
  Dim osvi As OSVERSIONINFO
  osvi.dwOSVersionInfoSize = Len(osvi)
  GetVersionEx osvi
  IsWinNT = (osvi.dwPlatformId = VER-PLATFORM-WIN32-NT)
  End Function
  Public Function CheckString(msg As String) As String
  If bIsWinNT Then
  CheckString = StrConv(msg, vbUnicode)
  Else: CheckString = msg
  End If
  End Function
  Public Function GetStrFromPtr(lpszStr As Long, nBytes As Integer) As String
  ReDim ab(nBytes) As Byte
  CopyMemory ab(0), ByVal lpszStr, nBytes
  GetStrFromPtr = GetStrFromBuffer(StrConv(ab(), vbUnicode))
  End Function
  Public Function GetStrFromBuffer(szStr As String) As String
  If IsUnicodeStr(szStr) Then szStr = StrConv(szStr, vbFromUnicode)
  If InStr(szStr, vbNullChar) Then
  GetStrFromBuffer = Left$(szStr, InStr(szStr, vbNullChar) - 1)
  Else: GetStrFromBuffer = szStr
  End If
  End Function
  Public Function IsUnicodeStr(sBuffer As String) As Boolean
  Dim dwRtnFlags As Long
  dwRtnFlags = IS-TEXT-UNICODE-UNICODE-MASK
  IsUnicodeStr = IsTextUnicode(ByVal sBuffer, Len(sBuffer), dwRtnFlags)
  End Function
  然后在Form1中加入一个ComboBox控件、两个CommandButton控件,然后在Form1的代码窗口中加入以下代码:
  Private Sub Command1_Click()
  Call SHShutDownDialog(0)
  End Sub
  Private Sub Command2_Click()
  Dim sPrompt As String
  Dim uFlag As Long
  Select Case Combo1.ListIndex
  Case -1: uFlag = Val(Combo1.Text)
  Case 0: uFlag = shrsExitNoDefPrompt
  Case 1: uFlag = shrsRebootSystem
  End Select
  If SHRestartSystemMB(hWnd, sPrompt, uFlag) = vbYes Then
  End If
  End Sub
  Private Sub Form_Load()
  bIsWinNT = IsWinNT()
  If bIsWinNT Then 'WinNT操作系统
  With Combo1
  .AddItem “0 - 关闭程序并以其它用户身份登陆"
  .AddItem “1 - 关闭计算机"
  .AddItem “2 - 重新启动计算机"
  .Text = “"
  End With
  Else 'Win95/98操作系统
  With Combo1
  .AddItem“1 - 关闭计算机"
  .AddItem “2 - 重新启动计算机"
  .Text = “"
  End With
  End If
  Command1.Caption = “关闭系统对话框"
  Command2.Caption = “关闭或重新启动计算机"
  End Sub
  运行程序,点击“关闭系统对话框”按钮就可以弹出关闭系统对话框。在Combo1中选择关闭系统、重新启动或者关闭程序并以其它用户身份登陆项再点击“关闭或重新启动计算机”按钮,系统就会弹出提示对话框提示是否执行相应的操作,点击“是”就可以执行了。
  Windows下未公开的API函数还有很多,以后我将会一一向大家介绍。 以上程序在VB6,Windows98,Windows NT4,Windows 2000下运行通过

这次介绍的是如何利用Windows未公开函数实现系统文件操作监视功能。利用该功能可以对Windows下的任何文件操作,包括建立文件、文件夹;删除文件;改变文件大小等操作都可以纪录在案。
首先来介绍实现上面操作的两个未公开函数:SHChangeNotifyRegister和SHChangeNotifyDeregister,SHChangeNotifyRegister函数的定义如下:
Declare Function SHChangeNotifyRegister Lib “shell32" Alias “#2" _
(ByVal hWnd As Long, _
ByVal uFlags As SHCN_ItemFlags, _
ByVal dwEventID As SHCN_EventIDs,
ByVal uMsg As Long, _
ByVal cItems As Long, _
lpps As PIDLSTRUCT) As Long
其中参数hWnd指定接受系统通告的窗口句柄,参数uMsg指定消息值,如果函数调用成功,系统就会将hWnd指定的窗口加入到系统通告链中,并且返回系统通告句柄。当有建立文件等系统操作发生时,系统会向hWnd指定的窗口发送uMsg消息,关于其它参数,会在下面的程序中说明。函数SHChangeNotifyDeregister的定义如下:
Declare Function SHChange Notify Deregister Lib“shell32" Alias “#4" _
(ByVal hNotify As Long) As Boolean
其中参数hNotify指定系统通告的句柄。
下面是操作的具体的VB范例:
首先建立一个新的工程,在Form1中加入一个TextBox控件。在Form1的代码窗口之中加入以下代码:
Option Explicit
Private Sub Form_Load()
If SubClass(hWnd) Then '改变Form1的消息处理函数
If IsIDE Then
Text1.Text = vbCrLf & _
“一个 Windows的文件目录操作即时监视程序," & vbCrLf & “可以监视在Explore中的重命名、新建、删除文" & _
vbCrLf & “件或目录;改变文件关联;插入、取出CD和添加“& vbCrLf & "删除网络共享都可以被该程序记录下来。"
End If
Call SHNotify_Register(hWnd)
Else
Text1 =“系统不支持操作监视程序 :-)"
End If
Move Screen.Width - Width, Screen.Height - Height
End Sub
Private Function IsIDE() As Boolean
On Error GoTo Out
Debug.Print 1 / 0
Out:
IsIDE = Err
End Function
Private Sub Form_Unload(Cancel As Integer)
Call SHNotify_Unregister
Call UnSubClass(hWnd)
End Sub
Public Sub NotificationReceipt(wParam As Long, lParam As Long)
Dim sOut As String
Dim shns As SHNOTIFYSTRUCT
Dim sDisplayname1 As String
Dim sDisplayname2 As String
MoveMemory shns, ByVal wParam, Len(shns)
If shns.dwItem1 Then
sDisplayname1 = GetDisplayNameFromPIDL(shns.dwItem1)
End If
If shns.dwItem2 Then
sDisplayname2 = GetDisplayNameFromPIDL(shns.dwItem2)
End If
sOut = SHNotify_ GetEvent Str(sDisplayname1, sDisplayname2, lParam) & vbCrLf
Text1 = Text1 & sOut & vbCrLf
Text1.SelStart = Len(Text1)
End Sub
然后在工程中加入三个模块(Bas)文件,将三个文件分别保存为mDef.Bas、mShell.Bas、mSub.Bas。在mDef.Bas中加入以下代码:
'mDef.Bas包含Shell操作的函数和数据类型的定义
Option Explicit
Declare Sub MoveMemory Lib “kernel32" Alias“RtlMoveMemory" (pDest As Any, _
pSource As Any, ByVal dwLength As Long)
Declare Sub CoTaskMemFree Lib “ole32.dll" (ByVal pv As Long)
Public Const MAX_PATH = 260
Public Const NOERROR = 0
'SHGetSpecialFolderLocation获得某一个特殊的目录的位置,如果函数调用成功返回NOERROR
'或者一个OLE错误
Declare Function SHGetSpecialFolderLocation Lib “shell32.dll" _
(ByVal hwndOwner As Long, _
ByVal nFolder As SHSpecialFolderIDs, _
pidl As Long) As Long
Public Enum SHSpecialFolderIDs
'列出所有Windows下特殊文件夹的ID
CSIDL_DESKTOP = &H0
CSIDL_INTERNET = &H1
CSIDL_PROGRAMS = &H2
CSIDL_CONTROLS = &H3
CSIDL_PRINTERS = &H4
CSIDL_PERSONAL = &H5
CSIDL_FAVORITES = &H6
CSIDL_STARTUP = &H7
CSIDL_RECENT = &H8
CSIDL_SENDTO = &H9
CSIDL_BITBUCKET = &HA
CSIDL_STARTMENU = &HB
CSIDL_DESKTOPDIRECTORY = &H10
CSIDL_DRIVES = &H11
CSIDL_NETWORK = &H12
CSIDL_NETHOOD = &H13
CSIDL_FONTS = &H14
CSIDL_TEMPLATES = &H15
CSIDL_COMMON_STARTMENU = &H16
CSIDL_COMMON_PROGRAMS = &H17
CSIDL_COMMON_STARTUP = &H18
CSIDL_COMMON_DESKTOPDIRECTORY = &H19
CSIDL_APPDATA = &H1A
CSIDL_PRINTHOOD = &H1B
CSIDL_ALTSTARTUP = &H1D
CSIDL_COMMON_ALTSTARTUP = &H1E
CSIDL_COMMON_FAVORITES = &H1F
CSIDL_INTERNET_CACHE = &H20
CSIDL_COOKIES = &H21
CSIDL_HISTORY = &H22
End Enum
'SHGetPathFromIDList函数将一个Item转换为文件路径
Declare Function SHGetPathFromIDList Lib“shell32.dll" Alias “SHGetPathFromIDListA" _
(ByVal pidl As Long, _
ByVal pszPath As String) As Long
'SHGetFileInfoPidl函数获得某个文件对象的信息。
Declare Function SHGetFileInfoPidl Lib “shell32" Alias“SHGetFileInfoA" (ByVal pidl As Long, _
ByVal dwFileAttributes As Long, _
psfib As SHFILEINFOBYTE, _
ByVal cbFileInfo As Long, _
ByVal uFlags As SHGFI_flags) As Long
Public Type SHFILEINFOBYTE
hIcon As Long
iIcon As Long
dwAttributes As Long
szDisplayName(1 To MAX_PATH) As Byte
szTypeName(1 To 80) As Byte
End Type
Declare Function SHGetFileInfo Lib “shell32" Alias “SHGetFileInfoA" _
(ByVal pszPath As String, _
ByVal dwFileAttributes As Long, _
psfi As SHFILEINFO, _
ByVal cbFileInfo As Long, _
ByVal uFlags As SHGFI_flags) As Long
Public Type SHFILEINFO
hIcon As Long
iIcon As Long
dwAttributes As Long
szDisplayName As String * MAX_PATH
szTypeName As String * 80
End Type
Enum SHGFI_flags
SHGFI_LARGEICON = &H0
SHGFI_SMALLICON = &H1
SHGFI_OPENICON = &H2
SHGFI_SHELLICONSIZE = &H4
SHGFI_PIDL = &H8
SHGFI_USEFILEATTRIBUTES = &H10
SHGFI_ICON = &H100
SHGFI_DISPLAYNAME = &H200
SHGFI_TYPENAME = &H400
SHGFI_ATTRIBUTES = &H800
SHGFI_ICONLOCATION = &H1000
SHGFI_EXETYPE = &H2000
SHGFI_SYSICONINDEX = &H4000
SHGFI_LINKOVERLAY = &H8000
SHGFI_SELECTED = &H10000
End Enum

(后续)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多