以前看很多教科书,都只是说流驱动是通过device.exe来加载的,但是具体是怎么加载,注册表的几要素到底有什么作用我一无所知,刚才在论坛看到一些眉目,现在收集下来,造福you and me。同时感谢songtitan
songtitan引用楼主 wangxin_801115 的帖子:
在CE下电源管理 MDD层代码中:
电池驱动对外接口函数没有“BAT_”前缀,因为HKEY_LOCAL_MACHINE/Drivers/BuiltIn/Battery/Flags注册表项设置了DEVFLAGS_NAKEDENTRIES属性,表示“Init”代替“BAT_Init”,这样修改注册表“Prefix”项的值时不需要修改驱动代码。
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/Battery]
"Prefix"="BAT"
"Dll"="battdrvr.dll"
"Flags"=dword:8 ; DEVFLAGS_NAKEDENTRIES…
所有的流式驱动都是XXX_Init...其中XXX必须在注册表中定义,这样device.exe才会根据注册表的prefix值去load制定dll并call其中的Prefix+Init函数。
但是,当用DEVFLAGS_NAKEDENTRIES时,说明将使用未修饰的入口点名称,即自己定义的接口函数。这样的话,device.exe就不会按照之前的Prefix+Init的方式了,就是Init。
还是代码说明问题:
D:/WINCE500/PRIVATE/WINCEOS/COREOS/DEVICE/DEVCORE/devload.c中的CreateDevice函数中有如下判断:
if((dwFlags & DEVFLAGS_NAKEDENTRIES) == 0) {
if(lpszPrefix[0] != 0) {
DEBUGCHK(lpszBusPrefix[0] == 0 || wcsicmp(lpszBusPrefix, lpszPrefix) == 0);
pEffType = lpszPrefix; // use standard prefix decoration
} else if(lpszBusPrefix[0] != 0 && lpdev->pszBusName != NULL) {
pEffType = lpszBusPrefix; // no standard prefix, use bus prefix decoration
} else {
if(lpdev->pszDeviceName != NULL) {
// device is expected to have a device or bus name, but we don't know
// how to look for its entry points
DEBUGMSG(ZONE_ACTIVE || ZONE_ERROR,
(_T("DEVICE!CreateDevice: no entry point information for '%s' can't load '%s'/r/n"),
lpszLib, lpdev->pszDeviceName));
dwStatus = ERROR_INVALID_FUNCTION;
}
}
}
lpdev->fnInit = (pInitFn)GetDMProcAddr(pEffType,L"Init",lpdev->hLib);
lpdev->fnPreDeinit = (pDeinitFn)GetDMProcAddr(pEffType,L"PreDeinit",lpdev->hLib);
lpdev->fnDeinit = (pDeinitFn)GetDMProcAddr(pEffType,L"Deinit",lpdev->hLib);
lpdev->fnOpen = (pOpenFn)GetDMProcAddr(pEffType,L"Open",lpdev->hLib);
lpdev->fnPreClose = (pCloseFn)GetDMProcAddr(pEffType,L"PreClose",lpdev->hLib);
lpdev->fnClose = (pCloseFn)GetDMProcAddr(pEffType,L"Close",lpdev->hLib);
lpdev->fnRead = (pReadFn)GetDMProcAddr(pEffType,L"Read",lpdev->hLib);
lpdev->fnWrite = (pWriteFn)GetDMProcAddr(pEffType,L"Write",lpdev->hLib);
lpdev->fnSeek = (pSeekFn)GetDMProcAddr(pEffType,L"Seek",lpdev->hLib);
lpdev->fnControl = (pControlFn)GetDMProcAddr(pEffType,L"IOControl",lpdev->hLib);
lpdev->fnPowerup = (pPowerupFn)GetDMProcAddr(pEffType,L"PowerUp",lpdev->hLib);
lpdev->fnPowerdn = (pPowerupFn)GetDMProcAddr(pEffType,L"PowerDown",lpdev->hLib);
又查了一下MSDN和代码,只说明可以使用不加前缀的入口函数,即
当DEVFLAGS_NAKEDENTRIES 时,pEffType = NULL;
所以下面这些函数都会直接call Init...而不是Prefix_Init
自己定义接口函数应该不行。
lpdev->fnInit = (pInitFn)GetDMProcAddr(pEffType,L"Init",lpdev->hLib);
lpdev->fnPreDeinit = (pDeinitFn)GetDMProcAddr(pEffType,L"PreDeinit",lpdev->hLib);
lpdev->fnDeinit = (pDeinitFn)GetDMProcAddr(pEffType,L"Deinit",lpdev->hLib);
lpdev->fnOpen = (pOpenFn)GetDMProcAddr(pEffType,L"Open",lpdev->hLib);
lpdev->fnPreClose = (pCloseFn)GetDMProcAddr(pEffType,L"PreClose",lpdev->hLib);
lpdev->fnClose = (pCloseFn)GetDMProcAddr(pEffType,L"Close",lpdev->hLib);
lpdev->fnRead = (pReadFn)GetDMProcAddr(pEffType,L"Read",lpdev->hLib);
lpdev->fnWrite = (pWriteFn)GetDMProcAddr(pEffType,L"Write",lpdev->hLib);
lpdev->fnSeek = (pSeekFn)GetDMProcAddr(pEffType,L"Seek",lpdev->hLib);
lpdev->fnControl = (pControlFn)GetDMProcAddr(pEffType,L"IOControl",lpdev->hLib);
lpdev->fnPowerup = (pPowerupFn)GetDMProcAddr(pEffType,L"PowerUp",lpdev->hLib);
lpdev->fnPowerdn = (pPowerupFn)GetDMProcAddr(pEffType,L"PowerDown",lpdev->hLib);