经过近半个月的全力开发,这个小工具终于完成了,整个开发过程基本都是一步步摸索着走过来的,现在就把我开发过程所积累的一点点经验做一下总结。
开发环境为VPC2007虚机,所装系统软件为Win2003+AD,数据库使用SQL2005,其他应用软件有MOSS2007和OFFICE2007等,当然,RMS 1.0 SP2的客户端、服务器端是必不可少的。
值得注意的是,在安装配置完RMS的服务器端之后,需要把机器名称添加到Certification和Licensing目录文件的访问列表中,否则可能会出现拒绝访问的情况。如下图:
至于MOSS2007、RMS1.0 SP2的安装过程已经有很多人介绍过了,这里就不罗嗦了,如有需要,可以在网上查找相关资料。
系统安装完成后请确认是否能够通过IE正常访问该Web Services。在计算机管理中( 开始 -> 运行 -> compmgmt.msc)的事件查看器中查看有无RMS相关的错误日志。在IIS管理器中打开RMS管理站点,查看虚拟路径Certification和Licensing目录中的Web Services是否都能正常显示,最好使用站点名称而不是以Localhost方式访问这两个目录进行验证。
本工具的开发工具为VS2008,开发语言VC++,程序类型为命令行(控制台)程序,使用标准Windows 库(None MFC)。
如果需要详细了解生产环境和开发环境之间的切换,请参考MSDN,下面就把重点步骤简要列举一下。
1) 更改注册表,请根据自身情况替换黑体字部分的内容,如下:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DRMS\1.0] "GC"="xxxxxxxxxx.xxxxx.com" "GICURL"="http://xxxxxxxxxx.xxxxx.com:xxxx/_wmcs/certification/certification.asmx" "UddiProvider"="0e3d9bb8-b765-4a68-a329-51548685fed3"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\udrm] "Hierarchy"=dword:00000001
|
第一段注册表内容为切换服务器端到Pre-Production环境,第二段为客户端切换到Pre-Production环境,其中Hierarchy=1表示Pre-Production,Hierarchy=0表示Production环境。
2) 到如下地址注册Pre-Production环境的RMS服务器:
https://activation.isv.drm.microsoft.com/OfflineEnroll/Enrollment.aspx
3) 清除Production环境下的所有计算机和用户认证证书,脚本如下:
@echo off del /q /f /s "%ALLUSERSPROFILE%\Application Data\Microsoft\DRM\Server\*.*" del /q /f "%USERPROFILE%\Application Data\Microsoft\DRM\*.*" del /q /f "%USERPROFILE%\Local Settings\Application Data\Microsoft\DRM\*.*" del /q /f "%SYSTEMROOT%\system32\secrep.dll" del /q /f "%SYSTEMROOT%\system32\secure*.sst" attrib -h -s "%SYSTEMROOT%\system32\clockfile.drm" del /q /f "%SYSTEMROOT%\system32\clockfile.drm"
|
4) 使用 Rmactivate_isv.exe 激活计算机,获取认证证书。
由于MOSS2007、OFFICE2007等应用程序默认是处于生产环境中运行,把RMS迁移到开发环境后,会造成上述程序无法正常使用IRM功能,所以也要做相应的迁移,由于脚本较大,就不在这里浪费篇幅了。
1) 确认用于认证加密的公\私钥键值对的位置,默认在RMS安装目录的BIN目录下。
2) 制作用于生成应用程序清单文件的描述文件(.MCF)
3) 制作生成应用程序清单文件的脚步文件(.BAT),该脚本在程序编译成功后的事件中自动执行
实际具体步骤以MSDN为主,这里只做简要描述。
加密前,WordDocument节点存储Word文档内容,加密后,内容存储在DRMContent节点中。该节是的生成需要自定义一个IStroage\IStream对象,然后把该对象插入该节中,其后的各种操作都是通过OLE方式调用该对象,读写需要调用RMS所提供的加解密函数进行解析。
关于权限问题,由于目前没有任何其他资料能够详细介绍,所以这里就多说两句。
ADRMS内置的权限只有三种,分别是EDIT, OWNER, 和 VIEWRIGHTSDATA,其他所有权限都是消费程序(Consuming Application)自定义的,比如OFFICE系统。
本工具实现了Word文档的XrML权限的只读、打印、复制、完全控制等功能,代码示例如下:
switch( irmRightType ) { // // 取得XrML 权限映射 // case FILE_IRM_RIGHT_TYPE_WRITE: // 写权限,可复制、可打印、可编程访问 *pwszRightList = new PWCHAR[7]; (PWCHAR)(*pwszRightList)[0] = L"VIEW"; (PWCHAR)(*pwszRightList)[1] = L"EXPORT"; (PWCHAR)(*pwszRightList)[2] = L"PRINT"; (PWCHAR)(*pwszRightList)[3] = L"EXTRACT"; (PWCHAR)(*pwszRightList)[4] = L"OBJMODEL"; (PWCHAR)(*pwszRightList)[5] = L"DOCEDIT"; (PWCHAR)(*pwszRightList)[6] = L"EDIT"; break; case FILE_IRM_RIGHT_TYPE_ALLCONTROL: // 完全控制,可进行再授权、可编程访问 *pwszRightList = new PWCHAR[11]; (PWCHAR)(*pwszRightList)[0] = L"EXPORT"; (PWCHAR)(*pwszRightList)[1] = L"PRINT"; (PWCHAR)(*pwszRightList)[2] = L"EXTRACT"; (PWCHAR)(*pwszRightList)[3] = L"DOCEDIT"; (PWCHAR)(*pwszRightList)[4] = L"OBJMODEL"; (PWCHAR)(*pwszRightList)[5] = L"FORWARD"; (PWCHAR)(*pwszRightList)[6] = L"REPLY"; (PWCHAR)(*pwszRightList)[7] = L"REPLYALL"; (PWCHAR)(*pwszRightList)[8] = L"OWNER"; (PWCHAR)(*pwszRightList)[9] = L"VIEWRIGHTSDATA"; (PWCHAR)(*pwszRightList)[10]= L"EDIT"; break; case FILE_IRM_RIGHT_TYPE_READPRINT: // 只读可打印、可编程访问 *pwszRightList = new PWCHAR[3]; (PWCHAR)(*pwszRightList)[0] = L"PRINT"; (PWCHAR)(*pwszRightList)[1] = L"OBJMODEL"; (PWCHAR)(*pwszRightList)[2] = L"VIEW"; break; case FILE_IRM_RIGHT_TYPE_READCOPY: // 只读可复制、可编程访问 *pwszRightList = new PWCHAR[4]; (PWCHAR)(*pwszRightList)[0] = L"EXPORT"; (PWCHAR)(*pwszRightList)[1] = L"EXTRACT"; (PWCHAR)(*pwszRightList)[2] = L"OBJMODEL"; (PWCHAR)(*pwszRightList)[3] = L"VIEW"; break; case FILE_IRM_RIGHT_TYPE_READCOPYPRINT: // 只读可复制打印、可编程访问 *pwszRightList = new PWCHAR[5]; (PWCHAR)(*pwszRightList)[0] = L"EXPORT"; (PWCHAR)(*pwszRightList)[1] = L"EXTRACT"; (PWCHAR)(*pwszRightList)[2] = L"OBJMODEL"; (PWCHAR)(*pwszRightList)[3] = L"VIEW"; (PWCHAR)(*pwszRightList)[4] = L"PRINT"; break; case FILE_IRM_RIGHT_TYPE_READ: // 只读、可编程访问 default: *pwszRightList = new PWCHAR[2]; (PWCHAR)(*pwszRightList)[0] = L"VIEW"; (PWCHAR)(*pwszRightList)[1] = L"OBJMODEL"; break; } |
软件开发的工作流程就不详细介绍了,这里引用MSDN里的两幅图,来表示开发RMS消费程序和发布程序的先后调用顺序。
下图为消费程序的开发顺序:
下图为发布程序的开发顺序:
RMS程序调试起来比较麻烦,因为应用程序在调用密码箱时,只要存在调试工具(Debugger),一定会导致调用失败。在SDK中介绍了一个微软提供的工具叫LCP,他起到一个代理的作用,该代理本身无断点、未加载调试工具,所以在程序中设置断点,不会触发密码箱的调试检查。
我没有研究过LCP,只有函数DRMInitEnvironment会调用密码箱,所以先调试完该函数之前的代码,然后在函数之后加上一行 _getch() ; 这样就会在调用完成后等待用户输入,此时附加调试器就可以调试该函数后面的代码了。
使用RMS SDK中提供的公私钥键值对只能生成开发环境中的程序,一拿到正常环境(生产环境)中立即歇菜,所以要想发布程序,需要首先生成自己的键值对,然后把公钥发给微软注册,然后才能进行发布。
希望这篇文章能对新上手开发的RMS应用程序的开发者多一点帮助,少走一点弯路。