1 /*
2 * main.cpp
3 *
4 * Created on: Aug 17, 2015
5 * Author: smallcroco
6 *
7 * Discription:
8 * 1 首先打开解压包,可以设置打开方式,获得句柄;
9 * RAROpenArchive函数,需要RAROpenArchiveData结构体
10 * 或者
11 * RAROpenArchiveEx函数,需要RAROpenArchiveDataEx结构体
12 *
13 * 2 然后设置回调函数;
14 * RARSetCallback函数,需要设置回调函数
15 *
16 * 3 读取文件头,并判断是否解压完成;
17 * RARReader函数,需要RARHeaderData结构体
18 * 或者
19 * RARReaderEx函数,需要RARHeaderDataEx结构体
20 *
21 * 4 跳到下一个文件;
22 * RARProcessFile函数
23 * 或者
24 * RARProcessFileW函数
25 *
26 * 5 关闭句柄;
27 * RARCloseArchive函数
28 */
29
30 #include <cstdio>
31
32 #define _UNIX
33
34 #include <string.h>
35 #include <iostream>
36
37 #include "dll.hpp"
38
39 using namespace std;
40
41 typedef int function(unsigned int msg, long int UserData, long int P1,
42 long int P2);
43
44 int main() {
45
46 cout<<"请输入解压模式:"<<endl;
47 cout<<"读取文件头不解压,输入:1"<<endl;
48 cout<<"解压文件,输入:2"<<endl;
49
50 long Mode;
51 cin>>Mode;
52
53 // 打开压缩包
54 RAROpenArchiveData ArchiveData;
55 memset(&ArchiveData, 0, sizeof(RAROpenArchiveData));
56 char name[] = "./testRar/test.rar";
57 ArchiveData.ArcName = name;
58
59 // 打开模式:RAR_OM_LIST或RAR_OM_EXTRACT
60 // RAR_OM_LIST 只读取文件头,获取一些文件信息,而不解压文件
61 // RAR_OM_EXTRACT 为检测或者解压缩而打开压缩包
62 if (Mode == 1) {
63 ArchiveData.OpenMode = RAR_OM_LIST;
64 } else if (Mode == 2){
65 ArchiveData.OpenMode = RAR_OM_EXTRACT;
66 }
67
68 // 输出结果:
69 // 0成功
70 // ERAR_NO_MEMORY 内存不足,无法初始化数据结构
71 // ERAR_BAD_DATA 压缩包头损坏
72 // ERAR_BAD_ARCHIVE 不是有效的Rar压缩包
73 // ERAR_UNKNOWN_FORMAT 无法识别的压缩方式
74 // ERAR_EOPEN 压缩包打开错误
75 ArchiveData.OpenResult = 0;
76 // 设置存放注释缓冲区,最大不能超过64KB;设为null表示不读取注释
77 ArchiveData.CmtBuf = NULL;
78 // 设置缓冲区大小
79 ArchiveData.CmtBufSize = 0;
80 // 实际读取到的注释大小
81 ArchiveData.CmtSize = 0;
82 // 输出注释状态:
83 // 0 注释不存在
84 // 1 注释读取完毕
85 // ERAR_NO_MEMORY 内存不足
86 // ERAR_BAD_DATA 注释损坏
87 // ERAR_UNKNOWN_FORMAT 注释格式无效
88 // ERAR_SMALL_BUF 缓冲区过小
89 ArchiveData.CmtState = 0;
90
91 HANDLE handle = RAROpenArchive(&ArchiveData);
92 if (ArchiveData.OpenResult != 0) {
93 cout << "解压出错" << endl;
94 return -1;
95 }
96
97 // 设置回调函数
98 RARSetCallback(handle, function, Mode);
99
100
101 RARHeaderData headerdata;
102 int RHCode;
103 while ((RHCode = RARReadHeader(handle, &headerdata)) == 0) {
104
105 if (Mode == 1) {
106 cout << "解压:" << headerdata.FileName << endl;
107
108 // 第一个参数:句柄
109 // 第二个参数:路转方式
110 // 第三个参数:文件解压路径不带文件名,NULL表示当前路径;这个参数只有在DestName为NULL时才有效
111 // 第四个参数:文件解压路径带文件名,当第三个参数和第个参数同时设置时,以第四个参数为准
112 int PFCode = RARProcessFile(handle, RAR_EXTRACT, NULL, NULL);
113 if (PFCode != 0) {
114 cout << "解压出错" << endl;
115 break;
116 }
117 }
118
119 if (Mode == 2) {
120 cout << "测试:" << headerdata.FileName << endl;
121 int PFCode = RARProcessFile(handle, RAR_TEST, NULL, NULL);
122 if (PFCode != 0) {
123 cout << "解压出错" << endl;
124 break;
125 }
126 }
127 }
128
129 if (RHCode == ERAR_BAD_DATA) {
130 cout << "File Header broken" << endl;
131 }
132
133 RARCloseArchive(handle);
134
135 return 0;
136
137 }
138
139 // 回调函数
140 int function(unsigned int msg, long int UserData, long int P1, long int P2) {
141
142 switch (msg) {
143
144 // 表示解压多个卷的压缩包
145 case UCM_CHANGEVOLUME: {
146
147 // 如果P2为RAR_VOL_ASK,则表示需要的一个卷找不到,例如几个分卷不在同一文件夹下
148 // 需要的卷名称为P1指向的字符串。
149 // 此时有两种解决办法,一种是把需要的卷路径(带卷名称)赋值给P1,然后返回一个非负数,解压继续
150 // 另一种办法就是直接返回-1,终止解压过程
151 if (P2 == RAR_VOL_ASK) {
152 cout << "\n\nVolume " << (char*) P1 << "is required\n"
153 << "Possible options:\n" << endl;
154 cout << "\nEnter - try again" << endl;
155 cout << "'R' -specify a new volume name" << endl;
156 cout << "'Q' -quit" << endl;
157 cout << "Enter your choice:" << endl;
158
159 switch (getchar()) {
160 case 'Q':
161 return -1;
162 case 'R': {
163 cin >> (char*) P1;
164 return 0;
165 }
166 default:
167 return 0;
168 }
169 return 0;
170 }
171
172 // 如果P2为RAR_VOL_NOTIFY则表示,需要的卷找到了,正常打开了,P1指向的就是另一个卷的名称,此时不能修改P1的值
173 // 此时也有两种操作:
174 // 一种是直接返回非负数,继续解压过程
175 // 另一种是返回-1,终止解压过程
176 if (P2 == RAR_VOL_NOTIFY) {
177 cout << "\n... volume\n" << (char*) P1 << endl;
178 return 0;
179 }
180 return 0;
181 }
182
183 // 正常的解压过程
184 // P1指向解压数据的地址
185 // P2解压数据的大小
186 case UCM_PROCESSDATA: {
187 return 0;
188 }
189
190 // 需要密码才能解压
191 // P1指向密码缓冲区地址
192 // P2缓冲区大小
193 case UCM_NEEDPASSWORD: {
194 cin >> (char*) P1;
195 P2 = strlen((char*) P1);
196 return 0;
197 }
198 }
199 }