从 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 位 的相关文章

  • VSTS 构建失败/发布无法在 bin 文件夹中找到 roslyn\csc.exe

    我们有一个网站项目 安装了以下 nuget 软件包 Microsoft CodeDom Providers DotNetCompilerPlatform 1 0 8 Microsoft Net Compilers 2 4 0 The web
  • MVC Core IActionResult 含义

    什么是IActionResult 我尝试查看 MSDN 和其他网站 但需要通用 常见 易于理解的答案 MSDN IActionResult https learn microsoft com en us dotnet api microso
  • CMake 和 Visual Studio:如何获得快速、安静的命令行构建?

    我有一个 cmake 项目 它成功地完成了我想要的一切 但我有大约 100 个文件 当我只需要重新编译一个文件时 我厌倦了每次看到生成的巨大输出 每个文件 30 行 明确地说 我正在编译cmake build 得到这个结果 我需要传递给编译
  • C 中的复合语句表达式

    下面的代码不起作用 int i void 999 100 添加括号就可以了 为什么 int i void 999 100 还有另一种方法可以完成此类分配 int i void 999 100 是什么让他们与众不同 在这份声明中 int i
  • 将指针转换为浮点数?

    我有一个unsigned char 通常 这指向一块数据 但在某些情况下 指针就是数据 即 铸造一个int的价值unsigned char 指针 unsigned char intData unsigned char myInteger 反
  • C++ 中的单例和抽象基类

    最近我遇到了关于实现 Singleton 但涉及抽象基类的问题 假设我们有这样的类层次结构 class IFoo it s ABC class Foo public IFoo 我们的单例类定义如下 template
  • 将列表(对象)转换为列表(字符串)

    有没有办法转换List of Object to a List of String 在 c 或 vb net 中而不迭代所有项目 幕后迭代很好 我只想要简洁的代码 Update 最好的方法可能就是进行新的选择 myList Select f
  • 有没有办法使 C90 标准中的枚举无符号? (符合 MISRA-C 2004 标准)

    我正在尝试找到一种使枚举 无符号 的方法 enum x1 0 x2 x3 uint8 t x2 lt PC LINT MISRA C 2004 will complain about mixing signed and unsigned h
  • Azure 2012 年 10 月 SDK 损坏 UseDevelopmentStorage=true

    有人尝试过使用 usedevelopmentstorage true 连接字符串的 2012 年 10 月 Azure sdk 吗 CloudStorageAccount Parse UseDevelopmentStorage true 抛
  • 控制器中的异常处理 (ASP.NET MVC)

    当您自己的代码抛出异常并从控制器中的操作调用时 应该如何处理 我看到很多最佳实践的例子 其中根本没有 try catch 语句 例如 从存储库访问数据 public ViewResult Index IList
  • 如何防止字符串被截留

    我的理解 可能是错误的 是 在 C 中 当你创建一个字符串时 它会被实习到 实习生池 中 这保留了对字符串的引用 以便多个相同的字符串可以共享操作内存 但是 我正在处理很多很可能是唯一的字符串 一旦完成每个字符串 我需要将它们从操作内存中完
  • 替换 JSON 中的转义字符

    我想用空格替换 JSON 字符串中的 字符 我怎样才能做到这一点 我发现从 JSON 字符串中删除所有转义字符的最简单 最好的方法是将字符串传递到正则表达式 Unescape 方法 此方法返回一个没有转义字符的新字符串 甚至删除了 n t
  • 获取给定EntityType的导航属性

    我在用VS2010 EF4 0 需要如下功能 private string GetNaviProps Type entityType eg typeof Employee NorthwindEntities en new Northwind
  • 如何用C++解析复杂的字符串?

    我试图弄清楚如何使用 解析这个字符串sstream 和C 其格式为 string int int 我需要能够将包含 IP 地址的字符串的第一部分分配给 std string 以下是该字符串的示例 std string 127 0 0 1 1
  • .Net Core 中的脚手架以及解决方案中的多个项目

    我创建了一个针对 net461 的 Net Core MVC6 应用程序 我使用了一个我非常熟悉的项目结构 其中我将数据 模型和服务类放置在单独的类库项目中 并且 Web 项目引用这些项目 当我尝试搭建控制器时 我收到一条错误 指出我正在搭
  • 使用互斥锁来阻止临界区外部的执行

    我不确定我的术语是否正确 但这里是 我有一个由多个线程使用的函数来写入数据 在注释中使用伪代码来说明我想要的内容 these are initiated in the constructor int data std atomic
  • C 中的 N 依赖注入 - 比链接器定义的数组更好的方法?

    Given a 库模块 在下文中称为Runner 它作为可重复使用的组件 无需重新编译 即静态链接库 中应用程序分区架构的 而不是主分区 请注意 它仅包含main 出于演示目的 Given a set 顺序无关 调用的其他模块 对象Call
  • win32 API 和 .NET 框架之间的选择

    我必须开发一个适用于 Windows 的应用程序 该应用程序将能够通过网络摄像头识别手势来控制鼠标 我将使用 vc 2008 进行开发 但我很困惑是使用 NET 框架还是核心 win32 API 性能对于我的应用程序非常重要 根据 Ivor
  • 在代码中而不是 XAML 中呈现 UserControl

    我想用RenderTargetBitmap将 UserControl 呈现为位图 而无需为其编写 XAML 当我这样做时 我得到一张空白图像 我是否错过了关键的一步 ValTool Controls VideoFisheyeOverlayC
  • 如何向 ItemsControl 中的 WPF 按钮添加相同的命令

    如何将命令添加到 wpf 按钮 该按钮是ItemsControl并正在修改ItemsSource itself 这是我的 XAML

随机推荐

  • 合并多个表

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