




已阅读5页,还剩44页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
标 题: 【原创】NDIS中间层驱动开发在Win7系统下和Windows XP系统下的区别作 者: tianhz时 间: 2011-07-21,14:58:04链 接: /showthread.php?t=137545NDIS中间层驱动的开发在Win7系统上和Windows XP系统上有差别。我把NDIS中间层的讨论分成2块。 windows 7系统和Windows XP系统。(一)在 Windows XP系统上进行开发平时很多朋友包括我在内,我们都在XP系统上使用NDIS5.1的框架来进行程序开发。我们都使用Microsoft WDK提供的 NDIS 的 Passthru例子,在这个例子上做进一步的修改,来达到我们的目地。在Passthru工程的 DriverEntry函数里面,我们都看见如下的代码:NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)NDIS_STATUS Status;NDIS_PROTOCOL_CHARACTERISTICS PChars;NDIS_MINIPORT_CHARACTERISTICS MChars;PNDIS_CONFIGURATION_PARAMETER Param;NDIS_STRING Name;NDIS_HANDLE WrapperHandle;UNICODE_STRING nameString, linkString; UINT FuncIndex;PDEVICE_OBJECT MyDeviceObject; PDRIVER_DISPATCH MajorFunctionIRP_MJ_MAXIMUM_FUNCTION + 1;Status = NDIS_STATUS_SUCCESS;/申请自旋锁 以到达资源共享的同步访问NdisAllocateSpinLock(&GlobalLock);/调用NdisMInitializeWrapper函数来保存在NdisWrapperHandle返回的句柄NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);do/调用NdisMInitializeWrapper函数来保存在WrapperHandle返回的句柄NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);/对于MiniportCharacteristics组件,如果驱动程序不用导出MiniportXxx这样的函数,则必须赋值为NULL。/如果要导出任何新版本的V4.0或V5.0的MiniportXxx函数,那么中间层驱动程序的主版本必须是V4.0,并且提供4.0或5.0版本的MiniportCharacteristics组件.NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS);MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;/*下面开始注册中间层驱动程序的 MiniportXxx函数 */MChars.HaltHandler = MPHalt;MChars.InitializeHandler = MPInitialize;MChars.QueryInformationHandler = MPQueryInformation;MChars.SetInformationHandler = MPSetInformation;MChars.ResetHandler = MPReset;MChars.SendHandler = NULL;MChars.SendPacketsHandler = MPSendPackets;MChars.TransferDataHandler = MPTransferData;MChars.ReturnPacketHandler = MPReturnPacket;MChars.CheckForHangHandler = NULL;#ifdef NDIS51_MINIPORTMChars.CancelSendPacketsHandler = MPCancelSendPackets;MChars.PnPEventNotifyHandler = MPDevicePnPEvent;MChars.AdapterShutdownHandler = MPAdapterShutdown;#endif / NDIS51_MINIPORT /*传递上一步保存的句柄,并调用NdisIMRegisterLayeredMiniport函数来注册驱动程序的MiniportXxx系列函数。其中句柄NdisWrapperHandle是由先前的NdisMInitializeWrapper函数返回的。当驱动程序调用NdisIMInitializeDeviceInstance函数,请求中间层驱动程序的MiniportInitialize函数对虚拟NIC进行初始化时,需要把句柄NdisWrapperHandle传入NDIS当中间层驱动程序成功地绑定到一个或者多个NIC驱动程序上的时候, 或者是绑定到一个非NIC驱动程序上的时候也会调用NdisIMInitializeDeviceInstance函数。这样做使得中间层驱动程序可以初始化Miniport组件来接受虚拟NIC上的I/O请求*/Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle, &MChars, sizeof(MChars), &DriverHandle);if (Status != NDIS_STATUS_SUCCESS)break;#ifndef WIN9XNdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);#endif/中间层驱动程序要做的事情:/初始化NDIS_PROTOCOL_CHARACTERISTICS类型的结构. NDIS不再支持3.0版本的协议驱动./能够使用4.0或5.0版本的ProtocolCharacteristic结构体,协议驱动必须支持PNP即插即用功能.NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS);PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;NdisInitUnicodeString(&Name, LPassthru); PChars.Name = Name;/* 下面开始注册中间层驱动程序的 ProtocolXxx函数 这里主要是注册-下边界面向无连接的中间层驱动程序的ProtocolXxx函数 */PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;PChars.SendCompleteHandler = PtSendComplete;PChars.TransferDataCompleteHandler = PtTransferDataComplete;PChars.ResetCompleteHandler = PtResetComplete;PChars.RequestCompleteHandler = PtRequestComplete;PChars.ReceiveHandler = PtReceive;PChars.ReceivePacketHandler = PtReceivePacket;PChars.ReceiveCompleteHandler = PtReceiveComplete;PChars.StatusHandler = PtStatus;PChars.StatusCompleteHandler = PtStatusComplete;PChars.BindAdapterHandler = PtBindAdapter;PChars.UnbindAdapterHandler = PtUnbindAdapter;PChars.UnloadHandler = PtUnloadProtocol;PChars.PnPEventHandler= PtPNPHandler;/*如果驱动程序随后要绑定到底层的NDIS驱动程序上,则调用NdisRegisterProtocol函数来注册驱动程序的ProtocolXxx函数。全局变量ProtHandle是在NDIS协议驱动里面的NdisRegisterProtocol函数里面初始化的,然后中间层驱动必须保存protHandle的值,并在将来NDIS中间层驱动程序的协议部分的函数调用中作为输入参数来传递.*/NdisRegisterProtocol(&Status, &ProtHandle,&PChars,sizeof(NDIS_PROTOCOL_CHARACTERISTICS);if (Status != NDIS_STATUS_SUCCESS)NdisIMDeregisterLayeredMiniport(DriverHandle);break;/如果驱动程序导出了MiniportXxx和ProtocolXxx这一些列的函数,那么就调用NdisIMAssociateMiniport函数向NDIS通告有关驱动程序的微端口低边界和协议高边界信息NdisIMAssociateMiniport(DriverHandle, ProtHandle);while (FALSE);/- 创建设备对象与符号连接-RtlInitUnicodeString(&nameString, LDeviceMyPassthru ); RtlInitUnicodeString(&linkString, L?MyPassthru); for(FuncIndex = 0; FuncIndex =IRP_MJ_MAXIMUM_FUNCTION; FuncIndex+)MajorFunctionFuncIndex = NULL;MajorFunctionIRP_MJ_CREATE = MydrvDispatch;MajorFunctionIRP_MJ_CLOSE = MydrvDispatch;MajorFunctionIRP_MJ_DEVICE_CONTROL = MydrvDispatchIoctl;Status = NdisMRegisterDevice(WrapperHandle, &nameString,&linkString,MajorFunction,&MyDeviceObject,&NdisDeviceHandle);if(Status != STATUS_SUCCESS)DbgPrint(NdisMRegisterDevice failed!n);return(Status);然后,我们就开始实现相应的回调函数。 然而为了收、发网络数据包,对它们进行控制,我们基本上只会去修改以下的回调函数:下面我把相关的函数的功能给罗列出来。/*MPSend函数的功能是: 发送单个数据包。 若中间层驱动不支持MiniportSendPackets,那么MPSend函数必须实现。 参数说明: MiniportAdapterContext 它是适配器。 PacketArray 它是包描述符指针。 Flags 它未被使用。 */NDIS_STATUSMPSend(IN NDIS_HANDLE MiniportAdapterContext,IN PNDIS_PACKET Packet,IN UINT Flags)/*MPSendPackets函数的功能是: 用于指定网络上传输数据包的包描述符指针数组。该函数可以用来发送多个数据包。而不是只发送单个数据包。除非中间层驱动程序绑定到低层WAN NIC驱动程序上,并提供MiniportWanSend函数,否则驱动程序应提供对MPSendPackets函数的支持, 而不是对MPSend函数的支持。参数说明:MiniportAdapterContext 它是适配器。 PacketArray 它是包描述符数组。 NumberOfPackets 它是PacketArray的长度。 每个数据包发送完成后无论是否成功都要调用 NdisMSendComplete函数。让上层的协议驱动能够收到SendCompleteHandler来判断数据包的完成状态。 */VOIDMPSendPackets(IN NDIS_HANDLE MiniportAdapterContext,IN PPNDIS_PACKET PacketArray,IN UINT NumberOfPackets)/*MPTransferData函数的功能: 该函数用于传输在前视缓冲区中没有指示的接收数据包的剩余部分。前视缓冲区由 中间层驱动程序传递给 NdisMXxxIndicateReceive函数。这个被指示的数据包可以是 中间层驱动程序的ProtocolReceive函数或者是ProtocolReceivePackets处理程序接收的 转换数据包。 如果中间层驱动程序通过调用NdisMXxxIndicateReceive函数向上层驱动程序指示接收 数据包,那么MPTransferData函数必须提供。 如果中间层通过调用驱动程序总是NdisMIndicateReceive函数向上层驱动程序指示接收 数据包,那么MPTransferData函数可以不必提供。即 NdisMIndicateReceivePacket指示接收数据包,那么传递给ProtocoltReceive函数 的前视缓冲区将总是获得完整的数据包。 */NDIS_STATUSMPTransferData(OUT PNDIS_PACKET Packet, /目的数据包OUT PUINT BytesTransferred,/复制了多少数据IN NDIS_HANDLE MiniportAdapterContext,/适配器结构体IN NDIS_HANDLE MiniportReceiveContext,/上下文IN UINT ByteOffset,/指向拷贝数据包的偏移IN UINT BytesToTransfer/实际传输了多少字节的数据)/*PtTransferDataComplete函数的功能: 它是MPTransferData()的异步完成函数。 当ProtocolReceive函数需要调用NdisTransferData函数,那么我们必须实现PtTransferDataComplete的代码。当NdisTransferData调用之后,并且返回值是NDIS_STATUS_PENDING,在数据包传输完成了以后,会去调用PtTransferDataComplete函数用来表明一个数据包的传输完成。这时就会得到一个完整的数据包。 */VOIDPtTransferDataComplete(IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET Packet,IN NDIS_STATUS Status,IN UINT BytesTransferred)/* PtReceive函数的功能是: 该函数以指向包含网络接收数据的前视缓冲区的指针为参数被调用执行。如果这个前视缓冲区没有包含完整的网络数据包,那么ProtocolReceive函数将以包描述符作为参数,调用NdisTransferData函数。 当NdisTransferData调用之后,数据包传输完成了以后,会去调用ProtocolTransferDataComplete函数以用来表明一个数据包的传输完成。这时就会得到一个完整的数据包。 如果低层驱动程序调用了 NdisMIndicateReceivePacket指示接收数据包,那么传递给PtReceive函数的前视缓冲区将总是获得完整的数据包。 如果中间层驱动不需要完整的数据包时,可以调用NdisMXxxIndicateReceice函数向上通知,这样就省略了获取完整数据包的过程。前视缓冲区:考虑数据包的接收,如果我们只需要看见数据内容的前几个字节(如TCP头)就可以决定这个包是否是本协议所需要处理的,那么显然下层驱动就没有必要提交整个数据包,只提供一个包开始的几个字节就可以了。 参数说明: ProtocolBindingContext 在绑定是得到的绑定句柄,即它是在NdisOpenAdapter被调用时设置的。 MacReceiveContext 它指向一个不透明的环境变量,由底层NIC驱动传入,它用此句柄与从网络上收到的Packet关联。当调用NdisGetReceivePacket函数取得低层驱动上面的包描述符时,需要用到这个参数。当NDIS协议驱动的ProtocolReceive函数的实现中,可能要调用NdisTransferData函数,那么也会用到这个参数。 HeaderBuffer 它是一个以太网帧,就是以太网的包头。它是个虚拟的地址,只能在当前函数中有效, 它不能被存储而作为全局变量来使用。 HeaderBufferSize 它是包头的长度,它的值一般为14 LookAheadBuffer 它是前视缓冲区指针。 LookAheadBufferSize LookAheadBuffer的大小。 PacketSize 它是完整的数据包长度(不包括包头)。 当PtReceive函数被调用了以后,系统将会去调用完成函数PtReceiveComplete 如果传递给PtReceive的数据是通过NdisMXxxIndicateReceive进行指示的,那么传递给PtReceive的前视缓冲区的长度不会超过用OID_GEN_CURRENT_LOOKAHEAD调用NdisRequest返回的值。 如果PtReceive的调用执行在NdisMIndicateReceivePacket之前进行,那么底层驱动程序把包数组中的一个或者多个包状态设置为 NDIS_STATUS_RESOURCES,那么前视缓冲区的大小总是等于整个网络数据包的大小。所以中间层驱动程序可以不必调用NdisTransferData函数。 */NDIS_STATUSPtReceive(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,IN UINT LookAheadBufferSize,IN UINT PacketSize)/* PtReceivePacket函数的功能是: 这是一个可选函数。 如果中间层驱动程序所基于的NIC驱动程序指示的是数据包描述符指针数组,或者调用NdisMIndicateReceivePacket函数指示接收带外数据,那么驱动程序应该提供PtReceivePacket函数。 如果开发者不能够确定中间层驱动程序的执行环境,也应该提供该函数,因为在能够产生多包指示的底层NIC驱动程序上,中间层驱动程序将获得更好的性能。 */INTPtReceivePacket(IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET Packet)我们可以在这几个回调函数里面来处理、过滤、分析 捕捉到的数据包。防火墙软件一般也都是在这几个回调函数里面进行编程。其它的回调函数的代码,我们基本上不用去修改。NDIS Passthru的例子很多,在网络上搜索一下,就有很多源代码例子,也有很多相关的技术说明。 下面,我想重点的说明在Windows 7系统下,(当然是Win7 32/64位系统)如何做NDIS中间层驱动程序的开发,代码和之前老的Windows操作系统提供的Passthru例子的区别。(二)在 Windows 7系统上进行开发在Win7系统下开发驱动程序,需要数字证书,还需要驱动签名认证。由于Win7系统的内核做了大幅度的修改,它和XP系统的内核起了很大的变化,最显著的就是刚才说的:需要签名和证书。 还有就是:不能随意的HOOK SSDT了。在开发NDIS驱动程序的时候,WDK开发包提供了一个新的框架,叫着NDIS FilterNDIS Filter是一个例子工程。假入我把WDK安装在E盘,那么这个工程代码就在:E:WinDDK7600.16385.1srcnetworkndisfilter目录下。把这个例子工程和原来的Passthru工程代码做比较,您会发现,原来需要导出来的2种类型的回调函数MiniportXXX和ProtocolXXX 在新的框架里面被全部隐藏起来了。微软提供了新的函数。 一起来看看,微软提供了什么。在这里,为了方便分析, 我把函数代码都做了功能注释,请大家一起看看。代码如下:#pragma NDIS_INIT_FUNCTION(DriverEntry)#define LITTLE_ENDIAN (1)/ Global variables/ NDIS_HANDLE FilterDriverHandle; / NDIS handle for filter driverNDIS_HANDLE FilterDriverObject;NDIS_HANDLE NdisFilterDeviceHandle = NULL;PDEVICE_OBJECT DeviceObject = NULL;FILTER_LOCK FilterListLock;LIST_ENTRY FilterModuleList;PWCHAR InstanceStrings = NULL;NDIS_FILTER_PARTIAL_CHARACTERISTICS DefaultChars = 0, 0, 0,0,FilterSendNetBufferLists,FilterSendNetBufferListsComplete,NULL,FilterReceiveNetBufferLists,FilterReturnNetBufferLists; typedef struct in_addr union struct UCHAR s_b1,s_b2,s_b3,s_b4; S_un_b;struct USHORT s_w1,s_w2; S_un_w;ULONG S_addr; S_un; IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;#pragma push(1)typedef struct IP_HEADER#if LITTLE_ENDIANunsigned char ip_hl:4; /* 头长度 */unsigned char ip_v:4; /* 版本号 */#elseunsigned char ip_v:4;unsigned char ip_hl:4; #endifunsigned char TOS; / 服务类型unsigned short TotLen; / 封包总长度,即整个IP包的长度unsigned short ID; / 封包标识,唯一标识发送的每一个数据报unsigned short FlagOff; / 标志unsigned char TTL; / 生存时间,就是TTLunsigned char Protocol; / 协议,可能是TCP、UDP、ICMP等unsigned short Checksum; / 校验和struct in_addr iaSrc; / 源IP地址struct in_addr iaDst; / 目的PI地址IP_HEADER, *PIP_HEADER;typedef struct tcp_headerunsigned short src_port; /源端口号unsigned short dst_port; /目的端口号unsigned int seq_no; /序列号unsigned int ack_no; /确认号#if LITTLE_ENDIANunsigned char reserved_1:4; /保留6位中的4位首部长度unsigned char thl:4; /tcp头部长度unsigned char flag:6; /6位标志unsigned char reseverd_2:2; /保留6位中的2位#elseunsigned char thl:4; /tcp头部长度unsigned char reserved_1:4; /保留6位中的4位首部长度unsigned char reseverd_2:2; /保留6位中的2位unsigned char flag:6; /6位标志 #endifunsigned short wnd_size; /16位窗口大小unsigned short chk_sum; /16位TCP检验和unsigned short urgt_p; /16为紧急指针TCP_HEADER,*PTCP_HEADER;typedef struct udp_header USHORT srcport; / 源端口USHORT dstport; / 目的端口USHORT total_len; / 包括UDP报头及UDP数据的长度(单位:字节)USHORT chksum; / 校验和UDP_HEADER,*PUDP_HEADER;#pragma push()#define IP_OFFSET 0x0E/IP 协议类型#define PROT_ICMP 0x01 #define PROT_TCP 0x06 #define PROT_UDP 0x11 USHORT UTIL_htons( USHORT hostshort )PUCHAR pBuffer;USHORT nResult;nResult = 0;pBuffer = (PUCHAR )&hostshort;nResult = ( (pBuffer 0 DriverEntry.n);RtlInitUnicodeString(&ServiceName, FILTER_SERVICE_NAME);RtlInitUnicodeString(&FriendlyName, FILTER_FRIENDLY_NAME);RtlInitUnicodeString(&UniqueName, FILTER_UNIQUE_NAME);FilterDriverObject = DriverObject;doNdisZeroMemory(&FChars, sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS); /*大多数的NDIS6.0数据结构中包含的对象头结构的成员,即NDIS_OBJECT_HEADER结构。对象头有三个成员:类型,大小和修改。如果头信息是不正确的,那么调用NDIS6.0函数将失败。*/FChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;FChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS);FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_1;FChars.MajorNdisVersion = FILTER_MAJOR_NDIS_VERSION;FChars.MinorNdisVersion = FILTER_MINOR_NDIS_VERSION;FChars.MajorDriverVersion = 1;FChars.MinorDriverVersion = 0;FChars.Flags = 0;FChars.FriendlyName = FriendlyName;FChars.UniqueName = UniqueName;FChars.ServiceName = ServiceName;/*NDIS_FILTER_DRIVER_CHARACTERISTICS结构中Mandatory例程*/FChars.AttachHandler = FilterAttach;FChars.DetachHandler = FilterDetach;FChars.RestartHandler = FilterRestart;FChars.PauseHandler = FilterPause;/*NDIS_FILTER_DRIVER_CHARACTERISTICS结构中Optional且不能在运行时变更的例程*/FChars.SetOptionsHandler = FilterRegisterOptions;FChars.SetFilterModuleOptionsHandler = FilterSetModuleOptions;FChars.OidRequestHandler = FilterOidRequest;FChars.OidRequestCompleteHandler = FilterOidRequestComplete;FChars.StatusHandler = FilterStatus;FChars.DevicePnPEventNotifyHandler = FilterDevicePnPEventNotify;FChars.NetPnPEventHandler = FilterNetPnPEvent; FChars.CancelSendNetBufferListsHandler = FilterCancelSendNetBufferLists;/*DIS_FILTER_DRIVER_CHARACTERISTICS结构中Optional且能在运行时变更的例程。下面这4个例程也被定义在NDIS_FILTER_PARTIAL_CHARACTERISTICS中,这个结构指定的例程可以在运行时的FilterSetModuleOptions例程中调用NdisSetOptionHandles来改变。如果过滤驱动要在例程中修改自身的一个特性,那么必须提供FilterSetModuleOptions例程。*/FChars.SendNetBufferListsHandler = FilterSendNetBufferLists; FChars.SendNetBufferListsCompleteHandler = FilterSendNetBufferListsComplete;FChars.ReturnNetBufferListsHandler = FilterReturnNetBufferLists;FChars.ReceiveNetBufferListsHandler = FilterReceiveNetBufferLists;/FChars.CancelOidRequestHandler = FilterCancelOidRequest; DriverObject-DriverUnload = FilterUnload;FilterDriverHandle = NULL;FILTER_INIT_LOCK(&FilterListLock);InitializeListHead(&FilterModuleList);/ 把Filter驱动注册给NDISStatus = NdisFRegisterFilterDriver(DriverObject,(NDIS_HANDLE)FilterDriverObject,&FChars, &FilterDriverHandle);if (Status != NDIS_STATUS_SUCCESS)DEBUGP(DL_WARN, (MSFilter: Register filter driver failed.n); break;/ Initilize spin locks/Status = FilterRegisterDevice();if (Status != NDIS_STATUS_SUC
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 金融合同金融租赁资金信托合同5篇
- 2025健身房转让合同模板格式
- 2025成都诺克衣柜经销商合同范本
- 2025全日制用工新劳动合同书
- 任务二 超市、菜场购物说课稿-2023-2024学年初中劳动八年级下册浙教版
- 第5课 画多边形教学设计-2023-2024学年小学信息技术(信息科技)第三册黔教版
- 2025成都劳动合同样本(合同版本)
- 2025年个人汽车质押担保借款合同范本
- 2025关于租地合同
- DNA是主要的遗传物质-教学设计
- 室内装修安全生产培训课件
- 2025租房合同范本下载(可直接打印)
- 《公民意味着什么》课件
- 2025辽宁交投集团所属运营公司招聘30人考试参考题库及答案解析
- 幼儿园各项安全管理制度汇编
- 广西福泰印染有限公司年产全棉针织面料3.6万吨生产项目环境影响报告书
- 【《我国小学生课外培训现状调查及问题和建议浅析》10000字(论文)】
- 民航招飞面试常见的面试问题及答案
- 每日食品安全检查记录 (一)
- 航空技术革新与发展趋势
- 四川日普精化有限公司年产3000吨脂肪酸酰胺与1000吨有机硅树脂涂剂配套设施改造项目环评报告
评论
0/150
提交评论