活动介绍

windows _LIST_ENTRY

时间: 2023-07-08 17:51:13 浏览: 198
_LIST_ENTRY 是 Windows 中的一个双向链表结构体,用于实现双向链表数据结构。它的定义如下: ``` typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; ``` 其中,Flink 和 Blink 分别指向链表中的下一个和上一个元素。 在 Windows 中,_LIST_ENTRY 主要用于实现各种内核数据结构,例如进程链表、线程链表、驱动程序链表等。例如,可以使用 _LIST_ENTRY 定义一个进程链表: ``` typedef struct _PROCESS_ENTRY { LIST_ENTRY ListEntry; DWORD ProcessId; HANDLE ProcessHandle; // 其他成员变量 } PROCESS_ENTRY, *PPROCESS_ENTRY; ``` 其中,ListEntry 成员变量用于实现进程链表,ProcessId 和 ProcessHandle 等成员变量用于存储进程相关信息。 在使用 _LIST_ENTRY 实现链表时,需要注意以下几点: 1. 需要使用 InitializeListHead 函数初始化链表头。 2. 需要使用 InsertHeadList、InsertTailList、RemoveHeadList、RemoveTailList 等函数操作链表元素。 3. 需要使用 CONTAINING_RECORD 宏将链表元素转换为结构体指针。 总之,_LIST_ENTRY 是 Windows 中实现双向链表的常用数据结构,它可以用于实现各种内核数据结构,例如进程链表、线程链表、驱动程序链表等。
阅读全文

相关推荐

kd> x nt!MmPfnDatabase fffff8057b8fc500 nt!MmPfnDatabase = <no type information> kd> dt _mmpfn fffff8057b8fc500+0x460f7*0x30 nt!_MMPFN +0x000 ListEntry : _LIST_ENTRY [ 0x470348fa8b4ce3f7 - 0xc4034900d7834908 ] +0x000 TreeNode : _RTL_BALANCED_NODE +0x000 u1 : <anonymous-tag> +0x008 PteAddress : 0xc4034900d7834908 _MMPTE +0x008 PteLong : 0xc4034900d7834908 +0x010 OriginalPte : _MMPTE +0x018 u2 : _MIPFNBLINK +0x020 u3 : <anonymous-tag> +0x024 NodeBlinkLow : 0x1047 +0x026 Unused : 0y1001 +0x026 Unused2 : 0y0100 +0x027 ViewCount : 0x83 '' +0x027 NodeFlinkLow : 0x83 '' +0x027 ModifiedListBucketIndex : 0y0011 +0x027 AnchorLargePageSize : 0y11 +0x028 u4 : <anonymous-tag> kd> dt _mmpfn fffff8057b8fc500+0x4609*0x30 nt!_MMPFN +0x000 ListEntry : _LIST_ENTRY [ 0x006f006c006c0041 - 0x0000006400650077 ] +0x000 TreeNode : _RTL_BALANCED_NODE +0x000 u1 : <anonymous-tag> +0x008 PteAddress : 0x0000006400650077 _MMPTE +0x008 PteLong : 0x0000006400650077 +0x010 OriginalPte : _MMPTE +0x018 u2 : _MIPFNBLINK +0x020 u3 : <anonymous-tag> +0x024 NodeBlinkLow : 0x54 +0x026 Unused : 0y0101 +0x026 Unused2 : 0y0110 +0x027 ViewCount : 0 '' +0x027 NodeFlinkLow : 0 '' +0x027 ModifiedListBucketIndex : 0y0000 +0x027 AnchorLargePageSize : 0y00 +0x028 u4 : <anonymous-tag> kd> dx -id 0,0,ffffbd046545f1c0 -r1 (*((ntkrnlmp!_LIST_ENTRY *)0xfffff8057c61f350)) (*((ntkrnlmp!_LIST_ENTRY *)0xfffff8057c61f350)) [Type: _LIST_ENTRY] [+0x000] Flink : 0x470348fa8b4ce3f7 [Type: _LIST_ENTRY *] [+0x008] Blink : 0xc4034900d7834908 [Type: _LIST_ENTRY *]

C:\Users\LENOVO>nrfutil version Traceback (most recent call last): File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\Scripts\nrfutil-script.py", line 11, in <module> load_entry_point('nrfutil==5.2.0', 'console_scripts', 'nrfutil')() File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\pkg_resources\__init__.py", line 565, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\pkg_resources\__init__.py", line 2631, in load_entry_point return ep.load() File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\pkg_resources\__init__.py", line 2291, in load return self.resolve() File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\pkg_resources\__init__.py", line 2297, in resolve module = __import__(self.module_name, fromlist=['__name__'], level=0) File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\nordicsemi\__main__.py", line 53, in <module> from nordicsemi.dfu.dfu_transport_serial import DfuTransportSerial File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\nordicsemi\dfu\dfu_transport_serial.py", line 52, in <module> from nordicsemi.lister.device_lister import DeviceLister File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\nordicsemi\lister\device_lister.py", line 39, in <module> from nordicsemi.lister.windows.lister_win32 import Win32Lister File "C:\Users\LENOVO\AppData\Local\Programs\Python\Python35\lib\site-packages\nordicsemi\lister\windows\lister_win32.py", line 43, in <module> from constants import DIGCF_PRESENT, DEVPKEY, DIGCF_DEVICEINTERFACE ImportError: No module named 'constants'

import os import random import tkinter as tk from tkinter import filedialog, messagebox, ttk import shutil import hashlib import time import pefile import os import sys class ExeProtectorApp: def __init__(self, root): self.root = root self.root.title("EXE文件保护工具 v4.1") self.root.geometry("750x680") self.root.resizable(True, True) # 设置中文字体 self.style = ttk.Style() self.style.configure("TLabel", font=("SimHei", 10)) self.style.configure("TButton", font=("SimHei", 10)) self.style.configure("TProgressbar", thickness=20) # 创建主框架 self.main_frame = ttk.Frame(root, padding="20") self.main_frame.pack(fill=tk.BOTH, expand=True) # 文件选择部分 ttk.Label(self.main_frame, text="选择EXE文件:").grid(row=0, column=0, sticky=tk.W, pady=5) self.file_path_var = tk.StringVar() ttk.Entry(self.main_frame, textvariable=self.file_path_var, width=50).grid(row=0, column=1, padx=5, pady=5) ttk.Button(self.main_frame, text="浏览...", command=self.browse_file).grid(row=0, column=2, padx=5, pady=5) # 输出目录选择 ttk.Label(self.main_frame, text="输出目录:").grid(row=1, column=0, sticky=tk.W, pady=5) self.output_dir_var = tk.StringVar() ttk.Entry(self.main_frame, textvariable=self.output_dir_var, width=50).grid(row=1, column=1, padx=5, pady=5) ttk.Button(self.main_frame, text="浏览...", command=self.browse_output_dir).grid(row=1, column=2, padx=5, pady=5) # 选项设置 options_frame = ttk.LabelFrame(self.main_frame, text="选项", padding="10") options_frame.grid(row=2, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=10) ttk.Label(options_frame, text="随机字节增加范围 (KB):").grid(row=0, column=0, sticky=tk.W, pady=5) self.min_size_var = tk.IntVar(value=100) ttk.Entry(options_frame, textvariable=self.min_size_var, width=10).grid(row=0, column=1, padx=5, pady=5) ttk.Label(options_frame, text="至").grid(row=0, column=2, padx=5, pady=5) self.max_size_var = tk.IntVar(value=500) ttk.Entry(options_frame, textvariable=self.max_size_var, width=10).grid(row=0, column=3, padx=5, pady=5) ttk.Label(options_frame, text="随机性强度:").grid(row=0, column=4, sticky=tk.W, pady=5) self.random_strength = tk.StringVar(value="中") strength_options = ttk.Combobox(options_frame, textvariable=self.random_strength, state="readonly", width=12) strength_options['values'] = ("低", "中", "高") strength_options.grid(row=0, column=5, padx=5, pady=5) ttk.Label(options_frame, text="模拟程序类型:").grid(row=1, column=0, sticky=tk.W, pady=5) self.app_type = tk.StringVar(value="通用程序") app_types = ttk.Combobox(options_frame, textvariable=self.app_type, state="readonly", width=15) app_types['values'] = ("通用程序", "游戏程序", "办公软件", "系统工具", "开发工具") app_types.grid(row=1, column=1, padx=5, pady=5) self.process_method = tk.StringVar(value="standard") ttk.Radiobutton(options_frame, text="标准保护", variable=self.process_method, value="standard").grid(row=1, column=2, sticky=tk.W, pady=5) ttk.Radiobutton(options_frame, text="高级保护", variable=self.process_method, value="advanced").grid(row=1, column=3, sticky=tk.W, pady=5) # 高级选项 advanced_frame = ttk.LabelFrame(self.main_frame, text="保护选项", padding="10") advanced_frame.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=10) self.obfuscate_resources = tk.BooleanVar(value=True) ttk.Checkbutton(advanced_frame, text="混淆资源文件", variable=self.obfuscate_resources).grid(row=0, column=0, sticky=tk.W, pady=5) self.encrypt_sections = tk.BooleanVar(value=True) ttk.Checkbutton(advanced_frame, text="轻度代码变换", variable=self.encrypt_sections).grid(row=0, column=1, sticky=tk.W, pady=5) self.add_dummy_sections = tk.BooleanVar(value=True) ttk.Checkbutton(advanced_frame, text="添加随机数据块", variable=self.add_dummy_sections).grid(row=1, column=0, sticky=tk.W, pady=5) self.randomize_imports = tk.BooleanVar(value=True) ttk.Checkbutton(advanced_frame, text="随机化导入表顺序", variable=self.randomize_imports).grid(row=1, column=1, sticky=tk.W, pady=5) # 处理按钮 ttk.Button(self.main_frame, text="保护文件", command=self.process_file).grid(row=4, column=0, columnspan=3, pady=20) # 状态和进度条 self.status_var = tk.StringVar(value="就绪") ttk.Label(self.main_frame, textvariable=self.status_var).grid(row=5, column=0, columnspan=2, sticky=tk.W, pady=5) self.progress_var = tk.DoubleVar(value=0) self.progress_bar = ttk.Progressbar(self.main_frame, variable=self.progress_var, length=100) self.progress_bar.grid(row=5, column=2, sticky=(tk.W, tk.E), pady=5) # 默认输出目录 self.output_dir_var.set(os.path.join(os.getcwd(), "protected_exes")) # 绑定窗口关闭事件 self.root.protocol("WM_DELETE_WINDOW", self.on_closing) # 初始化随机种子 self.initialize_random_seed() def initialize_random_seed(self): seed_material = ( time.time_ns().to_bytes(8, 'big') + os.getpid().to_bytes(4, 'big') + os.urandom(16) ) seed = int.from_bytes(hashlib.sha256(seed_material).digest(), 'big') random.seed(seed) def browse_file(self): file_path = filedialog.askopenfilename(filetypes=[("可执行文件", "*.exe"), ("所有文件", "*.*")]) if file_path: self.file_path_var.set(file_path) def browse_output_dir(self): dir_path = filedialog.askdirectory() if dir_path: self.output_dir_var.set(dir_path) def process_file(self): exe_path = self.file_path_var.get() output_dir = self.output_dir_var.get() if not exe_path: messagebox.showerror("错误", "请选择一个EXE文件") return if not os.path.exists(exe_path): messagebox.showerror("错误", "选择的文件不存在") return if not output_dir: messagebox.showerror("错误", "请选择输出目录") return if not os.path.exists(output_dir): try: os.makedirs(output_dir) except: messagebox.showerror("错误", "无法创建输出目录") return file_name, file_ext = os.path.splitext(os.path.basename(exe_path)) random_suffix = hashlib.md5(str(time.time_ns()).encode()).hexdigest()[:8] output_path = os.path.join(output_dir, f"{file_name}_protected_{random_suffix}{file_ext}") try: self.status_var.set("正在处理文件...") self.progress_var.set(0) self.root.update() min_size = self.min_size_var.get() max_size = self.max_size_var.get() if min_size < 0 or max_size < 0 or min_size > max_size: messagebox.showerror("错误", "请设置有效的字节增加范围") return strength_factor = 1.0 if self.random_strength.get() == "高": strength_factor = 1.5 elif self.random_strength.get() == "低": strength_factor = 0.5 adjusted_min = int(min_size * strength_factor) adjusted_max = int(max_size * strength_factor) random_size_kb = random.randint(adjusted_min, adjusted_max) random_size_bytes = random_size_kb * 1024 shutil.copy2(exe_path, output_path) original_hash = self.calculate_file_hash(exe_path) self.progress_var.set(5) self.root.update() if self.process_method.get() == "standard": self.standard_protection(output_path, random_size_bytes) else: self.advanced_protection(output_path, random_size_bytes) modified_hash = self.calculate_file_hash(output_path) self.progress_var.set(95) self.root.update() if self.verify_exe_file(output_path): self.status_var.set("文件处理完成") self.progress_var.set(100) messagebox.showinfo( "成功", f"文件保护成功!\n" f"原始文件大小: {os.path.getsize(exe_path) // 1024} KB\n" f"处理后文件大小: {os.path.getsize(output_path) // 1024} KB\n" f"增加了: {random_size_kb} KB\n\n" f"原始文件哈希 (MD5): {original_hash}\n" f"处理后文件哈希 (MD5): {modified_hash}\n\n" f"文件已保存至: {output_path}" ) else: self.status_var.set("文件验证失败") self.progress_var.set(100) messagebox.showwarning("警告", "处理后的文件可能需要在特定环境运行") except Exception as e: self.status_var.set("处理过程中出错") messagebox.showerror("错误", f"处理文件时出错: {str(e)}") finally: self.progress_var.set(0) self.initialize_random_seed() def calculate_file_hash(self, file_path): hash_md5 = hashlib.md5() with open(file_path, "rb") as f: for chunk in iter(lambda: f.read(4096), b""): hash_md5.update(chunk) return hash_md5.hexdigest() def standard_protection(self, file_path, additional_bytes): try: pe = pefile.PE(file_path) section_count = random.randint(1, 3) for _ in range(section_count): new_section = pefile.SectionStructure(pe.__IMAGE_SECTION_HEADER_format__) new_section.Name = self.generate_sane_section_name() section_size = random.randint(0x1000, 0x8000) new_section.Misc_VirtualSize = section_size base_virtual_address = (pe.sections[-1].VirtualAddress + pe.sections[-1].Misc_VirtualSize + 0x1000 - 1) & ~0xFFF new_section.VirtualAddress = base_virtual_address + random.randint(0, 0x1000) base_raw_data = (pe.sections[-1].PointerToRawData + pe.sections[-1].SizeOfRawData + 0x1000 - 1) & ~0xFFF new_section.PointerToRawData = base_raw_data + random.randint(0, 0x1000) new_section.SizeOfRawData = section_size section_flags = [0xC0000040, 0x40000040, 0x20000040, 0x80000040, 0x00000040, 0xE0000040] new_section.Characteristics = random.choice(section_flags) app_type = self.app_type.get() new_data = self.generate_application_specific_data(section_size, app_type) pe.set_bytes_at_offset(new_section.PointerToRawData, new_data) pe.sections.append(new_section) pe.FILE_HEADER.NumberOfSections += 1 pe.OPTIONAL_HEADER.SizeOfImage = (new_section.VirtualAddress + new_section.Misc_VirtualSize + 0x1000 - 1) & ~0xFFF if self.encrypt_sections.get(): self.apply_mild_code_transformations(pe) if self.randomize_imports.get() and hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): random.shuffle(pe.DIRECTORY_ENTRY_IMPORT) self.safe_modify_exe_file(file_path, additional_bytes) pe.FILE_HEADER.TimeDateStamp = int(time.time()) + random.randint(-3600, 3600) pe.write(file_path) pe.close() except Exception as e: print(f"标准保护执行: {e}") self.safe_modify_exe_file(file_path, additional_bytes) def advanced_protection(self, file_path, additional_bytes): try: pe = pefile.PE(file_path) section_count = random.randint(2, 4) for _ in range(section_count): new_section = pefile.SectionStructure(pe.__IMAGE_SECTION_HEADER_format__) new_section.Name = self.generate_sane_section_name() section_size = random.randint(0x1000, 0x10000) new_section.Misc_VirtualSize = section_size base_virtual_address = (pe.sections[-1].VirtualAddress + pe.sections[-1].Misc_VirtualSize + 0x1000 - 1) & ~0xFFF new_section.VirtualAddress = base_virtual_address + random.randint(0, 0x2000) base_raw_data = (pe.sections[-1].PointerToRawData + pe.sections[-1].SizeOfRawData + 0x1000 - 1) & ~0xFFF new_section.PointerToRawData = base_raw_data + random.randint(0, 0x2000) new_section.SizeOfRawData = section_size section_flags = [0xC0000040, 0x40000040, 0x20000040, 0x80000040, 0x00000040, 0xE0000040, 0x00000080, 0x40000080] new_section.Characteristics = random.choice(section_flags) app_type = self.app_type.get() new_data = self.generate_application_specific_data(section_size, app_type) pe.set_bytes_at_offset(new_section.PointerToRawData, new_data) pe.sections.append(new_section) pe.FILE_HEADER.NumberOfSections += 1 pe.OPTIONAL_HEADER.SizeOfImage = (new_section.VirtualAddress + new_section.Misc_VirtualSize + 0x1000 - 1) & ~0xFFF if self.encrypt_sections.get(): self.apply_mild_code_transformations(pe) if self.obfuscate_resources.get() and hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): self.obfuscate_pe_resources(pe) if self.randomize_imports.get() and hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): for _ in range(random.randint(1, 3)): random.shuffle(pe.DIRECTORY_ENTRY_IMPORT) if self.add_dummy_sections.get(): dummy_size = random.randint(additional_bytes // 2, additional_bytes) self.safe_modify_exe_file(file_path, dummy_size) additional_bytes -= dummy_size self.safe_modify_exe_file(file_path, additional_bytes) pe.FILE_HEADER.TimeDateStamp = int(time.time()) + random.randint(-86400, 86400) pe.write(file_path) pe.close() except Exception as e: print(f"高级保护执行: {e}") self.standard_protection(file_path, additional_bytes) def safe_modify_exe_file(self, file_path, additional_bytes): with open(file_path, 'ab') as f: app_type = self.app_type.get() data = self.generate_application_specific_data(additional_bytes, app_type) f.write(data) def generate_application_specific_data(self, size, app_type): data = bytearray() type_templates = { "通用程序": [ b"C:\\Program Files\\Common Files\\\x00", b"HKLM\\Software\\Microsoft\\Windows\\\x00", b"ERROR_ACCESS_DENIED\x00", b"SUCCESS\x00", b"CONFIG_FILE\x00", b"LOG_FILE\x00", (0x00000001).to_bytes(4, 'little'), (0x00000100).to_bytes(4, 'little'), (0x00010000).to_bytes(4, 'little'), ], "游戏程序": [ b"C:\\Program Files\\Game\\Data\\\x00", b"C:\\Users\\Public\\Documents\\GameSaves\\\x00", b"TEXTURE_", b"MODEL_", b"SOUND_", b"LEVEL_", b"SCORE_", b"PLAYER_", b"ENEMY_", b"WEAPON_", (0x000F4240).to_bytes(4, 'little'), (0x000003E8).to_bytes(4, 'little'), ], "办公软件": [ b"C:\\Users\\%USERNAME%\\Documents\\\x00", b"File Format: DOCX\x00", b"File Format: XLSX\x00", b"Page ", b"Sheet ", b"Table ", b"Font ", b"Style ", b"Paragraph ", b"Header", b"Footer", (0x0000000A).to_bytes(4, 'little'), (0x00000014).to_bytes(4, 'little'), ], "系统工具": [ b"C:\\Windows\\System32\\\x00", b"C:\\Windows\\SysWOW64\\\x00", b"HKLM\\SYSTEM\\CurrentControlSet\\\x00", b"Driver ", b"Service ", b"Device ", b"Registry ", b"Process ", b"Thread ", (0x00000001).to_bytes(4, 'little'), (0x00000000).to_bytes(4, 'little'), (0xFFFFFFFF).to_bytes(4, 'little'), ], "开发工具": [ b"C:\\Program Files\\Developer\\SDK\\\x00", b"C:\\Users\\%USERNAME%\\Source\\\x00", b"Compiler ", b"Linker ", b"Debugger ", b"Library ", b"Include ", b"Namespace ", b"Class ", b"Function ", b"Variable ", (0x00000000).to_bytes(4, 'little'), (0x00000001).to_bytes(4, 'little'), (0x00000002).to_bytes(4, 'little'), ] } templates = type_templates.get(app_type, type_templates["通用程序"]) template_usage = 0.7 if self.random_strength.get() == "高": template_usage = 0.5 elif self.random_strength.get() == "低": template_usage = 0.9 while len(data) < size: if random.random() < template_usage: data.extend(random.choice(templates)) else: random_len = random.randint(1, 64) data.extend(os.urandom(random_len)) if random.random() < 0.3: data.extend(b'\x00' * random.randint(1, 8)) elif random.random() < 0.2: data.extend(b' ' * random.randint(1, 16)) return data[:size] def generate_sane_section_name(self): base_names = [ b'.data', b'.rdata', b'.text', b'.rsrc', b'.reloc', b'.bss', b'.edata', b'.idata', b'.pdata', b'.tls', b'.data1', b'.rdata2', b'.text1', b'.rsrc1', b'.data_', b'.rdata_', b'.text_', b'.rsrc_', b'.init', b'.fini', b'.ctors', b'.dtors', b'.gnu', b'.note', b'.eh_frame', b'.debug' ] name = random.choice(base_names) if random.random() < 0.7: if random.random() < 0.5: suffix = str(random.randint(10, 99)).encode() else: suffix = bytes(random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(2)) name = name[:8-len(suffix)] + suffix return name.ljust(8, b'\x00')[:8] def apply_mild_code_transformations(self, pe): text_section = None for section in pe.sections: if b'.text' in section.Name: text_section = section break if text_section: data = pe.get_data(text_section.VirtualAddress, text_section.SizeOfRawData) if not isinstance(data, bytes): data = bytes(data) data_list = list(data) transform_count = len(data_list) // 200 if self.random_strength.get() == "高": transform_count = len(data_list) // 100 elif self.random_strength.get() == "低": transform_count = len(data_list) // 400 transform_count = min(100, transform_count) for _ in range(transform_count): i = random.randint(0, len(data_list) - 1) transform_type = random.choice([0, 1, 2, 3, 4]) if transform_type == 0: data_list[i] = (data_list[i] + 1) % 256 elif transform_type == 1: data_list[i] = (data_list[i] - 1) % 256 elif transform_type == 2: data_list[i] ^= 0xFF elif transform_type == 3: data_list[i] = (data_list[i] << 1) % 256 else: data_list[i] = (data_list[i] >> 1) % 256 pe.set_bytes_at_offset(text_section.PointerToRawData, bytes(data_list)) def obfuscate_pe_resources(self, pe): try: for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data_rva = resource_lang.data.struct.OffsetToData size = resource_lang.data.struct.Size resource_data = list(pe.get_data(data_rva, size)) step_size = 200 if self.random_strength.get() == "高": step_size = 100 elif self.random_strength.get() == "低": step_size = 400 for i in range(0, len(resource_data), random.randint(step_size-50, step_size+50)): if i < len(resource_data): if random.random() < 0.3: resource_data[i] = (resource_data[i] + random.randint(1, 5)) % 256 elif random.random() < 0.6: resource_data[i] = (resource_data[i] - random.randint(1, 5)) % 256 else: resource_data[i] ^= random.randint(1, 255) pe.set_bytes_at_offset(data_rva, bytes(resource_data)) except Exception as e: print(f"资源混淆错误: {e}") def verify_exe_file(self, file_path): try: pe = pefile.PE(file_path) pe.close() return True except: return False def on_closing(self): if messagebox.askokcancel("退出", "确定要退出程序吗?"): self.root.destroy() if __name__ == "__main__": root = tk.Tk() app = ExeProtectorApp(root) root.mainloop() 用户希望输出的程序每次都会有静态特征变化 绕过QVM 将代码段熵值降到最低 在此基础上修改

源代码: filter.cpp 源文件: #include "filter.h" #include "ioctl.h" ///global var wddm_filter_t __gbl_wddm_filter; #define DEV_NAME L"\\Device\\WddmFilterCtrlDevice" #define DOS_NAME L"\\DosDevices\\WddmFilterCtrlDevice" ///// static NTSTATUS create_ctrl_device() { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT devObj; UNICODE_STRING dev_name; UNICODE_STRING dos_name; RtlInitUnicodeString(&dev_name, DEV_NAME); RtlInitUnicodeString(&dos_name, DOS_NAME); status = IoCreateDevice( wf->driver_object, 0, &dev_name, //dev name FILE_DEVICE_VIDEO, FILE_DEVICE_SECURE_OPEN, FALSE, &devObj); if (!NT_SUCCESS(status)) { DPT("IoCreateDevice err=0x%X\n", status ); return status; } status = IoCreateSymbolicLink(&dos_name, &dev_name); if (!NT_SUCCESS(status)) { DPT("IoCreateSymbolicLink err=0x%X\n", status ); IoDeleteDevice(devObj); return status; } // attach wf->dxgkrnl_nextDevice = IoAttachDeviceToDeviceStack(devObj, wf->dxgkrnl_pdoDevice); if (!wf->dxgkrnl_nextDevice) { DPT("IoAttachDeviceToDeviceStack error.\n"); IoDeleteDevice(devObj); IoDeleteSymbolicLink(&dos_name); return STATUS_NOT_FOUND; } devObj->Flags |= DO_POWER_PAGABLE | DO_BUFFERED_IO | DO_DIRECT_IO; wf->ctrl_devobj = devObj; ///// return status; } NTSTATUS create_wddm_filter_ctrl_device(PDRIVER_OBJECT drvObj ) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING drvPath; UNICODE_STRING drvName; RtlInitUnicodeString(&drvPath, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES\\DXGKrnl"); RtlInitUnicodeString(&drvName, L"\\Device\\Dxgkrnl"); // RtlZeroMemory(wf, sizeof(wddm_filter_t)); wf->driver_object = drvObj; KeInitializeSpinLock(&wf->spin_lock); InitializeListHead(&wf->vidpn_if_head); InitializeListHead(&wf->topology_if_head); //����dxgkrnl.sys���� status = ZwLoadDriver(&drvPath); if (!NT_SUCCESS(status)) { if (status != STATUS_IMAGE_ALREADY_LOADED) { DPT("ZwLoadDriver error st=0x%X\n", status ); return status; } } status = IoGetDeviceObjectPointer(&drvName, FILE_ALL_ACCESS, &wf->dxgkrnl_fileobj, &wf->dxgkrnl_pdoDevice); if (!NT_SUCCESS(status)) { DPT("IoGetDeviceObjectPointer Get DxGkrnl err=0x%X\n", status ); return status; } KEVENT evt; IO_STATUS_BLOCK ioStatus; KeInitializeEvent(&evt, NotificationEvent, FALSE); PIRP pIrp = IoBuildDeviceIoControlRequest( IOCTL_VIDEO_DDI_FUNC_REGISTER, //0x23003F , dxgkrnl.sys ����ע�ắ�� wf->dxgkrnl_pdoDevice, NULL, 0, &wf->dxgkrnl_dpiInit, sizeof(PDXGKRNL_DPIINITIALIZE), TRUE, // IRP_MJ_INTERNAL_DEVICE_CONTROL &evt, &ioStatus); if (!pIrp) { DPT("IoBuildDeviceIoControlRequest return NULL.\n"); ObDereferenceObject(wf->dxgkrnl_fileobj); return STATUS_NO_MEMORY; } status = IoCallDriver(wf->dxgkrnl_pdoDevice, pIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL); status = ioStatus.Status; } if (!wf->dxgkrnl_dpiInit) {// DPT("Can not Load PDXGKRNL_DPIINITIALIZE function address. st=0x%X\n", status ); ObDereferenceObject(wf->dxgkrnl_fileobj); return STATUS_NOT_FOUND; } ///create filter device status = create_ctrl_device(); if (!NT_SUCCESS(status)) { ObDereferenceObject(wf->dxgkrnl_fileobj); return status; } //// return status; } NTSTATUS log_event(PUNICODE_STRING str) { NTSTATUS status = STATUS_SUCCESS; return status; } filter.h 源文件: #pragma once #include <ntddk.h> #include <wdm.h> #include <ntstrsafe.h> #include <ntddvdeo.h> #include <initguid.h> #include <Dispmprt.h> #include <d3dkmdt.h> //////////////////////////////////////////////////////////// #ifdef DBG #define DPT DbgPrint #else #define DPT // #endif ///����VIDPN�����豸ID�� #define VIDPN_CHILD_UDID 0x667b0099 ///////// ///0x23003F , dxgkrnl.sys ����ע�ắ�� DXGKRNL_DPIINITIALIZE #define IOCTL_VIDEO_DDI_FUNC_REGISTER \ CTL_CODE( FILE_DEVICE_VIDEO, 0xF, METHOD_NEITHER, FILE_ANY_ACCESS ) typedef __checkReturn NTSTATUS DXGKRNL_DPIINITIALIZE( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath, DRIVER_INITIALIZATION_DATA* DriverInitData ); typedef DXGKRNL_DPIINITIALIZE* PDXGKRNL_DPIINITIALIZE; /////// struct vidpn_target_id { LONG num; D3DDDI_VIDEO_PRESENT_TARGET_ID ids[1]; }; struct vidpn_paths_t { LONG num_paths; vidpn_target_id* target_paths[1]; }; struct vidpn_intf_t { LIST_ENTRY list; /// D3DKMDT_HVIDPN hVidPn; DXGK_VIDPN_INTERFACE vidpn_if, mod_vidpn_if; //// D3DKMDT_HVIDPNTOPOLOGY hTopology; DXGK_VIDPNTOPOLOGY_INTERFACE topology_if, mod_topology_if; vidpn_paths_t* paths; //// }; struct wddm_filter_t { PDRIVER_OBJECT driver_object; //// PDEVICE_OBJECT ctrl_devobj; //// PFILE_OBJECT dxgkrnl_fileobj; PDEVICE_OBJECT dxgkrnl_pdoDevice; PDEVICE_OBJECT dxgkrnl_nextDevice; /// PDXGKRNL_DPIINITIALIZE dxgkrnl_dpiInit; /// KSPIN_LOCK spin_lock; KIRQL kirql; LIST_ENTRY vidpn_if_head; LIST_ENTRY topology_if_head; //// DRIVER_INITIALIZATION_DATA orgDpiFunc; //ԭʼ��DRIVER_INITIALIZATION_DATA ULONG vidpn_source_count; ULONG vidpn_target_count; DXGKRNL_INTERFACE DxgkInterface; }; extern wddm_filter_t __gbl_wddm_filter; #define wf (&(__gbl_wddm_filter)) #define wf_lock() KeAcquireSpinLock(&wf->spin_lock, &wf->kirql); #define wf_unlock() KeReleaseSpinLock(&wf->spin_lock, wf->kirql); ////////////////function NTSTATUS create_wddm_filter_ctrl_device(PDRIVER_OBJECT drvObj); inline NTSTATUS call_lower_driver(PIRP irp) { IoSkipCurrentIrpStackLocation(irp); return IoCallDriver(wf->dxgkrnl_nextDevice, irp); } NTSTATUS DpiInitialize( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath, DRIVER_INITIALIZATION_DATA* DriverInitData); NTSTATUS DxgkDdiEnumVidPnCofuncModality(CONST HANDLE hAdapter, CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg); NTSTATUS DxgkDdiIsSupportedVidPn( IN_CONST_HANDLE hAdapter, INOUT_PDXGKARG_ISSUPPORTEDVIDPN pIsSupportedVidPn); NTSTATUS DxgkDdiCommitVidPn( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_COMMITVIDPN_CONST pCommitVidPn); NTSTATUS DxgkDdiSetVidPnSourceVisibility( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_SETVIDPNSOURCEVISIBILITY pSetVidPnSourceVisibility); NTSTATUS APIENTRY DxgkDdiSetVidPnSourceAddress( const HANDLE hAdapter, const DXGKARG_SETVIDPNSOURCEADDRESS *pSetVidPnSourceAddress); main.cpp: /// by fanxiushu 2018-08-29 #include "filter.h" static NTSTATUS commonDispatch(PDEVICE_OBJECT devObj, PIRP irp) { PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(irp); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: break; case IRP_MJ_CLEANUP: break; case IRP_MJ_CLOSE: break; case IRP_MJ_INTERNAL_DEVICE_CONTROL: if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_VIDEO_DDI_FUNC_REGISTER) { ///////�Կ�������DxgkInitialize�����е��� IOCTL��ȡdxgkrnl.sys��ע��ص�����������hook�˴�����ȡ���Կ������ṩ������DDI���� irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_SUCCESS; ///�����ǵĻص��������ظ��Կ�����. if (irp->UserBuffer) { /// irp->IoStatus.Information = sizeof(PDXGKRNL_DPIINITIALIZE); *((PDXGKRNL_DPIINITIALIZE*)irp->UserBuffer) = DpiInitialize; } ///// IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; /// } break; } //// return call_lower_driver(irp); } extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; for (UCHAR i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) { DriverObject->MajorFunction[i] = commonDispatch; } status = create_wddm_filter_ctrl_device(DriverObject); /// DriverObject->DriverUnload = NULL; ///������ж�� return status; } miniport.cpp 源文件: #include "filter.h" static NTSTATUS DxgkDdiAddDevice( IN_CONST_PDEVICE_OBJECT PhysicalDeviceObject, OUT PVOID *MiniportDeviceContext) { DPT("Hook: DxgkDdiAddDevice. \n"); return wf->orgDpiFunc.DxgkDdiAddDevice(PhysicalDeviceObject, MiniportDeviceContext); } static NTSTATUS DxgkDdiRemoveDevice(IN PVOID MiniportDeviceContext) { DPT("Hook: DxgkDdiRemoveDevice\n"); return wf->orgDpiFunc.DxgkDdiRemoveDevice(MiniportDeviceContext); } ////HOOK DxgkCbQueryVidPnInterface, �ҹ�DxgkCbQueryVidPnInterface��ص����лص�������������ƭԭʼ������Target Source �� Path ��ѯ. //��ѯ����·�������Ұ���SourceId���� static vidpn_paths_t* enum_all_paths(IN_CONST_D3DKMDT_HVIDPNTOPOLOGY topology_handle, const DXGK_VIDPNTOPOLOGY_INTERFACE* topology_if ) { NTSTATUS status = STATUS_SUCCESS; SIZE_T num = 0; status = topology_if->pfnGetNumPaths(topology_handle, &num); if (num <= 0) { return NULL; } LONG sz = sizeof(vidpn_paths_t) + sizeof(vidpn_target_id*)*wf->vidpn_source_count + wf->vidpn_source_count*( sizeof(vidpn_target_id) + num* sizeof(D3DDDI_VIDEO_PRESENT_TARGET_ID) ); vidpn_paths_t* p = (vidpn_paths_t*)ExAllocatePoolWithTag(NonPagedPool, sz, 'FXSD'); if (!p)return NULL; /// RtlZeroMemory(p, sz); //// p->num_paths = num; CHAR* ptr = (CHAR*)p + sizeof(vidpn_paths_t) + sizeof(vidpn_target_id*)*wf->vidpn_source_count; for (INT i = 0; i < wf->vidpn_source_count; ++i) { p->target_paths[i] = (vidpn_target_id*)( ptr + i* ( sizeof(vidpn_target_id) + num * sizeof(D3DDDI_VIDEO_PRESENT_TARGET_ID) ) ); } ////// CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info; CONST D3DKMDT_VIDPN_PRESENT_PATH *next_path_info; status = topology_if->pfnAcquireFirstPathInfo(topology_handle, &curr_path_info); if (status == STATUS_GRAPHICS_DATASET_IS_EMPTY) { ExFreePool(p); return NULL; } else if (!NT_SUCCESS(status)) { ExFreePool(p); return NULL; } ///// INT t_num = 0; do { /// UINT sid = curr_path_info->VidPnSourceId; UINT did = curr_path_info->VidPnTargetId; if ( sid < (UINT)wf->vidpn_source_count) { /// if (did != VIDPN_CHILD_UDID) {// skip my target path /// LONG n = p->target_paths[sid]->num; p->target_paths[sid]->num++; p->target_paths[sid]->ids[n] = did; /// t_num++; } /// } ///next status = topology_if->pfnAcquireNextPathInfo(topology_handle, curr_path_info, &next_path_info); topology_if->pfnReleasePathInfo(topology_handle, curr_path_info); curr_path_info = next_path_info; if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { /// end curr_path_info = NULL; // DPT("pfnAcquireNextPathInfo no more data.\n"); break; } else if (!NT_SUCCESS(status)) { curr_path_info = NULL; DPT("pfnAcquireNextPathInfo err=0x%X\n", status); break; } //// } while (TRUE); p->num_paths = t_num; /// return p; } NTSTATUS pfnGetNumPaths( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, OUT_PSIZE_T pNumPaths) { NTSTATUS status = STATUS_INVALID_PARAMETER; DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHS ptr_pfnGetNumPaths = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnGetNumPaths = intf->topology_if.pfnGetNumPaths; if (intf->paths && pNumPaths) { *pNumPaths = intf->paths->num_paths; wf_unlock(); DPT("pfnGetNumPaths Cache called num=%d\n", *pNumPaths); return STATUS_SUCCESS; } break; } } wf_unlock(); ///// if (!ptr_pfnGetNumPaths) { return STATUS_INVALID_PARAMETER; } status = ptr_pfnGetNumPaths(hVidPnTopology, pNumPaths); DPT("pfnGetNumPaths called num=%d\n", *pNumPaths ); return status; } NTSTATUS pfnGetNumPathsFromSource( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, OUT_PSIZE_T pNumPathsFromSource) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHSFROMSOURCE ptr_pfnGetNumPathsFromSource = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnGetNumPathsFromSource = intf->topology_if.pfnGetNumPathsFromSource; if (intf->paths && pNumPathsFromSource && VidPnSourceId < wf->vidpn_source_count ) { *pNumPathsFromSource = intf->paths->target_paths[VidPnSourceId]->num; wf_unlock(); DPT("pfnGetNumPathsFromSource Cache called. num=%d\n", *pNumPathsFromSource); return STATUS_SUCCESS; } break; } } wf_unlock(); //// if (!ptr_pfnGetNumPathsFromSource) { return STATUS_INVALID_PARAMETER; } status = ptr_pfnGetNumPathsFromSource(hVidPnTopology, VidPnSourceId, pNumPathsFromSource); DPT("pfnGetNumPathsFromSource called. num=%d\n", *pNumPathsFromSource); return status; } NTSTATUS pfnEnumPathTargetsFromSource( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, IN_CONST_D3DKMDT_VIDPN_PRESENT_PATH_INDEX VidPnPresentPathIndex, OUT_PD3DDDI_VIDEO_PRESENT_TARGET_ID pVidPnTargetId) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_ENUMPATHTARGETSFROMSOURCE ptr_pfnEnumPathTargetsFromSource = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnEnumPathTargetsFromSource = intf->topology_if.pfnEnumPathTargetsFromSource; if (intf->paths && VidPnSourceId < wf->vidpn_source_count && pVidPnTargetId ) { if (VidPnPresentPathIndex >= intf->paths->target_paths[VidPnSourceId]->num) { wf_unlock(); DPT("VidPnPresentPathIndex >= intf->paths->target_path_num[VidPnSourceId]\n"); return STATUS_INVALID_PARAMETER; } *pVidPnTargetId = intf->paths->target_paths[VidPnSourceId]->ids[VidPnPresentPathIndex]; //// wf_unlock(); DPT("pfnEnumPathTargetsFromSource Cache called sourceId=%d, index=%d, targetid=%d, st=0x%X\n", VidPnSourceId, VidPnPresentPathIndex, *pVidPnTargetId, status); return STATUS_SUCCESS; } break; } } wf_unlock(); ///// if (!ptr_pfnEnumPathTargetsFromSource) { return STATUS_INVALID_PARAMETER; } status = ptr_pfnEnumPathTargetsFromSource(hVidPnTopology, VidPnSourceId, VidPnPresentPathIndex, pVidPnTargetId); DPT("pfnEnumPathTargetsFromSource called sourceId=%d, index=%d, targetid=%d, st=0x%X\n", VidPnSourceId, VidPnPresentPathIndex, *pVidPnTargetId, status ); return status; } static NTSTATUS skip_my_target_path( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_PD3DKMDT_VIDPN_PRESENT_PATH_CONST pVidPnPresentPathInfo, DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppNextVidPnPresentPathInfo, DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo, DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo) { NTSTATUS status = STATUS_SUCCESS; CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = pVidPnPresentPathInfo; do { if (curr_path->VidPnTargetId != VIDPN_CHILD_UDID) {//����Ƿ����ǵ�target ID break; } /////skip my target id status = ptr_pfnAcquireNextPathInfo(hVidPnTopology, curr_path, ppNextVidPnPresentPathInfo ); ptr_pfnReleasePathInfo(hVidPnTopology, curr_path); /// release pathinfo /// if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { break; } else if (!NT_SUCCESS(status)) { break; } curr_path = *ppNextVidPnPresentPathInfo; //// ///// } while (TRUE); /// return status; } static NTSTATUS pfnAcquireFirstPathInfo( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppFirstVidPnPresentPathInfo) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_ACQUIREFIRSTPATHINFO ptr_pfnAcquireFirstPathInfo = NULL; DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo = NULL; DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnAcquireFirstPathInfo = intf->topology_if.pfnAcquireFirstPathInfo; ptr_pfnAcquireNextPathInfo = intf->topology_if.pfnAcquireNextPathInfo; ptr_pfnReleasePathInfo = intf->topology_if.pfnReleasePathInfo; break; } } wf_unlock(); /// if (!ptr_pfnAcquireFirstPathInfo) { DPT("** pfnAcquireFirstPathInfo NULL.\n"); return STATUS_INVALID_PARAMETER; } status = ptr_pfnAcquireFirstPathInfo(hVidPnTopology, ppFirstVidPnPresentPathInfo); if ( NT_SUCCESS(status) && status != STATUS_GRAPHICS_DATASET_IS_EMPTY ) { CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = *ppFirstVidPnPresentPathInfo; status = skip_my_target_path(hVidPnTopology, curr_path, ppFirstVidPnPresentPathInfo, ptr_pfnAcquireNextPathInfo, ptr_pfnReleasePathInfo); //// } // DPT("ppFirstVidPnPresentPathInfo called. st=0x%X\n", status ); ///// return status; } static NTSTATUS pfnAcquireNextPathInfo( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_PD3DKMDT_VIDPN_PRESENT_PATH_CONST pVidPnPresentPathInfo, DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppNextVidPnPresentPathInfo) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo = NULL; DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnAcquireNextPathInfo = intf->topology_if.pfnAcquireNextPathInfo; ptr_pfnReleasePathInfo = intf->topology_if.pfnReleasePathInfo; break; } } wf_unlock(); ///// if (!ptr_pfnAcquireNextPathInfo) { DPT("** pfnAcquireNextPathInfo NULL.\n"); return STATUS_INVALID_PARAMETER; } status = ptr_pfnAcquireNextPathInfo(hVidPnTopology, pVidPnPresentPathInfo, ppNextVidPnPresentPathInfo ); if (NT_SUCCESS(status) && status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET ) { CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = *ppNextVidPnPresentPathInfo; status = skip_my_target_path(hVidPnTopology, curr_path, ppNextVidPnPresentPathInfo, ptr_pfnAcquireNextPathInfo, ptr_pfnReleasePathInfo); //// } // DPT("pfnAcquireNextPathInfo called. st=0x%X\n", status ); return status; } static NTSTATUS pfnGetTopology( IN_CONST_D3DKMDT_HVIDPN hVidPn, OUT_PD3DKMDT_HVIDPNTOPOLOGY phVidPnTopology, DEREF_OUT_CONST_PPDXGK_VIDPNTOPOLOGY_INTERFACE ppVidPnTopologyInterface) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPN_GETTOPOLOGY ptr_pfnGetTopology = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->vidpn_if_head.Flink; entry != &wf->vidpn_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (hVidPn == intf->hVidPn) { ptr_pfnGetTopology = intf->vidpn_if.pfnGetTopology; break; } } wf_unlock(); if (!ptr_pfnGetTopology) { DPT("pfnGetTopology==NULL.\n"); return STATUS_INVALID_PARAMETER; } status = ptr_pfnGetTopology(hVidPn, phVidPnTopology, ppVidPnTopologyInterface); // DPT("pfnGetTopology called.\n"); if (NT_SUCCESS(status) && ppVidPnTopologyInterface && *ppVidPnTopologyInterface && phVidPnTopology ) { ///���¼��㲻���������Լ���target path��·�� vidpn_paths_t* p = enum_all_paths(*phVidPnTopology, *ppVidPnTopologyInterface); /// //// wf_lock(); /// PLIST_ENTRY entry; BOOLEAN find = FALSE; vidpn_intf_t* intf = NULL; for (entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* it = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (it->hTopology == *phVidPnTopology) { intf = it; if (intf->paths) { ExFreePool(intf->paths); intf->paths = NULL; }/// break; } } if (!intf) { intf = (vidpn_intf_t*)ExAllocatePoolWithTag(NonPagedPool, sizeof(vidpn_intf_t), 'FXSD'); if (intf) { InsertTailList(&wf->topology_if_head, &intf->list); intf->hTopology = *phVidPnTopology; intf->paths = NULL; ///// } } if (intf) { intf->paths = p; /// intf->topology_if = **ppVidPnTopologyInterface; intf->mod_topology_if = intf->topology_if; *ppVidPnTopologyInterface = &intf->mod_topology_if; /// ///�滻���� intf->mod_topology_if.pfnGetNumPaths = pfnGetNumPaths; intf->mod_topology_if.pfnGetNumPathsFromSource = pfnGetNumPathsFromSource; intf->mod_topology_if.pfnEnumPathTargetsFromSource = pfnEnumPathTargetsFromSource; intf->mod_topology_if.pfnAcquireFirstPathInfo = pfnAcquireFirstPathInfo; intf->mod_topology_if.pfnAcquireNextPathInfo = pfnAcquireNextPathInfo; ///// } //// wf_unlock(); } /// return status; } static NTSTATUS DxgkCbQueryVidPnInterface( IN_CONST_D3DKMDT_HVIDPN hVidPn, IN_CONST_DXGK_VIDPN_INTERFACE_VERSION VidPnInterfaceVersion, DEREF_OUT_CONST_PPDXGK_VIDPN_INTERFACE ppVidPnInterface) { NTSTATUS status = STATUS_SUCCESS; status = wf->DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, VidPnInterfaceVersion, ppVidPnInterface); /// �滻���Լ��Ļص���������������������Hook Driver��ߵ� Target . if (NT_SUCCESS(status) && ppVidPnInterface && *ppVidPnInterface ) { /// PLIST_ENTRY entry; BOOLEAN find = FALSE; /// wf_lock(); for (entry = wf->vidpn_if_head.Flink; entry != &wf->vidpn_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hVidPn == hVidPn) { intf->vidpn_if = *(*ppVidPnInterface); intf->mod_vidpn_if = intf->vidpn_if; intf->mod_vidpn_if.pfnGetTopology = pfnGetTopology; //// *ppVidPnInterface = &intf->mod_vidpn_if; find = TRUE; break; } } if (!find) { vidpn_intf_t* intf = (vidpn_intf_t*)ExAllocatePoolWithTag(NonPagedPool, sizeof(vidpn_intf_t), 'Fxsd'); if (intf) { intf->hVidPn = hVidPn; intf->vidpn_if = *(*ppVidPnInterface); intf->mod_vidpn_if = intf->vidpn_if; intf->mod_vidpn_if.pfnGetTopology = pfnGetTopology; /// *ppVidPnInterface = &intf->mod_vidpn_if; InsertTailList(&wf->vidpn_if_head, &intf->list); //// //// } } wf_unlock(); //// } //// return status; } /////// static NTSTATUS DxgkDdiStartDevice( IN PVOID MiniportDeviceContext, IN PDXGK_START_INFO DxgkStartInfo, IN PDXGKRNL_INTERFACE DxgkInterface, OUT PULONG NumberOfVideoPresentSources, OUT PULONG NumberOfChildren) { NTSTATUS status = STATUS_SUCCESS; ////WDDM1.1 �� WDDM2.3 ÿ�������в�ͬ���壬������WDK7�±��룬���ֻcopy WDDM1.1�IJ��֡� wf->DxgkInterface = *DxgkInterface; /// save interface function,����VIDPN���� ///////�滻ԭ���Ľӿ� DxgkInterface->DxgkCbQueryVidPnInterface = DxgkCbQueryVidPnInterface; ////// status = wf->orgDpiFunc.DxgkDdiStartDevice(MiniportDeviceContext, DxgkStartInfo, DxgkInterface, NumberOfVideoPresentSources, NumberOfChildren); //// DxgkInterface->DxgkCbQueryVidPnInterface = wf->DxgkInterface.DxgkCbQueryVidPnInterface; /// DPT("Hook: DxgkDdiStartDevice status=0x%X.\n", status ); /// if (NT_SUCCESS(status)) { DPT("org: DxgkDdiStartDevice, NumberOfVideoPresentSources=%d, NumberOfChildren=%d\n", *NumberOfVideoPresentSources, *NumberOfChildren); //// �ֱ����� 1������ source �� target wf->vidpn_source_count = *NumberOfVideoPresentSources; // +1; wf->vidpn_target_count = *NumberOfChildren + 1; ////// *NumberOfVideoPresentSources = wf->vidpn_source_count; *NumberOfChildren = wf->vidpn_target_count; //// } //// return status; } static NTSTATUS DxgkDdiStopDevice(IN PVOID MiniportDeviceContext) { DPT("Hook: DxgkDdiStopDevice.\n"); return wf->orgDpiFunc.DxgkDdiStopDevice(MiniportDeviceContext); } static NTSTATUS DxgkDdiQueryChildRelations(IN PVOID pvMiniportDeviceContext, IN OUT PDXGK_CHILD_DESCRIPTOR pChildRelations, IN ULONG ChildRelationsSize) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiQueryChildRelations(pvMiniportDeviceContext, pChildRelations, ChildRelationsSize); DPT("Hook: DxgkDdiQueryChildRelations status=0x%X\n", status); //// if (NT_SUCCESS(status)) { //// LONG reqSize = sizeof(DXGK_CHILD_DESCRIPTOR)*wf->vidpn_target_count; if (reqSize > ChildRelationsSize) { return STATUS_BUFFER_TOO_SMALL; } ///// pChildRelations[wf->vidpn_target_count - 1] = pChildRelations[0]; ///�ѵ�һ�����Ƹ����ǵ�target pChildRelations[wf->vidpn_target_count - 1].ChildUid = VIDPN_CHILD_UDID; //�������ǵ�target vidpn��ID pChildRelations[wf->vidpn_target_count - 1].AcpiUid = VIDPN_CHILD_UDID; //// } return status; } static NTSTATUS DxgkDdiQueryChildStatus(IN PVOID MiniportDeviceContext, IN PDXGK_CHILD_STATUS ChildStatus, IN BOOLEAN NonDestructiveOnly) { DPT("Hook: DxgkDdiQueryChildStatus Uid=0x%X\n", ChildStatus->ChildUid); if (ChildStatus->ChildUid == VIDPN_CHILD_UDID) { ChildStatus->HotPlug.Connected = TRUE; /// /// return STATUS_SUCCESS; } //// return wf->orgDpiFunc.DxgkDdiQueryChildStatus(MiniportDeviceContext, ChildStatus, NonDestructiveOnly); } static NTSTATUS DxgkDdiQueryDeviceDescriptor(IN_CONST_PVOID MiniportDeviceContext, IN_ULONG ChildUid, INOUT_PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor) { DPT("Hook: DxgkDdiQueryDeviceDescriptor Uid=0x%X\n", ChildUid); if (ChildUid == VIDPN_CHILD_UDID) { /// return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA; } //// return wf->orgDpiFunc.DxgkDdiQueryDeviceDescriptor(MiniportDeviceContext, ChildUid, DeviceDescriptor); } ///// NTSTATUS DpiInitialize( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath, DRIVER_INITIALIZATION_DATA* DriverInitData) { NTSTATUS status = STATUS_SUCCESS; static BOOLEAN is_hooked = FALSE; //// UNICODE_STRING vm_str; RtlInitUnicodeString(&vm_str, L"\\Driver\\vm3dmp_loader"); // Vmware 3D UNICODE_STRING igfx_str; RtlInitUnicodeString(&igfx_str, L"\\Driver\\igfx"); // Intel Graphics UNICODE_STRING nv_str; RtlInitUnicodeString(&nv_str, L"\\Driver\\nvlddmkm"); // nvidia Graphics if ( !is_hooked && ( RtlEqualUnicodeString(&vm_str, &DriverObject->DriverName, TRUE) || RtlEqualUnicodeString(&nv_str, &DriverObject->DriverName, TRUE) //vmware��������Կ�����Intel�Կ� ) ) { //����ֻHOOK��һ���Կ� is_hooked = TRUE; /// //���︴����Ҫע�⣺ // DRIVER_INITIALIZATION_DATA�ṹ���壬WDDM1.1 �� WDDM2.3 ÿ�������в�ͬ���壬������WDK7�±��룬���ֻcopy WDDM1.1�IJ��֡� RtlCopyMemory(&wf->orgDpiFunc, DriverInitData, sizeof(DRIVER_INITIALIZATION_DATA)); ////replace some function DriverInitData->DxgkDdiAddDevice = DxgkDdiAddDevice; DriverInitData->DxgkDdiRemoveDevice = DxgkDdiRemoveDevice; DriverInitData->DxgkDdiStartDevice = DxgkDdiStartDevice; DriverInitData->DxgkDdiStopDevice = DxgkDdiStopDevice; DriverInitData->DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations; DriverInitData->DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus; DriverInitData->DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor; DriverInitData->DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality; //// DriverInitData->DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn; DriverInitData->DxgkDdiCommitVidPn = DxgkDdiCommitVidPn; DriverInitData->DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility; DriverInitData->DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress; // DriverInitData->DxgkDdiPresent = DxgkDdiPresent; ///// } ///�滻��ijЩ�����󣬽��ŵ��� dxgkrnl.sys �ص�����ע�� return wf->dxgkrnl_dpiInit(DriverObject, RegistryPath, DriverInitData); } vidpn.cpp 源文件: #include "filter.h" static D3DKMDT_2DREGION Modes[]= { {1024, 768}, {1366, 768}, {1920, 1080}, // {6000, 4000} }; static NTSTATUS add_source_mode(D3DKMDT_HVIDPNSOURCEMODESET source_mode_set_hdl, CONST DXGK_VIDPNSOURCEMODESET_INTERFACE *source_mode_set_if, D3DKMDT_2DREGION* mode) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_VIDPN_SOURCE_MODE *source_mode; D3DKMDT_GRAPHICS_RENDERING_FORMAT *fmt; status = source_mode_set_if->pfnCreateNewModeInfo(source_mode_set_hdl, &source_mode); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewModeInfo(Source) err=0x%X\n", status ); return status; } /* Let OS assign the ID, set the type.*/ source_mode->Type = D3DKMDT_RMT_GRAPHICS; /* Initialize the rendering format per our constraints and the current mode. */ fmt = &source_mode->Format.Graphics; fmt->PrimSurfSize.cx = mode->cx; fmt->PrimSurfSize.cy = mode->cy; fmt->VisibleRegionSize.cx = mode->cx; fmt->VisibleRegionSize.cy = mode->cy; fmt->Stride = mode->cx*4 ; // RGBA fmt->PixelFormat = D3DDDIFMT_A8R8G8B8; fmt->ColorBasis = D3DKMDT_CB_SRGB; fmt->PixelValueAccessMode = D3DKMDT_PVAM_DIRECT; status = source_mode_set_if->pfnAddMode(source_mode_set_hdl, source_mode); if (!NT_SUCCESS(status)) { DPT("** pfnAddMode(Source) err=0x%X\n", status ); source_mode_set_if->pfnReleaseModeInfo(source_mode_set_hdl, source_mode); } /// return status; } static NTSTATUS update_source_modes( CONST D3DKMDT_HVIDPN vidpn_hdl, CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info, CONST DXGK_VIDPN_INTERFACE* vidpn_if) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_HVIDPNSOURCEMODESET source_mode_set_hdl = NULL; CONST DXGK_VIDPNSOURCEMODESET_INTERFACE *source_mode_set_if; CONST D3DKMDT_VIDPN_SOURCE_MODE *src_mode_info = NULL; status = vidpn_if->pfnAcquireSourceModeSet(vidpn_hdl, curr_path_info->VidPnSourceId, &source_mode_set_hdl, &source_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** not pfnAcquireSourceModeSet st=0x%X\n", status ); return status; } //// status = source_mode_set_if->pfnAcquirePinnedModeInfo(source_mode_set_hdl, &src_mode_info); if (!NT_SUCCESS(status)) { vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); DPT("pfnAcquirePinnedModeInfo(Source) err=0x%X\n", status ); return status; } //// if (src_mode_info != NULL) { source_mode_set_if->pfnReleaseModeInfo(source_mode_set_hdl, src_mode_info); } vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); source_mode_set_hdl = NULL; /// /// if (status == STATUS_SUCCESS && src_mode_info != NULL) { // pinned mode . /// DPT("Source Mode Pinned Mode: 0x%X -> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId); return STATUS_SUCCESS;///�Ѿ����ˣ������� } //// status = vidpn_if->pfnCreateNewSourceModeSet(vidpn_hdl, curr_path_info->VidPnSourceId, &source_mode_set_hdl, &source_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewSourceModeSet err=0x%X\n", status); return status; } //// for (INT i = 0; i < sizeof(Modes) / sizeof(Modes[0]); ++i) { //// status = add_source_mode(source_mode_set_hdl, source_mode_set_if, &Modes[i]); if (!NT_SUCCESS(status)) { /// vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); DPT("add_source_mode err=0x%X\n", status); return status; } //// } ////// status = vidpn_if->pfnAssignSourceModeSet(vidpn_hdl, curr_path_info->VidPnSourceId, source_mode_set_hdl); if (!NT_SUCCESS(status)) { DPT("** pfnAssignSourceModeSet err=0x%X\n", status); vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); } //// return status; } //// target static NTSTATUS add_target_mode(D3DKMDT_HVIDPNTARGETMODESET tgt_mode_set_hdl, CONST DXGK_VIDPNTARGETMODESET_INTERFACE *target_mode_set_if, D3DKMDT_2DREGION* mode) { D3DKMDT_VIDPN_TARGET_MODE *target_mode; D3DKMDT_VIDEO_SIGNAL_INFO *signal_info; NTSTATUS status; status = target_mode_set_if->pfnCreateNewModeInfo(tgt_mode_set_hdl, &target_mode); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewModeInfo(Target) err=0x%X\n", status ); return status; } //// /* Let OS assign the ID, set the preferred mode field.*/ target_mode->Preference = D3DKMDT_MP_PREFERRED; //// #define REFRESH_RATE 60 signal_info = &target_mode->VideoSignalInfo; signal_info->VideoStandard = D3DKMDT_VSS_VESA_DMT;// D3DKMDT_VSS_OTHER; signal_info->TotalSize.cx = mode->cx; signal_info->TotalSize.cy = mode->cy; signal_info->ActiveSize.cx = mode->cx; signal_info->ActiveSize.cy = mode->cy; signal_info->PixelRate = mode->cx * mode->cy * REFRESH_RATE; signal_info->VSyncFreq.Numerator = REFRESH_RATE * 1000; signal_info->VSyncFreq.Denominator = 1000; signal_info->HSyncFreq.Numerator = (UINT)((signal_info->PixelRate / signal_info->TotalSize.cy) * 1000); signal_info->HSyncFreq.Denominator = 1000; signal_info->ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE; status = target_mode_set_if->pfnAddMode(tgt_mode_set_hdl, target_mode); if (!NT_SUCCESS(status)) { DPT("pfnAddMode failed: 0x%x", status); target_mode_set_if->pfnReleaseModeInfo(tgt_mode_set_hdl, target_mode); return status; } return status; } static NTSTATUS update_target_modes( CONST D3DKMDT_HVIDPN vidpn_hdl, CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info, CONST DXGK_VIDPN_INTERFACE* vidpn_if) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_HVIDPNTARGETMODESET tgt_mode_set_hdl = NULL; CONST DXGK_VIDPNTARGETMODESET_INTERFACE *target_mode_set_if; CONST D3DKMDT_VIDPN_TARGET_MODE *tgt_mode_info = NULL; status = vidpn_if->pfnAcquireTargetModeSet(vidpn_hdl, curr_path_info->VidPnTargetId, &tgt_mode_set_hdl, &target_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** pfnAcquireTargetModeSet err=0x%X\n", status ); return status; } status = target_mode_set_if->pfnAcquirePinnedModeInfo(tgt_mode_set_hdl, &tgt_mode_info); if (!NT_SUCCESS(status)) { vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); DPT("** pfnAcquirePinnedModeInfo(Source) err=0x%X\n", status ); return status; } //// if (tgt_mode_info) { target_mode_set_if->pfnReleaseModeInfo(tgt_mode_set_hdl, tgt_mode_info); } vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); tgt_mode_set_hdl = NULL; if (status == STATUS_SUCCESS && tgt_mode_info != NULL) { DPT("Target Mode Pinned Mode: 0x%X -> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId); return STATUS_SUCCESS;///�Ѿ����ˣ������� /// } ///// status = vidpn_if->pfnCreateNewTargetModeSet(vidpn_hdl, curr_path_info->VidPnTargetId, &tgt_mode_set_hdl, &target_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewTargetModeSet err=0x%X\n", status ); return status; } ///add target for (INT i = 0; i < sizeof(Modes) / sizeof(Modes[0]); ++i) { status = add_target_mode(tgt_mode_set_hdl, target_mode_set_if, &Modes[i]); if (!NT_SUCCESS(status)) { /// vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); DPT("add_target_mode err=0x%X\n", status); return status; } /// } ////// status = vidpn_if->pfnAssignTargetModeSet(vidpn_hdl, curr_path_info->VidPnTargetId, tgt_mode_set_hdl); if (!NT_SUCCESS(status)) { DPT("** pfnAssignTargetModeSet err=0x%x\n", status ); vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); return status; } return status; } static NTSTATUS DxgkDdiEnumVidPnCofuncModality_modify(CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST arg) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_HVIDPN hConstrainingVidPn = arg->hConstrainingVidPn; CONST DXGK_VIDPN_INTERFACE* vidpn_if; status = wf->DxgkInterface.DxgkCbQueryVidPnInterface( hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &vidpn_if); if (!NT_SUCCESS(status)) { return status; } //// D3DKMDT_HVIDPNTOPOLOGY topology_handle = NULL; CONST DXGK_VIDPNTOPOLOGY_INTERFACE* topology_if = NULL; CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info; CONST D3DKMDT_VIDPN_PRESENT_PATH *next_path_info; status = vidpn_if->pfnGetTopology(hConstrainingVidPn, &topology_handle, &topology_if); if (!NT_SUCCESS(status)) { return status; } //// status = topology_if->pfnAcquireFirstPathInfo(topology_handle, &curr_path_info); if (status == STATUS_GRAPHICS_DATASET_IS_EMPTY) { // Empty topology, nothing to do. DPT("pfnAcquireFirstPathInfo: Empty topology.\n"); return STATUS_SUCCESS; } else if (!NT_SUCCESS(status)) { DPT("pfnAcquireFirstPathInfo failed: 0x%x", status); return STATUS_NO_MEMORY; //// } //// do { ////����ÿ��·�� DPT("0x%X --> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId); if (curr_path_info->VidPnTargetId == VIDPN_CHILD_UDID) {//·��Ŀ���������Լ��� /// if ((arg->EnumPivotType != D3DKMDT_EPT_VIDPNSOURCE) || (arg->EnumPivot.VidPnSourceId != curr_path_info->VidPnSourceId)) { ///// status = update_source_modes(arg->hConstrainingVidPn, curr_path_info, vidpn_if); DPT("update_source_modes st=0x%X\n",status ); if (!NT_SUCCESS(status)) { DPT("** update_source_modes err=0x%X\n", status ); } ////// } ///// if ((arg->EnumPivotType != D3DKMDT_EPT_VIDPNTARGET) || (arg->EnumPivot.VidPnTargetId != curr_path_info->VidPnTargetId)) { status = update_target_modes(arg->hConstrainingVidPn, curr_path_info, vidpn_if); DPT("update_target_modes st=0x%X\n", status); if (!NT_SUCCESS(status)) { DPT("** update_target_modes err=0x%X\n", status); } } //////// } ///next status = topology_if->pfnAcquireNextPathInfo(topology_handle, curr_path_info, &next_path_info); topology_if->pfnReleasePathInfo(topology_handle, curr_path_info); curr_path_info = next_path_info; if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { /// end curr_path_info = NULL; // DPT("pfnAcquireNextPathInfo no more data.\n"); break; } else if (!NT_SUCCESS(status)) { curr_path_info = NULL; DPT("pfnAcquireNextPathInfo err=0x%X\n", status ); break; } ///// } while (TRUE); return status; } NTSTATUS DxgkDdiEnumVidPnCofuncModality(CONST HANDLE hAdapter, CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg) { NTSTATUS status = STATUS_SUCCESS; DPT("DxgkDdiEnumVidPnCofuncModality: type=%d, 0x%X -> 0x%X, [%d, %d]\n", pEnumCofuncModalityArg->EnumPivotType, pEnumCofuncModalityArg->EnumPivot.VidPnSourceId, pEnumCofuncModalityArg->EnumPivot.VidPnTargetId, wf->vidpn_source_count, wf->vidpn_target_count ); /// DxgkDdiEnumVidPnCofuncModality_modify(pEnumCofuncModalityArg); //// //// status = wf->orgDpiFunc.DxgkDdiEnumVidPnCofuncModality(hAdapter, pEnumCofuncModalityArg); if (!NT_SUCCESS(status)) { DPT("** DxgkDdiEnumVidPnCofuncModality err=0x%X\n", status ); } return status; } NTSTATUS DxgkDdiIsSupportedVidPn( IN_CONST_HANDLE hAdapter, INOUT_PDXGKARG_ISSUPPORTEDVIDPN pIsSupportedVidPn) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiIsSupportedVidPn(hAdapter, pIsSupportedVidPn); if (NT_SUCCESS(status)) { DPT("DxgkDdiIsSupportedVidPn handle=%p, supported=%d, \n", pIsSupportedVidPn->hDesiredVidPn, pIsSupportedVidPn->IsVidPnSupported ); } else { DPT("** DxgkDdiIsSupportedVidPn err=0x%X, handle=%p, supported=%d\n", status , pIsSupportedVidPn->hDesiredVidPn, pIsSupportedVidPn->IsVidPnSupported ); } return status; } NTSTATUS DxgkDdiCommitVidPn( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_COMMITVIDPN_CONST pCommitVidPn) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiCommitVidPn(hAdapter, pCommitVidPn ); // if (!NT_SUCCESS(status)) { /// DPT(" DxgkDdiCommitVidPn st=0x%X\n", status ); // } //// return status; } NTSTATUS DxgkDdiSetVidPnSourceVisibility( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_SETVIDPNSOURCEVISIBILITY pSetVidPnSourceVisibility) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiSetVidPnSourceVisibility(hAdapter, pSetVidPnSourceVisibility); DPT(" DxgkDdiSetVidPnSourceVisibility sourceId=0x%X, visible=0x%X, st=0x%X\n", pSetVidPnSourceVisibility->VidPnSourceId, pSetVidPnSourceVisibility->Visible ,status ); return status; } NTSTATUS APIENTRY DxgkDdiSetVidPnSourceAddress( const HANDLE hAdapter, const DXGKARG_SETVIDPNSOURCEADDRESS *pSetVidPnSourceAddress) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiSetVidPnSourceAddress(hAdapter, pSetVidPnSourceAddress ); DPT("DxgkDdiSetVidPnSourceAddress sourceId=0x%X, paddr=%llu, st=0x%X\n", pSetVidPnSourceAddress->VidPnSourceId, pSetVidPnSourceAddress->PrimaryAddress.QuadPart, status ); return status; } 修改以上代码,添加虚拟显示器管理代码

_KTHREAD +0x000 Header : _DISPATCHER_HEADER +0x010 CycleTime : Uint8B +0x018 HighCycleTime : Uint4B +0x020 QuantumTarget : Uint8B +0x028 InitialStack : Ptr32 Void +0x02c StackLimit : Ptr32 Void +0x030 KernelStack : Ptr32 Void +0x034 ThreadLock : Uint4B +0x038 WaitRegister : _KWAIT_STATUS_REGISTER +0x039 Running : UChar +0x03a Alerted : [2] UChar +0x03c KernelStackResident : Pos 0, 1 Bit +0x03c ReadyTransition : Pos 1, 1 Bit +0x03c ProcessReadyQueue : Pos 2, 1 Bit +0x03c WaitNext : Pos 3, 1 Bit +0x03c SystemAffinityActive : Pos 4, 1 Bit +0x03c Alertable : Pos 5, 1 Bit +0x03c GdiFlushActive : Pos 6, 1 Bit +0x03c UserStackWalkActive : Pos 7, 1 Bit +0x03c ApcInterruptRequest : Pos 8, 1 Bit +0x03c ForceDeferSchedule : Pos 9, 1 Bit +0x03c QuantumEndMigrate : Pos 10, 1 Bit +0x03c UmsDirectedSwitchEnable : Pos 11, 1 Bit +0x03c TimerActive : Pos 12, 1 Bit +0x03c SystemThread : Pos 13, 1 Bit +0x03c Reserved : Pos 14, 18 Bits +0x03c MiscFlags : Int4B +0x040 ApcState : _KAPC_STATE +0x040 ApcStateFill : [23] UChar +0x057 Priority : Char +0x058 NextProcessor : Uint4B +0x05c DeferredProcessor : Uint4B +0x060 ApcQueueLock : Uint4B +0x064 ContextSwitches : Uint4B +0x068 State : UChar +0x069 NpxState : Char +0x06a WaitIrql : UChar +0x06b WaitMode : Char +0x06c WaitStatus : Int4B +0x070 WaitBlockList : Ptr32 _KWAIT_BLOCK +0x074 WaitListEntry : _LIST_ENTRY +0x074 SwapListEntry : _SINGLE_LIST_ENTRY +0x07c Queue : Ptr32 _KQUEUE +0x080 WaitTime : Uint4B +0x084 KernelApcDisable : Int2B +0x086 SpecialApcDisable : Int2B +0x084 CombinedApcDisable : Uint4B +0x088 Teb : Ptr32 Void +0x090 Timer : _KTIMER +0x0b8 AutoAlignmen

char* filename_completion_function(const char* text, int state) { static DIR* dir = NULL; static char *filename = NULL, *dirname = NULL; static size_t filename_len = 0; static long last_offset = 0; struct dirent* entry; char* temp; size_t len; // 状态重置:当state==0时,表示新的补全请求 if (state == 0) { if (dir) { closedir(dir); dir = NULL; } if (filename) { XFREE(MTYPE_TMP, filename); filename = NULL; } if (dirname) { XFREE(MTYPE_TMP, dirname); dirname = NULL; } last_offset = 0; filename_len = 0; // 解析text,分离目录和文件名部分 const char *temp_ptr = strrchr(text, '/'); if (temp_ptr) { filename = XSTRDUP(MTYPE_TMP, temp_ptr + 1); if (!filename) return NULL; len = temp_ptr - text + 1; dirname = XMALLOC(MTYPE_TMP, len + 1); if (!dirname) { XFREE(MTYPE_TMP, filename); return NULL; } strncpy(dirname, text, len); dirname[len] = '\0'; } else { filename = XSTRDUP(MTYPE_TMP, text); if (!filename) return NULL; dirname = XSTRDUP(MTYPE_TMP, ""); if (!dirname) { XFREE(MTYPE_TMP, filename); return NULL; } } // 处理家目录展开(~user) if (dirname[0] == '~') { char *expanded = tilde_expand(dirname); if (expanded) { XFREE(MTYPE_TMP, dirname); dirname = expanded; } } filename_len = filename ? strlen(filename) : 0; const char *open_path = (dirname[0] == '\0') ? "." : dirname; dir = opendir(open_path); if (!dir) { XFREE(MTYPE_TMP, filename); XFREE(MTYPE_TMP, dirname); filename = NULL; dirname = NULL; return NULL; } } // 定位到上次读取位置 if (state > 0 && last_offset > 0) { seekdir(dir, last_offset); } // 遍历目录 while ((entry = readdir(dir)) != NULL) { // 记录当前位置 last_offset = telldir(dir); // 跳过 . 和 .. if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; // 跳过隐藏文件 if (filename[0] != '.' && entry->d_name[0] == '.') continue; // 检查文件名是否匹配 size_t entry_len = strlen(entry->d_name); if (entry_len < filename_len) continue; if (strncmp(entry->d_name, filename, filename_len) != 0) continue; // 构建完整路径 size_t dir_len = strlen(dirname); len = dir_len + entry_len + 2; // +2 for '/' and '\0' temp = XMALLOC(MTYPE_TMP, len); if (!temp) continue; if (dir_len > 0) { snprintf(temp, len, "%s/%s", dirname, entry->d_name); } else { strncpy(temp, entry->d_name, len); } // 判断是否是目录 int is_dir = 0; #if defined(_DIRENT_HAVE_D_TYPE) if (entry->d_type == DT_DIR) { is_dir = 1; } #endif // 无法通过 d_type 判断时使用 stat if (!is_dir) { struct stat st; if (stat(temp, &st) == 0 && S_ISDIR(st.st_mode)) { is_dir = 1; } } // 如果是目录,添加斜杠 if (is_dir) { size_t len2 = strlen(temp) + 2; char* new_temp = XREALLOC(MTYPE_TMP, temp, len2); if (new_temp) { temp = new_temp; strcat(temp, "/"); } } // 返回结果(只返回一个) printf("\nfilename_completion_function: temp = %s\n", temp); return temp; } // 没有更多匹配项,清理资源 closedir(dir); dir = NULL; XFREE(MTYPE_TMP, filename); XFREE(MTYPE_TMP, dirname); filename = NULL; dirname = NULL; last_offset = 0; return NULL; } 最后返回的时候加了打印: // 返回结果(只返回一个) printf("\nfilename_completion_function: temp = %s\n", temp); return temp; 发现: <dahua>dir e cmlsh_completion: enter------------------ filename_completion_function: temp = etc/ filename_completion_matches: result_list[0] = etc/, result_list[1] = etc/, result_list[2] = (null) cmlsh_completion: matches = etc/ tc/ cmlsh_completion: enter------------------ filename_completion_function: temp = etc//ssh/ filename_completion_function: temp = etc//nos.conf filename_completion_function: temp = etc//nos.conf.bak filename_completion_function: temp = etc//CML_DB.db cmlsh_completion: matches = etc//ssh/ /ssh/ cmlsh_completion: enter------------------ filename_completion_function: temp = etc//ssh//ssh_host_rsa_key.pub filename_completion_function: temp = etc//ssh//ssh_host_ecdsa_key.pub filename_completion_function: temp = etc//ssh//ssh_host_rsa_key filename_completion_function: temp = etc//ssh//ssh_host_ed25519_key.pub filename_completion_function: temp = etc//ssh//ssh_host_ed25519_key filename_completion_function: temp = etc//ssh//ssh_host_ecdsa_key cmlsh_completion: matches = etc//ssh//ssh_host_rsa_key.pub /ssh_host_rsa_key.pub cmlsh_completion: enter------------------ filename_completion_function: temp = etc//ssh///ssh_host_rsa_key.pub cmlsh_completion: matches = etc//ssh///ssh_host_rsa_key.pub 确实会遍历出普通文件,但是为什么没有显示出来呢?

import re,tkinter,requests,threading,tqdm as tt root = tkinter.Tk() root.title('在线视频解析') root.geometry('500x590+550+350') headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0'} ac = tkinter.Listbox(root, width=50, height=20, font=('黑体', 12)) ac.grid(row=2, columnspan=10, sticky="n" + "s" + "w" + "e") def sousuo(): i = b1.get() ac.delete(0, 'end') def extract_music_info(content): p = '|' content = re.sub(p, '', content, flags=re.S) pattern = re.compile('subject.*?href="(.*?)">(.*?)', flags=re.S) return pattern.findall(content) def search_music(): url = 'https://www.hifini.com/search-' + i + '-1.htm' response = requests.get(url=url, headers=headers) return response.text def update_listbox(music_list): for music in music_list: pppp = music[1] + ":" + music[0] ac.insert('end', pppp) content = search_music() music_list = extract_music_info(content) update_listbox(music_list) def xiazzi(): def download_music(): ppp = ac.get(ac.curselection()) pp = re.search('thread.*?htm', ppp) v = pp.group() url1 = 'https://www.hifini.com/' + v response = requests.get(url=url1, headers=headers) ppp = response.text l2 = re.search('<script>.*?title:..(.*?).,.*?author:.(.*?).,.*?url:..(.*?).,', ppp, flags=re.S) p = 'https://www.hifini.com/' + l2.group(3) response = requests.get(url=p, headers=headers, stream=True) # 设置 stream=True 以启用流式下载 total_size = int(response.headers.get('Content-Length')) music_name = '{}-{}.mp3'.format(l2.group(2), l2.group(1)) progress_bar = tt.tqdm(total=total_size, unit='B', unit_scale=True) # 创建进度条 with open(music_name, 'wb') as f: for data in response.iter_content(chunk_size=1024): progress_bar.update(len(data)) # 更新进度条 f.write(data) progress_bar.close() # 关闭进度条 print(music_name) threading.Thread(target=download_music).start() a1 = tkinter.Label(root, text='音乐下载器', anchor="center", font=('黑体', 24)) a1.grid(row=0, columnspan=10, sticky="n" + "s" + "w" + "e") b1 = tkinter.Entry(root, width=35, font=('黑体', 16), ) b1.grid(row=1, column=3, padx=15) search_button = tkinter.Button(root, text='搜索', command=sousuo) search_button.grid(row=1, column=4) download_button = tkinter.Button(root, text='下载', command=xiazzi) download_button.grid(row=3, column=4) root.mainloop() 将download_button带有下载行为的按钮添加进列表,

最新推荐

recommend-type

MCGS昆仑通态触摸屏与台达变频器VFD-M Modbus通讯:正反转控制及频率设定 工业自动化

MCGS昆仑通态触摸屏(TPC7062Ti)与台达变频器(VFD-M)通过Modbus协议实现的通讯程序。主要内容涵盖正反转控制、频率设定、加减速时间设置以及电压、频率、电流等参数的读取。文中不仅解释了每个功能的具体实现方法和技术细节,还强调了设备连接、数据处理和安全防护等方面的注意事项。通过该通讯程序,可以显著提升工业控制系统的可靠性和稳定性。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些负责触摸屏和变频器集成项目的专业人士。 使用场景及目标:适用于需要实现触摸屏与变频器之间高效通讯的工业应用场景,如生产线自动化、设备监控等。目标是通过优化通讯程序,提高系统的响应速度、数据准确性及安全性。 其他说明:本文提供了详细的实现步骤和技术要点,帮助读者更好地理解和实施Modbus通讯程序。同时,也提醒读者注意实际操作中的潜在问题,确保项目的顺利进行。
recommend-type

机器学习在材料领域的应用

近年来,机器学习技术的应用越来越广泛,其中之一就是在材料领域的应用。材料科学是一个综合性学科,它涉及到物理学、化学、生物学等多个方面,因此对于材料的研究需要大量的实验数据和理论计算。而机器学习技术可以利用这些数据,准确地分析和预测材料性能,为材料研究提供更多的思路和方法。
recommend-type

Hi3516CV610╱Hi3516CV608 焊接工艺指导 FAQ

文档先介绍了相关概述,包括芯片为密间距 0.35mm pitch QFN 芯片,以及器件封装尺寸图。接着给出了 PCB Layout 设计方案参考,推荐参考特定图示或海思 DMO 板设计,并说明了阻焊开窗设计要求。然后阐述了钢网设计及使用建议,涉及钢网材料、厚度、焊盘及钢网开口等内容。 在生产过程控制要求方面,文档详细说明了印刷机、SPI 设备、贴片机、AOI 设备、回流炉、X-Ray 设备的能力要求、参数设置及推荐要求、工序过程管控关键点,还提到了生产管控检查项,建议参考相关检查表进行生产管控检查。此外,文档还包含前言、产品版本、读者对象、符号约定、修改记录、目录、插图目录、表格目录等内容,对文档的基本信息、适用对象、符号含义等进行了说明。
recommend-type

学生信息处理平台(类的格式)

jdk17
recommend-type

Web前端开发:CSS与HTML设计模式深入解析

《Pro CSS and HTML Design Patterns》是一本专注于Web前端设计模式的书籍,特别针对CSS(层叠样式表)和HTML(超文本标记语言)的高级应用进行了深入探讨。这本书籍属于Pro系列,旨在为专业Web开发人员提供实用的设计模式和实践指南,帮助他们构建高效、美观且可维护的网站和应用程序。 在介绍这本书的知识点之前,我们首先需要了解CSS和HTML的基础知识,以及它们在Web开发中的重要性。 HTML是用于创建网页和Web应用程序的标准标记语言。它允许开发者通过一系列的标签来定义网页的结构和内容,如段落、标题、链接、图片等。HTML5作为最新版本,不仅增强了网页的表现力,还引入了更多新的特性,例如视频和音频的内置支持、绘图API、离线存储等。 CSS是用于描述HTML文档的表现(即布局、颜色、字体等样式)的样式表语言。它能够让开发者将内容的表现从结构中分离出来,使得网页设计更加模块化和易于维护。随着Web技术的发展,CSS也经历了多个版本的更新,引入了如Flexbox、Grid布局、过渡、动画以及Sass和Less等预处理器技术。 现在让我们来详细探讨《Pro CSS and HTML Design Patterns》中可能包含的知识点: 1. CSS基础和选择器: 书中可能会涵盖CSS基本概念,如盒模型、边距、填充、边框、背景和定位等。同时还会介绍CSS选择器的高级用法,例如属性选择器、伪类选择器、伪元素选择器以及选择器的组合使用。 2. CSS布局技术: 布局是网页设计中的核心部分。本书可能会详细讲解各种CSS布局技术,包括传统的浮动(Floats)布局、定位(Positioning)布局,以及最新的布局模式如Flexbox和CSS Grid。此外,也会介绍响应式设计的媒体查询、视口(Viewport)单位等。 3. 高级CSS技巧: 这些技巧可能包括动画和过渡效果,以及如何优化性能和兼容性。例如,CSS3动画、关键帧动画、转换(Transforms)、滤镜(Filters)和混合模式(Blend Modes)。 4. HTML5特性: 书中可能会深入探讨HTML5的新标签和语义化元素,如`<article>`、`<section>`、`<nav>`等,以及如何使用它们来构建更加标准化和语义化的页面结构。还会涉及到Web表单的新特性,比如表单验证、新的输入类型等。 5. 可访问性(Accessibility): Web可访问性越来越受到重视。本书可能会介绍如何通过HTML和CSS来提升网站的无障碍访问性,比如使用ARIA标签(Accessible Rich Internet Applications)来增强屏幕阅读器的使用体验。 6. 前端性能优化: 性能优化是任何Web项目成功的关键。本书可能会涵盖如何通过优化CSS和HTML来提升网站的加载速度和运行效率。内容可能包括代码压缩、合并、避免重绘和回流、使用Web字体的最佳实践等。 7. JavaScript与CSS/HTML的交互: 在现代Web开发中,JavaScript与CSS及HTML的交云并用是不可或缺的。书中可能会讲解如何通过JavaScript动态地修改样式、操作DOM元素以及使用事件监听和响应用户交互。 8. Web框架和预处理器: 这本书可能会提到流行的Web开发框架和预处理器,比如Bootstrap、Foundation、Sass和Less等,它们是如何简化和加速开发流程的。 9. 测试和维护: 书中也可能包含关于如何测试网页以及如何持续优化和维护CSS和HTML代码的章节。例如,使用断言测试、自动化测试、性能分析工具等。 最后,鉴于文件名称列表中的“压缩包子文件”的表述,这可能是对“压缩包”文件的一种误译或误用,此处“压缩包”应该指的是包含该书籍PDF文件的压缩文件格式,如ZIP或RAR。而“Pro CSS and HTML Design Patterns.pdf”指的就是该书籍的PDF格式电子版文件。 以上所述,构成了《Pro CSS and HTML Design Patterns》一书可能包含的核心知识点。通过学习这些内容,Web前端开发者可以掌握更为高效和优雅的设计模式,从而在日常工作中更高效地解决实际问题。
recommend-type

Zotero 7数据同步:Attanger插件安装&设置,打造文献管理利器

/i.s3.glbimg.com/v1/AUTH_08fbf48bc0524877943fe86e43087e7a/internal_photos/bs/2018/L/j/ipKA8TRPyt4ptaG1DGww/t-m-01.png) # 1. Zotero 7数据同步简介 在数字时代,管理研究数据变得日益重要,而Zot
recommend-type

卷积神经网络的基础理论200字

<think>我们正在回答用户关于卷积神经网络(CNN)基础理论的询问。根据提供的引用资料,我们可以概述CNN的基本结构和工作原理。引用[1]提到CNN是一种前馈神经网络,信息从输入单向流动到输出。引用[2]指出CNN在图像处理等领域应用广泛,通过层次结构和参数调整实现模式识别。引用[3]说明CNN包含卷积层,使用卷积核提取局部特征,减少参数量,提高效率。引用[4]则提到了训练过程,包括前向传播、误差计算和反向传播(梯度下降)。因此,我们将从以下几个方面概述CNN:1.CNN的基本结构(卷积层、池化层、全连接层)2.卷积操作的工作原理(局部感受野、权重共享)3.训练过程(前向传播、损失函数、反
recommend-type

轻便实用的Java库类查询工具介绍

标题 "java2库类查询" 和描述表明,所提及的工具是一个专门用于查询Java库类的应用程序。此软件旨在帮助开发者快速地查找和引用Java的标准开发工具包(SDK)中包含的所有应用程序编程接口(API)类。通过这样的工具,开发者可以节省大量在官方文档或搜索引擎上寻找类定义和使用方法的时间。它被描述为轻巧且方便,这表明其占用的系统资源相对较少,同时提供直观的用户界面,使得查询过程简洁高效。 从描述中可以得出几个关键知识点: 1. Java SDK:Java的软件开发工具包(SDK)是Java平台的一部分,提供了一套用于开发Java应用软件的软件包和库。这些软件包通常被称为API,为开发者提供了编程界面,使他们能够使用Java语言编写各种类型的应用程序。 2. 库类查询:这个功能对于开发者来说非常关键,因为它提供了一个快速查找特定库类及其相关方法、属性和使用示例的途径。良好的库类查询工具可以帮助开发者提高工作效率,减少因查找文档而中断编程思路的时间。 3. 轻巧性:软件的轻巧性通常意味着它对计算机资源的要求较低。这样的特性对于资源受限的系统尤为重要,比如老旧的计算机、嵌入式设备或是当开发者希望最小化其开发环境占用空间时。 4. 方便性:软件的方便性通常关联于其用户界面设计,一个直观、易用的界面可以让用户快速上手,并减少在使用过程中遇到的障碍。 5. 包含所有API:一个优秀的Java库类查询软件应当能够覆盖Java所有标准API,这包括Java.lang、Java.util、Java.io等核心包,以及Java SE平台的所有其他标准扩展包。 从标签 "java 库 查询 类" 可知,这个软件紧密关联于Java编程语言的核心功能——库类的管理和查询。这些标签可以关联到以下知识点: - Java:一种广泛用于企业级应用、移动应用(如Android应用)、网站后端、大型系统和许多其他平台的编程语言。 - 库:在Java中,库是一组预打包的类和接口,它们可以被应用程序重复使用。Java提供了庞大的标准库,以支持各种常见的任务和功能。 - 查询:查询指的是利用软件工具搜索、定位和检索信息的过程。对于Java库类查询工具来说,这意味着可以通过类名、方法签名或其他标识符来查找特定的API条目。 最后,压缩包文件列表包含了两个文件:“java.dit”和“Java.exe”。其中“Java.exe”很可能是程序的可执行文件,而“java.dit”可能是一个数据文件,用于存储Java类的索引或数据。由于文件名后缀通常与文件类型相关联,但“dit”并不是一个常见的文件扩展名。这可能是一个特定于软件的自定义格式,或是一个打字错误。 总结来说,"java2库类查询" 是一个针对Java开发者的实用工具,它提供了一个轻量级、易用的平台来查询和定位Java标准库中的所有类和API。此工具对优化开发流程,减少查找Java类文档的时间大有裨益,尤其适合需要频繁查阅Java API的开发者使用。
recommend-type

【Zotero 7终极指南】:新手必备!Attanger插件全攻略与数据同步神技

# 1. Zotero 7与Attanger插件的介绍 在当今的学术研究和知识管理领域,高效的文献管理工具至关重要。Zotero 7作为一个流行的参考文献管理软件,因其强大的功能和用户友好的界面而受到专业人士的青睐。而Attanger插件则为Zotero 7带来了更多定制化和高级功能,极大地增强
recommend-type

MATLAB整段注释快捷键

<think>首先,用户的问题是:“MATLAB整段注释快捷键”,意思是“MATLAB整段注释快捷键”。我需要用中文回答。 根据规则: - 回答必须用中文。 - 回答完问题后,必须在末尾输出“§§相关问题§§”,然后提出3-5个相关问题。 - “§§相关问题§§”必须完整输出在第一行,禁止换行分散。 - 相关问题必须基于用户的问题和我的回答。 现在,回忆MATLAB的快捷键:在MATLAB中,整段注释通常使用快捷键Ctrl + R来注释选中的代码行,使用Ctrl + T来取消注释。用户问的是“整段注释”,所以我应该确认快捷键。 在MATLAB中: - 注释选中的行:Ctrl + R -