2012年12月26日星期三
IWebBrowserApp.Cpp
/*
本文取名为:IWebBrowserApp.Cpp
下载数据有很多种办法,如:
1.URLDownloadToFile或者URLDownloadToCacheFile
2.HttpOpenRequest
3.WinHttpReadData
4.IWinHttpRequest
5.脚本的"WinHttp.WinHttpRequest.5.1"
6.SOCKET,自己写http头。
7.其他接口,如本文的,就有可能。
8.驱动
9.其他。
类似的上传数据也和上面的大同小异
首先搭建服务器,并且成功。
其次,建立一个asp文件,用于处理接收到的数据,命名为data.asp,内容如下:
<%
Dim vntPostedData, lngCount
Response.AddHeader "Request-Method", Request.ServerVariables("REQUEST_METHOD")
lngCount = Request.TotalBytes
if (lngCount <> 0) then
vntPostedData = Request.BinaryRead(lngCount)
Response.BinaryWrite vntPostedData
end if
%>
以上代码摘自:Microsoft SDKs\Windows\v7.1\Samples\web\winhttp\winhttppostsample\data.asp。
并把此文件放到iis服务器中,例如:C:\inetpub\wwwroot\data.asp.
此文件不必放在浏览器中主动的打开,因为你主动的打开是看不到啥的。
运行下面的代码,既可以看到你发送的数据。
下面的代码修改自:
如何自动发送表单数据到 Internet Explorer
http://support.microsoft.com/kb/q167658
*/
#include <windows.h>
#define INITGUID
#include <initguid.h>
#include <exdisp.h>
#include <memory.h>
HRESULT GetPostData(LPVARIANT pvPostData);
void main()
{
HRESULT hr;
IWebBrowserApp* pWBApp = NULL; // Derived from IWebBrowser
BSTR bstrURL = NULL, bstrHeaders = NULL;
VARIANT vFlags = {0},
vTargetFrameName = {0},
vPostData = {0},
vHeaders = {0};
if (FAILED(hr = CoInitialize(NULL)))
{
return;
}
if (FAILED(hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER, IID_IWebBrowserApp, (LPVOID*)&pWBApp)))
{
goto Error;
}
bstrURL = SysAllocString(L"http://127.0.0.1/data.asp");//http://<server>/scripts/navpost.asp
if (!bstrURL)
{
goto Error;
}
bstrHeaders = SysAllocString(L"Content-Type: application/x-www-form-urlencoded\r\n");
if (!bstrHeaders)
{
goto Error;
}
V_VT(&vHeaders) = VT_BSTR;
V_BSTR(&vHeaders) = bstrHeaders;
hr = GetPostData(&vPostData);
hr = pWBApp->Navigate(bstrURL, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
pWBApp->put_Visible(VARIANT_TRUE);//显示。
Error:
if (bstrURL) SysFreeString(bstrURL);
if (bstrHeaders) SysFreeString(bstrHeaders);
VariantClear(&vPostData);
if (pWBApp) pWBApp->Release();
CoUninitialize();
}
// Pack some data into a SAFEARRAY of BYTEs. Return in a VARIANT
HRESULT GetPostData(LPVARIANT pvPostData)
{
HRESULT hr;
LPSAFEARRAY psa;
LPCTSTR cszPostData = "made by correy";//FName=Matt&Flavor=Mocha+Chip
UINT cElems = lstrlen(cszPostData);
LPSTR pPostData;
if (!pvPostData)
{
return E_POINTER;
}
VariantInit(pvPostData);
psa = SafeArrayCreateVector(VT_UI1, 0, cElems);
if (!psa)
{
return E_OUTOFMEMORY;
}
hr = SafeArrayAccessData(psa, (LPVOID*)&pPostData);
memcpy(pPostData, cszPostData, cElems);
hr = SafeArrayUnaccessData(psa);
V_VT(pvPostData) = VT_ARRAY | VT_UI1;
V_ARRAY(pvPostData) = psa;
return NOERROR;
}
2012年12月19日星期三
CDO.Message.vbs
'一直以为只有在服务端或者安装有iis等的电脑上才有CDO.Message组件,才可以发送邮件。
'其实有时候.send失败,原因好久没有查出。
'这次试验成功,特保存。
Const Email_From = "leguanyuan@163.com" '发件人邮箱
Const Password = "XXXXXXXX" '发件人邮箱密码
Const Email_To = "112426112@qq.com" '收件人邮箱
Set CDO = CreateObject("CDO.Message") '创建CDO.Message对象
CDO.Subject = "test" '邮件主题
CDO.From = Email_From '发件人地址
CDO.To = Email_To '收件人地址
CDO.TextBody = "Hello world!" '邮件正文
'cdo.AddAttachment = "C:\hello.txt" '邮件附件文件路径
Const schema = "http://schemas.microsoft.com/cdo/configuration/" '规定必须是这个,我也不知道为什么
With CDO.Configuration.Fields '用with关键字减少代码输入
.Item(schema & "sendusing") = 2 '使用网络上的SMTP服务器而不是本地的SMTP服务器
.Item(schema & "smtpserver") = "smtp.163.com" 'SMTP服务器地址
.Item(schema & "smtpauthenticate") = 1 '服务器认证方式
.Item(schema & "sendusername") = Email_From '发件人邮箱
.Item(schema & "sendpassword") = Password '发件人邮箱密码
.Item(schema & "smtpserverport") = 465 'SMTP服务器端口
.Item(schema & "smtpusessl") = True '是否使用SSL
.Item(schema & "smtpconnectiontimeout") = 60 '连接服务器的超时时间
.Update '更新设置
End With
CDO.Send '发送邮件
2012年12月12日星期三
Win32_Process.vbs
'在远程电脑运行远程电脑上的一个文件(程序)
'made at 2012.07.07
'email:kouleguan at hotmail dot com
'homepage:http://correy.webs.com
strComputer ="10.101.0.99"
strUserName="administrator"
strPassword="123456"
Set swbeml=createobject("wbemscripting.swbemlocator")
set rcimv2=swbeml.connectserver(strComputer,"root/cimv2",strUserName,strPassword)
Set Process=rcimv2.get("Win32_Process")
Process.create("secedit /export /cfg inf.inf") '不会显示界面。文件生成在系统目录。
2012年12月10日星期一
KeSetTimerEx.C
/*
时间很重要,在现实中如是,在计算机中亦是,如时钟中断。
时间怎能不会,特别是阴阳历转换。
此文展示几种用法,暂命名为KeSetTimerEx.C,
因为IoInitializeTimer需要一个设备对象。
KeSetTimerEx对dpc可有可无,使用更方便。
本文的不足之处,可能是定时器对象的删除等,
不然内存泄露,verifier.exe报错。
made by correy
made at 2012.12.10
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
PVOID g_pkThread;
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT pdoNextDeviceObj;
KeWaitForSingleObject(g_pkThread, Executive, KernelMode, FALSE, NULL);
ObDereferenceObject(g_pkThread);
pdoNextDeviceObj = DriverObject->DeviceObject;//pdoGlobalDrvObj
//IoDeleteSymbolicLink(&usSymlinkName);//本程序没有创建符号链接。
while(pdoNextDeviceObj) // Delete all the device objects
{
PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
IoDeleteDevice(pdoThisDeviceObj);
}
}
KSTART_ROUTINE ThreadStart;
VOID ThreadStart(__in PVOID StartContext)
{
KdPrint(("创建线程的完整规范示例用法,注意卸载的时候!\n"));
PsTerminateSystemThread(STATUS_SUCCESS);
}
IO_TIMER_ROUTINE IoTimer;
VOID IoTimer(__in PDEVICE_OBJECT DeviceObject, __in_opt PVOID Context)
{
DbgPrint("i am in IoTimer!\n");
KeSetEvent((PKEVENT)Context, 0, FALSE);
}
KDEFERRED_ROUTINE CustomDpc;
VOID CustomDpc(
__in struct _KDPC *Dpc,
__in_opt PVOID DeferredContext,
__in_opt PVOID SystemArgument1,
__in_opt PVOID SystemArgument2)
{
DbgPrint("i am in CustomDpc!\n");
KeSetEvent((PKEVENT)DeferredContext, IO_NO_INCREMENT, FALSE);//结束。
//还可以再调用KeSetTimer,但是要注意次数,和参数。 特别注意时间。
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
LARGE_INTEGER li;
HANDLE ThreadHandle;
UNICODE_STRING usDeviceName;
PDEVICE_OBJECT pdoDeviceObj = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
KEVENT ke;
KTIMER kt;
BOOLEAN b;
KDPC dpc;
int i;
//KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = Unload;
//////////////////////////////////////////////////////////////////////////
KdPrint(("暂停5秒:KeStallExecutionProcessor\n"));
KeStallExecutionProcessor(5000000);//5秒钟。
//////////////////////////////////////////////////////////////////////////
KdPrint(("暂停5秒:KeDelayExecutionThread\n"));
li.QuadPart = (5 * (((-10) * 1000) * 1000)); //负数是暂停5秒钟。
status = KeDelayExecutionThread(KernelMode, FALSE, &li);
if (status != STATUS_SUCCESS)
{
KdPrint(("KeDelayExecutionThread return:%d\n", status));
//return r;
}
//////////////////////////////////////////////////////////////////////////
RtlInitUnicodeString(&usDeviceName, L"\\Device\\correy"); //必须创建设备。
status = IoCreateDevice(DriverObject, 0, &usDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pdoDeviceObj);
if(!NT_SUCCESS(status))
{
return status;
}
KeInitializeEvent(&ke, NotificationEvent, FALSE);
IoInitializeTimer(pdoDeviceObj, IoTimer, &ke);//感觉和WorkItem差不多,只不过把方法改名为开始和结束。
IoStartTimer(pdoDeviceObj);
KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
IoStopTimer(pdoDeviceObj);
//////////////////////////////////////////////////////////////////////////
KeInitializeTimerEx(&kt, SynchronizationTimer);
li.QuadPart = (5 * (((-10) * 1000) * 1000));
//第三个参数,如果是负数,会失败,并且蓝屏。并且不能大于#define MAXLONG 0x7fffffff // winnt
b = KeSetTimerEx(&kt, li, 5000000, 0);//其实有5个参数。如kmdkit里面的用法,ida里面也是的。
if (b == 1)
{
KdPrint(("the timer object was already in the system timer queue\n"));
//继续前进,千万不要退出。注意,注意,再注意。
}
for (i = 0; i < 3; i++)
{
KeWaitForSingleObject(&kt, Executive, KernelMode, FALSE, NULL);
KdPrint(("KeSetTimer:5秒%d次\n", i+1));
KeSetTimerEx(&kt, li, 5000000, 0);
}
b = KeCancelTimer(&kt);
if (b == 0)
{
return b;
}
//////////////////////////////////////////////////////////////////////////
KeResetEvent(&ke);
KeInitializeTimerEx(&kt, SynchronizationTimer);
KeInitializeDpc(&dpc, CustomDpc, &ke);//最后一个参数是传递用的。
li.QuadPart = (5 * (((-10) * 1000) * 1000));
KdPrint(("5秒后调用CustomDpc函数\n", i));
//第三个参数,如果是负数,会失败,并且蓝屏。并且不能大于#define MAXLONG 0x7fffffff // winnt
b = KeSetTimerEx(&kt, li, 5000000, &dpc);//其实有5个参数。
if (b == 1)
{
KdPrint(("the timer object was already in the system timer queue\n"));
//继续前进,千万不要退出。注意,注意,再注意。
}
KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
b = KeCancelTimer(&kt);
if (b == 0)
{
return b;
}
KeClearEvent(&ke);
KeCancelTimer(&kt);
//////////////////////////////////////////////////////////////////////////
status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadStart, NULL);
if (status != STATUS_SUCCESS)
{
KdPrint(("PsCreateSystemThread return:%d\n", status));
//return r;
}
else
{
ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &g_pkThread, NULL);
ZwClose(ThreadHandle);
}
//////////////////////////////////////////////////////////////////////////
return 0;
}
2012年12月8日星期六
工作线程两例
/*
工作线程或者劳务线程,很重要,比起一般的内核线程。
它的运行环境不一般,在system中,特别是IRQL。
适用于小的任务,很方便。
made by correy
made at 2012.12.08
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT pdoNextDeviceObj = DriverObject->DeviceObject;//pdoGlobalDrvObj
//IoDeleteSymbolicLink(&usSymlinkName);//本程序没有创建符号链接。
while(pdoNextDeviceObj) // Delete all the device objects
{
PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
IoDeleteDevice(pdoThisDeviceObj);
}
}
IO_WORKITEM_ROUTINE WorkItem;
VOID WorkItem(__in PDEVICE_OBJECT DeviceObject, __in_opt PVOID Context)
{//如果不是同步的,有可能在DriverEntry函数运行结束后才运行到这里。
DbgPrint("i am in WorkItem!\n");
KeSetEvent((PKEVENT)Context, 0, FALSE);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNICODE_STRING usDeviceName;
PDEVICE_OBJECT pdoDeviceObj = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
PIO_WORKITEM g_piowi;
KEVENT g_ke;
KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = OnUnload;
RtlInitUnicodeString(&usDeviceName, L"\\Device\\correy"); //必须创建设备,特别是Vista以前。
status = IoCreateDevice(DriverObject, 0, &usDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pdoDeviceObj);
if(!NT_SUCCESS(status))
{
return status;
}
g_piowi = IoAllocateWorkItem(pdoDeviceObj); //参数是设备对象的指针,不是驱动对象的指针。不然WorkItem退出的时候,蓝屏。
if (g_piowi == 0)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//IoInitializeWorkItem和IoAllocateWorkItem的功能差不多。
//If the caller will later pass the work item to IoQueueWorkItem, IoObject must point to a device object.
//IoInitializeWorkItem(DriverObject, &g_piowi);//Versions: Available on Windows Vista and later versions of Windows.
KeInitializeEvent(&g_ke, SynchronizationEvent, FALSE);//设置事件以便同步,也可以不同步。就多3行代码。
IoQueueWorkItem(g_piowi, &WorkItem, DelayedWorkQueue, &g_ke);
KeWaitForSingleObject(&g_ke, Executive,KernelMode, FALSE, NULL);
if (g_piowi)
{
IoFreeWorkItem(g_piowi);
}
return STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
其实这个办法跟简单,没有和设备关联,而且暂时没有被软件废弃。
made by correy
made at 2012.08.13
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntifs.h>
#define TAG 'tset' //本驱动在内存中的标志,即test.
typedef struct WorkItemContext{
PWORK_QUEUE_ITEM Item;
HANDLE Pid;
}WorkItemContext;
PVOID allocate(IN SIZE_T NumberOfBytes)
{
PVOID p = NULL;
//PAGED_CODE();
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
{
KdBreakPoint();//DbgBreakPoint()
}
/*
Callers of ExAllocatePoolWithTag must be executing at IRQL <= DISPATCH_LEVEL.
A caller executing at DISPATCH_LEVEL must specify a NonPagedXxx value for PoolType.
A caller executing at IRQL <= APC_LEVEL can specify any POOL_TYPE value, but the IRQL and environment must also be considered for determining the page type.
*/
p = ExAllocatePoolWithTag(NonPagedPool, NumberOfBytes, TAG);
if (p == NULL ) {
return p;
}
/*
Warning Memory that ExAllocatePoolWithTag allocates is uninitialized.
A kernel-mode driver must first zero this memory if it is going to make it visible to user-mode software (to avoid leaking potentially privileged contents).
*/
RtlZeroMemory(p, NumberOfBytes);
return p;
}
VOID free(IN PVOID p)
{
unsigned long r;
/*
Callers of ExFreePoolWithTag must be running at IRQL <= DISPATCH_LEVEL.
A caller at DISPATCH_LEVEL must have specified a NonPagedXxx PoolType when the memory was allocated.
Otherwise, the caller must be running at IRQL <= APC_LEVEL.
*/
//PAGED_CODE();
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
{
KdBreakPoint();//DbgBreakPoint()
}
if (p) //防止多次释放导致的蓝屏。
{
__try //防止传入非法的地址。
{
r = MmIsAddressValid(p);
ExFreePoolWithTag(p, TAG);//KeGetCurrentIrql() > DISPATCH_LEVEL时依旧蓝屏。
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
r = GetExceptionCode();//啥也不做。
}
p = NULL;
}
}
VOID MY_PWORKER_THREAD_ROUTINE (IN PVOID Parameter)
{
WorkItemContext * pwic = (WorkItemContext *)Parameter;
//做一些事。
free(pwic->Item);
free(pwic);
}
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
#pragma INITCODE
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
WorkItemContext * wic;
KdBreakPoint();// == DbgBreakPoint()
DriverObject->DriverUnload = Unload;
//之所以采用结构是因为传递的参数不是一个(实际应用的也不是一个),并且不是同步控制的。
wic = (WorkItemContext *)allocate(sizeof(WorkItemContext));
if (wic == NULL) {
return status;
}
wic->Pid = 0;
wic->Item = (PWORK_QUEUE_ITEM)allocate(sizeof(WORK_QUEUE_ITEM));
if (wic->Item == NULL) {
free(wic);
return status;
}
ExInitializeWorkItem(wic->Item,MY_PWORKER_THREAD_ROUTINE,wic);
ExQueueWorkItem(wic->Item, DelayedWorkQueue);
return status;
}
工作线程或者劳务线程,很重要,比起一般的内核线程。
它的运行环境不一般,在system中,特别是IRQL。
适用于小的任务,很方便。
made by correy
made at 2012.12.08
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT pdoNextDeviceObj = DriverObject->DeviceObject;//pdoGlobalDrvObj
//IoDeleteSymbolicLink(&usSymlinkName);//本程序没有创建符号链接。
while(pdoNextDeviceObj) // Delete all the device objects
{
PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
IoDeleteDevice(pdoThisDeviceObj);
}
}
IO_WORKITEM_ROUTINE WorkItem;
VOID WorkItem(__in PDEVICE_OBJECT DeviceObject, __in_opt PVOID Context)
{//如果不是同步的,有可能在DriverEntry函数运行结束后才运行到这里。
DbgPrint("i am in WorkItem!\n");
KeSetEvent((PKEVENT)Context, 0, FALSE);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNICODE_STRING usDeviceName;
PDEVICE_OBJECT pdoDeviceObj = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
PIO_WORKITEM g_piowi;
KEVENT g_ke;
KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = OnUnload;
RtlInitUnicodeString(&usDeviceName, L"\\Device\\correy"); //必须创建设备,特别是Vista以前。
status = IoCreateDevice(DriverObject, 0, &usDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pdoDeviceObj);
if(!NT_SUCCESS(status))
{
return status;
}
g_piowi = IoAllocateWorkItem(pdoDeviceObj); //参数是设备对象的指针,不是驱动对象的指针。不然WorkItem退出的时候,蓝屏。
if (g_piowi == 0)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//IoInitializeWorkItem和IoAllocateWorkItem的功能差不多。
//If the caller will later pass the work item to IoQueueWorkItem, IoObject must point to a device object.
//IoInitializeWorkItem(DriverObject, &g_piowi);//Versions: Available on Windows Vista and later versions of Windows.
KeInitializeEvent(&g_ke, SynchronizationEvent, FALSE);//设置事件以便同步,也可以不同步。就多3行代码。
IoQueueWorkItem(g_piowi, &WorkItem, DelayedWorkQueue, &g_ke);
KeWaitForSingleObject(&g_ke, Executive,KernelMode, FALSE, NULL);
if (g_piowi)
{
IoFreeWorkItem(g_piowi);
}
return STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
其实这个办法跟简单,没有和设备关联,而且暂时没有被软件废弃。
made by correy
made at 2012.08.13
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntifs.h>
#define TAG 'tset' //本驱动在内存中的标志,即test.
typedef struct WorkItemContext{
PWORK_QUEUE_ITEM Item;
HANDLE Pid;
}WorkItemContext;
PVOID allocate(IN SIZE_T NumberOfBytes)
{
PVOID p = NULL;
//PAGED_CODE();
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
{
KdBreakPoint();//DbgBreakPoint()
}
/*
Callers of ExAllocatePoolWithTag must be executing at IRQL <= DISPATCH_LEVEL.
A caller executing at DISPATCH_LEVEL must specify a NonPagedXxx value for PoolType.
A caller executing at IRQL <= APC_LEVEL can specify any POOL_TYPE value, but the IRQL and environment must also be considered for determining the page type.
*/
p = ExAllocatePoolWithTag(NonPagedPool, NumberOfBytes, TAG);
if (p == NULL ) {
return p;
}
/*
Warning Memory that ExAllocatePoolWithTag allocates is uninitialized.
A kernel-mode driver must first zero this memory if it is going to make it visible to user-mode software (to avoid leaking potentially privileged contents).
*/
RtlZeroMemory(p, NumberOfBytes);
return p;
}
VOID free(IN PVOID p)
{
unsigned long r;
/*
Callers of ExFreePoolWithTag must be running at IRQL <= DISPATCH_LEVEL.
A caller at DISPATCH_LEVEL must have specified a NonPagedXxx PoolType when the memory was allocated.
Otherwise, the caller must be running at IRQL <= APC_LEVEL.
*/
//PAGED_CODE();
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
{
KdBreakPoint();//DbgBreakPoint()
}
if (p) //防止多次释放导致的蓝屏。
{
__try //防止传入非法的地址。
{
r = MmIsAddressValid(p);
ExFreePoolWithTag(p, TAG);//KeGetCurrentIrql() > DISPATCH_LEVEL时依旧蓝屏。
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
r = GetExceptionCode();//啥也不做。
}
p = NULL;
}
}
VOID MY_PWORKER_THREAD_ROUTINE (IN PVOID Parameter)
{
WorkItemContext * pwic = (WorkItemContext *)Parameter;
//做一些事。
free(pwic->Item);
free(pwic);
}
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
#pragma INITCODE
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
WorkItemContext * wic;
KdBreakPoint();// == DbgBreakPoint()
DriverObject->DriverUnload = Unload;
//之所以采用结构是因为传递的参数不是一个(实际应用的也不是一个),并且不是同步控制的。
wic = (WorkItemContext *)allocate(sizeof(WorkItemContext));
if (wic == NULL) {
return status;
}
wic->Pid = 0;
wic->Item = (PWORK_QUEUE_ITEM)allocate(sizeof(WORK_QUEUE_ITEM));
if (wic->Item == NULL) {
free(wic);
return status;
}
ExInitializeWorkItem(wic->Item,MY_PWORKER_THREAD_ROUTINE,wic);
ExQueueWorkItem(wic->Item, DelayedWorkQueue);
return status;
}
2012年12月7日星期五
ExInterlockedInsertTailList.C
/*
链表一个重要的概念,
数据结构里面有,内核里面有双链表。
本文主要操作的是同步安全的双链表。
不用单链表的原因是,内核里面的结构大多是双链表。
应用层的有stl等。
那几个应用层的链表API不适用,还不如自己实现链表的结构和操作。
内核中的主要操作安全性的双链表的函数有:
KeInitializeSpinLock
InitializeListHead
ExInterlockedInsertTailList //插入尾,这是正常的思维。
ExInterlockedInsertHeadList //这个不常用,特殊的情况下使用。
ExInterlockedRemoveHeadList //带锁的双链表没有尾删除的。所以使用的用途第队列不是堆栈。
IsListEmpty //这个可以不用。
本文是简单的示例,要使用,还要进一步的加强。
链表怎能不会,光看别人的代码是不行的,必须自己体验:编码调试。
微软没有完整的例子,所以自己写。
made by correy
made at 2012.12.07
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
KSPIN_LOCK g_sl;
LIST_ENTRY g_le;
#define TAG 'tset' //test
typedef struct _dl{ //加不加下划线都可以。
LIST_ENTRY le;
int x;
}dl;//定义指针会出错。不知啥原因。*dl
VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { }
void InsertTail()
{
int i = 0;
for (i = 0; i < 9; i++)
{
dl * dl1 = (dl *)ExAllocatePoolWithTag(NonPagedPool, sizeof(dl), TAG);//不能用栈内空间,否则移除会蓝屏。
if (dl1 == NULL)
{
return;
}
dl1->x = i;
ExInterlockedInsertTailList(&g_le, &dl1->le, &g_sl);//前两个个参数的顺序翻了会蓝屏的,并且注意第二个参数的用法。
DbgPrint("%08x\n",dl1->x);
}
}
void Ergodic_chain_table()
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
break;
}
DbgPrint("%08x\n",temp->x);
} while (p != g_le.Flink);
}
void RemoveHead()
{
PLIST_ENTRY temp;
do
{
temp = ExInterlockedRemoveHeadList(&g_le, &g_sl);
if (temp)
{
dl * dl2 = CONTAINING_RECORD(temp, dl, le);//是一个宏,用于取自己定义的结构的指针。
DbgPrint("%08x\n",dl2->x);
ExFreePoolWithTag(dl2, TAG);
}
} while (temp != 0);//为啥是不等呢?还有分号。
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = OnUnload;
KeInitializeSpinLock(&g_sl);
InitializeListHead(&g_le);
InsertTail();//插入,形成一个双链表示例
Ergodic_chain_table();//遍历示例。查询就是添加个比较的条件而已。
RemoveHead();//从全部头删除示例
return STATUS_SUCCESS;
}
//添加一些函数.
int InsertTail(HANDLE pid) //插入一个到尾部 HANDLE DWORD
{
dl * dl1;
dl1 = (dl *)ExAllocatePoolWithTag(NonPagedPool, sizeof(dl), TAG);//不能用栈内空间,否则移除会蓝屏。
if (dl1 == NULL)
{
return 0 /*false*/;
}
dl1->x = pid;
if (ExInterlockedInsertTailList(&g_le, &dl1->le, &g_sl) == 0)//前两个个参数的顺序翻了会蓝屏的,并且注意第二个参数的用法。
{ //第一次操作,链表为空,ExInterlockedInsertTailList返回值为0。
return 1 /*false*/;
}
KdPrint(("成功插入:%d\n",pid));
return 1 /*true*/;
}
int delete_node(HANDLE pid) //DWORD
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
dl * head = CONTAINING_RECORD(p, dl, le);
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
break;
}
if (temp->x == pid)
{
//没有删除特定节点的函数,所以自己实现:
/*
1.替换链表的节点的指针,把本节点释放掉。
* p = temp->le;
ExFreePoolWithTag(temp, TAG);
2.把第一个节点的值赋值给指定的节点,然后ExInterlockedRemoveHeadList删除第一个。
3.把指定的节点的值赋值给0,这个值是没有用的。但这样做浪费内存。
4.删除链表的特定的节点:
遍历,从头删除,不是就添加到尾部,
是就直接删除,不再添加.
不过要先判断一下存在不,以防使循环.
还可以先添加在删除(看看允许重复添加不).
*/
temp->x = head->x;//注意这个结构的一些操作最好加锁同步。
ExInterlockedRemoveHeadList(&g_le, &g_sl);//IsListEmpty
KdPrint(("成功删除:%d\n",pid));
return 1;
}
} while (p != g_le.Flink);
KdPrint(("删除失败:%d\n",pid));
return 0;
}
BOOLEAN find (HANDLE pid) //查询 DWORD
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
//KdPrint(("没有找到:%d\n",temp->x));//这个显示的频率太多.
break;
}
if (temp->x == pid)
{
//KdPrint(("成功找到:%d\n",temp->x));//这个显示的频率太多.
return 1;
}
} while (p != g_le.Flink);
return 0;
}
int ListAll() //遍历示例。
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
KdPrint(("开始显示\n"));
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
break;
}
KdPrint(("pid:%d\n",temp->x));
} while (p != g_le.Flink);
KdPrint(("显示结束\n\n"));
return 0;
}
void RemoveAll() //从全部头删除示例
{
PLIST_ENTRY temp;
NTSTATUS status = STATUS_UNSUCCESSFUL;
do
{
temp = ExInterlockedRemoveHeadList(&g_le, &g_sl);
if (temp)
{
dl * dl2 = CONTAINING_RECORD(temp, dl, le);//是一个宏,用于取自己定义的结构的指针。
ExFreePoolWithTag(dl2, TAG);
}
} while (temp != 0);//为啥是不等呢?还有分号。
}
//以后添加单链表的操作,因为但链表的操作更多,只不过要加个同步的处理而已.
链表一个重要的概念,
数据结构里面有,内核里面有双链表。
本文主要操作的是同步安全的双链表。
不用单链表的原因是,内核里面的结构大多是双链表。
应用层的有stl等。
那几个应用层的链表API不适用,还不如自己实现链表的结构和操作。
内核中的主要操作安全性的双链表的函数有:
KeInitializeSpinLock
InitializeListHead
ExInterlockedInsertTailList //插入尾,这是正常的思维。
ExInterlockedInsertHeadList //这个不常用,特殊的情况下使用。
ExInterlockedRemoveHeadList //带锁的双链表没有尾删除的。所以使用的用途第队列不是堆栈。
IsListEmpty //这个可以不用。
本文是简单的示例,要使用,还要进一步的加强。
链表怎能不会,光看别人的代码是不行的,必须自己体验:编码调试。
微软没有完整的例子,所以自己写。
made by correy
made at 2012.12.07
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
KSPIN_LOCK g_sl;
LIST_ENTRY g_le;
#define TAG 'tset' //test
typedef struct _dl{ //加不加下划线都可以。
LIST_ENTRY le;
int x;
}dl;//定义指针会出错。不知啥原因。*dl
VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { }
void InsertTail()
{
int i = 0;
for (i = 0; i < 9; i++)
{
dl * dl1 = (dl *)ExAllocatePoolWithTag(NonPagedPool, sizeof(dl), TAG);//不能用栈内空间,否则移除会蓝屏。
if (dl1 == NULL)
{
return;
}
dl1->x = i;
ExInterlockedInsertTailList(&g_le, &dl1->le, &g_sl);//前两个个参数的顺序翻了会蓝屏的,并且注意第二个参数的用法。
DbgPrint("%08x\n",dl1->x);
}
}
void Ergodic_chain_table()
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
break;
}
DbgPrint("%08x\n",temp->x);
} while (p != g_le.Flink);
}
void RemoveHead()
{
PLIST_ENTRY temp;
do
{
temp = ExInterlockedRemoveHeadList(&g_le, &g_sl);
if (temp)
{
dl * dl2 = CONTAINING_RECORD(temp, dl, le);//是一个宏,用于取自己定义的结构的指针。
DbgPrint("%08x\n",dl2->x);
ExFreePoolWithTag(dl2, TAG);
}
} while (temp != 0);//为啥是不等呢?还有分号。
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = OnUnload;
KeInitializeSpinLock(&g_sl);
InitializeListHead(&g_le);
InsertTail();//插入,形成一个双链表示例
Ergodic_chain_table();//遍历示例。查询就是添加个比较的条件而已。
RemoveHead();//从全部头删除示例
return STATUS_SUCCESS;
}
//添加一些函数.
int InsertTail(HANDLE pid) //插入一个到尾部 HANDLE DWORD
{
dl * dl1;
dl1 = (dl *)ExAllocatePoolWithTag(NonPagedPool, sizeof(dl), TAG);//不能用栈内空间,否则移除会蓝屏。
if (dl1 == NULL)
{
return 0 /*false*/;
}
dl1->x = pid;
if (ExInterlockedInsertTailList(&g_le, &dl1->le, &g_sl) == 0)//前两个个参数的顺序翻了会蓝屏的,并且注意第二个参数的用法。
{ //第一次操作,链表为空,ExInterlockedInsertTailList返回值为0。
return 1 /*false*/;
}
KdPrint(("成功插入:%d\n",pid));
return 1 /*true*/;
}
int delete_node(HANDLE pid) //DWORD
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
dl * head = CONTAINING_RECORD(p, dl, le);
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
break;
}
if (temp->x == pid)
{
//没有删除特定节点的函数,所以自己实现:
/*
1.替换链表的节点的指针,把本节点释放掉。
* p = temp->le;
ExFreePoolWithTag(temp, TAG);
2.把第一个节点的值赋值给指定的节点,然后ExInterlockedRemoveHeadList删除第一个。
3.把指定的节点的值赋值给0,这个值是没有用的。但这样做浪费内存。
4.删除链表的特定的节点:
遍历,从头删除,不是就添加到尾部,
是就直接删除,不再添加.
不过要先判断一下存在不,以防使循环.
还可以先添加在删除(看看允许重复添加不).
*/
temp->x = head->x;//注意这个结构的一些操作最好加锁同步。
ExInterlockedRemoveHeadList(&g_le, &g_sl);//IsListEmpty
KdPrint(("成功删除:%d\n",pid));
return 1;
}
} while (p != g_le.Flink);
KdPrint(("删除失败:%d\n",pid));
return 0;
}
BOOLEAN find (HANDLE pid) //查询 DWORD
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
//KdPrint(("没有找到:%d\n",temp->x));//这个显示的频率太多.
break;
}
if (temp->x == pid)
{
//KdPrint(("成功找到:%d\n",temp->x));//这个显示的频率太多.
return 1;
}
} while (p != g_le.Flink);
return 0;
}
int ListAll() //遍历示例。
{
LIST_ENTRY * p = g_le.Flink;//&g_le;//
KdPrint(("开始显示\n"));
do
{
dl * temp = CONTAINING_RECORD(p, dl, le);
p = p->Flink;
if (p == g_le.Flink)//不加这一句的后果是:这样会再最后一次多现实第一个一次。
{
break;
}
KdPrint(("pid:%d\n",temp->x));
} while (p != g_le.Flink);
KdPrint(("显示结束\n\n"));
return 0;
}
void RemoveAll() //从全部头删除示例
{
PLIST_ENTRY temp;
NTSTATUS status = STATUS_UNSUCCESSFUL;
do
{
temp = ExInterlockedRemoveHeadList(&g_le, &g_sl);
if (temp)
{
dl * dl2 = CONTAINING_RECORD(temp, dl, le);//是一个宏,用于取自己定义的结构的指针。
ExFreePoolWithTag(dl2, TAG);
}
} while (temp != 0);//为啥是不等呢?还有分号。
}
//以后添加单链表的操作,因为但链表的操作更多,只不过要加个同步的处理而已.
2012年12月5日星期三
SHFileOperation.Cpp
/*
删除文件夹有两种办法:
1.递归遍历加RemoveDirectory(移除空目录)。只读属性需要去掉。
2.SHFileOperation函数的FO_DELETE。
修改自:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365200(v=vs.85).aspx等。
If you are writing a 32-bit application to list all the files in a directory and the application may be run on a 64-bit computer,
you should call the Wow64DisableWow64FsRedirectionfunction before calling FindFirstFile and call Wow64RevertWow64FsRedirection after the last call to FindNextFile.
*/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#pragma comment(lib, "User32.lib")
#include "Shlwapi.h"
#pragma comment (lib,"Shlwapi.lib")
#include <locale.h>
void DisplayErrorBox(LPTSTR lpszFunction);
bool deldir(TCHAR * path)
{
// Check that the input path plus 3 is not longer than MAX_PATH.
// Three characters are for the "\*" plus NULL appended below.
size_t length_of_arg;
StringCchLength(path, MAX_PATH, &length_of_arg);//argv[1]
if (length_of_arg > (MAX_PATH - 3)) {
_tprintf(TEXT("\nDirectory path is too long.\n"));
return (-1);
}
// Prepare string for use with FindFile functions. First, copy the string to a buffer, then append '\*' to the directory name.
TCHAR szDir[MAX_PATH];
StringCchCopy(szDir, MAX_PATH, path);//argv[1]
StringCchCat(szDir, MAX_PATH, TEXT("\\*"));
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind) {
DisplayErrorBox(TEXT("FindFirstFile"));
return false;
}
// List all the files in the directory with some info about them.
do
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//_tprintf(TEXT(" %s <DIR>\n"), ffd.cFileName);
if (lstrcmpi(ffd.cFileName,L".") == 0 ||
lstrcmpi(ffd.cFileName,L"..") == 0)
{
//这里不操作。
}
else
{
TCHAR sztemp[MAX_PATH] = {0};
StringCchCopy(sztemp, MAX_PATH, path);//argv[1]
PathAppend(sztemp, ffd.cFileName);
deldir(sztemp);
/*_tprintf(TEXT(" %s <DIR>\n"), ffd.cFileName);*/
}
}
else
{
//LARGE_INTEGER filesize;//这几行显示信息用的,无实际用途。
//filesize.LowPart = ffd.nFileSizeLow;
//filesize.HighPart = ffd.nFileSizeHigh;
//_tprintf(TEXT(" %s %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
TCHAR sztemp[MAX_PATH] = {0};
StringCchCopy(sztemp, MAX_PATH, path);//argv[1]
PathAppend(sztemp, ffd.cFileName);
bool b = DeleteFile(sztemp);
if (b == 0)
{
int x = GetLastError();
x = x;//查看x的值用的。
}
}
} while (FindNextFile(hFind, &ffd) != 0);
//dwError = GetLastError();
//if (dwError != ERROR_NO_MORE_FILES) {
// DisplayErrorBox(TEXT("FindFirstFile"));
//}
FindClose(hFind);
return RemoveDirectory(path);//里面有空文件夹依旧任务是空目录。返回0失败。
}
void DelDir2(TCHAR * dir)
{
if (!PathFileExists(dir))
{
return;
}
TCHAR DelDir[MAX_PATH] = {0};
lstrcpy(DelDir,dir);
int len = lstrlen(dir);
DelDir[len] = 0;
DelDir[len+1] = 0;
SHFILEOPSTRUCT FileOp;
ZeroMemory((void*)&FileOp, sizeof(SHFILEOPSTRUCT));
FileOp.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
FileOp.hNameMappings = NULL;
FileOp.hwnd = NULL;
FileOp.lpszProgressTitle = NULL;
FileOp.pFrom = DelDir;
FileOp.pTo = NULL;
FileOp.wFunc = FO_DELETE;
int err = SHFileOperation(&FileOp);
if (0 != err)
{
//失败。
}
}
int _tmain(int argc, TCHAR *argv[])
{
setlocale(LC_CTYPE, ".936");
TCHAR path[MAX_PATH] = L"e:\\test";
bool b = deldir(path);
DelDir2(L"e:\\test2");
return 0;
}
void DisplayErrorBox(LPTSTR lpszFunction) //这个函数封装的还不错的,以后就拿来用吧!
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
// Display the error message and clean up
LPVOID lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
2012年12月4日星期二
ReportEvent.Cpp
/*
日志,怎能不会?
特别是系统的,这些基本的功能。
有时它还是特有用的。
所以有此文。
参考:
http://msdn.microsoft.com/en-us/library/aa363680(v=vs.85).aspx等相关的内容。
http://www.aogosoft.com/downpage.asp?mode=viewtext&id=220
*/
#include <windows.h>
int main()
{
HANDLE hEventLog = RegisterEventSource(NULL, L"来源");
if (NULL == hEventLog) {
return 1;
}
CONST LPWSTR pBadCommand = L"data";//这里不准用汉字,是不会显示汉字的,是以字节显示的字母的。以双0字节结尾。
DWORD dwEventDataSize = ((DWORD)wcslen(pBadCommand) + 1) * sizeof(WCHAR);
if (!ReportEvent(hEventLog,
EVENTLOG_INFORMATION_TYPE, //类型(级别)是信息。
(WORD)0x00000003L, //分类或者任务类别。
(DWORD)0xC0020100L, //低16位是事件或者事件ID,
NULL,//A pointer to the current user's security identifier. This parameter can be NULL if the security identifier is not required
0, //The number of insert strings in the array pointed to by the lpStrings parameter. A value of zero indicates that no strings are present.
dwEventDataSize, //数据的长度。
NULL, //另一种情况使用,是数组用的,与上上个参数配合使用,有大小的限制。
pBadCommand))//数据的内容。
{
return 1;
}
if (hEventLog) {
DeregisterEventSource(hEventLog);
}
}
订阅:
博文 (Atom)