产品推广前的准备工作:求助 :DefineDosDevice的内核实现

来源:百度文库 编辑:中财网 时间:2024/05/03 20:26:34

需要在非管理员用户下实现虚拟磁盘 但是DefineDosDevice非管理员下似乎无法使用
打算使用驱动实现给虚拟盘加载盘符
参考了TRUECRYPT  
驱动下给MOUNTMGR发送
IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
IOCTL_MOUNTMGR_CREATE_POINT

卷中也相应实现了
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
然后返回用户层广播设备信息
结果是
注册表已经显示诸如 \DosDevices\G:  \??\MyVolume0等
但是始终无法显示盘符
请问哪里忽略了
或者麻烦指点下 如何跟踪DefineDosDevice的调用过程
谢谢

-----------------------------

这点小问题还煎熬啊,系统实现见nt4源码Srvinit.c (nt4\\private\\csr\\server)        BaseSrvDefineDosDevice函数


ULONG
BaseSrvDefineDosDevice(
    IN OUT PCSR_API_MSG m,
    IN OUT PCSR_REPLY_STATUS ReplyStatus
    )
{
    NTSTATUS Status;
    PBASE_DEFINEDOSDEVICE_MSG a = (PBASE_DEFINEDOSDEVICE_MSG)&m->u.ApiMessageData;
    UNICODE_STRING LinkName;
    UNICODE_STRING LinkValue;
    HANDLE LinkHandle;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PWSTR Buffer, s, Src, Dst, pchValue;
    ULONG cchBuffer, cch;
    ULONG cchName, cchValue, cchSrc, cchSrcStr, cchDst;
    BOOLEAN QueryNeeded, MatchFound, RevertToSelfNeeded, DeleteRequest;
    ULONG ReturnedLength;
    SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
    SECURITY_DESCRIPTOR SecurityDescriptor;
    CHAR Acl[256];               // 256 is more than big enough
    ULONG AclLength=256;
    PSID WorldSid;

    cchBuffer = 4096;
    Buffer = RtlAllocateHeap( BaseSrvHeap,
                              MAKE_TAG( TMP_TAG ),
                              cchBuffer * sizeof( WCHAR )
                            );
    if (Buffer == NULL) {
        return (ULONG)STATUS_NO_MEMORY;
        }

    Status = RtlEnterCriticalSection( &BaseSrvDosDeviceCritSec );
    if (!NT_SUCCESS( Status )) {
        RtlFreeHeap( BaseSrvHeap, 0, Buffer );
        return (ULONG)Status;
        }

    if (a->Flags & DDD_REMOVE_DEFINITION) {
        DeleteRequest = TRUE;
        }
    else {
        DeleteRequest = FALSE;
        }

    LinkHandle = NULL;
    try {
        s = Buffer;
        cch = cchBuffer;
        cchName = _snwprintf( s,
                              cch,
                              L\"\\\\??\\\\%wZ\",
                              &a->DeviceName
                            );
        s += cchName + 1;
        cch -= (cchName + 1);

        RtlInitUnicodeString( &LinkName, Buffer );
        InitializeObjectAttributes( &ObjectAttributes,
                                    &LinkName,
                                    OBJ_CASE_INSENSITIVE,
                                    (HANDLE) NULL,
                                    (PSECURITY_DESCRIPTOR)NULL
                                  );
        QueryNeeded = TRUE;
        RevertToSelfNeeded = CsrImpersonateClient( NULL );  // This stacks client contexts
        Status = NtOpenSymbolicLinkObject( &LinkHandle,
                                           SYMBOLIC_LINK_QUERY | DELETE,
                                           &ObjectAttributes
                                         );
        if (RevertToSelfNeeded) {
            CsrRevertToSelf();                              // This unstacks client contexts
            }
        if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
            LinkHandle = NULL;
            if (DeleteRequest) {
                if (a->TargetPath.Length == 0) {
                    Status = STATUS_SUCCESS;
                    }

                leave;
                }

            QueryNeeded = FALSE;
            Status = STATUS_SUCCESS;
            }
        else
        if (!NT_SUCCESS( Status )) {
            LinkHandle = NULL;
            leave;
            }

        if (a->TargetPath.Length != 0) {
            cchValue = wcslen( Src = a->TargetPath.Buffer );
            if ((cchValue + 1) >= cch) {
                Status = STATUS_TOO_MANY_NAMES;
                leave;
                }

            RtlMoveMemory( s, Src, (cchValue + 1) * sizeof( WCHAR ) );
            pchValue = s;
            s += cchValue + 1;
            cch -= (cchValue + 1);
            }
        else {
            pchValue = NULL;
            cchValue = 0;
            }

        if (QueryNeeded) {
            LinkValue.Length = 0;
            LinkValue.MaximumLength = (USHORT)(cch * sizeof( WCHAR ));
            LinkValue.Buffer = s;
            ReturnedLength = 0;
            Status = NtQuerySymbolicLinkObject( LinkHandle,
                                                &LinkValue,
                                                &ReturnedLength
                                              );
            if (ReturnedLength == (ULONG)LinkValue.MaximumLength) {
                Status = STATUS_BUFFER_OVERFLOW;
                }

            if (!NT_SUCCESS( Status )) {
                leave;
                }

            s[ ReturnedLength / sizeof( WCHAR ) ] = UNICODE_NULL;
            LinkValue.MaximumLength = (USHORT)(ReturnedLength + sizeof( UNICODE_NULL ));
            }
        else {
            if (DeleteRequest) {
                RtlInitUnicodeString( &LinkValue, NULL );
                }
            else {
                RtlInitUnicodeString( &LinkValue, s - (cchValue + 1) );
                }
            }

        if (LinkHandle != NULL) {
            Status = NtMakeTemporaryObject( LinkHandle );
            NtClose( LinkHandle );
            LinkHandle = NULL;
            }

        if (!NT_SUCCESS( Status )) {
            leave;
            }

        if (DeleteRequest) {
            Src = Dst = LinkValue.Buffer;
            cchSrc = LinkValue.MaximumLength / sizeof( WCHAR );
            cchDst = 0;
            MatchFound = FALSE;
            while (*Src) {
                cchSrcStr = 0;
                s = Src;
                while (*Src++) {
                    cchSrcStr++;
                    }

                if (!MatchFound) {
                    if ((a->Flags & DDD_EXACT_MATCH_ON_REMOVE &&
                         cchValue == cchSrcStr &&
                         !_wcsicmp( s, pchValue )
                        ) ||
                        (!(a->Flags & DDD_EXACT_MATCH_ON_REMOVE) &&
                         (cchValue == 0 || !_wcsnicmp( s, pchValue, cchValue ))
                        )
                       ) {
                        MatchFound = TRUE;
                        }
                    else {
                        goto CopySrc;
                        }
                    }
                else {
CopySrc:
                    if (s != Dst) {
                        RtlMoveMemory( Dst, s, (cchSrcStr + 1) * sizeof( WCHAR ) );
                        }
                    Dst += cchSrcStr + 1;
                    }
                }
            *Dst++ = UNICODE_NULL;
            LinkValue.Length = wcslen( LinkValue.Buffer ) * sizeof( UNICODE_NULL );
            if (LinkValue.Length != 0) {
                LinkValue.MaximumLength = (USHORT)((PCHAR)Dst - (PCHAR)LinkValue.Buffer);
                }
            }
        else
        if (QueryNeeded) {
            LinkValue.Buffer -= (cchValue + 1);
            LinkValue.Length = (USHORT)(cchValue * sizeof( WCHAR ));
            LinkValue.MaximumLength += LinkValue.Length + sizeof( UNICODE_NULL );
            }

        //
        // Create a new value for the link.
        //

        if (LinkValue.Length != 0) {
            //
            // Create the new symbolic link object with a security descriptor
            // that grants world SYMBOLIC_LINK_QUERY access.
            //

            Status = RtlAllocateAndInitializeSid( &WorldSidAuthority,
                                                  1,
                                                  SECURITY_WORLD_RID,
                                                  0, 0, 0, 0, 0, 0, 0,
                                                  &WorldSid
                                                );

            if (!NT_SUCCESS( Status )) {
                leave;
                }

            Status = RtlCreateSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );

            ASSERT(NT_SUCCESS(Status));

            Status = RtlCreateAcl( (PACL)Acl,
                                    AclLength,
                                    ACL_REVISION2
                                  );
            ASSERT(NT_SUCCESS(Status));

            Status = RtlAddAccessAllowedAce( (PACL)Acl,
                                             ACL_REVISION2,
                                             SYMBOLIC_LINK_QUERY | DELETE,
                                             WorldSid
                                           );

            ASSERT(NT_SUCCESS(Status));

            //
            // Sid has been copied into the ACL
            //

            RtlFreeSid( WorldSid );

            Status = RtlSetDaclSecurityDescriptor ( &SecurityDescriptor,
                                                    TRUE,
                                                    (PACL)Acl,
                                                    TRUE                // Don\'t over-ride inherited protection
                                                  );
            ASSERT(NT_SUCCESS(Status));

            ObjectAttributes.SecurityDescriptor = &SecurityDescriptor;
            ObjectAttributes.Attributes |= OBJ_PERMANENT;
            Status = NtCreateSymbolicLinkObject( &LinkHandle,
                                                 SYMBOLIC_LINK_ALL_ACCESS,
                                                 &ObjectAttributes,
                                                 &LinkValue
                                               );
            if (NT_SUCCESS( Status )) {
                NtClose( LinkHandle );
                if (DeleteRequest && !MatchFound) {
                    Status = STATUS_OBJECT_NAME_NOT_FOUND;
                    }
                }

            LinkHandle = NULL;
            }
        }
    finally {
        if (LinkHandle != NULL) {
            NtClose( LinkHandle );
            }
        RtlFreeHeap( BaseSrvHeap, 0, Buffer );
        RtlLeaveCriticalSection( &BaseSrvDosDeviceCritSec );
        }

    return (ULONG)Status;
    ReplyStatus;    // get rid of unreferenced parameter warning message
}
-------------------会者不难 难者不会啊  
谢谢了
不过可能是我提问的方向有问题
我需要在非管理员用户下实现加载虚拟盘
但是DefineDosDevice
MJ001列出的代码恐怕我是无法运用了
再次感谢