精华内容
下载资源
问答
  • 最近需要实现一个功能,在驱动中创建文件的符号链接。搜了一圈,只能找到 mklink 命令, mklink 命令显然不能在内核调用。 因为大部分的系统调用最终都会调用到内核层的实现,所以整体思路就是搞清楚 mklink 的实现...

    0x00

    最近需要实现一个功能,在驱动中创建文件的符号链接。搜了一圈,只能找到 mklink 命令, mklink 命令显然不能在内核调用。

    因为大部分的系统调用最终都会调用到内核层的实现,所以整体思路就是搞清楚 mklink 的实现,找到对应的内核接口。

    0x01

    简单搜索了下系统目录,发现并没有 mklink 文件,因此怀疑 mklink 是 cmd 的内置命令。验证这个想法很简单,直接把 cmd 拖入 IDA,搜索相关字符串(mklink),果然:
    在这里插入图片描述
    双击条目,找到对应的符号再X下,就能找到相关的引用:
    看到这个,一般的猜想就是 mklink 是命令名,eMkLink 是对应的命令处理函数。
    我们可以验证一把。
    使用 windbg 加载 cmd,根据 _MakeLinkStr 的偏移,也就是图一中的 401be8,计算出加载后的真实地址。对这个地址下一个读断点(windbg:ba r命令;gdb:watch命令),之后 F5。在 cmd 中输入 mklink,回车。我们就会发现断点被断下来了,断下的位置是 wcsicmp,也就是在字符串比较,那么只可能是在比较命令字符串,毕竟 cmd 中内置了很多命令,需要一个一个比较。
    我们可以先 shift+f11 出来,到达 cmd 的领空,之后一直 f10,记得盯着 cmd 的输出,如果 cmd 有新的输出,那么就说明咱们走过了_。最终可以确定,eMkLink 就是 mklink 的命令处理函数。

    0x02

    进入 eMkLink 之后,我们跳过 stub 函数,到达 MakeLink 函数。从函数的实现来看除了验证参数之外,一共有以下的几个实现:
    MakeSymLink
    MakeHardLink
    MakeJunction
    对应着 mklink 的几个功能。因为这次我们要实现的功能是文件的符号链接,所以我们进入 MakeSymLink 函数。函数的实现很简单,调用了 CreateSymbolicLinkW 函数。从 msdn 上或者 windbg 上都能知道,这个函数从 kernel32(win7)中导出(因为家里的工作机是 win8.1,所以函数是从 kernelbase.dll 中导出的)。那么接着我们就需要开撸CreateSymbolicLinkW。
    CreateSymbolicLinkW 的实现也很简单,主要做了路径转换,之后调用 NtCreateFile 与 NtFsControlFile。我们知道 ntdll 中的 Nt* 函数,最终对应 nt 中的 Zw* 函数,nt!Zw* 函数最终执行到 nt!Nt* 函数。
    因此对于我们而言,到目前为止,我们已经知道了创建文件符号链接的整个过程,只要在驱动层调用 ZwCreateFile 与 ZwFsControlFile 即可。唯一需要确定的就是调用这两个函数的参数。
    在这里插入图片描述
    本着大家都要动手实践的原则,具体参数的赋值我就不给出了,只说明下关键的一个参数。
    在 NtCreateFile 中,CreateOptions 包含了 FILE_OPEN_REPARSE_POINT 属性;在 NtFsControlFile 中,其FsControlCode 值为 FSCTL_SET_REPARSE_POINT。
    另外还有一个神坑需要注意:NtFsControlFile 中的 InputBuffer 在末尾不能包含多余的0字节,否则会直接返回 错误。

    0x03

    重解析点的原理比较简单,有兴趣的可以翻阅 Ntfs 的源码,里面有相关的实现。

    另外有部分博客讲的也很好,推荐下面这个博客 NTFS重解析点(Reparse Points)

    展开全文
  • NT驱动加载工具DriverMonitor,WDM驱动加载工具EzDriverInstaller,查看符号链接工具SymLinks,无需安装,解压即可以实用。
  • 驱动开发之符号链接和设备名称

    千次阅读 2014-10-21 16:41:40
    驱动符号链接名是这样写的 L"//??//HelloDDK" --->/??/HelloDDK  L"//DosDevices//HelloDDK"--->/DosDevices/HelloDDK 在应用程序中,符号链接名: L"////.//HelloDDK"-->//./HelloDDK winobj和Device...
    

    windows下的设备是以"/Device/[设备名]”形式命名的。
    例如磁盘分区的c盘,d盘的设备名称就是"/Device/HarddiskVolume1”,"/Device/HarddiskVolume2”,
    当然也可以不指定设备名称。如果IoCreateDevice中没有指定设备名称,那么I/O管理器会自动分配一个数字作为设备的名称。
    例如"/Device/00000001"。/Device/[设备名],不容易记忆,通常符号链接可以理解为设备的别名,
    更重要的是设备名,只能被内核模式下的其他驱动所识别,而别名可以被用户模式下的应用程序识别,
    例如c盘,就是名为"c:"的符号链接,其真正的设备对象是"/Device/HarddiskVolume1”,所以在写驱动时候,
    一般我们创建符号链接,即使驱动中没有用到,这也算是一个好的习惯吧。

    驱动中符号链接名是这样写的
    L"//??//HelloDDK" --->/??/HelloDDK
     L"//DosDevices//HelloDDK"--->/DosDevices/HelloDDK
    在应用程序中,符号链接名:
    L".//HelloDDK"-->//./HelloDDK

    winobj和DeviceTree可以用来查看这些信息。

    DosDevices的符号链接名就是??, 所以"//DosDevices//XXXX"其实就是"//??//XXXX"

    展开全文
  • 关键词: windows驱动开发 删除符号链接出错 变量作用域问题 RtlInitUnicodeString 摘要:NT式驱动中,在DriverUnload()中尝试删除之前创建的符号链接失败,最后发现原因是变量作用域和RtlInitUnicodeString的...

    关键词: windows驱动开发  删除符号链接出错  变量作用域问题 RtlInitUnicodeString

    摘要:NT式驱动中,在DriverUnload()中尝试删除之前创建的符号链接失败,最后发现原因是变量作用域和RtlInitUnicodeString的问题


    原始存在问题的简化代码如下:

    typedef struct _DEVICE_EXTENSION {
        UINT32 magicNum;
    	PDEVICE_OBJECT pDevice;
    	UNICODE_STRING symLinkName;	
    } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    
    PDEVICE_OBJECT gControlDeviceObject;
    
    DriverEntry()
    {
    	PDEVICE_EXTENSION pDevExt;
    	WCHAR             linkNameBuffer[]  = L"\\DosDevices\\diskFilter";
            UNICODE_STRING          LinkName;
    	
    	IoCreateDevice(..., &gControlDeviceObject);
    	RtlInitUnicodeString (&LinkName, linkNameBuffer );
    	
    	pDevExt->magicNum = 0x4c44;
    	pDevExt->symLinkName = LinkName;
    	
    	DriverObject->DriverUnload = DiskFilterUnload;
    }
    
    DiskFilterUnload (IN PDRIVER_OBJECT pDriverObject) 
    {
    	NTSTATUS status;
    	PDEVICE_EXTENSION pDevExt;
    	
    	pDevExt = (PDEVICE_EXTENSION)gControlDeviceObject->DeviceExtension;
    	KdPrint(("  devObj(0x%x), magicNum(0x%x), SymLinkName(%wZ)\n", gControlDeviceObject, pDevExt->magicNum, &pDevExt->symLinkName));
    	status = IoDeleteSymbolicLink( &pDevExt->ustrSymLinkName );
    }

    上述代码中,从IoDeleteSymbolicLink返回的status是路径不正确,但KdPrint中打印的magicNum是正确的,windbg调试里发现在DiskFilterUnload()中的pDevExt->symLinkName没有包含正确的值,当时真有点百思不得其解啊。


    后来看到linkNameBuffer是局部变量,想到了变量作用域的问题,把WCHAR             linkNameBuffer[]  = L"\\DosDevices\\diskFilter";拿到DriverEntry外做全局变量,

    问题就消失了。当然,更一般的做法应该是在头文件中#define SymbolicLinkName L"\\DosDevices\\diskFilter"。


    现在来看,要产生这个问题,还有一个原因是RtlInitUnicodeString(),它应该没有做内存拷贝(它没有为smLinkName分配内存然后把值拷贝过去,但我认为它这样做了)

    看来下次使用RtlInitUnicodeString()的时候得要注意了。


    展开全文
  • 枚举符号链接: #include #include #include #include // 定义函数返回值 //typedef ULONG NTSTATUS; // 宽字节字符串结构定义 typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; ...

    枚举符号链接:

     

    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <tchar.h>
    
    // 定义函数返回值
    //typedef ULONG NTSTATUS;
    
    // 宽字节字符串结构定义
    typedef struct _UNICODE_STRING {
    	USHORT  Length;
    	USHORT  MaximumLength;
    	PWSTR  Buffer;
    } UNICODE_STRING, *PUNICODE_STRING;
    
    // 对象属性定义
    typedef struct _OBJECT_ATTRIBUTES {
    	ULONG Length;
    	HANDLE RootDirectory;
    	UNICODE_STRING *ObjectName;
    	ULONG Attributes;
    	PSECURITY_DESCRIPTOR SecurityDescriptor;
    	PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
    } OBJECT_ATTRIBUTES,*POBJECT_ATTRIBUTES;
    
    // 基本信息定义
    typedef struct _DIRECTORY_BASIC_INFORMATION {
    	UNICODE_STRING ObjectName;
    	UNICODE_STRING ObjectTypeName;
    } DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;
    
    // 返回值或状态类型定义
    #define OBJ_CASE_INSENSITIVE      0x00000040L
    #define DIRECTORY_QUERY           (0x0001)
    #define STATUS_SUCCESS            ((NTSTATUS)0x00000000L) // ntsubauth
    #define STATUS_MORE_ENTRIES       ((NTSTATUS)0x00000105L)
    #define STATUS_NO_MORE_ENTRIES    ((NTSTATUS)0x8000001AL)
    #define STATUS_BUFFER_TOO_SMALL   ((NTSTATUS)0xC0000023L)
    #define SYMBOLIC_LINK_QUERY       (0x0001)
    #define SYMBOLIC_LINK_ALL_ACCESS  (STANDARD_RIGHTS_REQUIRED | 0x1)
    
    // 初始化对象属性宏定义
    #define InitializeObjectAttributes( p, n, a, r, s ) { \
    	(p)->Length = sizeof( OBJECT_ATTRIBUTES );          \
    	(p)->RootDirectory = r;                             \
    	(p)->Attributes = a;                                \
    	(p)->ObjectName = n;                                \
    	(p)->SecurityDescriptor = s;                        \
    	(p)->SecurityQualityOfService = NULL;               \
    }
    
    // 字符串初始化
    typedef VOID (CALLBACK* RTLINITUNICODESTRING)(PUNICODE_STRING,PCWSTR);
    RTLINITUNICODESTRING RtlInitUnicodeString;
    
    // 字符串比较
    typedef
    BOOLEAN
    (WINAPI *RTLEQUALUNICODESTRING)(
    								const UNICODE_STRING *String1,
    								const UNICODE_STRING *String2,
    								BOOLEAN CaseInSensitive
    								);
    RTLEQUALUNICODESTRING RtlEqualUnicodeString;
    
    // 打开对象
    typedef NTSTATUS (WINAPI *ZWOPENDIRECTORYOBJECT)(
    	OUT PHANDLE DirectoryHandle,
    	IN ACCESS_MASK DesiredAccess,
    	IN POBJECT_ATTRIBUTES ObjectAttributes
    	);
    ZWOPENDIRECTORYOBJECT ZwOpenDirectoryObject;
    
    // 查询对象
    typedef
    NTSTATUS
    (WINAPI *ZWQUERYDIRECTORYOBJECT)(
    								 IN HANDLE DirectoryHandle,
    								 OUT PVOID Buffer,
    								 IN ULONG BufferLength,
    								 IN BOOLEAN ReturnSingleEntry,
    								 IN BOOLEAN RestartScan,
    								 IN OUT PULONG Context,
    								 OUT PULONG ReturnLength OPTIONAL
    								 );
    ZWQUERYDIRECTORYOBJECT ZwQueryDirectoryObject;
    
    // 打开符号链接对象
    typedef
    NTSTATUS
    (WINAPI *ZWOPENSYMBOLICKLINKOBJECT)(
    									OUT PHANDLE SymbolicLinkHandle,
    									IN ACCESS_MASK DesiredAccess,
    									IN POBJECT_ATTRIBUTES ObjectAttributes
    									);
    ZWOPENSYMBOLICKLINKOBJECT ZwOpenSymbolicLinkObject;
    
    // 查询符号链接对象
    typedef
    NTSTATUS
    (WINAPI *ZWQUERYSYMBOLICKLINKOBJECT)(
    									 IN HANDLE SymbolicLinkHandle,
    									 IN OUT PUNICODE_STRING TargetName,
    									 OUT PULONG ReturnLength OPTIONAL
    									 );
    ZWQUERYSYMBOLICKLINKOBJECT ZwQuerySymbolicLinkObject;
    
    // 关闭已经打开的对象
    typedef
    NTSTATUS
    (WINAPI *ZWCLOSE)(
    				  IN HANDLE Handle
    				  );
    ZWCLOSE ZwClose;
    
    
    //
    int main()
    {
    	HMODULE hNtdll = NULL;
    	hNtdll = LoadLibrary(_T("ntdll.dll" ));
    	if ( NULL == hNtdll )
    	{
    		printf("[%s]--Load ntdll.dll failed(%ld).\r\n", __FUNCTION__, GetLastError());
    		goto EXIT;
    	}
    	printf("[%s]--Load ntdll.dll sucess now get proc.\r\n", __FUNCTION__);
    	RtlInitUnicodeString      = (RTLINITUNICODESTRING)GetProcAddress(hNtdll, "RtlInitUnicodeString");
    	RtlEqualUnicodeString     = (RTLEQUALUNICODESTRING)GetProcAddress(hNtdll, "RtlEqualUnicodeString");
    	ZwOpenDirectoryObject     = (ZWOPENDIRECTORYOBJECT)GetProcAddress(hNtdll, "ZwOpenDirectoryObject");
    	ZwQueryDirectoryObject    = (ZWQUERYDIRECTORYOBJECT)GetProcAddress(hNtdll, "ZwQueryDirectoryObject");
    	ZwOpenSymbolicLinkObject  = (ZWOPENSYMBOLICKLINKOBJECT)GetProcAddress(hNtdll, "ZwOpenSymbolicLinkObject");
    	ZwQuerySymbolicLinkObject = (ZWQUERYSYMBOLICKLINKOBJECT)GetProcAddress(hNtdll, "ZwQuerySymbolicLinkObject");
    	ZwClose                   = (ZWCLOSE)GetProcAddress(hNtdll, "ZwClose");
    
    	UNICODE_STRING     strDirName;
    	OBJECT_ATTRIBUTES  oba;
    	NTSTATUS           ntStatus; 
    	HANDLE             hDirectory;
    	RtlInitUnicodeString(&strDirName, _T("\\BaseNamedObjects"));//global??,BaseNamedObjects
    	InitializeObjectAttributes(&oba, &strDirName, OBJ_CASE_INSENSITIVE, NULL, NULL);
    
    	printf("[%s]--Open directory object now.\r\n", __FUNCTION__);
    	ntStatus = ZwOpenDirectoryObject(&hDirectory, DIRECTORY_QUERY, &oba);
    	if ( ntStatus != STATUS_SUCCESS )
    	{
    		printf("[%s]--Open directory object failed(%ld).\r\n", __FUNCTION__, GetLastError());
    		goto EXIT;
    	}
    
    	printf("[%s]--Open directory object success.\r\n", __FUNCTION__);
    	UNICODE_STRING symbolicLink;
    	UNICODE_STRING targetName;
    	BYTE           buffer[2048] = {0};
    	ULONG          ulLength  = 2048;  
    	ULONG          ulContext = 0;
    	ULONG          ulRet     = 0; 
    	RtlInitUnicodeString(&symbolicLink, L"SymbolicLink");
    	targetName.Length = 0;
    	targetName.Buffer = (PWSTR)calloc(2, 1024);
    	if ( targetName.Buffer == NULL )
    	{
    		printf("[%s]--calloc failed(%ld).\r\n", __FUNCTION__, GetLastError());
    		goto EXIT;
    	}
    
    	targetName.MaximumLength = 1024;
    	do
    	{
    		ntStatus = ZwQueryDirectoryObject(hDirectory, buffer, ulLength, TRUE, FALSE, &ulContext, &ulRet);
    		if ( (ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_NO_MORE_ENTRIES) )
    		{
    			printf("[%s]--ZwQueryDirectoryObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
    			goto EXIT;
    		}
    		else if ( STATUS_NO_MORE_ENTRIES == ntStatus )
    		{
    			printf("[%s]--No more object.\r\n", __FUNCTION__);
    			goto EXIT;
    		}
    
    		PDIRECTORY_BASIC_INFORMATION  directoryInfo = (PDIRECTORY_BASIC_INFORMATION)buffer;
    		printf("ObjectName: [%S]---ObjectTypeName: [%S]\n", 
    			directoryInfo->ObjectName.Buffer, 
    			directoryInfo->ObjectTypeName.Buffer);
    
    		if ( RtlEqualUnicodeString(&directoryInfo->ObjectTypeName, &symbolicLink, TRUE) )
    		{
    			OBJECT_ATTRIBUTES symbolicLinkAttributes;
    			HANDLE            hSymbolicLink;
    			// 初始化符号链接对象属性
    			InitializeObjectAttributes(&symbolicLinkAttributes,
    				&directoryInfo->ObjectName, 
    				OBJ_CASE_INSENSITIVE, 
    				hDirectory, 
    				NULL);
    
    			// 打开符号链接对象
    			ntStatus = ZwOpenSymbolicLinkObject(&hSymbolicLink, SYMBOLIC_LINK_QUERY, &symbolicLinkAttributes);
    			if ( ntStatus != STATUS_SUCCESS )
    			{
    				printf("[%s]--ZwOpenSymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
    				goto EXIT;
    			}
    
    			// 查询符号链接对象
    			ntStatus = ZwQuerySymbolicLinkObject(hSymbolicLink, &targetName, NULL); 
    			if ( ntStatus != STATUS_SUCCESS )
    			{
    				printf("[%s]--ZwQuerySymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
    				ZwClose(hSymbolicLink);
    				goto EXIT;
    			}
    			// TODO: 添加针对符号链接的处理代码
    			// 清空targetName
    			memset((LPVOID)targetName.Buffer, 0, targetName.Length*sizeof(WCHAR));
    			// 关闭符号链接句柄
    			ZwClose(hSymbolicLink);
    		}
    	}while(TRUE);
    EXIT:
    	if ( hDirectory != NULL )
    	{
    		ZwClose(hDirectory);
    	}
    	getchar();
    	return 0;
    }

     

    比如说,需要枚举程序A有几个实例在运行,可以根据其 GUID 实现查找:

     

    PDIRECTORY_BASIC_INFORMATION  directoryInfo = (PDIRECTORY_BASIC_INFORMATION)buffer;
    		std::wstring objectName = directoryInfo->ObjectName.Buffer;
    		if ( objectName.find( L"{FED3DBE6-1256-46fc-8DAE-C13360CB46C8}" ) != std::wstring::npos )
    		{
    			++g_nAppClientCount;//
    		}

     

    展开全文
  • 刚开始驱动编程的时候实现了pDriverObject->MajorFunction中的大部分函数,但是回头重新一步一步开展的时候发现应用层打开驱动层的符号链接的时候报错了,打开文件失败 虽然错误很简单,但还是记录一下 主要原因是...
  • 【我的】Window驱动开发——通过符号链接获取真实设备 作者:zcr214 时间:2016/5/5   我们想要把驱动绑定到指定的盘符,实际是绑定到它对应的真实设备卷,实际上windows用户看到的C盘D盘只是符号链接名,而真实...
  • Windows 创建符号链接

    千次阅读 2019-11-24 12:50:02
    符号链接(软链接)是一类特殊的文件, 其包含有一条以绝对路径或者相对路径的形式指向其它文件或者目录的引用。[1] 符号链接最早在4.2BSD版本中出现(1983年)。今天POSIX操作系统标准、大多数类Unix系统、Windows ...
  • 驱动设备名:
  • 符号链接和硬链接有什么区别?

    千次阅读 2019-12-22 15:32:05
    最近我在求职面试时被问到这个问题。 我是诚实的,并说我知道符号链接的行为以及如何创建一个,但不理解硬链接的使用以及它与符号链接的区别。
  • 它使用Windows符号链接和连接(感谢micahmo)来链接位于任何硬盘驱动器或网络路径中OneDrive文件夹外部的文件夹。 OneDrive当前不支持它。 它只会忽略对这些文件夹的任何更改。 OneDrive Bully通过触发OneDrive...
  • 笔者关于Windows驱动开发讲演视频之1.7,以3W的方式介绍什么是符号链接,为什么要有符号连接内核对象,以及如何使用它。最后将内核符号链接对象的结构体show了出来,加深人们的理解。
  • delphi 加载驱动

    2014-10-01 19:00:36
    delphi 加载驱动
  • Windows支持4种”链接”机制,分别是shortcut(快捷方式)、hard link(硬链接)、junction point(软链接)、symbolic link(符号链接)。接下来我们一起来看看他们的区别: 1)shortcut/快捷方式 以.lnk文件方式...
  • Windows硬链接 软链接 符号链接 快捷方式 2 years ago scz 阅读: 13,081 Windows支持4种”链接”机制,分别是shortcut、hard link、junction point、symbolic link。本文针对这4种机制进行简要介绍,可作为速...
  • Symlink Helper 是一种工具,旨在使符号链接符号链接)的创建变得容易和快速。 通常符号链接是通过命令行创建的,这使得许多用户无法访问它们。 此工具使您只需在资源管理器中单击几下鼠标即可创建符号链接。 如果...
  • 系统盘(通常为 C盘)空间经常不够用是计算机用户常见的烦恼。造成这种情况的原因很可能是因为硬盘分区是手贱为系统盘分配的空间太小,...我们可以使用符号链接的方法,将该目录“移动”到磁盘的非系统盘分区(D盘、...
  • 目的:在项目中的一个文件夹photo链接到网络资源盘符。如图所示:   具体操作命令如下图所示(操作前必须将项目中的photo目录删除,如果原来就有photo就重命名。当备份了): 这样就链接完成了!...
  • 笔者关于Windows驱动开发讲演视频之1.7,以3W的方式介绍什么是符号链接,为什么要有符号连接内核对象,以及如何使用它。最后将内核符号链接对象的结构体show了出来,加深人们的理解。很可惜,CSDN不能内嵌视频。但...
  • 1.驱动对象. typedef struct _DRIVER_OBJECT { CSHORT Type; CSHORT Size; // // The following links all of the devices created by a single driver // together on a list, and the Fla
  • 应用层调用驱动程序的方法

    千次阅读 2011-06-23 12:18:00
    转:... 2.1 应用程序如何使用驱动 应用程序中使用 CreateFile,ReadFile,WriteFile,DeviceIoControl,CloseHandle 来指示驱动程序完成某种
  • 留言回复答案,选择2个最优秀答案和解释,赠送作者签名版《Linux设备驱动开发详解》。 (完) "Linux阅码场"是专业的Linux及系统软件技术交流社区,Linux系统人才培养基地,企业和Linux人才的连接枢纽。 查看我们精华...
  • MyBatis面试题(2020最新版)

    万次阅读 多人点赞 2019-09-24 16:40:33
    为什么需要预编译 定义: SQL 预编译指的是数据库驱动在发送 SQL 语句和参数给 DBMS 之前对 SQL 语句进行编译,这样 DBMS 执行 SQL 时,就不需要重新编译。 为什么需要预编译 JDBC 中使用对象 PreparedStatement 来...
  • /创建设备名称 UNICODE_STRING devName; RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");...IoCreateDevice(pDriverObject,//驱动对象 sizeof(DEVICE_EXTENSION),//自定义的扩展结构的大小 &(UNI
  • 设备名和符号链接

    千次阅读 2012-09-10 15:36:52
    以前总是对符号链接不太明白,今天看到了一篇文章,讲的很好,记录一下。 ------------------------------------------------------------------------------------------------- UNICODE_STRING devName; ...
  • 用于将具有可重用源代码的目录符号链接到项目中的命令行工具。 与语言无关。 带有Python和Flutter特定的扩展。 为什么 重用代码应该很简单。 如果我在本地驱动器上的目录中有所需的代码,我只想将其包含在项目中。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 65,263
精华内容 26,105
关键字:

驱动符号链接