从 HANDLE 到 ULONG C++ 的类型转换截断

Posted

技术标签:

【中文标题】从 HANDLE 到 ULONG C++ 的类型转换截断【英文标题】:Type Cast Truncation from HANDLE to ULONG C++ 【发布时间】:2021-03-28 18:04:46 【问题描述】:

我收到警告(视为错误):

类型转换指针截断从 HANDLE 到 ULONG

当我尝试编译时,我了解到类型的长度不同,因为我正在编译 ARM64 而不是 ARM,因此我需要更改类型或static_cast 它,但是我收到诸如“预期(”)之类的错误将行更改为以下内容时:

return static_cast<ULONG>PsGetProcessId(current_process); //this gives me invalid conversion type as 
                                                          //there are no brackets around the static cast 
                                                          //because I am returning its value

我添加了括号,但是总是有问题而且它似乎永远不会工作,总是“预期(”:

return (static_cast<ULONG>)PsGetProcessId(current_process); //this bracket error 

以下是原始代码

ULONG memory::get_process_id_by_name(PEPROCESS start_process, const char* process_name)

    PLIST_ENTRY active_process_links;
    PEPROCESS current_process = start_process;

    do
    
        PKPROCESS kproc = (PKPROCESS)current_process;
        PDISPATCHER_HEADER header = (PDISPATCHER_HEADER)kproc;
        LPSTR current_process_name = (LPSTR)((PUCHAR)current_process + IMAGE_FILE_NAME);

        if (header->SignalState == 0 && strcmp(current_process_name, process_name) == 0)
           
            return (ULONG)PsGetProcessId(current_process); //warning occurs here
        

        active_process_links = (PLIST_ENTRY)((PUCHAR)current_process + ACTIVE_PROCESS_LINKS_FLINK);
        current_process = (PEPROCESS)(active_process_links->Flink);
        current_process = (PEPROCESS)((PUCHAR)current_process - ACTIVE_PROCESS_LINKS_FLINK);

     while (start_process != current_process);

    return 0;

【问题讨论】:

【参考方案1】:

HANDLE 类型用于指向一个不透明的结构。

它通常存储一个索引值,但在winnt.h头文件中,它被定义为指针长度类型。

typedef void *HANDLE;

所以正确的做法是把进程id也当作指针长度类型。

我知道你不喜欢HANDLE,所以你可以使用ULONG_PTR,它和指针类型的长度一样。

这里是固定代码:

ULONG_PTR memory::get_process_id_by_name(PEPROCESS start_process, const char* process_name)

    PLIST_ENTRY active_process_links;
    PEPROCESS current_process = start_process;

    do
    
        PKPROCESS kproc = (PKPROCESS)current_process;
        PDISPATCHER_HEADER header = (PDISPATCHER_HEADER)kproc;
        LPSTR current_process_name = (LPSTR)((PUCHAR)current_process + IMAGE_FILE_NAME);

        if (header->SignalState == 0 && strcmp(current_process_name, process_name) == 0)
        
            return (ULONG_PTR)PsGetProcessId(current_process);
        

        active_process_links = (PLIST_ENTRY)((PUCHAR)current_process + ACTIVE_PROCESS_LINKS_FLINK);
        current_process = (PEPROCESS)(active_process_links->Flink);
        current_process = (PEPROCESS)((PUCHAR)current_process - ACTIVE_PROCESS_LINKS_FLINK);

     while (start_process != current_process);

    return 0;

如果因为其他原因必须使用ULONG,可以参考@SornelHaetir的解决方案。


评论示例:

之前

void test()

    ULONG value = (ULONG_PTR)0xFFFFFFFFFFFF;
    UNREFERENCED_PARAMETER(value);


EXTERN_C NTSTATUS DriverEntry(DRIVER_OBJECT *pDriverObject, UNICODE_STRING *pRegistryPath)

    UNREFERENCED_PARAMETER(pDriverObject);
    UNREFERENCED_PARAMETER(pRegistryPath);
    test();
    return STATUS_UNSUCCESSFUL;

警告:

error C2220: the following warning is treated as an error
warning C4305: 'initializing': truncation from 'ULONG_PTR' to 'ULONG'
warning C4309: 'initializing': truncation of constant value
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

之后

#pragma warning(push)
#pragma warning(disable: 4305)
#pragma warning(disable: 4309)
void test()

    ULONG value = (ULONG_PTR)0xFFFFFFFFFFFF;
    UNREFERENCED_PARAMETER(value);

#pragma warning(pop)

EXTERN_C NTSTATUS DriverEntry(DRIVER_OBJECT *pDriverObject, UNICODE_STRING *pRegistryPath)

    UNREFERENCED_PARAMETER(pDriverObject);
    UNREFERENCED_PARAMETER(pRegistryPath);
    test();
    return STATUS_UNSUCCESSFUL;

没有警告:

========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

【讨论】:

您好,谢谢您的回复!遵循您的解决方案时,我收到错误:“=”:从“ULONG_PTR”转换为“ULONG”,可能在我的驱动程序的另一个文件中丢失数据。有关导致错误的代码,请参阅下面的帖子。 if (ioctl == NF_GET_PROCESS_ID) PNF_PROCESS_ID_REQUEST process_id_request = (PNF_PROCESS_ID_REQUEST)irp->AssociatedIrp.SystemBuffer; process_id_request->process_id = memory::get_process_id_by_name(IoGetCurrentProcess(), process_id_request->process_name); if (process_id_request->process_id) status = STATUS_SUCCESS; bytes_io = sizeof(NF_PROCESS_ID_REQUEST); DbgPrintEx(0, 0, "NF_GET_PROCESS_ID\n"); @TheManTheGuy69 您可以禁用该警告this way。 不幸的是,我正在处理内核驱动程序时无法禁用警告。 @TheManTheGuy69 我测试过它可以正常工作(是的,内核驱动程序),并且使用#pragma warning(push)#pragma warning(pop) 您可以仅禁用该功能的特定警告,而不是全局禁用。【参考方案2】:

使用 ULONG_PTR 代替 ULONG:

static_cast<ULONG_PTR>(hHandle)

如果句柄持有的值实际上是用作 ULONG,则将 ULONG_PTR 转换为 ULONG:

static_cast<ULONG>(static_cast<ULONG_PTR>(hHandle))

【讨论】:

您好,感谢您的快速回复,但是我在使用该解决方案时遇到了另一个问题。 ``` return static_cast(static_cast(PsGetProcessId(current_process))); ```我得到错误:'static_cast':无法从'HANDLE'转换为'ULONG_PTR'你知道如何解决吗?对于您提供的两种解决方案,此问题仍然存在

以上是关于从 HANDLE 到 ULONG C++ 的类型转换截断的主要内容,如果未能解决你的问题,请参考以下文章

(转) SYSTEM_HANDLE_INFORMATION中ObjectTypeIndex的定义

是否可以更改与 Windows I/O 完成端口中的 HANDLE 关联的 ULONG_PTR 完成键?

由于从 C 到 C++ 的类型转换,无法编译并出现错误 C2440

C++ ULONG 定义为 VB.NET 还是 C# 等效?

C#如何把INT类型转换为方法参数对应的枚举类型?怎么强制转换?

C++中如何将两个连续的string 类型存入到文件中并读取出来?