从 32 位拖放到 64 位

2024-04-24

我正在编写一个接受文件拖放的 C 程序。 当它以 32 位编译时,它在任何情况下都可以工作。但当它以 64 位编译时,它仅适用于从 64 位应用程序拖动的文件:

  • 32 位 -> 32 位:成功
  • 64 位 -> 64 位:成功
  • 64 位 -> 32 位:成功
  • 32 位 -> 64 位:失败

我仍然收到 WM_DROPFILES 消息,但 DragQueryFile 没有返回任何内容(文件数为 0)。

这对于很多应用程序来说似乎都是一个问题,但我想知道是否有解决方法。

Edit:

  • 如果我将文件从 64 位可执行文件拖放到我的 64 位应用程序中,wParam 的值将为 0x000000F211C000B8(这表明不存在转换问题)。
  • 接下来,在不关闭我的应用程序的情况下,如果我从 32 位可执行文件中拖动文件,wParam 将具有类似 0x0000000011C000B8 或 0xFFFFFFFF11C000B8 的内容,这意味着高位 32 位无效。
  • 如果我将无效的高位替换为上一条消息中的有效高位(在本例中,这将是 0x000000F2),则 DragQueryFile 可以工作!

所以数据在这里,在某个地方,我只是不知道如何检索它们(至少没有丑陋的黑客)。

Edit 2:

我不会提供任何代码,因为我假设回答者了解这个影响大量软件的问题。

- - - 编辑 - - - - -

重现它的最少代码

LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    WCHAR sz[32];
    switch (uMsg)
    {
    case WM_DROPFILES:
        swprintf(sz, L"%p", wParam);// look for wParam
        MessageBox(0,0,sz,0);
        break;
    case WM_NCCREATE:
        DragAcceptFiles(hwnd, TRUE);
        break;
    case WM_NCDESTROY:
        PostQuitMessage(0);
        break;
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void minimal()
{
    static WNDCLASS wndcls = { 0, WindowProc, 0, 0, 0, 0, 0, 0, 0, L"testwnd" };
    if (RegisterClass(&wndcls))
    {
        if (HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, wndcls.lpszClassName, 0, 
            WS_OVERLAPPEDWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, 0, 0, 0))
        {
            MSG msg;
            while (0 < GetMessage(&msg, 0, 0, 0))
            {
                if (msg.message == WM_DROPFILES)
                {
                    // look for msg.wParam returned by GetMessage
                    WCHAR name[256];
                    DragQueryFile((HDROP)msg.wParam, 0, name, RTL_NUMBER_OF(name));
                }

                DispatchMessage(&msg);
            }
        }
        UnregisterClass(wndcls.lpszClassName, 0);
    }
}

有趣的是,如果调用 DragAcceptFiles(即使只跳转到第一个 it 指令),wParam 的高 32 位将全部为 1。如果不调用它,则通过自行设置 WS_EX_ACCEPTFILES exstyle - wParam 的所有高位将为 0

为了测试可以执行 32 位记事本,打开“打开文件”对话框并将任何文件拖放到我们的窗口中


由于问题已重新提出,我可以发布正确的答案。

这确实是 Windows 的一个错误。在64位进程中,wParam是一个64位值,按原样用于发送“HDROP”,它实际上是一个指向删除文件 https://msdn.microsoft.com/en-us/library/windows/desktop/bb773269(v=vs.85).aspx结构。 测试表明shell使用了整个64位,并将数据写入堆中。 如果从 32 位应用程序中拖动文件,数据仍然会正确写入堆中,即使后者位于 4GB 以上。但尽管如此,在本例中,wParam 被转换为 32 位值,然后符号扩展为 64 位。

事实上,当我们将文件从 32 位应用程序拖到 64 位应用程序时,后者应该会崩溃,因为我们提供了一个错误的指针DragQueryFile()。但事实并非如此,因为DragQueryFile()处理这些异常。

现在,解决方案:

  • Use the 删除目标 https://msdn.microsoft.com/en-us/library/windows/desktop/ms679679(v=vs.85).aspx界面。如果您不关心使用 OLE 并在可执行文件中添加大约 10KB 仅用于读取 RAM 中已有的文件名(这不是我的情况),那么这是一个很好的解决方案(并且由 Microsoft 推荐)。

  • 找到一种方法来检索 wParam 的高位部分。正如所解释的,该值是指向堆的指针。最接近的值由下式给出GlobalAlloc(GMEM_MOVEABLE, 0)。它通常给出 wParam 的值(或者它应该具有的值)+16。即使有时可能稍高,这也足以检索 wParam 缺少的高位 32 位。 为了应对堆与 4GB 边界重叠的不太可能的情况,我们可以尝试向高位 32 位添加或删除 1。 注意GlobalFree()仍然需要。否则,每次调用后都会消耗几个字节(根据我的测试是 16 个字节)GlobalAlloc().

  • 禁用高熵ASLR https://msdn.microsoft.com/en-us/library/dn195771.aspx。此问题需要 Windows 8 或更高版本,这就是为什么此错误很少出现在 Windows 7 及更早版本上。在 Windows 7 上,地址是随机的,但仍低于 4GB 限制。 也就是说,由于符号扩展,您可能仍然需要将高位 32 位清零。而这种解决方案意味着安全性的降低。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 32 位拖放到 64 位 的相关文章

  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • 合并多个表

    我有很多表格描述了我的小公司的不同类型的支出和收益 并且我发现没有简单的方法来合并我的表格 就像我制作的这个例子一样 我希望在更新最后一个表时自动填充其他表的行 这样我就可以及时预见费用和收益 通过按日期升序自动排序绿色表 到目前为止 我发
  • python 中的结构体对象

    我想创建一个一次性的 结构 对象来保留各种状态标志 我的第一个方法是这样的 javascript风格 gt gt gt status object gt gt gt status foo 3 Traceback most recent ca
  • 如何在 Docker-Compose 中一起使用主机网络和任何其他用户定义的网络?

    我想将 Docker Compose 文件中定义的两个 Docker 容器相互连接 app and db 其中之一 app 也应该连接到host网络 容器应连接到通用的用户定义网络 appnet or default 使用嵌入式DNS来自
  • 如何在显示模态表时禁用 Cocoa 的默认动画?

    我想禁用 Cocoa 在显示模式表时执行的动画 Apple s 表编程指南 http developer apple com mac library documentation Cocoa Conceptual Sheets Concept
  • MySQL:什么是页面?

    在 MySQL 数据库的上下文中 我一辈子都不记得页面是什么 当我看到 8KB 页之类的内容时 这是否意味着每行 8KB 还是 数据库页是组织数据库文件中数据的内部基本结构 以下是有关 InnoDB 模型的一些信息 From 13 2 11
  • 使用 Apache Pig 的数据透视表

    我想知道是否可以在 Apache Pig 中一次性旋转一张表 Input Id Column1 Column2 Column3 1 Row11 Row12 Row13 2 Row21 Row22 Row23 Output Id Name V
  • 如何使 gradle processResources 任务更快

    我正在研究 Spring Boot 项目 并且我正在遭受构建时间的困扰 我的项目的 processResources 任务花费的时间太长 如果资源文件是最新的 大约只需要10秒 但如果文件至少更改一个 则需要几分钟的时间 这是因为一个资源库
  • Python 中图外的图例 - matplotlib

    我试图在 matplotlib 中的绘图之外放置一个相当广泛的图例 图例有相当多的条目 每个条目可能很长 但我不知道具体有多长 显然 这很容易使用 legendHandle plt legend loc center left bbox t
  • 使用毕加索库时目标不能为空

    我实现了一个listView使用 Picasso Library 2 4 0 我遇到了一个问题 发生了什么 我使用 Android Studio 启动应用程序 然后转到我实现的特定片段listView 一切看起来都很好 所有图像都正在加载
  • C# asp.net 中的 EVAL

    我将动态内容放置在绑定到对象数据源的数据列表中的内容占位符中 问题是我需要检查 EVAL 的值 这是代码
  • 将 mob() 树(partykit 包)与 nls() 模型结合使用

    我正在尝试使用基于模型的递归分区 MOB mob 函数 从partykit包 来分离使用导出的几条曲线nls 功能 我必须定义我的模型并确定起始值 我一直在尝试看看这是否可以与mob 功能无济于事 我尝试按照第 7 页上的示例进行操作 ht
  • 在 PHP 中显示数组值

    因此 我是第一次使用 PHP 并且尝试检索并显示数组的值 经过大量谷歌搜索后 我能找到的唯一方法是print r var dump or var export 然而 所有这些方法都会返回如下所示的内容 a gt apple b gt ban
  • NLog - 仅在调试时记录

    以这个简单的 NLog 示例配置为例
  • Chrome 更新阻止 Flash 自动播放 - 如何避免?

    我在 html 页面中嵌入了 YouTube 视频 我将 youtube iframe API 与 Flash 结合使用 在我的例子中 我无法使用 HTML5 视频 自上次 Google Chrome 更新以来 Chrome 会阻止自动播放
  • Firefox:drawImage(视频)失败并显示 NS_ERROR_NOT_AVAILABLE:组件不可用

    尝试打电话drawImage with a video其来源是网络摄像头源似乎在 Firefox 中失败了NS ERROR NOT AVAILABLE Component is not available 我尝试等待视频标签触发的每个事件
  • 静态访问 Android 应用程序的资源?

    我有一个问题 Android 应用程序的资源 我的应用程序有杂项 模式 编辑 计划 执行 我想使用枚举类型来描述 但是 我想用源自资源 string xml 文件的字符串填充枚举值 即而不是 enum Mode EDIT edit PLAN
  • Cookie 中缺少安全属性:WL_PERSISTENT_COOKIE 和 testcookie

    在安全扫描结果中 我收到以下错误 WL PERSISTENT COOKIE 和 testcookie 的 加密会话 SSL Cookie 中缺少安全属性 我不知道如何为这些 cookie 设置安全属性 从 websphere 服务器它只允许
  • 枚举DataFlow脚本组件中的RecordSet作为数据源

    这是一个 SSIS 相关问题 我有一个设置为对象类型的变量 一个数据流将一些过滤的行导入到记录集中 并且该记录集存储在对象变量中 在完全独立的数据流中 我需要使用该记录集作为源 所以我创建了一个脚本组件并告诉它它将是一个数据源 我将其设置为
  • 将本地脚本文件添加到 EJS 视图

    我有一个 Node Express EJS 应用程序 它有一个用于视图的文件夹和另一个用于客户端文件的文件夹 后者有另一个 javascript 文件夹 其中有一个名为 frontend js 的文件 我想在此视图中加载 jQuery 和
  • 从 32 位拖放到 64 位

    我正在编写一个接受文件拖放的 C 程序 当它以 32 位编译时 它在任何情况下都可以工作 但当它以 64 位编译时 它仅适用于从 64 位应用程序拖动的文件 32 位 gt 32 位 成功 64 位 gt 64 位 成功 64 位 gt 3