Welcome to My Blog (凌云 或 Emissary). 纵然再假,那甜言蜜语却是永远不能让我忘怀。
Nov 6
在有一次测试中,驱动出现在蓝屏,蓝屏在重启前后连接两次发生。而以前及今后的测试中。都没发生这样的情况。

通过小64K转储分析得到下面结果。


0: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 00000016, memory referenced
Arg2: 0000001c, IRQL
Arg3: 00000000, bitfield :
  bit 0 : value 0 = read operation, 1 = write operation
  bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: 805033b2, address which referenced memory

MODULE_NAME: ATWatch

FAULTING_MODULE: 804d8000 nt

DEBUG_FLR_IMAGE_TIMESTAMP:  490d8b27

READ_ADDRESS: unable to get nt!MmSpecialPoolStart
unable to get nt!MmSpecialPoolEnd
unable to get nt!MmPoolCodeStart
unable to get nt!MmPoolCodeEnd
00000016

CURRENT_IRQL:  1c

FAULTING_IP:
nt+2b3b2
805033b2 6683781601      cmp     word ptr [eax+16h],1

CUSTOMER_CRASH_COUNT:  1

DEFAULT_BUCKET_ID:  WRONG_SYMBOLS

BUGCHECK_STR:  0xA

LAST_CONTROL_TRANSFER:  from 804fb166 to 805033b2

STACK_TEXT:  
WARNING: Stack unwind information not available. Following frames may be wrong.
f79dbd44 804fb166 f7d6c2c4 f879bde8 864dfc30 nt+0x2b3b2
f79dbd58 f781c5a5 f879bde8 00000000 00000000 nt+0x23166
f79dbd7c 805389dd 844f0738 00000000 865b3da8 ATWatch!NLPGetDosDeviceNameWorker+0xaf [g:\ddk\filter0810\lib\namelookup.c @ 1505]
f79dbdac 805cf858 844f0738 00000000 00000000 nt+0x609dd
f79dbddc 8054634e 805388ee 00000001 00000000 nt+0xf7858
00000000 00000000 00000000 00000000 00000000 nt+0x6e34e


STACK_COMMAND:  kb

FOLLOWUP_IP:
ATWatch!NLPGetDosDeviceNameWorker+af [g:\ddk\filter0810\lib\namelookup.c @ 1505]
f781c5a5 8b7508          mov     esi,dword ptr [ebp+8]

FAULTING_SOURCE_CODE:  
  1501:       }
  1502:     }//else if(newDevExt->NLExtHeader.DosName.Length > 0)*/
  1503:   }//if(t_ControlDeviceObject != NULL)
  1504:
> 1505:     ObDereferenceObject( Context->DeviceObject );
  1506:     ExFreePoolWithTag( Context, NL_POOL_TAG );
  1507:
  1508:     return;
  1509:
  1510: }


SYMBOL_STACK_INDEX:  2

SYMBOL_NAME:  ATWatch!NLPGetDosDeviceNameWorker+af

FOLLOWUP_NAME:  MachineOwner

IMAGE_NAME:  ATWatch.sys

BUCKET_ID:  WRONG_SYMBOLS

Followup: MachineOwner
---------



这代码其实就是 filter 里 namelookup.c 中的。
很明显的,NLPGetDosDeviceNameWorker 工作在 PASSIVE_LEVEL 。是通过 ExQueueWorkItem( &completionContext->WorkItem ,DelayedWorkQueue ); 插入到 system 里执行的。

但是,蓝屏的时候提示 IRQL_NOT_LESS_OR_EQUAL (a) ,而 CURRENT_IRQL:  1c 。。。
天啦。我不懂了。难道微软出错了吗?????




Oct 31
也就是右键弹出菜单,我在VC 2008 SP1环境。单文档视图窗口

第一种方法。。。但是我却处理不好它。

ClientToScreen(&point);

CMenu menu;
menu.LoadMenu(IDR_POP_MENU1);

CMenu* pSumMenu = menu.GetSubMenu(0);

CMFCPopupMenu* pPopupMenu = new CMFCPopupMenu;

if (!pPopupMenu->Create(this, point.x, point.y, (HMENU)pSumMenu->m_hMenu, FALSE, TRUE))
    return;

((CMainFrame*)AfxGetMainWnd())->OnShowPopupMenu(pPopupMenu);
UpdateDialogControls(this, FALSE);

SetFocus();



第二种方法。。。是系统提供的,后来才发现。

void CControlApp::PreLoadState()
{
  BOOL bNameValid;
  CString strName;
  bNameValid = strName.LoadString(IDS_EDIT_MENU);
  ASSERT(bNameValid);
  GetContextMenuManager()->AddMenu(strName, IDR_POP_MENU1);
}

在View中
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POP_MENU1, point.x, point.y, this, TRUE);


还有一个问题是,在使用了CMFCListCtrl类后,发现不能处现某些消息循环。
没办法,只有在PreTranslateMessage里用SendMessage来处理它。

使用CMFCListCtrl类的方法:CControlView类,继承于CVIEW
int CControlView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  DWORD dwStyle;
  BOOL bResult;
  if (CView::OnCreate(lpCreateStruct) == -1)
    return -1;

  // TODO:  在此添加您专用的创建代码
  dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | LVS_REPORT | LVS_SINGLESEL;
  bResult = m_wndListCtrl.Create(dwStyle, CRect(0, 0, 0, 0), this, 1);
  InitList();
  return bResult ? 0 : -1;
  //return 0;
}

CListCtrl& CControlView::GetListCtrl()
{
  return m_wndListCtrl;
}

void CControlView::OnSize(UINT nType, int cx, int cy)
{
  CView::OnSize(nType, cx, cy);

  // TODO: 在此处添加消息处理程序代码
  m_wndListCtrl.MoveWindow(0,0,cx,cy,TRUE);
}

Oct 11
#include

void MyMain()
{
  char aaa[] = "aa";
  char AAA[] = "AA";
  char bbb[13];
  int i;
  for(i=0;i<=12;i++)
    bbb[i] = 0;
  lstrcmpiA(aaa,AAA);
  ExitProcess(0);
}

没有 Rtl 的函数,只调用了两个API。
使用 /0d 链接后。输入表多出了一些 SEH 相关的API

点击在新窗口中浏览此图片

在一些时候,大小相关是比较重要的。所以一般情况不关闭这个选项。


Sep 24
内核对象同步远远优于用户方式机制。
实际上,内核对象机制的唯一不足之处是它的速度比较慢。当调用函数时,调用线程必须从用户方式转为内核方式。这个转换需要很大的代价:往返一次需要占用x 8 6平台上的大约1 0 0 0个C P U周期,当然,这还不包括执行内核方式代码,即实现线程调用的函数的代码所需的时间。


下面的内核对象可以处于已通知状态或未通知状态:

对 象          何时处于未通知状态          何时处于已通知状态          成功等待的副作用


进程           当进程仍然活动时            当进程终止运行时                         无
线程           当线程仍然活动时            当线程终止运行时                         无
作业           当作业的时间尚未结束        当作业的时间已经结束时时                 无
文件           当I/O请求正在处理时         当I/O请求处理完毕时                      无
控制台输入     不存在任何输入              当存在输入时                             无
文件修改通知   没有任何文件被修改          当文件系统发现修改时                     重置通知
自动重置事件   ResetEvent,Pulse-Event        当调用SetEvent/PulseEvent时或等待成功    重置事件
人工重置事件   ResetEvent,Pulse-Event         当调用SetEvent/PulseEvent时              无
自动重置等待定时器 CancelWaitableTimer或等待成功 当时间到时                         重置定时器
人工重置等待定时器 CancelWaitableTimer       当时间到时                               无
信标           等待成功                    当数量>0时                              数量递减1
互斥对象       等待成功                    当未被线程拥有时                         将所有权赋予线程
关键代码段     等待成功                    当未被线程拥有时                         将所有权赋予线程


成功等待的副作用
当一个对象的状态改变时,我称之为成功等待的副作用。例如,有一个线程正在等待自动清除事件对象(本章后面将要介绍) 。当事件对象变为已通知状态时,函数就会发现这个情况,并将 WAIT_OBJECT_0 返回给调用线程。但是就在函数返回之前,该事件将被置为未通知状态,这就是成功等待的副作用。
这个副作用将用于自动清除内核对象,因为它是 microsoft 为这种类型的对象定义的规则之一。其他对象拥有不同的副作用,而有些对象则根本没有任何副作用。进程和线程内核对象就根本没有任何副作用,也就是说,在这些对象之一上进行等待决不会改变对象的状态。由于本章要介绍各种不同的内核对象,因此我们将要详细说明它们的成功等待的副作用。

事件能够通知一个操作已经完成。有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程。

设备对象是可以同步的内核对象
这意味着可以调用 WaitForSingleObject 函数,传递文件、套接字和通信端口的句柄。当系统执行异步I / O时,设备对象处于未通知状态。一旦操作完成,系统就将对象的状态改为已通知状态,这样,该线程就知道操作已经完成。此时,该线程就可以继续运行。



Sep 23
demonstrates how to create a process from an executable PE format file. The argument to the program is the full path in the native NT format of the executable file.To start notepad the argument could be “\SystemRoot\System32\notepad.exe”.

示范怎么样利用一个可执行的PE文件去创建一个进程,这个程序的参数是一个内核的绝对路径,运行记事本,这个参数就是“\SystemRoot\System32\notepad.exe”.

The following steps are taken by the exec routine to create a new process running a specific image file:

下面的步骤用exec函数去创建一个新的进程,运行一个指定的文件。

■ Open the executable file, and create an image section from it by calling ZwCreateSection with an argument of SEC_IMAGE. Once the section has been created, the file can be closed.

打开可执行文件,通过 ZwCreateSection 创建一个映像节,其中一个参数为SEC_IMAGE。一旦节被创建,这个文件可以被关闭。
■ Call ZwCreateProcess to create the process. If this call returns successfully, a new process has been created that has the image section and ntdll.dll mapped into its address space.

调用 ZwCreateProcess 创建进程,如果成功,一个新的进程创建,这个映像节和 ntdll.dll 被映射进它的地址空间.

■ Call ZwQuerySection to obtain information about the image, such as its entry point and suggested stack size. Once this information has been obtained, the section handle can be closed, because the section is now referenced by the new process.

调用 ZwQuerySection 获得关于这个映像的信息,例如它的入口点和默认的堆栈大小,一旦这个信息被获得,这个节的句柄可以关闭,因为这个节由新的进程参照。

■ Create the user mode stack. ZwAllocateVirtualMemory is used to perform the allocations, and ZwProtectVirtualMemory is used to establish a guard page at the end of the committed region of the stack.

创建用户模式堆栈,ZwAllocateVirtualMemory 被用来执行内存的分配,ZwProtectVirtualMemory 被用来建立一个保护页,在堆栈的后面。

■ Establish the execution context of the initial thread by storing fixed values into the CONTEXT structure and updating the stack pointer (Esp) to point to the new stack and the instruction pointer (Eip) to point to the entry point of the image.The Win32  functions CreateProcess and CreateThread set Eip to the address of a thunk in kernel32.dll that establishes a frame-based exception handler before
calling the image entry point, but this example does not bother with that refinement.

建立初始的主线程的执行上下文,通过保存固定的值到 CONTEXT 结构,并且更新堆栈指针(ESP)为新的,把指令指针EIP指向映像入口点。在调用这个映像入口点以前,Win32的函数 CreateProcess 和 CreateThread 设置EIP到 kernel32.dll 的一个地址,并建立一个基于异常处理的结构,但是这个例子没有这样精致的做。

■ Create the initial thread in a suspended state by calling ZwCreateThread.

通过 ZwCreateThread 创建初始的主线程在悬挂状态,

■ Create and copy the process parameters (including process environment) to the new process and update the PEB of the new process to point to them.

创建并复制进程参数(包括进程环境)到那个新的进程,并更新新进程的PEB指向它们。

■ InformCsrss informs the Win32 subsystem that a Win32 client process is about to start; this gives the subsystem the opportunity to modify some settings of the process, such as setting process debug and exception ports.

InformCsrss 通告Win32的子系统,一个Win32的进程正要启动,给这个子系统时机修改一些进程的设置,比如设置进程的调试和异常。

■ Resume the initial thread in the new process by calling ZwResumeThread.

调用 ZwResumeThread 重新启动这个新进程里的初始主线程。

At any time after the creation of the process and before resuming the initial thread, the process parameters can be created.The process parameters contain process information that is maintained and manipulated in user mode such as the current directory, the command line, the environment, and so on.Most values can be copied from the current process.

在创建进程以后和任何时间和重新启动初始主线程之前,进程参数都可以创建,进程参数包含进程信息在用户模式下被维护和使用,比如当时的目录,命令行,环境,还有,更多的值能从当前进程复制。

First the environment is copied to the new process, then the process parameters themselves (which contain a pointer to the environment), and finally the PEB of the new process is patched to point to the process parameters.

首先这个环境被复制到新的进程,这时,这个进程参数它们自己(包含一个指向环境的指针),完成这个新进程的PEB,修补指针指向进程参数。



Aug 11
IRQL 中断等级定义

KeGetCurrentIrql()

#define PASSIVE_LEVEL 0             // Passive release level
#define LOW_LEVEL 0                 // Lowest interrupt level
#define APC_LEVEL 1                 // APC interrupt level
#define DISPATCH_LEVEL 2            // Dispatcher level
#define CMCI_LEVEL 5                // CMCI handler level

#define PROFILE_LEVEL 27            // timer used for profiling.
#define CLOCK1_LEVEL 28             // Interval clock 1 level - Not used on x86
#define CLOCK2_LEVEL 28             // Interval clock 2 level
#define IPI_LEVEL 29                // Interprocessor interrupt level
#define POWER_LEVEL 30              // Power failure level
#define HIGH_LEVEL 31               // Highest interrupt level

碰到一个小小问题。

是这样,我在 DriverEntry 处用 RtlInitUnicodeString 初始化了一个字串。

但在插入系统线程中,访问时却出现错误,调用的是COPY函数。

搞了半天,终于明白了,我想是以下原因之一。

一,DriverEntry 为 INIT 节,初始化了后就自动删除。
二,RtlInitUnicodeString 初始化的是一个分页缓冲区。

但,系统线程是以 PASSIVE LEVEL 运行的。。。所以,访问分页缓冲区是可以的。
原因一,应该是重点!

Aug 3

DriverEntry (
    __in PDRIVER_OBJECT DriverObject,
    __in PUNICODE_STRING RegistryPath
    )
的例程中。我使用了 事件
pUSBExt->pRing3Event = IoCreateNotificationEvent(&Ring3USBEventString,&pUSBExt->hUSBEventHandle);


结果
*** Fatal System Error: 0x0000007e
                       (0xC0000005,0x804E4619,0xF78AA4BC,0xF78AA1B8)

WARNING: This break is not a step/trace completion.
The last command has been cleared to prevent
accidental continuation of this unrelated event.
Check the event, location and thread before resuming.
Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.


进而蓝屏死机。


看了帮助文档。

才发现

so drivers that are loaded at boot time cannot create event objects in the \\BaseNamedObjects directory in their DriverEntry routines

Aug 2
VC2008默认生成以下定义

/*#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif

#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif

这样的话,无法使用气球提示。
(NOTIFYICONDATA).dwInfoFlags= NIIF_INFO;

Shell_NotifyIcon 之后,没办法弹出。



花了一点时间。看了MSDN。终于明白了。 WINVER和_WIN32_WINNT的版本并不是越高越好的。


如果改为

#ifndef WINVER        // 指定要求的最低平台是 Windows Vista。
#define WINVER 0x0501    // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif

#ifndef _WIN32_WINNT    // 指定要求的最低平台是 Windows Vista。
#define _WIN32_WINNT 0x0501  // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif            


那么一切正常。。。。。


微软害人的习俗。。。。。。。。。。。。。。。。


点击在新窗口中浏览此图片

Jul 28
Indy 10(10.2.3) 2008-07-27 最新版本上传。这是一个快照版本,修正了一些以前版本的BUG。

从官方下载:http://www.indyproject.org   http://indy.fulgan.com/ZIP/


点击在新窗口中浏览此图片
Jul 11
我也懒得翻译了。。
简单说就是用 IOCTL_DISK_GET_DRIVE_GEOMETRY 去查询 MEDIA_TYPE 类型。


IOCTL_DISK_GET_DRIVE_GEOMETRY
Operation
Returns information about the physical disk's geometry (media type, number of cylinders, tracks per cylinder, sectors per track, and bytes per sector).

Input
Parameters.DeviceIoControl.OutputBufferLength in the I/O stack location of the IRP indicates the size, in bytes, of the buffer, which must be >= sizeof(DISK_GEOMETRY).

Output
The driver returns the DISK_GEOMETRY data in the buffer at Irp->AssociatedIrp.SystemBuffer.

I/O Status Block
The Information field is set to the size, in bytes, of the returned data. The Status field can be set to STATUS_SUCCESS, or possibly to STATUS_UNRECOGNIZED_MEDIA, STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_INFO_LENGTH_MISMATCH, STATUS_INSUFFICIENT_RESOURCES, or STATUS_BUFFER_TOO_SMALL.

Requirements
Headers: Defined in Ntdddisk.h. Include Ntdddisk.h.

DISK_GEOMETRY

The DISK_GEOMETRY structure is obsolete and provided only to support existing drivers. New drivers must use DISK_GEOMETRY_EX. DISK_GEOMETRY is used in conjunction with the IOCTL_DISK_GET_DRIVE_GEOMETRY and the IOCTL_DISK_GET_MEDIA_TYPES requests, in order to retrieve information about the geometry of a physical disk.

typedef struct _DISK_GEOMETRY {
  LARGE_INTEGER  Cylinders;
  MEDIA_TYPE  MediaType;
  ULONG  TracksPerCylinder;
  ULONG  SectorsPerTrack;
  ULONG  BytesPerSector;
} DISK_GEOMETRY, *PDISK_GEOMETRY;


Members
Cylinders
Indicates the number of cylinders on the disk device.
MediaType
Indicates the type of disk. The enumeration MEDIA_TYPE lists the values that can be assigned to this member.
TracksPerCylinder
Indicates the number of tracks in a cylinder.
SectorsPerTrack
Indicates the number of sectors in each track.
BytesPerSector
Indicates the number of bytes in a disk sector.

Comments
DISK_GEOMETRY_EX must be used with new drivers, in order to accommodate GUID Partition Table (GPT) partitions. The DISK_GEOMETRY structure is nested within the DISK_GEOMETRY_EX structure.

IOCTL_DISK_GET_MEDIA_TYPES causes an array of these structures to be returned.

Requirements
Headers: Declared in ntddk.h and ntdddisk.h. Include ntddk.h or ntdddisk.h.


MEDIA_TYPE

The MEDIA_TYPE enumerators are used in conjunction with the IOCTL_DISK_FORMAT_TRACKS request to format the specified set of contiguous tracks on the disk.

typedef enum _MEDIA_TYPE {
  Unknown,
  F5_1Pt2_512,
  F3_1Pt44_512,
  F3_2Pt88_512,
  F3_20Pt8_512,
  F3_720_512,
  F5_360_512,
  F5_320_512,
  F5_320_1024,
  F5_180_512,
  F5_160_512,
  RemovableMedia,
  FixedMedia,
  F3_120M_512,
  F3_640_512,
  F5_640_512,
  F5_720_512,
  F3_1Pt2_512,
  F3_1Pt23_1024,
  F5_1Pt23_1024,
  F3_128Mb_512,
  F3_230Mb_512,
  F8_256_128
} MEDIA_TYPE, *PMEDIA_TYPE;


Enumerators
Unknown
Format is unknown.
F5_1Pt2_512
Indicates 5.25", 1.2 MB, 512 bytes/sector media.
F3_1Pt44_512
Indicates 3.5", 1.44 MB, 512 bytes/sector media.
F3_2Pt88_512
Indicates 3.5", 2.88 MB, 512 bytes/sector media.
F3_20Pt8_512
Indicates 3.5", 20.8 MB, 512 bytes/sector media.
F3_720_512
Indicates 3.5", 720 KB, 512 bytes/sector media.
F5_360_512
Indicates 5.25", 360 KB, 512 bytes/sector media.
F5_320_512
Indicates 5.25", 320 KB, 512 bytes/sector media.
F5_320_1024
Indicates 5.25", 320 KB, 1024 bytes/sector media.
F5_180_512
Indicates 5.25", 180 KB, 512 bytes/sector media.
F5_160_512
Indicates 5.25", 160 KB, 512 bytes/sector media.
RemovableMedia
Indicates removable media other than a floppy disk.
FixedMedia
Indicates fixed hard disk media.
F3_120M_512
Indicates 3.5", 120 MB media.
F3_640_512
Indicates 3.5", 640 KB, 512 bytes/sector media.
F5_640_512
Indicates 5.25", 640 KB, 512 bytes/sector media.
F5_720_512
Indicates 5.25", 720 KB, 512 bytes/sector media.
F3_1Pt2_512
Indicates 3.5", 1.2 MB, 512 bytes/sector media.
F3_1Pt23_1024
Indicates 3.5", 1.23 MB, 1024 bytes/sector media.
F5_1Pt23_1024
Indicates 5.25", 1.23 MB, 1024 bytes/sector media.
F3_128Mb_512
Indicates 3.5" magneto-optical (MO), 128 MB, 512 bytes/sector media.
F3_230Mb_512
Indicates 3.5" magneto-optical (MO), 230 MB, 512 bytes/sector media.
F8_256_128
Indicates 8", 256 KB, 128 bytes/sector media.


Comments
The caller of the IOCTL_DISK_FORMAT_TRACK request indicates the disk size and number of bytes per sector, along with other formatting information, by specifying one of these values in the MediaType member of the FORMAT_PARAMETERS structure.

Removable disks include zip drivers, jaz drives, magneto-optical (MO) drives, and LS-120 floppies as well as regular floppies.

Requirements
Headers: Declared in ntdddisk.h. Include ntdddisk.h.


分页: 1/3 第一页 1 2 3 下页 最后页 [ 显示模式: 摘要 | 列表 ]