开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 254|回复: 5
收起左侧

[求助] 易语言调用 CryptProtectData 始终失败,错误码 126,动态调用...

[复制链接]
结帖率:0% (0/5)
发表于 2026-4-17 00:30:01 | 显示全部楼层 |阅读模式   河南省郑州市
5精币
各位大神好,我在开发一个 Windows 工具,需要使用 DPAPI 加密一些用户数据。核心是调用 crypt32.dll 中的 CryptProtectData 函数。但无论怎么尝试,在易语言中都无法成功调用,具体情况如下:

一、环境说明
  • 操作系统:Windows 10 64位
  • 易语言版本:5.9
  • 已引用精易模块 11.1.5
  • 使用 Python 的 win32crypt.CryptProtectData 测试相同参数调用完全正常,说明系统 DPAPI 服务无问题。


二、已尝试的方案及结果方案1:静态声明 DLL 命令[size=12.573px]basic



.DLL命令 CryptProtectData, 逻辑型, "crypt32.dll", "CryptProtectData"    .参数 pDataIn, 整数型, 传址    .参数 szDataDescr, 文本型    .参数 pOptionalEntropy, 整数型, 传址    .参数 pvReserved, 整数型    .参数 pPromptStruct, 整数型    .参数 dwFlags, 整数型    .参数 pDataOut, 整数型, 传址

调用后返回假,GetLastError() 返回 126(ERROR_MOD_NOT_FOUND)。
方案2:将加密封装成独立 .ec 模块
主程序通过引用模块调用,模块内部同样静态声明 DLL,错误码依旧 126。
方案3:动态加载 DLL(LoadLibrary + GetProcAddress + 汇编传参)
使用 LoadLibraryA("crypt32.dll") 成功获取模块句柄,GetProcAddress 成功获取函数地址,但通过汇编 call 调用时,程序直接闪退(调试模式下崩溃,编译后同样崩溃)。
方案4:尝试使用精易模块的 CryptBin 命令
我的精易模块版本(11.1.5)中未找到该命令。
方案5:将输出结构体 DATA_BLOB 的 cbData 和 pbData 初始化为 0
错误依旧 126。

三、核心代码片段
数据类型定义:
[size=12.573px]basic



.数据类型 DATA_BLOB    .成员 cbData, 整数型    .成员 pbData, 整数型

调用代码(简化版):
[size=12.573px]basic



.子程序 DPAPI_加密, 字节集.参数 待加密数据, 字节集.参数 描述文本, 文本型.参数 附加熵, 字节集.局部变量 stIn, DATA_BLOB.局部变量 stEntropy, DATA_BLOB.局部变量 stOut, DATA_BLOB.局部变量 成功, 逻辑型stIn.cbData = 取字节集长度 (待加密数据)stIn.pbData = 取变量数据地址 (待加密数据)stEntropy.cbData = 取字节集长度 (附加熵)stEntropy.pbData = 取变量数据地址 (附加熵)stOut.cbData = 0stOut.pbData = 0成功 = CryptProtectData (取变量地址 (stIn), 描述文本, 取变量地址 (stEntropy), 0, 0, 1, 取变量地址 (stOut)).如果真 (成功 = 假)    调试输出 (GetLastError())  ' 输出 126    返回 ({ }).如果真结束' 读取结果并释放...

动态调用汇编部分(闪退):
[size=12.573px]basic



置入代码 ({ 86, 87, 139, 125, 12, 139, 77, 16, 139, 85, 20, 139, 93, 24, 139, 109, 28, 139, 101, 32, 139, 117, 36, 255, 85, 8, 95, 94, 201, 194, 28, 0 })


四、求助问题
  • 错误码 126 在易语言中的根本原因是什么? Python 能正常调用,说明 DLL 存在且路径正确,为何易语言总是报找不到模块?
  • 动态调用时程序闪退的可能原因? 是堆栈不平衡还是参数传递方式有误?求一份稳定可用的动态调用 DPAPI 的易语言源码
  • 是否有其他纯易语言方案可以实现 DPAPI 加密?(例如利用精易模块的其他隐藏命令,或者使用 COM 对象)


五、备注
  • 我坚持使用纯易语言方案,不希望依赖外部脚本。
  • 如果有成功调用过 CryptProtectData 的大神,希望能指点迷津,感激不尽!



求助知识:请将问题描述清楚,最好把你有问题的源码打包上传上来,这样更方便大家帮助你。
友情提醒:本版被采纳的主题可在 申请荣誉值 帖子申请荣誉值,获得 3点 荣誉值,荣誉值可兑换荣誉会员、终身vip用户组。

结帖率:100% (11/11)

签到天数: 26 天

发表于 2026-4-17 07:02:05 | 显示全部楼层   浙江省嘉兴市
你帖子格式全乱, 看的头大,  测试代码还自己手动一个个修复  直接发源码不行吗?
2.e (4.19 KB, 下载次数: 9)
回复

使用道具 举报

结帖率:0% (0/5)

签到天数: 1 天

 楼主| 发表于 2026-4-17 10:12:26 | 显示全部楼层   河南省郑州市
qq793359277 发表于 2026-4-17 07:02
你帖子格式全乱, 看的头大,  测试代码还自己手动一个个修复  直接发源码不行吗?

...

易语言调用 crypt32.dll 的 CryptProtectData,静态声明和动态加载都试了,始终返回错误码 126。Python 调用正常,说明系统环境没问题。

求一份易语言可用的 DPAPI 加密源码,能直接跑通就行,多谢!

附上我当前的测试代码:.版本 2

.数据类型 DATA_BLOB
    .成员 cbData, 整数型
    .成员 pbData, 整数型

.DLL命令 CryptProtectData, 逻辑型, "crypt32.dll", "CryptProtectData"
    .参数 pDataIn, 整数型, 传址
    .参数 szDataDescr, 文本型
    .参数 pOptionalEntropy, 整数型, 传址
    .参数 pvReserved, 整数型
    .参数 pPromptStruct, 整数型
    .参数 dwFlags, 整数型
    .参数 pDataOut, 整数型, 传址

.DLL命令 LocalFree, 整数型, "kernel32.dll", "LocalFree"
    .参数 hMem, 整数型

.子程序 DPAPI_加密, 字节集
.参数 数据, 字节集
.参数 描述, 文本型
.参数 熵, 字节集
.局部变量 stIn, DATA_BLOB
.局部变量 stEntropy, DATA_BLOB
.局部变量 stOut, DATA_BLOB

stIn.cbData = 取字节集长度 (数据)
stIn.pbData = 取变量数据地址 (数据)

.如果真 (取字节集长度 (熵) > 0)
    stEntropy.cbData = 取字节集长度 (熵)
    stEntropy.pbData = 取变量数据地址 (熵)
.如果真结束

stOut.cbData = 0
stOut.pbData = 0

.如果 (CryptProtectData (取变量地址 (stIn), 描述, 取变量地址 (stEntropy), 0, 0, 1, 取变量地址 (stOut)) = 假)
    输出调试文本 (“加密失败,错误码:” + 到文本 (GetLastError()))
    返回 ({ })
.否则
    返回 (指针到字节集 (stOut.pbData, stOut.cbData))
    LocalFree (stOut.pbData)
.如果结束
回复

使用道具 举报

结帖率:0% (0/5)

签到天数: 1 天

 楼主| 发表于 2026-4-17 10:24:24 | 显示全部楼层   河南省郑州市
qq793359277 发表于 2026-4-17 07:02
你帖子格式全乱, 看的头大,  测试代码还自己手动一个个修复  直接发源码不行吗?

...

大佬好,我在易语言中调用 crypt32.dll 的 CryptProtectData 函数,单独新建工程测试成功,但整合到主程序后编译报错:

text
错误(10003): 指定Dll命令名称“CryptProtectData”未找到。
主程序引用了精易模块。DLL 声明如下:

basic
.数据类型 DATA_BLOB
    .成员 cbData, 整数型
    .成员 pbData, 整数型

.DLL命令 CryptProtectData, 逻辑型, "crypt32.dll", "CryptProtectData"
    .参数 pDataIn, DATA_BLOB
    .参数 szDataDescr, 整数型
    .参数 pOptionalEntropy, DATA_BLOB
    .参数 pvReserved, 整数型
    .参数 pPromptStruct, 整数型
    .参数 dwFlags, 整数型
    .参数 pDataOut, DATA_BLOB
调用方式(描述文本已转 UTF-16 宽字节):

basic
.如果 (CryptProtectData (stIn, 取变量数据地址 (宽描述), stEntropy, 0, 0, 1, stOut) = 假)
尝试过的方法:

将 DLL 命令改名并加别名 → 依旧 10003。

在 DLL 命令表首位添加占位空命令 → 依旧 10003。

请问这是精易模块内部冲突导致的吗?除了动态调用(LoadLibrary + GetProcAddress)外,是否有更简洁的解决办法?如果只能动态调用,能否提供一份稳定可用的汇编传参代码?

多谢!
回复

使用道具 举报

结帖率:0% (0/5)

签到天数: 1 天

 楼主| 发表于 2026-4-17 10:25:53 | 显示全部楼层   河南省郑州市
qq793359277 发表于 2026-4-17 07:02
你帖子格式全乱, 看的头大,  测试代码还自己手动一个个修复  直接发源码不行吗?

...

大佬好,我在易语言中调用 crypt32.dll 的 CryptProtectData 函数,单独新建工程测试成功,但整合到主程序后编译报错:

text
错误(10003): 指定Dll命令名称“CryptProtectData”未找到。
主程序引用了精易模块。DLL 声明如下:

basic
.数据类型 DATA_BLOB
    .成员 cbData, 整数型
    .成员 pbData, 整数型

.DLL命令 CryptProtectData, 逻辑型, "crypt32.dll", "CryptProtectData"
    .参数 pDataIn, DATA_BLOB
    .参数 szDataDescr, 整数型
    .参数 pOptionalEntropy, DATA_BLOB
    .参数 pvReserved, 整数型
    .参数 pPromptStruct, 整数型
    .参数 dwFlags, 整数型
    .参数 pDataOut, DATA_BLOB
调用方式(描述文本已转 UTF-16 宽字节):

basic
.如果 (CryptProtectData (stIn, 取变量数据地址 (宽描述), stEntropy, 0, 0, 1, stOut) = 假)
尝试过的方法:

将 DLL 命令改名并加别名 → 依旧 10003。

在 DLL 命令表首位添加占位空命令 → 依旧 10003。

请问这是精易模块内部冲突导致的吗?除了动态调用(LoadLibrary + GetProcAddress)外,是否有更简洁的解决办法?如果只能动态调用,能否提供一份稳定可用的汇编传参代码?

多谢!
回复

使用道具 举报

结帖率:100% (53/53)

签到天数: 25 天

发表于 2026-4-17 10:58:34 | 显示全部楼层   福建省宁德市
易语言API调用返回126错误,因为易语言首次调用API时,它要加载这个API的DLL,最后错误码就是在加载DLL时遗留的,API调用成功时通常是不会设置最后错误码的,所以当前线程的错误码还是126。调试的时候会有这个问题的,编译出来后最后错误码就正常了。
你直接看返回值就可以了,返回真就是成功了

  
字节集 = 加密字节集 (到字节集 (“123”), 到字节集 (“321”))
字节集 = 解密字节集 (字节集, 到字节集 (“321”))
调试输出 (字节集)
子程序名返回值类型公开备 注
加密字节集字节集 使用CryptProtectData函数加密一段数据,成功返回加密后的数据,失败返回空字节集。
参数名类 型参考可空数组备 注
数据字节集
密码字节集空字节集无密码
选项整数型0=与当前用户绑定;4=与当前计算机绑定。
变量名类 型静态数组备 注
数据地址整数型 
数据长度整数型 
数据结构整数型 
密码地址整数型 
密码长度整数型 
密码结构整数型 
字节集字节集 
数据地址 = 取变量数据地址 (数据)
如果真 (数据地址 ≠ 0)
数据长度 = 取字节集长度 (数据)
数据结构 = 取变量地址 (数据长度)
密码地址 = 取变量数据地址 (密码)
密码长度 = 取字节集长度 (密码)
如果真 (密码长度 ≠ 0)
密码结构 = 取变量地址 (密码长度)

如果真 (CryptProtectData (数据结构, 0, 密码结构, 0, 0, 选项, 取变量地址 (密码长度)))
字节集 = 指针到字节集 (密码地址, 密码长度)
LocalFree (密码地址)

返回 (字节集)
子程序名返回值类型公开备 注
解密字节集字节集 成功返回解密后的字节集,失败返回空字节集。
参数名类 型参考可空数组备 注
数据字节集
密码字节集空字节集无密码
选项整数型与加密字节集时填写的一致
变量名类 型静态数组备 注
数据地址整数型 
数据长度整数型 
数据结构整数型 
密码地址整数型 
密码长度整数型 
密码结构整数型 
字节集字节集 
数据地址 = 取变量数据地址 (数据)
如果真 (数据地址 ≠ 0)
数据长度 = 取字节集长度 (数据)
数据结构 = 取变量地址 (数据长度)
密码地址 = 取变量数据地址 (密码)
密码长度 = 取字节集长度 (密码)
如果真 (密码长度 ≠ 0)
密码结构 = 取变量地址 (密码长度)
如果真 (CryptUnprotectData (数据结构, 0, 密码结构, 0, 0, 选项, 取变量地址 (密码长度)))
字节集 = 指针到字节集 (密码地址, 密码长度)
LocalFree (密码地址)

返回 (字节集)


i支持库列表   支持库注释   
spec特殊功能支持库
  
DLL命令名返回值类型公开备 注
CryptProtectData逻辑型 
DLL库文件名:
Crypt32
在DLL库中对应命令名:
CryptProtectData
参数名类 型传址数组备 注
加密文本整数型指向要加密的纯文本的DATA_BLOB结构
说明文本整数型可以为NULL
附加信息整数型指向加密文本的密码或其它附加信息,如果加密截断提供解密阶段也必须提供。可以为NULL。DATA_BLOB结构
保留整数型保留参数,必须为NULL
提示结构整数型通常为null。_CRYPTPROTECT_PROMPTSTRUCT 结构
选项整数型0=绑定当前用户;4=绑定计算机;其他值百du;
返回数据整数型返回的是DATA_BLOB结构,数据长度、数据地址。用完需要释放数据地址
DLL命令名返回值类型公开备 注
CryptUnprotectData逻辑型 
DLL库文件名:
Crypt32
在DLL库中对应命令名:
CryptUnprotectData
参数名类 型传址数组备 注
解密文本整数型指向解密的DATA_BLOB结构
说明文本整数型可以为NULL
附加信息整数型指向加密文本的密码或其它附加信息,如果加密截断提供解密阶段也必须提供。可以为NULL。DATA_BLOB结构
保留整数型
提示结构整数型
选项整数型
返回数据整数型返回的是DATA_BLOB结构,数据长度、数据地址。用完需要释放数据地址
DLL命令名返回值类型公开备 注
LocalFree整数型 
DLL库文件名:
kernel32
在DLL库中对应命令名:
LocalFree
参数名类 型传址数组备 注
hMem整数型





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表