存档

作者存档
1,088 views

在 Windows下用 Visual studio 编译 OpenSSL (VC6 VS2003-VS2010)

2010年12月11日

我下载的 openssl 的源代码包是 openssl-1.0.0c.tar.gz, 版本 1.0.0c.

1. 安装 ActivePerl, 因为初始化的时候, 需要用到 perl 解释器

2. 使用 VS2005 下的 Visual Studio 2005 Command Prompt 进入控制台模式 (这个模式会自动设置各种环境变量)

3. 解压缩 openssl 源代码包, 进入 openssl 的根目录, 如 c:\openssl-1.0.0c

4. perl configure VC-WIN32
必须在 c:\openssl-1.0.0c 目录下执行该命令, 否则找不到 Configure 文件, 这时就必须指定完整的 Configure 文件路径.

5. ms\do_ms
在 c:\openssl-1.0.0c 目录下执行 ms\do_ms 命令

6. 在正式编译之前,
(1). 找到 c:\openssl-1.0.0c\ms\ntdll.mak 文件, 用记事本打开, 搜索 “/MD” 字符串, 替换成 “/MT”, 这将导致静态链接 C 运行时, 省却你要在目标机器上安装 VC 再发行包等等让人抓狂的事.

(2) 找到 c:\openssl-1.0.0c\e_os.h 文件, 用记事本打开, 找到

#  if !defined(OPENSSL_USE_IPV6)
#    if defined(AF_INET6) && !defined(OPENSSL_SYS_BEOS_BONE) && !defined(NETWARE_CLIB)
#      define OPENSSL_USE_IPV6 1
#    else
#      define OPENSSL_USE_IPV6 0
#    endif
#  endif

替换成

#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER > 1200 )
#  if !defined(OPENSSL_USE_IPV6)
#    if defined(AF_INET6) && !defined(OPENSSL_SYS_BEOS_BONE) && !defined(NETWARE_CLIB)
#      define OPENSSL_USE_IPV6 1
#    else
#      define OPENSSL_USE_IPV6 0
#    endif
#  endif
#else
#  if !defined(OPENSSL_USE_IPV6)
#      define OPENSSL_USE_IPV6 0
#  endif
#endif

这一步的目的是, 在 VC6 下编译时, 避免使用 IPv6 特性, 因为 VC6 不支持.

(3). 找到 c:\openssl-1.0.0c\crypto\mem.c 文件, 在文件靠近顶部包含文件语句的下面, 添加如下代码

#ifndef OPENSSL_CPUID_OBJ
extern unsigned char cleanse_ctr;
#endif

7. 编译动态链接库版本
nmake -f ms\ntdll.mak

8. 编译静态链接库版本
nmake -f ms\nt.mak

完成编译后, 输出的动态链接库版本文件在 out32dll 里面, 包括应用程序的可执行文件, lib 文件和 dll 文件;
静态链接库版本文件在 out32 里面, 包括应用程序的可执行文件和 lib 文件.

技术心得, 日常琐碎

981 views

2010 中国软件百强

2010年11月13日

CNET科技资讯网 6月4日 ZDNET至顶网专稿(文/蒋湘辉):今年发布的软件百强企业共实现软件业务收入2448.7亿元,根据当前汇率计算,已经超过了360亿美元,但仍然不如微软一家公司的收入。

5月28日,第9届中国软件业务收入前百家企业名单在沈阳发布。华为以725.68亿元软件收入连续9年位居榜首,中兴与神州数码分列二、三位,软件收入分别为 270.66亿元及130.4亿元。而浪潮集团、南京南瑞、浙大网新、上海宝信、用友软件、杭州恒生电子、东软集团、珠海金山软件、金蝶软件和山东中创软件等十家企业入选“2010中国自主品牌软件产品收入前十家企业”。

今年发布的软件百强企业共实现软件业务收入2448.7亿元,根据当前汇率计算,已经超过了360亿美元,但仍然不如微软一家公司的收入。(2009财年微软收入584亿美元,其中软件和互联网业务超过500亿美元)这表明,我们软件产业虽然保持了多年的高速增长(9年来,我国百家企业的软件业务总收入增长了5.3倍,年均增长23%),但在自主品牌软件的做大做强方面,仍有很长的路要走。在本届的软件百强中,收入超过50亿元的企业有6家,与上届持平。

以下为2010年中国软件百强名单:

阅读全文…

日常琐碎

1,016 views

使用 NT 缓存管理器

2010年11月9日

使用 NT 缓存管理器 (中文版) 转载自 这里
英文原版 Cache Me if You Can: Using the NT Cache Manager

缓存管理器

在这篇文章中, 我们将对缓存管理器的一个运行时例程做个基本的描述. 此外, 对于这些例程使用的一些方法以及示例代码, 可以参考 Microsoft IFS Kit.

缓存管理器概述

缓存管理器是一个软件部分, 集成在 Windows Nt 内存管理器中, 以集成文件系统 (数据) 和虚拟内存系统. 一些操作系统完成它们自己的文件系统, 所以它们有自己的数据cache. 然而, 因为这些caches受物理内存限制, 它们在大小上受限 – 用作cache的这块内存在系统中也不能做其它用途使用了.

因此, 使用windows NT缓存管理器的一个关键优势是, 它可以使文件缓存和程序运行所需要的物理内存达到平衡. 当应用程序是I/O密集型的时候, 所谓的“平衡”就倾向于做缓存数据. 当应用程序非常耗内存, 那么用来缓存数据的内存可能会被减为0. 因此最终结果是系统更好地使用物理内存从而提供更好的性能. 文件系统使用缓存管理器的另一个重要原因是, 文件能这样被访问: 通过标准文件系统接口 (例如读和写) 或者通过内存管理器 (一个内存映像文件) . 当对同一个文件同时使用这两种方法的时候, 缓存管理器能够提供机制以保证数据一致性.

阅读全文…

内核编程

939 views

关于 windows 内核下的读写锁

2010年11月9日

参考 FILEMON 中的代码,以及 DDK 中的说明:

ERESOURCE 对象相当于读写锁, 即用于同时只能有一个 WRITER 写入, 多个 READER 读的情况:

函数名称 作用
ExInitializeResourceLite 初始化一个 ERESOURCE 对象
ExDeleteResourceLite 删除一个 ERESOURC 对象
ExAcquireResourceExclusiveLite 用于获取 ERESOURCE (写访问)
ExAcquireResourceSharedLite 用于获取 ERESOURCE (读访问)
ExReleaseResourceLite 用于释放 ERESOURCE

参考文献:
Driver Threads, Dispatcher Objects, and Resources

内核编程

796 views

[转]Windows文件系统的杂谈

2010年11月5日

author: jonathan
本文档的CopyRight归jonathan所有,可自由转载,转载时请保持文档的完整性。
/*————————————————————————————————————*/
1 杂谈
1.1 FCB/SCB的COMMON结构定义

// fat
#define NTC_UNDEFINED                    ((NODE_TYPE_CODE)0x0000)
#define FAT_NTC_DATA_HEADER              ((NODE_TYPE_CODE)0x0500)
#define FAT_NTC_VCB                      ((NODE_TYPE_CODE)0x0501)
#define FAT_NTC_FCB                      ((NODE_TYPE_CODE)0x0502)
#define FAT_NTC_DCB                      ((NODE_TYPE_CODE)0x0503)
#define FAT_NTC_ROOT_DCB                 ((NODE_TYPE_CODE)0x0504)
#define FAT_NTC_CCB                      ((NODE_TYPE_CODE)0x0507)
#define FAT_NTC_IRP_CONTEXT              ((NODE_TYPE_CODE)0x0508)
// ntfs
#define NTC_UNDEFINED                    ((NODE_TYPE_CODE)0x0000)
#define NTFS_NTC_DATA_HEADER             ((NODE_TYPE_CODE)0x0700)
#define NTFS_NTC_VCB                     ((NODE_TYPE_CODE)0x0701)
#define NTFS_NTC_FCB                     ((NODE_TYPE_CODE)0x0702)
#define NTFS_NTC_SCB_INDEX               ((NODE_TYPE_CODE)0x0703)
#define NTFS_NTC_SCB_ROOT_INDEX          ((NODE_TYPE_CODE)0x0704)
#define NTFS_NTC_SCB_DATA                ((NODE_TYPE_CODE)0x0705)
#define NTFS_NTC_SCB_MFT                 ((NODE_TYPE_CODE)0x0706)
#define NTFS_NTC_SCB_NONPAGED            ((NODE_TYPE_CODE)0x0707)
#define NTFS_NTC_CCB_INDEX               ((NODE_TYPE_CODE)0x0708)
#define NTFS_NTC_CCB_DATA                ((NODE_TYPE_CODE)0x0709)
#define NTFS_NTC_IRP_CONTEXT             ((NODE_TYPE_CODE)0x070A)
#define NTFS_NTC_LCB                     ((NODE_TYPE_CODE)0x070B)
#define NTFS_NTC_PREFIX_ENTRY            ((NODE_TYPE_CODE)0x070C)
#define NTFS_NTC_QUOTA_CONTROL           ((NODE_TYPE_CODE)0x070D)
//cdfs
#define NTC_UNDEFINED                   ((NODE_TYPE_CODE)0x0000)
#define CDFS_NTC_DATA_HEADER            ((NODE_TYPE_CODE)0x0301)
#define CDFS_NTC_VCB                    ((NODE_TYPE_CODE)0x0302)
#define CDFS_NTC_FCB_PATH_TABLE         ((NODE_TYPE_CODE)0x0303)
#define CDFS_NTC_FCB_INDEX              ((NODE_TYPE_CODE)0x0304)
#define CDFS_NTC_FCB_DATA               ((NODE_TYPE_CODE)0x0305)
#define CDFS_NTC_FCB_NONPAGED           ((NODE_TYPE_CODE)0x0306)
#define CDFS_NTC_CCB                    ((NODE_TYPE_CODE)0x0307)
#define CDFS_NTC_IRP_CONTEXT            ((NODE_TYPE_CODE)0x0308)
#define CDFS_NTC_IRP_CONTEXT_LITE       ((NODE_TYPE_CODE)0x0309)

typedef struct _FSRTL_COMMON_FCB_HEADER {
  CSHORT NodeTypeCode;
  CSHORT NodeByteSize;
  UCHAR Flags;
  UCHAR IsFastIoPossible;
  UCHAR Flags2;
  UCHAR Reserved : 4;
  UCHAR Version : 4;
  PERESOURCE Resource;
  PERESOURCE PagingIoResource;
  LARGE_INTEGER AllocationSize;
  LARGE_INTEGER FileSize;
  LARGE_INTEGER ValidDataLength;
} FSRTL_COMMON_FCB_HEADER;
typedef FSRTL_COMMON_FCB_HEADER *  PFSRTL_COMMON_FCB_HEADER;

Flags2 & FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS

typedef struct _FSRTL_ADVANCED_FCB_HEADER {
  FSRTL_COMMON_FCB_HEADER;
  PFAST_MUTEX FastMutex;
  LIST_ENTRY FilterContexts;
  EX_PUSH_LOCK PushLock;
  PVOID* FileContextSupportPointer;
} FSRTL_ADVANCED_FCB_HEADER;

typedef FSRTL_ADVANCED_FCB_HEADER * PFSRTL_ADVANCED_FCB_HEADER;

typedef struct _FSRTL_PER_STREAM_CONTEXT {
  LIST_ENTRY Links;
  PVOID OwnerId;
  PVOID InstanceId;
  PFREE_FUNCTION FreeCallback;
} FSRTL_PER_STREAM_CONTEXT, * PFSRTL_PER_STREAM_CONTEXT;

OwnerId 和 InstanceId都需要有意义的值:
OwnerId = 可以是驱动对象的地址等
InstanceId = 可以是流上下文地址 (FsRtlGetPerStreamContextPointer)

1.2 Cleanup和Close的区别

在FCB或者SCB中都有如下两个变量:
CLONG CleanupCount; 打开未关闭文件句柄。
CLONG CloseCount; 打开未关闭文件对象。
在SCB中还有一变量:

    //
    // A count of the number of file objects opened on this stream
    // which represent user non-cached handles. We use this count to
    // determine when to flush and purge the data section in only
    // non-cached handles remain on the file.
    //
    CLONG NonCachedCleanupCount;

1.3 资源同步问题
在文件过滤驱动中,如要访问 ExAcquireResourceExclusive 等资源时,为了防止一般内核的 APC 调度,需调用如下接口:

FsRtlEnterFileSystem(KeEnterCriticalRegion)
FsRtlExitFileSystem(KeExitCriticalRegion)

关于设置 TopLevelIrp 也是很重要的,在访问ExAcquireResourceExclusive 等资源时,也需要考虑该接口调用:

if ( IoGetTopLevelIrp() == NULL ) {
        IoSetTopLevelIrp( Irp );
        return TRUE;
    } else {
        return FALSE;
    }

设置 IoSetTopLevelIrp 目的:当前调用的 irp 是否是原始的线程操作 irp 还是由于线程的其他操作从而又产生的新的 irp 操作。

1.4 文件对象状态跟踪
跟踪一个文件操作的状态,一般使用 FCB。而 FCB 的生命周期,又是以 CREATE 开始,以 CLOSE 结束。
但是文件系统内部也会通过 IoCreateStreamFileObject (会调用 IRP_MJ_CLEANUP) 和 IoCreateStreamFileObjectLite (会调用 IRP_MJ_CLEANUP 或者 IRP_MJ_CLOSE) 等创建文件对象,但是这些文件对象却不会调用 Create,为跟踪状态带来困难。
因此,必须在 IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_SET_INFORMATION 和 IRP_MJ_GET_INFORMATION 中动态创建。

1.5 文件加密中注意要清缓存
1.5.1 文件加密关注重点是缓存问题
1.5.2 清缓存有两个时机:create 和 cleanup
1.5.3 清缓存方式
1.5.4 双缓存与双 FCB,个人认为本质是相同,不过是管理缓存的方法和机制作了改变,结果可能双 FCB 有更加稳定和高移植性

1.6 同步机制
spin_lock, event, resource, mutex, time, semaphore, thread, process, file等各种对象

1.7 IRP_MJ_FILE_SYSTEM_CONTROL
此接口调用的device是设备,但是这个设备参数哪里来的呢?
其实就是IrpSp->Parameters.MountVolume.Vpb->RealDevice中的设备。

内核编程

983 views

文件过滤驱动的东东,总结的比较全面

2010年10月21日

1> IFS 流程图
a.生成一个控制设备.当然此前你必须给控制设置指定名称.
b.设置Dispatch Functions.
c.设置Fast Io Functions.
d.编写一个my_fs_notify回调函数,在其中绑定刚激活的FS CDO.
e.使用wdff_reg_notify调用注册这个回调函数。
f.编写默认的dispatch functions.
g.处理IRP_MJ_FILE_SYSTEM_CONTROL,在其中监控Volumne的Mount和Dismount.
h.下一步自然是绑定Volumne了.
(全路径是在 FileObject->FileName.Buffer中得到的.)
2>一些必要知识
a.几个概念的区别
1.多数的storage drivers 是PNP管理的,存在一个设备节点(DEVNODE),(It is important to note that file systems and file system filter drivers are not PnP device drivers;),每个设备节点上维护一个Storage Device Stacks,这个就是因为每个存储设备,例如磁盘设备,可能包含一个或者多个逻辑卷(分区或者动态卷),这些卷就是通过这个Storage Device Stack来保存的。该设备点的信息就是functional device object (FDO)。剩下的就是physical device objects (PDO)代表各个分区。
2.通过下面的方式可以得到卷的名称
The Mount Manager responds to the arrival of a new storage volume by querying the volume driver for the following information:
·The volume’s nonpersistent device object name (or target name), located in the Device directory of the system object tree (for example: “\Device\HarddiskVolume1″)
·The volume’s globally unique identifier (GUID), also called the unique volume name
·A suggested persistent symbolic link name for the volume, such as a drive letter (for example, “\DosDevices\D:”)
3.文件系统和卷的区别
When a file system is mounted on a storage volume, it creates a file system volume device object (VDO) to represent the volume to the file system. The file system VDO is mounted on the storage device object by means of a shared object called a volume parameter block (VPB).
File System Stacks :File system drivers create two different types of device objects: control device objects (CDO) and volume device objects (VDO).
File System Control Device Objects (CDO)
File System Volume Device Objects (VDO)

阅读全文…

内核编程

604 views

若干关于 file system driver stack

2010年10月21日

写这个文章的初衷是想知道究竟一个读写文件的 irp 都是怎样被处理的…..

大家都知道这样的一个读写文件 irp 是发送给 file system 的 driver 的, file system 把这个 irp 交给了下层的 device.

这个 device 叫 logical volume device, 它由 device 的 vbp 里面的 realdevice 指针指出 (不一定就会是这个 device, 而应该是这个 device 所在的 stack 的最上层的 device). 那这个 device 是个什么东西呢? 它是怎么来的呢? 按照道理, 这个 irp 应该被发送到 disk 的驱动去才对? 那么这个 device 是 disk 的驱动创建的么? 如果不是, 那中间都有些什么步骤呢?

本文就是回答上面这些问题的.

用 softice 看看就知道 file system 转发的 irp 并不是 vpb 指向的那个 device, 而是另外一个叫 volsnap 的 driver 创建的 device. 再跟踪看看, volsnap 创建的 device 是跟 vpb 的 device 在同一个 stack 里面, 而且 volsnap 创建的 device 的下一个 device 就是 vpb 的 device.

好了. 至少知道了确实 file system driver 要把 irp 转发到 vpb 指向的 device 去. 那接下来呢? irp 又会到哪里?

再跟踪下去. irp 到了一个由 partmgr.sys 创建的 device 里, 看看这个 partmgr… 它是一个 disk driver 的 filter (多用注册表,当初我在这里花了好长时间才发现这个东西是一个 filter), 所以 partmgr 把这个 irp 转发到了 disk driver. disk driver 接着发给了 acpi.sys, 然后 acpi.sys 转发给了 atapi.sys 创建的一个 device 去, 看看这个 device 的 stack, 已经是 1 了, irp 就到尽头了, 接下来的就不是 irp 的流程了, 而是所谓的 port/miniport 流程了.

大致的把整个的结构过了一次, 里面有很多的疑问, 下面要一一解释, 最好是能用 device tree 看看这个过程, 看看哪些是 pdo 哪些是 fdo, 看看每个 device 的 stack 值都是多少, 自己模仿下看看能不能了解 irp 的流程.

上面的整个 irp 的流程是很大的. 顶层 device 的 stack 达到了 8, 首先你就会奇怪这么庞大一个 device stack 是怎么建立起来的?

先说最上面的部分
file system 在受到一个 mount 的 fs control 的时候, 创建了一个无名的 device, 并且保存了 vpb 的 realdevice 所在的 stack 的最上层的 device, 以后所有的 irp 都转发到这个保存的指针上面. 注意这里并没有 attach 到那个 device 的 stack 上面, 而是直接使用指针 call driver 的. 这里会有一个问题, 在 file system mount 以后, 再 attach 到 volume device 的 stack 上的 device 收不到 file system 传递过来的 irp, 至于这个问题怎么解决, msdn 里面有说, 把这个 filter driver 设置成启动时加载,至于为什么这样作了就能行, 这个在后面会有解释.

阅读全文…

内核编程

634 views

驱动对象 设备对象 设备栈 乱杂谈

2010年10月21日

作者: JIURL
 
   用有限的几句话就舒舒服服的建立起对驱动对象和设备对象的概念是不可能的。刚开始是一片模糊,了解的多了,慢慢就清楚。下面的内容会使你对他们了解的清楚些。
  为了后面的叙述方便,首先列出驱动对象和设备对象的结构。
  驱动对象结构 DRIVER_OBJECT ,定义如下
  struct _DRIVER_OBJECT (sizeof=168)
  +00 int16 Type
  +02 int16 Size
  +04 struct _DEVICE_OBJECT *DeviceObject
  +08 uint32 Flags
  +0c void *DriverStart
  +10 uint32 DriverSize
  +14 void *DriverSection
  +18 struct _DRIVER_EXTENSION *DriverExtension
  +1c struct _UNICODE_STRING DriverName
  +1c uint16 Length
  +1e uint16 MaximumLength
  +20 uint16 *Buffer
  +24 struct _UNICODE_STRING *HardwareDatabase
  +28 struct _FAST_IO_DISPATCH *FastIoDispatch
  +2c function *DriverInit
  +30 function *DriverStartIo
  +34 function *DriverUnload
  +38 function *MajorFunction[28]

阅读全文…

内核编程

975 views

ATL Enumerator coding

2010年10月1日

template <typename EnumType, typename CollType>
HRESULT CreateSTLEnumerator(IUnknown ** ppUnk,
	IUnknown * pUnkForRelease,
	CollType & collection)
{
	HRESULT hr = E_POINTER;
	do
	{
		if (ppUnk == NULL) { break; }
		*ppUnk = NULL;

		CComObject<EnumType>* pEnum = NULL;
		HRESULT hr = CComObject<EnumType>::CreateInstance(&pEnum);

		if (FAILED(hr)) { break; }

		{
			pEnum->AddRef();
			hr = pEnum->Init(pUnkForRelease, collection);
			if (SUCCEEDED(hr)) {
				hr = pEnum->QueryInterface(ppUnk);
			}
			pEnum->Release();
		}
	} while (FALSE);
	return hr;
} // CreateSTLEnumerator

template<typename T>
class _CopyInterfaceFromCComPtr
{
public:
	typedef T * LPINTERFACE;

	static HRESULT copy(OUT T ** p1, IN CComPtr<T> const * p2)
	{
		ATLASSERT(p1 != NULL && p2 != NULL);
		return p2->QueryInterface(p1);
	}
	static void init(IN OUT T * * ) {}
	static void destroy(IN OUT T * * p)
	{
		if (*p) { (*p)->Release(); }
	}
};

使用方法:

STDMETHODIMP CFsFolder::EnumChildren(IEnumFsItem **ppChildren)
{
	//typedef _CopyInterface<IFsItem> _CopyFsItemInterface;
	typedef _CopyInterfaceFromCComPtr<IFsItem> _CopyFsItemInterface;

	typedef CComEnumOnSTL <
		IEnumFsItem,
		&__uuidof(IEnumFsItem),
		_CopyFsItemInterface::LPINTERFACE,
		_CopyFsItemInterface,
		std::vector< CComPtr<IFsItem> >
	> FsItemEnum;

	HRESULT hr = E_FAIL;
	do
	{
		CComPtr<IUnknown> spOut;
		hr = CreateSTLEnumerator<FsItemEnum,
                            std::vector< CComPtr<IFsItem> > > (
        			&spOut, GetUnknown(), m_vecChildren);
		if (SUCCEEDED(hr))
		{
			hr = spOut->QueryInterface(ppChildren);
		}
	} while (FALSE);
	return hr;
}

技术心得

1,927 views

VS 2010 远程调试

2010年9月13日