commit e68133f71fe0b8c6741edb53f413f90e2f3e6690 Author: gb <741021719@qq.com> Date: Wed May 4 11:09:23 2022 +0800 initialize diff --git a/docs/G100-G200.txt b/docs/G100-G200.txt new file mode 100644 index 0000000..293182f --- /dev/null +++ b/docs/G100-G200.txt @@ -0,0 +1,526 @@ +{ + "device_type": "G100", + "option_count": 47, + "1": { + "category": "base", + "name": "cfg-1", + "title": "恢复默认设置", + "desc": "恢复默认设置", + "type": "button", + "cur": "button", + "default": "button", + "size": 0 + }, + "2": { + "category": "advanced", + "name": "cfg-2", + "title": "帮助", + "desc": "显示软件帮助文档", + "type": "button", + "cur": "true", + "default": "true", + "size": 4 + }, + "3": { + "category": "base", + "name": "grp-1", + "title": "基本设置", + "type": "group" + }, + "4": { + "category": "base", + "name": "cfg-4", + "title": "颜色模式", + "desc": "设置颜色位深", + "type": "string", + "cur": "24位彩色", + "default": "24位彩色", + "size": 24, + "range": ["24位彩色", "256级灰度", "黑白", "颜色自动识别"] + }, + "5": { + "category": "base", + "name": "cfg-5", + "title": "灰度或黑白图像 - 除色", + "desc": "除去图像彩色", + "type": "string", + "cur": "不除色", + "default": "不除色", + "size": 20, + "range": ["不除色", "除红色", "除绿色", "除蓝色", "红色增强", "绿色增强", "蓝色增强"], + "depend_or": ["4==256级灰度", "4==黑白"] + }, + "6": { + "category": "base", + "name": "cfg-6", + "title": "24位彩色图像 - 多流输出除红", + "desc": "多通道输出中,去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "7": { + "category": "base", + "name": "cfg-7", + "title": "24位彩色图像 - 答题卡除红", + "desc": "答题卡扫描中去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "8": { + "category": "base", + "name": "cfg-8", + "title": "背景移除", + "desc": "移除彩色图像背景", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "9": { + "category": "base", + "name": "cfg-9", + "title": " 背景色彩浮动范围", + "desc": "设定背景色彩的浮动范围,在该范围内的都当作背景移除", + "type": "int", + "cur": 10, + "default": 10, + "size": 4, + "range": { + "min": 1, + "max": 40 + }, + "depend_or": ["8==true"] + }, + "10": { + "category": "base", + "name": "cfg-10", + "title": "黑白图像噪点优化", + "desc": "噪点优化", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==黑白"] + }, + "11": { + "category": "base", + "name": "cfg-11", + "title": " 噪点优化尺寸", + "desc": "噪点优化尺寸", + "type": "int", + "cur": 30, + "default": 30, + "size": 4, + "range": { + "min": 10, + "max": 50 + }, + "depend_or": ["10==true"] + }, + "12": { + "category": "base", + "name": "cfg-12", + "title": "纸张尺寸", + "desc": "设置纸张大小", + "type": "string", + "cur": "匹配原始尺寸", + "default": "匹配原始尺寸", + "size": 44, + "range": ["A3", "8开", "A4", "A4横向", "16开", "16开横向", "A5", "A5横向", "A6", "A6横向", "B4", "B5", "B5横向", "B6", "B6横向", "Letter", "Letter横向", "Double Letter", "LEGAL", "匹配原始尺寸", "最大扫描尺寸自动裁切", "最大扫描尺寸", "三联试卷"] + }, + "13": { + "category": "base", + "name": "cfg-13", + "title": "扫描页面", + "desc": "设置页面扫描方式", + "type": "string", + "cur": "双面", + "default": "双面", + "size": 40, + "range": ["单面", "双面", "跳过空白页(通用)", "跳过空白页(发票纸)", "对折"] + }, + "14": { + "category": "base", + "name": "cfg-14", + "title": " 跳过空白页灵敏度", + "desc": "灵敏度越高,则越容易跳过", + "type": "int", + "cur": 50, + "default": 50, + "size": 4, + "range": { + "min": 1, + "max": 100 + }, + "depend_or": ["13==跳过空白页(通用)", "13==跳过空白页(发票纸)"] + }, + "15": { + "category": "base", + "name": "cfg-15", + "title": "分辨率", + "desc": "扫描仪分辨率", + "type": "int", + "cur": 200, + "default": 200, + "size": 4, + "range": { + "min": 100, + "max": 300 + } + }, + "16": { + "category": "base", + "name": "cfg-16", + "title": "交换正反面", + "desc": "交换正反面", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=单面"] + }, + "17": { + "category": "base", + "name": "cfg-17", + "title": "图像拆分", + "desc": "自动拆分图像", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["13!=对折"] + }, + "18": { + "category": "base", + "name": "cfg-18", + "title": "自动纠偏", + "desc": "自动纠偏", + "type": "bool", + "cur": true, + "default": true, + "size": 4, + "depend_or": ["13!=对折"] + }, + "19": { + "category": "base", + "name": "cfg-19", + "title": "穿孔移除", + "desc": "移除纸张中的穿孔", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "20": { + "category": "base", + "name": "cfg-20", + "title": " 穿孔搜索范围占幅面比例", + "desc": "穿孔搜索范围占幅面比例", + "type": "float", + "cur": 0.100000, + "default": 0.100000, + "size": 4, + "range": { + "min": 0.010000, + "max": 0.500000 + }, + "depend_or": ["19==true"] + }, + "21": { + "category": "base", + "name": "grp-2", + "title": "亮度", + "type": "group" + }, + "22": { + "category": "base", + "name": "cfg-22", + "title": "亮度", + "desc": "调整图片亮度", + "type": "int", + "cur": 128, + "default": 128, + "size": 4, + "range": { + "min": 1, + "max": 255 + } + }, + "23": { + "category": "base", + "name": "cfg-23", + "title": "对比度", + "desc": "调整图片对比度", + "type": "int", + "cur": 4, + "default": 4, + "size": 4, + "range": { + "min": 1, + "max": 7 + } + }, + "24": { + "category": "base", + "name": "cfg-24", + "title": "伽玛", + "desc": "调整图片伽玛值", + "type": "float", + "cur": 1.000000, + "default": 1.000000, + "size": 4, + "range": { + "min": 0.010000, + "max": 5.000000 + } + }, + "25": { + "category": "base", + "name": "grp-3", + "title": "图像处理", + "type": "group" + }, + "26": { + "category": "base", + "name": "cfg-26", + "title": "锐化与模糊", + "desc": "锐化与模糊", + "type": "string", + "cur": "无", + "default": "无", + "size": 20, + "range": ["无", "锐化", "进一步锐化", "模糊", "进一步模糊"] + }, + "27": { + "category": "base", + "name": "cfg-27", + "title": "消除黑框", + "desc": "消除黑框", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "28": { + "category": "base", + "name": "cfg-28", + "title": "深色样张", + "desc": "深色样张", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=对折", "27!=true", "12!=匹配原始尺寸", "12!=最大扫描尺寸", "12!=最大扫描尺寸自动裁切", "18!=true"] + }, + "29": { + "category": "advanced", + "name": "cfg-29", + "title": "阈值", + "desc": "阈值", + "type": "int", + "cur": 40, + "default": 40, + "size": 4, + "range": { + "min": 30, + "max": 50 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸", "12==最大扫描尺寸自动裁切", "18==true"] + }, + "30": { + "category": "advanced", + "name": "cfg-30", + "title": "背景抗噪等级", + "desc": "背景抗噪等级", + "type": "int", + "cur": 8, + "default": 8, + "size": 4, + "range": { + "min": 1, + "max": 20 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸", "12==最大扫描尺寸自动裁切", "18==true"] + }, + "31": { + "category": "advanced", + "name": "cfg-31", + "title": "边缘缩进", + "desc": "边缘缩进", + "type": "int", + "cur": 5, + "default": 5, + "size": 4, + "range": { + "min": 5, + "max": 30 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸自动裁切", "18==true", "12==最大扫描尺寸"] + }, + "32": { + "category": "advanced", + "name": "cfg-32", + "title": "背景填充方式", + "desc": "背景填充方式", + "type": "string", + "cur": "凸多边形", + "default": "凸多边形", + "size": 40, + "range": ["凸多边形", "凹多边形"], + "depend_or": ["27==true"] + }, + "33": { + "category": "base", + "name": "cfg-33", + "title": "防止渗透", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "34": { + "category": "base", + "name": "cfg-34", + "title": " 防止渗透等级", + "desc": "", + "type": "string", + "cur": "较弱", + "default": "较弱", + "size": 12, + "range": ["较弱", "弱", "一般", "强", "较强"], + "depend_or": ["33==true"] + }, + "35": { + "category": "base", + "name": "cfg-35", + "title": "去除摩尔纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "36": { + "category": "base", + "name": "cfg-36", + "title": "错误扩散", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "37": { + "category": "base", + "name": "cfg-37", + "title": "除网纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "38": { + "category": "base", + "name": "grp-4", + "title": "送纸方式设置", + "type": "group" + }, + "39": { + "category": "base", + "name": "cfg-39", + "title": "超声波检测", + "desc": "超声波检测送纸状态", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "40": { + "category": "base", + "name": "cfg-40", + "title": "装订检测", + "desc": "检测纸张上是否有钉书钉", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "41": { + "category": "base", + "name": "cfg-41", + "title": "扫描张数", + "desc": "扫描纸张数量", + "type": "string", + "cur": "连续扫描", + "default": "连续扫描", + "size": 24, + "range": ["连续扫描", "扫描指定张数"] + }, + "42": { + "category": "base", + "name": "cfg-42", + "title": " 扫描数量", + "desc": "扫描指定数量", + "type": "int", + "cur": 1, + "default": 1, + "size": 4, + "depend_or": ["41==扫描指定张数"] + }, + "43": { + "category": "base", + "name": "cfg-43", + "title": "文稿方向", + "desc": "文稿方向", + "type": "string", + "cur": "0°", + "default": "0°", + "size": 40, + "range": ["0°", "90°", "180°", "-90°", "自动文本方向识别°"] + }, + "44": { + "category": "base", + "name": "cfg-44", + "title": "背面旋转180°", + "desc": "背面扫描的图像旋转180°", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=单面", "13!=对折", "43!=自动文本方向识别°"] + }, + "45": { + "category": "base", + "name": "cfg-45", + "title": "歪斜检测", + "desc": "纸张歪斜检测", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "46": { + "category": "base", + "name": "cfg-46", + "title": " 歪斜检测复杂度", + "desc": "纸张歪斜检测复杂度", + "type": "int", + "cur": 3, + "default": 3, + "size": 4, + "range": { + "min": 1, + "max": 5 + }, + "depend_or": ["45==true"] + } +} \ No newline at end of file diff --git a/docs/G139-239.txt b/docs/G139-239.txt new file mode 100644 index 0000000..1d36e25 --- /dev/null +++ b/docs/G139-239.txt @@ -0,0 +1,574 @@ +{ + "device_type": "G239", + "option_count": 51, + "1": { + "category": "base", + "name": "cfg-1", + "title": "恢复默认设置", + "desc": "恢复默认设置", + "type": "button", + "cur": "button", + "default": "button", + "size": 0 + }, + "2": { + "category": "advanced", + "name": "cfg-2", + "title": "帮助", + "desc": "显示软件帮助文档", + "type": "button", + "cur": "true", + "default": "true", + "size": 4 + }, + "3": { + "category": "base", + "name": "grp-1", + "title": "基本设置", + "type": "group" + }, + "4": { + "category": "base", + "name": "cfg-4", + "title": "颜色模式", + "desc": "设置颜色位深", + "type": "string", + "cur": "24位彩色", + "default": "24位彩色", + "size": 24, + "range": ["24位彩色", "256级灰度", "黑白", "颜色自动识别"] + }, + "5": { + "category": "base", + "name": "cfg-5", + "title": "24位彩色图像-多流输出", + "desc": "", + "type": "string", + "cur": "不选择输出模式", + "default": "不选择输出模式", + "size": 28, + "range": ["不选择输出模式", "彩色+灰度+黑白", "彩色+灰度", "彩色+黑白", "灰度+黑白"], + "depend_or": ["4==24位彩色"] + }, + "6": { + "category": "base", + "name": "cfg-6", + "title": "灰度或黑白图像 - 除色", + "desc": "除去图像彩色", + "type": "string", + "cur": "不除色", + "default": "不除色", + "size": 20, + "range": ["不除色", "除红色", "除绿色", "除蓝色", "红色增强", "绿色增强", "蓝色增强"], + "depend_or": ["4==256级灰度", "4==黑白"] + }, + "7": { + "category": "base", + "name": "cfg-7", + "title": "24位彩色图像 - 多流输出除红", + "desc": "多通道输出中,去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "8": { + "category": "base", + "name": "cfg-8", + "title": "24位彩色图像 - 答题卡除红", + "desc": "答题卡扫描中去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "9": { + "category": "base", + "name": "cfg-9", + "title": "背景移除", + "desc": "移除彩色图像背景", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "10": { + "category": "base", + "name": "cfg-10", + "title": " 背景色彩浮动范围", + "desc": "设定背景色彩的浮动范围,在该范围内的都当作背景移除", + "type": "int", + "cur": 10, + "default": 10, + "size": 4, + "range": { + "min": 1, + "max": 40 + }, + "depend_or": ["9==true"] + }, + "11": { + "category": "base", + "name": "cfg-11", + "title": "黑白图像噪点优化", + "desc": "噪点优化", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==黑白"] + }, + "12": { + "category": "base", + "name": "cfg-12", + "title": " 噪点优化尺寸", + "desc": "噪点优化尺寸", + "type": "int", + "cur": 30, + "default": 30, + "size": 4, + "range": { + "min": 10, + "max": 50 + }, + "depend_or": ["11==true"] + }, + "13": { + "category": "base", + "name": "cfg-13", + "title": "纸张尺寸", + "desc": "设置纸张大小", + "type": "string", + "cur": "匹配原始尺寸", + "default": "匹配原始尺寸", + "size": 44, + "range": ["A3", "8开", "A4", "A4横向", "16开", "16开横向", "A5", "A5横向", "A6", "A6横向", "B4", "B5", "B5横向", "B6", "B6横向", "Letter", "Letter横向", "Double Letter", "LEGAL", "匹配原始尺寸", "最大扫描尺寸自动裁切", "最大扫描尺寸", "三联试卷"] + }, + "14": { + "category": "base", + "name": "cfg-14", + "title": "尺寸检测", + "desc": "检测纸张实际尺寸", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["13==A3", "13==A4", "13==A4横向", "13==A5", "13==A5横向", "13==A6", "13==A6横向", "13==B4", "13==B5", "13==B5横向", "13==B6", "13==B6横向", "13==Double Letter", "13==LEGAL", "13==Letter", "13==Letter横向"] + }, + "15": { + "category": "base", + "name": "cfg-15", + "title": "扫描页面", + "desc": "设置页面扫描方式", + "type": "string", + "cur": "双面", + "default": "双面", + "size": 40, + "range": ["单面", "双面", "跳过空白页(通用)", "跳过空白页(发票纸)", "对折"] + }, + "16": { + "category": "base", + "name": "cfg-16", + "title": " 跳过空白页灵敏度", + "desc": "灵敏度越高,则越容易跳过", + "type": "int", + "cur": 50, + "default": 50, + "size": 4, + "range": { + "min": 1, + "max": 100 + }, + "depend_or": ["15==跳过空白页(通用)", "15==跳过空白页(发票纸)"] + }, + "17": { + "category": "base", + "name": "cfg-17", + "title": "分辨率", + "desc": "扫描仪分辨率", + "type": "int", + "cur": 200, + "default": 200, + "size": 4, + "range": { + "min": 100, + "max": 300 + } + }, + "18": { + "category": "base", + "name": "cfg-18", + "title": "交换正反面", + "desc": "交换正反面", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["15!=单面"] + }, + "19": { + "category": "base", + "name": "cfg-19", + "title": "图像拆分", + "desc": "自动拆分图像", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["15!=对折"] + }, + "20": { + "category": "base", + "name": "cfg-20", + "title": "自动纠偏", + "desc": "自动纠偏", + "type": "bool", + "cur": true, + "default": true, + "size": 4, + "depend_or": ["15!=对折"] + }, + "21": { + "category": "base", + "name": "cfg-21", + "title": "穿孔移除", + "desc": "移除纸张中的穿孔", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "22": { + "category": "base", + "name": "cfg-22", + "title": " 穿孔搜索范围占幅面比例", + "desc": "穿孔搜索范围占幅面比例", + "type": "float", + "cur": 0.100000, + "default": 0.100000, + "size": 4, + "range": { + "min": 0.010000, + "max": 0.500000 + }, + "depend_or": ["21==true"] + }, + "23": { + "category": "base", + "name": "grp-2", + "title": "亮度", + "type": "group" + }, + "24": { + "category": "base", + "name": "cfg-24", + "title": "亮度", + "desc": "调整图片亮度", + "type": "int", + "cur": 128, + "default": 128, + "size": 4, + "range": { + "min": 1, + "max": 255 + } + }, + "25": { + "category": "base", + "name": "cfg-25", + "title": "对比度", + "desc": "调整图片对比度", + "type": "int", + "cur": 4, + "default": 4, + "size": 4, + "range": { + "min": 1, + "max": 7 + } + }, + "26": { + "category": "base", + "name": "cfg-26", + "title": "伽玛", + "desc": "调整图片伽玛值", + "type": "float", + "cur": 1.000000, + "default": 1.000000, + "size": 4, + "range": { + "min": 0.010000, + "max": 5.000000 + } + }, + "27": { + "category": "base", + "name": "grp-3", + "title": "图像处理", + "type": "group" + }, + "28": { + "category": "base", + "name": "cfg-28", + "title": "锐化与模糊", + "desc": "锐化与模糊", + "type": "string", + "cur": "无", + "default": "无", + "size": 20, + "range": ["无", "锐化", "进一步锐化", "模糊", "进一步模糊"] + }, + "29": { + "category": "base", + "name": "cfg-29", + "title": "消除黑框", + "desc": "消除黑框", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "30": { + "category": "base", + "name": "cfg-30", + "title": "深色样张", + "desc": "深色样张", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["15!=对折", "29!=true", "13!=匹配原始尺寸", "13!=最大扫描尺寸", "13!=最大扫描尺寸自动裁切", "20!=true"] + }, + "31": { + "category": "advanced", + "name": "cfg-31", + "title": "阈值", + "desc": "阈值", + "type": "int", + "cur": 40, + "default": 40, + "size": 4, + "range": { + "min": 30, + "max": 50 + }, + "depend_or": ["29==true", "13==匹配原始尺寸", "13==最大扫描尺寸", "13==最大扫描尺寸自动裁切", "20==true"] + }, + "32": { + "category": "advanced", + "name": "cfg-32", + "title": "背景抗噪等级", + "desc": "背景抗噪等级", + "type": "int", + "cur": 8, + "default": 8, + "size": 4, + "range": { + "min": 1, + "max": 20 + }, + "depend_or": ["29==true", "13==匹配原始尺寸", "13==最大扫描尺寸", "13==最大扫描尺寸自动裁切", "20==true"] + }, + "33": { + "category": "advanced", + "name": "cfg-33", + "title": "边缘缩进", + "desc": "边缘缩进", + "type": "int", + "cur": 5, + "default": 5, + "size": 4, + "range": { + "min": 5, + "max": 30 + }, + "depend_or": ["29==true", "13==匹配原始尺寸", "13==最大扫描尺寸自动裁切", "20==true", "13==最大扫描尺寸"] + }, + "34": { + "category": "advanced", + "name": "cfg-34", + "title": "背景填充方式", + "desc": "背景填充方式", + "type": "string", + "cur": "凸多边形", + "default": "凸多边形", + "size": 40, + "range": ["凸多边形", "凹多边形"], + "depend_or": ["29==true"] + }, + "35": { + "category": "base", + "name": "cfg-35", + "title": "防止渗透", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "36": { + "category": "base", + "name": "cfg-36", + "title": " 防止渗透等级", + "desc": "", + "type": "string", + "cur": "较弱", + "default": "较弱", + "size": 12, + "range": ["较弱", "弱", "一般", "强", "较强"], + "depend_or": ["35==true"] + }, + "37": { + "category": "base", + "name": "cfg-37", + "title": "去除摩尔纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "38": { + "category": "base", + "name": "cfg-38", + "title": "错误扩散", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "39": { + "category": "base", + "name": "cfg-39", + "title": "除网纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "40": { + "category": "base", + "name": "grp-4", + "title": "送纸方式设置", + "type": "group" + }, + "41": { + "category": "base", + "name": "cfg-41", + "title": "超声波检测", + "desc": "超声波检测送纸状态", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "42": { + "category": "base", + "name": "cfg-42", + "title": "装订检测", + "desc": "检测纸张上是否有钉书钉", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "43": { + "category": "base", + "name": "cfg-43", + "title": "扫描张数", + "desc": "扫描纸张数量", + "type": "string", + "cur": "连续扫描", + "default": "连续扫描", + "size": 24, + "range": ["连续扫描", "扫描指定张数"] + }, + "44": { + "category": "base", + "name": "cfg-44", + "title": " 扫描数量", + "desc": "扫描指定数量", + "type": "int", + "cur": 1, + "default": 1, + "size": 4, + "depend_or": ["43==扫描指定张数"] + }, + "45": { + "category": "base", + "name": "cfg-45", + "title": "文稿方向", + "desc": "文稿方向", + "type": "string", + "cur": "0°", + "default": "0°", + "size": 40, + "range": ["0°", "90°", "180°", "-90°", "自动文本方向识别°"] + }, + "46": { + "category": "base", + "name": "cfg-46", + "title": "背面旋转180°", + "desc": "背面扫描的图像旋转180°", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["15!=单面", "15!=对折", "45!=自动文本方向识别°"] + }, + "47": { + "category": "base", + "name": "cfg-47", + "title": "折角检测", + "desc": "纸张折角检测", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "48": { + "category": "base", + "name": "cfg-48", + "title": " 折角检测复杂度", + "desc": "纸张折角检测复杂度", + "type": "int", + "cur": 10, + "default": 10, + "size": 4, + "range": { + "min": 0, + "max": 100 + }, + "depend_or": ["47==true"] + }, + "49": { + "category": "base", + "name": "cfg-49", + "title": "歪斜检测", + "desc": "纸张歪斜检测", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "50": { + "category": "base", + "name": "cfg-50", + "title": " 歪斜检测复杂度", + "desc": "纸张歪斜检测复杂度", + "type": "int", + "cur": 3, + "default": 3, + "size": 4, + "range": { + "min": 1, + "max": 5 + }, + "depend_or": ["49==true"] + } +} \ No newline at end of file diff --git a/docs/G300.txt b/docs/G300.txt new file mode 100644 index 0000000..c2b4bff --- /dev/null +++ b/docs/G300.txt @@ -0,0 +1,491 @@ +{ + "device_type": "G300", + "option_count": 44, + "1": { + "category": "base", + "name": "cfg-1", + "title": "恢复默认设置", + "desc": "恢复默认设置", + "type": "button", + "cur": "button", + "default": "button", + "size": 0 + }, + "2": { + "category": "advanced", + "name": "cfg-2", + "title": "帮助", + "desc": "显示软件帮助文档", + "type": "button", + "cur": "true", + "default": "true", + "size": 4 + }, + "3": { + "category": "base", + "name": "grp-1", + "title": "基本设置", + "type": "group" + }, + "4": { + "category": "base", + "name": "cfg-4", + "title": "颜色模式", + "desc": "设置颜色位深", + "type": "string", + "cur": "24位彩色", + "default": "24位彩色", + "size": 24, + "range": ["24位彩色", "256级灰度", "黑白", "颜色自动识别"] + }, + "5": { + "category": "base", + "name": "cfg-5", + "title": "灰度或黑白图像 - 除色", + "desc": "除去图像彩色", + "type": "string", + "cur": "不除色", + "default": "不除色", + "size": 16, + "range": ["不除色", "除红色", "除绿色", "除蓝色", "红色增强", "绿色增强", "蓝色增强"], + "depend_or": ["4==256级灰度", "4==黑白"] + }, + "6": { + "category": "base", + "name": "cfg-6", + "title": "24位彩色图像 - 多流输出除红", + "desc": "多通道输出中,去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "7": { + "category": "base", + "name": "cfg-7", + "title": "24位彩色图像 - 答题卡除红", + "desc": "答题卡扫描中去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "8": { + "category": "base", + "name": "cfg-8", + "title": "背景移除", + "desc": "移除彩色图像背景", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "9": { + "category": "base", + "name": "cfg-9", + "title": " 背景色彩浮动范围", + "desc": "设定背景色彩的浮动范围,在该范围内的都当作背景移除", + "type": "int", + "cur": 10, + "default": 10, + "size": 4, + "range": { + "min": 1, + "max": 40 + }, + "depend_or": ["8==true"] + }, + "10": { + "category": "base", + "name": "cfg-10", + "title": "黑白图像噪点优化", + "desc": "噪点优化", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==黑白"] + }, + "11": { + "category": "base", + "name": "cfg-11", + "title": " 噪点优化尺寸", + "desc": "噪点优化尺寸", + "type": "int", + "cur": 30, + "default": 30, + "size": 4, + "range": { + "min": 10, + "max": 50 + }, + "depend_or": ["10==true"] + }, + "12": { + "category": "base", + "name": "cfg-12", + "title": "纸张尺寸", + "desc": "设置纸张大小", + "type": "string", + "cur": "匹配原始尺寸", + "default": "匹配原始尺寸", + "size": 36, + "range": ["A4", "A5", "A5横向", "A6", "A6横向", "B5", "B5横向", "B6", "B6横向", "匹配原始尺寸", "最大扫描尺寸自动裁切", "最大扫描尺寸"] + }, + "13": { + "category": "base", + "name": "cfg-13", + "title": "扫描页面", + "desc": "设置页面扫描方式", + "type": "string", + "cur": "双面", + "default": "双面", + "size": 50, + "range": ["单面", "双面", "跳过空白页(通用)", "跳过空白页(发票纸)", "对折"] + }, + "14": { + "category": "base", + "name": "cfg-14", + "title": " 跳过空白页灵敏度", + "desc": "灵敏度越高,则越容易跳过", + "type": "int", + "cur": 50, + "default": 50, + "size": 4, + "range": { + "min": 1, + "max": 100 + }, + "depend_or": ["13==跳过空白页(通用)", "13==跳过空白页(发票纸)"] + }, + "15": { + "category": "base", + "name": "cfg-15", + "title": "分辨率", + "desc": "扫描仪分辨率", + "type": "int", + "cur": 200, + "default": 200, + "size": 4, + "range": { + "min": 100, + "max": 300 + } + }, + "16": { + "category": "base", + "name": "cfg-16", + "title": "交换正反面", + "desc": "交换正反面", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=单面"] + }, + "17": { + "category": "base", + "name": "cfg-17", + "title": "图像拆分", + "desc": "自动拆分图像", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["13!=对折"] + }, + "18": { + "category": "base", + "name": "cfg-18", + "title": "自动纠偏", + "desc": "自动纠偏", + "type": "bool", + "cur": true, + "default": true, + "size": 4, + "depend_or": ["13!=对折"] + }, + "19": { + "category": "base", + "name": "cfg-19", + "title": "穿孔移除", + "desc": "移除纸张中的穿孔", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "20": { + "category": "base", + "name": "cfg-20", + "title": " 穿孔搜索范围占幅面比例", + "desc": "穿孔搜索范围占幅面比例", + "type": "float", + "cur": 0.100000, + "default": 0.100000, + "size": 4, + "range": { + "min": 0.010000, + "max": 0.500000 + }, + "depend_or": ["19==true"] + }, + "21": { + "category": "base", + "name": "grp-2", + "title": "亮度", + "type": "group" + }, + "22": { + "category": "base", + "name": "cfg-22", + "title": "亮度", + "desc": "调整图片亮度", + "type": "int", + "cur": 128, + "default": 128, + "size": 4, + "range": { + "min": 1, + "max": 255 + } + }, + "23": { + "category": "base", + "name": "cfg-23", + "title": "对比度", + "desc": "调整图片对比度", + "type": "int", + "cur": 4, + "default": 4, + "size": 4, + "range": { + "min": 1, + "max": 7 + } + }, + "24": { + "category": "base", + "name": "cfg-24", + "title": "伽玛", + "desc": "调整图片伽玛值", + "type": "float", + "cur": 1.000000, + "default": 1.000000, + "size": 4, + "range": { + "min": 1.000000, + "max": 5.000000 + } + }, + "25": { + "category": "base", + "name": "grp-3", + "title": "图像处理", + "type": "group" + }, + "26": { + "category": "base", + "name": "cfg-26", + "title": "锐化与模糊", + "desc": "锐化与模糊", + "type": "string", + "cur": "无", + "default": "无", + "size": 20, + "range": ["无", "锐化", "进一步锐化", "模糊", "进一步模糊"] + }, + "27": { + "category": "base", + "name": "cfg-27", + "title": "消除黑框", + "desc": "消除黑框", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "28": { + "category": "base", + "name": "cfg-28", + "title": "深色样张", + "desc": "深色样张", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=对折", "27!=true", "12!=匹配原始尺寸", "12!=最大扫描尺寸", "12!=最大扫描尺寸自动裁切", "18!=true"] + }, + "29": { + "category": "advanced", + "name": "cfg-29", + "title": "阈值", + "desc": "阈值", + "type": "int", + "cur": 40, + "default": 40, + "size": 4, + "range": { + "min": 30, + "max": 50 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸", "12==最大扫描尺寸自动裁切", "18==true"] + }, + "30": { + "category": "advanced", + "name": "cfg-30", + "title": "背景抗噪等级", + "desc": "背景抗噪等级", + "type": "int", + "cur": 8, + "default": 8, + "size": 4, + "range": { + "min": 1, + "max": 20 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸", "12==最大扫描尺寸自动裁切", "18==true"] + }, + "31": { + "category": "advanced", + "name": "cfg-31", + "title": "边缘缩进", + "desc": "边缘缩进", + "type": "int", + "cur": 5, + "default": 5, + "size": 4, + "range": { + "min": 5, + "max": 30 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸自动裁切", "18==true", "12==最大扫描尺寸"] + }, + "32": { + "category": "advanced", + "name": "cfg-32", + "title": "背景填充方式", + "desc": "背景填充方式", + "type": "string", + "cur": "凸多边形", + "default": "凸多边形", + "size": 40, + "range": ["凸多边形", "凹多边形"], + "depend_or": ["27==true"] + }, + "33": { + "category": "base", + "name": "cfg-33", + "title": "防止渗透", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "34": { + "category": "base", + "name": "cfg-34", + "title": " 防止渗透等级", + "desc": "", + "type": "string", + "cur": "较弱", + "default": "较弱", + "size": 12, + "range": ["较弱", "弱", "一般", "强", "较强"], + "depend_or": ["33==true"] + }, + "35": { + "category": "base", + "name": "cfg-35", + "title": "去除摩尔纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "36": { + "category": "base", + "name": "cfg-36", + "title": "错误扩散", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "37": { + "category": "base", + "name": "cfg-37", + "title": "除网纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "38": { + "category": "base", + "name": "grp-4", + "title": "送纸方式设置", + "type": "group" + }, + "39": { + "category": "base", + "name": "cfg-39", + "title": "超声波检测", + "desc": "超声波检测送纸状态", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "40": { + "category": "base", + "name": "cfg-40", + "title": "扫描张数", + "desc": "扫描纸张数量", + "type": "string", + "cur": "连续扫描", + "default": "连续扫描", + "size": 24, + "range": ["连续扫描", "扫描指定张数"] + }, + "41": { + "category": "base", + "name": "cfg-41", + "title": " 扫描数量", + "desc": "扫描指定数量", + "type": "int", + "cur": 1, + "default": 1, + "size": 4, + "depend_or": ["40==扫描指定张数"] + }, + "42": { + "category": "base", + "name": "cfg-42", + "title": "文稿方向", + "desc": "文稿方向", + "type": "string", + "cur": "0°", + "default": "0°", + "size": 16, + "range": ["0°", "90°", "180°", "-90°"] + }, + "43": { + "category": "base", + "name": "cfg-43", + "title": "背面旋转180°", + "desc": "背面扫描的图像旋转180°", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=单面", "13!=对折", "42!=自动文本方向识别°"] + } +} \ No newline at end of file diff --git a/docs/G400.txt b/docs/G400.txt new file mode 100644 index 0000000..bc5e138 --- /dev/null +++ b/docs/G400.txt @@ -0,0 +1,491 @@ +{ + "device_type": "G400", + "option_count": 44, + "1": { + "category": "base", + "name": "cfg-1", + "title": "恢复默认设置", + "desc": "恢复默认设置", + "type": "button", + "cur": "button", + "default": "button", + "size": 0 + }, + "2": { + "category": "advanced", + "name": "cfg-2", + "title": "帮助", + "desc": "显示软件帮助文档", + "type": "button", + "cur": "true", + "default": "true", + "size": 4 + }, + "3": { + "category": "base", + "name": "grp-1", + "title": "基本设置", + "type": "group" + }, + "4": { + "category": "base", + "name": "cfg-4", + "title": "颜色模式", + "desc": "设置颜色位深", + "type": "string", + "cur": "24位彩色", + "default": "24位彩色", + "size": 24, + "range": ["24位彩色", "256级灰度", "黑白", "颜色自动识别"] + }, + "5": { + "category": "base", + "name": "cfg-5", + "title": "灰度或黑白图像 - 除色", + "desc": "除去图像彩色", + "type": "string", + "cur": "不除色", + "default": "不除色", + "size": 16, + "range": ["不除色", "除红色", "除绿色", "除蓝色", "红色增强", "绿色增强", "蓝色增强"], + "depend_or": ["4==256级灰度", "4==黑白"] + }, + "6": { + "category": "base", + "name": "cfg-6", + "title": "24位彩色图像 - 多流输出除红", + "desc": "多通道输出中,去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "7": { + "category": "base", + "name": "cfg-7", + "title": "24位彩色图像 - 答题卡除红", + "desc": "答题卡扫描中去除红色", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "8": { + "category": "base", + "name": "cfg-8", + "title": "背景移除", + "desc": "移除彩色图像背景", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==24位彩色"] + }, + "9": { + "category": "base", + "name": "cfg-9", + "title": " 背景色彩浮动范围", + "desc": "设定背景色彩的浮动范围,在该范围内的都当作背景移除", + "type": "int", + "cur": 10, + "default": 10, + "size": 4, + "range": { + "min": 1, + "max": 40 + }, + "depend_or": ["8==true"] + }, + "10": { + "category": "base", + "name": "cfg-10", + "title": "黑白图像噪点优化", + "desc": "噪点优化", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["4==黑白"] + }, + "11": { + "category": "base", + "name": "cfg-11", + "title": " 噪点优化尺寸", + "desc": "噪点优化尺寸", + "type": "int", + "cur": 30, + "default": 30, + "size": 4, + "range": { + "min": 10, + "max": 50 + }, + "depend_or": ["10==true"] + }, + "12": { + "category": "base", + "name": "cfg-12", + "title": "纸张尺寸", + "desc": "设置纸张大小", + "type": "string", + "cur": "匹配原始尺寸", + "default": "匹配原始尺寸", + "size": 44, + "range": ["A3", "A4", "A4横向", "A5", "A5横向", "A6", "A6横向", "B4", "B5", "B5横向", "B6", "B6横向", "Letter", "Letter横向", "Double Letter", "LEGAL", "匹配原始尺寸"] + }, + "13": { + "category": "base", + "name": "cfg-13", + "title": "扫描页面", + "desc": "设置页面扫描方式", + "type": "string", + "cur": "双面", + "default": "双面", + "size": 50, + "range": ["单面", "双面", "跳过空白页(通用)", "跳过空白页(发票纸)", "对折"] + }, + "14": { + "category": "base", + "name": "cfg-14", + "title": " 跳过空白页灵敏度", + "desc": "灵敏度越高,则越容易跳过", + "type": "int", + "cur": 50, + "default": 50, + "size": 4, + "range": { + "min": 1, + "max": 100 + }, + "depend_or": ["13==跳过空白页(发票纸)", "13==跳过空白页(通用)"] + }, + "15": { + "category": "base", + "name": "cfg-15", + "title": "分辨率", + "desc": "扫描仪分辨率", + "type": "int", + "cur": 200, + "default": 200, + "size": 4, + "range": { + "min": 100, + "max": 300 + } + }, + "16": { + "category": "base", + "name": "cfg-16", + "title": "交换正反面", + "desc": "交换正反面", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=单面"] + }, + "17": { + "category": "base", + "name": "cfg-17", + "title": "图像拆分", + "desc": "自动拆分图像", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_or": ["13!=对折"] + }, + "18": { + "category": "base", + "name": "cfg-18", + "title": "自动纠偏", + "desc": "自动纠偏", + "type": "bool", + "cur": true, + "default": true, + "size": 4, + "depend_or": ["13!=对折"] + }, + "19": { + "category": "base", + "name": "cfg-19", + "title": "穿孔移除", + "desc": "移除纸张中的穿孔", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "20": { + "category": "base", + "name": "cfg-20", + "title": " 穿孔搜索范围占幅面比例", + "desc": "穿孔搜索范围占幅面比例", + "type": "float", + "cur": 0.100000, + "default": 0.100000, + "size": 4, + "range": { + "min": 0.010000, + "max": 0.500000 + }, + "depend_or": ["19==true"] + }, + "21": { + "category": "base", + "name": "grp-2", + "title": "亮度", + "type": "group" + }, + "22": { + "category": "base", + "name": "cfg-22", + "title": "亮度", + "desc": "调整图片亮度", + "type": "int", + "cur": 128, + "default": 128, + "size": 4, + "range": { + "min": 1, + "max": 255 + } + }, + "23": { + "category": "base", + "name": "cfg-23", + "title": "对比度", + "desc": "调整图片对比度", + "type": "int", + "cur": 4, + "default": 4, + "size": 4, + "range": { + "min": 1, + "max": 7 + } + }, + "24": { + "category": "base", + "name": "cfg-24", + "title": "伽玛", + "desc": "调整图片伽玛值", + "type": "float", + "cur": 1.000000, + "default": 1.000000, + "size": 4, + "range": { + "min": 1.000000, + "max": 5.000000 + } + }, + "25": { + "category": "base", + "name": "grp-3", + "title": "图像处理", + "type": "group" + }, + "26": { + "category": "base", + "name": "cfg-26", + "title": "锐化与模糊", + "desc": "锐化与模糊", + "type": "string", + "cur": "无", + "default": "无", + "size": 20, + "range": ["无", "锐化", "进一步锐化", "模糊", "进一步模糊"] + }, + "27": { + "category": "base", + "name": "cfg-27", + "title": "消除黑框", + "desc": "消除黑框", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "28": { + "category": "base", + "name": "cfg-28", + "title": "深色样张", + "desc": "深色样张", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=对折", "27!=true", "12!=匹配原始尺寸", "12!=最大扫描尺寸", "12!=最大扫描尺寸自动裁切", "18!=true"] + }, + "29": { + "category": "advanced", + "name": "cfg-29", + "title": "阈值", + "desc": "阈值", + "type": "int", + "cur": 40, + "default": 40, + "size": 4, + "range": { + "min": 30, + "max": 50 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸", "12==最大扫描尺寸自动裁切", "18==true"] + }, + "30": { + "category": "advanced", + "name": "cfg-30", + "title": "背景抗噪等级", + "desc": "背景抗噪等级", + "type": "int", + "cur": 8, + "default": 8, + "size": 4, + "range": { + "min": 1, + "max": 20 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸", "12==最大扫描尺寸自动裁切", "18==true"] + }, + "31": { + "category": "advanced", + "name": "cfg-31", + "title": "边缘缩进", + "desc": "边缘缩进", + "type": "int", + "cur": 5, + "default": 5, + "size": 4, + "range": { + "min": 5, + "max": 30 + }, + "depend_or": ["27==true", "12==匹配原始尺寸", "12==最大扫描尺寸自动裁切", "18==true", "12==最大扫描尺寸"] + }, + "32": { + "category": "advanced", + "name": "cfg-32", + "title": "背景填充方式", + "desc": "背景填充方式", + "type": "string", + "cur": "凸多边形", + "default": "凸多边形", + "size": 40, + "range": ["凸多边形", "凹多边形"], + "depend_or": ["27==true"] + }, + "33": { + "category": "base", + "name": "cfg-33", + "title": "防止渗透", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "34": { + "category": "base", + "name": "cfg-34", + "title": " 防止渗透等级", + "desc": "", + "type": "string", + "cur": "较弱", + "default": "较弱", + "size": 12, + "range": ["较弱", "弱", "一般", "强", "较强"], + "depend_or": ["33==true"] + }, + "35": { + "category": "base", + "name": "cfg-35", + "title": "去除摩尔纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "36": { + "category": "base", + "name": "cfg-36", + "title": "错误扩散", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "37": { + "category": "base", + "name": "cfg-37", + "title": "除网纹", + "desc": "", + "type": "bool", + "cur": false, + "default": false, + "size": 4 + }, + "38": { + "category": "base", + "name": "grp-4", + "title": "送纸方式设置", + "type": "group" + }, + "39": { + "category": "base", + "name": "cfg-39", + "title": "超声波检测", + "desc": "超声波检测送纸状态", + "type": "bool", + "cur": true, + "default": true, + "size": 4 + }, + "40": { + "category": "base", + "name": "cfg-40", + "title": "扫描张数", + "desc": "扫描纸张数量", + "type": "string", + "cur": "连续扫描", + "default": "连续扫描", + "size": 24, + "range": ["连续扫描", "扫描指定张数"] + }, + "41": { + "category": "base", + "name": "cfg-41", + "title": " 扫描数量", + "desc": "扫描指定数量", + "type": "int", + "cur": 1, + "default": 1, + "size": 4, + "depend_or": ["40==扫描指定张数"] + }, + "42": { + "category": "base", + "name": "cfg-42", + "title": "文稿方向", + "desc": "文稿方向", + "type": "string", + "cur": "0°", + "default": "0°", + "size": 32, + "range": ["0°", "90°", "180°", "-90°", "自动文本方向识别°"] + }, + "43": { + "category": "base", + "name": "cfg-43", + "title": "背面旋转180°", + "desc": "背面扫描的图像旋转180°", + "type": "bool", + "cur": false, + "default": false, + "size": 4, + "depend_and": ["13!=单面", "13!=对折", "42!=自动文本方向识别°"] + } +} \ No newline at end of file diff --git a/docs/HUAGOTWAIN协议说明220418.xlsx b/docs/HUAGOTWAIN协议说明220418.xlsx new file mode 100644 index 0000000..ecbb5a0 Binary files /dev/null and b/docs/HUAGOTWAIN协议说明220418.xlsx differ diff --git a/docs/SANE-APP需求说明.doc b/docs/SANE-APP需求说明.doc new file mode 100644 index 0000000..e62f663 Binary files /dev/null and b/docs/SANE-APP需求说明.doc differ diff --git a/docs/UI.vsdx b/docs/UI.vsdx new file mode 100644 index 0000000..3605b93 Binary files /dev/null and b/docs/UI.vsdx differ diff --git a/docs/sane.docx b/docs/sane.docx new file mode 100644 index 0000000..fac3cf5 Binary files /dev/null and b/docs/sane.docx differ diff --git a/docs/scanner_flow.vsdx b/docs/scanner_flow.vsdx new file mode 100644 index 0000000..c5d4f31 Binary files /dev/null and b/docs/scanner_flow.vsdx differ diff --git a/tools/README.txt b/tools/README.txt new file mode 100644 index 0000000..ab18cd6 --- /dev/null +++ b/tools/README.txt @@ -0,0 +1,9 @@ +hgjson: 用于编辑SANE设备配置属性JSON文件 +cvstr: 用于将中文字符转换为八进制表示的UTF8编码,如将"中文"转换为"\344\270\255\346\226\207" + 也可以对代码文件中以#define定义的中文字符串进行转换 + +C:>cvstr 中文 +Load file '中文' failed. +Oct: \344\270\255\346\226\207 + +C:> \ No newline at end of file diff --git a/tools/apps/cvstr/ReadMe.txt b/tools/apps/cvstr/ReadMe.txt new file mode 100644 index 0000000..6c9eeb3 --- /dev/null +++ b/tools/apps/cvstr/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : cvstr Project Overview +======================================================================== + +AppWizard has created this cvstr application for you. + +This file contains a summary of what you will find in each of the files that +make up your cvstr application. + + +cvstr.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +cvstr.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +cvstr.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named cvstr.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/tools/apps/cvstr/cvstr.cpp b/tools/apps/cvstr/cvstr.cpp new file mode 100644 index 0000000..9cf89b4 --- /dev/null +++ b/tools/apps/cvstr/cvstr.cpp @@ -0,0 +1,259 @@ +// cvstr.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include +#include +#include +#include +#include +#include + +static bool conver_define_str(const wchar_t* file); + +int _tmain(int argc, _TCHAR* argv[]) +{ + size_t size = 1024 * 1024 * 1024 * 1; + char *buf = new char[size]; + + buf = new char[size]; + + if (argc < 2) + { + wchar_t *pe = wcsrchr(argv[0], L'\\'); + if (pe++ == NULL) + pe = argv[0]; + if (wcsrchr(pe, L'.')) + wcsrchr(pe, L'.')[0] = 0; + + std::wcout << L" Usage: " << pe << L" \r\n"; + } + + for (int i = 1; i < argc; ++i) + { + std::wstring str(argv[i]); + + STR_TO_ABSOLUTE_PATH(str); + conver_define_str(str.c_str()); + } + + return 0; +} + +INTER_MODULE_CALLBACK(got_str) +{ + *((std::string*)param) += std::string(data, len); + + return inter_module_data::SET_RESULT_CONTINUE; +} +INTER_MODULE_CALLBACK(got_wstr) +{ + *((std::wstring*)param) += std::wstring((wchar_t*)data, len / 2); + + return inter_module_data::SET_RESULT_CONTINUE; +} +std::wstring get_line(const std::wstring& src, int start) +{ + std::wstring line(src.substr(start)); + + start = line.find(L"\n"); + if (start++ != std::wstring::npos) + line.erase(start); + + return line; +} +std::wstring find_hz(std::wstring& src, int* off) +{ + std::wstring mark(L"#define"), ret(L""); + size_t pos = src.find(mark); + + if (pos == 0) + { + pos = src.find(L"\""); + if (pos++ != std::wstring::npos) + { + bool ascii = true; + size_t end = pos; + while (src[end]) + { + if (src[end] == L'\\') + end++; + else if (src[end] == L'\"') + { + ret = src.substr(pos, end - pos); + if (off) + *off = pos; + break; + } + end++; + } + + for (size_t i = 0; i < ret.length(); ++i) + { + if (ret[i] > 0x7f) + { + ascii = false; + break; + } + } + if (ascii) + { + ret = L""; + } + } + } + + return ret; +} +std::wstring to_oct(const std::string& str) +{ + std::wstring oct(L""); + + for (int i = 0; i < str.length(); ++i) + { + wchar_t buf[8] = { 0 }; + + if ((unsigned char)str[i] <= 0x7f) + buf[0] = str[i]; + else + swprintf_s(buf, _countof(buf) - 1, L"\\%03o", (unsigned char)str[i]); + oct += buf; + } + + return oct; +} +bool is_oct(const wchar_t* str) +{ + bool yes = true; + + for (int i = 0; i < lstrlenW(str); ++i) + { + if ((unsigned short)str[i] > 0x7f) + { + yes = false; + break; + } + } + + return yes; +} +std::string revert_oct(const wchar_t* str) +{ + std::wstring org(L""); + std::string ansi(""); + + for (int i = 0; i < lstrlenW(str); ++i) + { + if (str[i] == L'\\') + { + if (i + 3 < lstrlenW(str)) + { + char ch = str[i + 1] - L'0'; + ch *= 8; + ch += str[i + 2] - L'0'; + ch *= 8; + ch += str[i + 3] - L'0'; + i += 3; + ansi.append(1, ch); + } + } + else + { + if (ansi.length()) + { + coding_util::utf8_2_unicode(ansi.c_str(), got_wstr, &org); + ansi = ""; + } + org.append(1, str[i]); + } + } + if (ansi.length()) + { + coding_util::utf8_2_unicode(ansi.c_str(), got_wstr, &org); + ansi = ""; + } + org.append(2, 0); + + coding_util::unicode_2_ansi(org.c_str(), got_str, &ansi); + + return ansi; +} +static bool conver_define_str(const wchar_t* file) +{ + std::wstring cont(L""), start(L"#define"); + std::string org(""); + size_t pos = 0; + bool unic = false, utf8 = false; + int changed = 0; + + if (file_util::load_file(file, got_str, &org)) + { + coding_util::unicode_2_ansi(file, got_str, &org); + std::cout << "Load file '" << org.c_str() << "' failed.\r\n"; + + if (is_oct(file)) + { + std::cout << "Origin: " << revert_oct(file).c_str() << std::endl; + } + else + { + org = ""; + coding_util::unicode_2_utf8(file, got_str, &org); + cont = to_oct(org); + org = ""; + coding_util::unicode_2_ansi(cont.c_str(), got_str, &org); + std::cout << "Oct: " << org.c_str() << std::endl; + } + return false; + } + + coding_util::bom::to_unicode(org.c_str(), org.length(), got_wstr, &cont); + unic = coding_util::bom::is_unicode(org.c_str(), NULL); + utf8 = coding_util::bom::is_utf8(org.c_str()); + pos = cont.find(start); + while (pos != std::wstring::npos) + { + if (pos == 0 || cont[pos - 1] == L'\n') + { + int off = 0; + std::wstring line(get_line(cont, pos)), + hz(find_hz(line, &off)); + + if (hz.length()) + { + int len = line.length(); + std::string str_utf8(""); + std::wstring oct(L""); + + coding_util::unicode_2_utf8(hz.c_str(), got_str, &str_utf8); + oct = to_oct(str_utf8); + line.replace(off, hz.length(), oct); + + cont.insert(pos, L"// "); + pos += len + 3; + cont.insert(pos, line); + changed++; + } + } + pos = cont.find(L"#define", pos + start.length()); + } + + std::wcout << L"changed " << changed << " HZ in file: " << file << std::endl; + if (changed) + { + org = ""; + if (unic) + coding_util::bom::from_unicode(cont.c_str(), cont.length() * 2, got_str, &org); + else if (utf8) + { + std::string t(""); + coding_util::unicode_2_utf8(cont.c_str(), got_str, &t); + coding_util::bom::from_utf8(t.c_str(), t.length(), got_str, &org); + } + else + coding_util::unicode_2_ansi(cont.c_str(), got_str, &org); + + file_util::save_2_file(org.c_str(), org.length(), file); + } +} + diff --git a/tools/apps/cvstr/cvstr.vcxproj b/tools/apps/cvstr/cvstr.vcxproj new file mode 100644 index 0000000..464fa2b --- /dev/null +++ b/tools/apps/cvstr/cvstr.vcxproj @@ -0,0 +1,102 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E} + Win32Proj + cvstr + 10.0 + + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + $(SolutionDir)..\sdk\include;$(IncludePath) + $(SolutionDir)..\sdk\lib;$(LibraryPath) + $(OutDir)$(ProjectName)\ + + + false + $(SolutionDir)..\sdk\include;$(IncludePath) + $(SolutionDir)..\sdk\lib;$(LibraryPath) + $(OutDir)$(ProjectName)\ + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + Create + Create + + + + + + \ No newline at end of file diff --git a/tools/apps/cvstr/cvstr.vcxproj.filters b/tools/apps/cvstr/cvstr.vcxproj.filters new file mode 100644 index 0000000..963fed7 --- /dev/null +++ b/tools/apps/cvstr/cvstr.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/tools/apps/cvstr/cvstr.vcxproj.user b/tools/apps/cvstr/cvstr.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/tools/apps/cvstr/cvstr.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tools/apps/cvstr/stdafx.cpp b/tools/apps/cvstr/stdafx.cpp new file mode 100644 index 0000000..1250f10 --- /dev/null +++ b/tools/apps/cvstr/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// cvstr.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/tools/apps/cvstr/stdafx.h b/tools/apps/cvstr/stdafx.h new file mode 100644 index 0000000..b005a83 --- /dev/null +++ b/tools/apps/cvstr/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/tools/apps/cvstr/targetver.h b/tools/apps/cvstr/targetver.h new file mode 100644 index 0000000..87c0086 --- /dev/null +++ b/tools/apps/cvstr/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/tools/apps/hgjson/DlgInput.cpp b/tools/apps/hgjson/DlgInput.cpp new file mode 100644 index 0000000..587f5ac --- /dev/null +++ b/tools/apps/hgjson/DlgInput.cpp @@ -0,0 +1,58 @@ +// DlgInput.cpp : implementation file +// + +#include "stdafx.h" +#include "hgjson.h" +#include "DlgInput.h" +#include "afxdialogex.h" + + +// CDlgInput dialog + +IMPLEMENT_DYNAMIC(CDlgInput, CDialogEx) + +CDlgInput::CDlgInput(CWnd* pParent /*=NULL*/) + : CDialogEx(CDlgInput::IDD, pParent) + , value_(_T("")) +{ + +} + +CDlgInput::~CDlgInput() +{ +} + +void CDlgInput::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Text(pDX, IDC_EDIT1, value_); +} + + +BEGIN_MESSAGE_MAP(CDlgInput, CDialogEx) + ON_BN_CLICKED(IDOK, &CDlgInput::OnBnClickedOk) +END_MESSAGE_MAP() + + +// CDlgInput message handlers + + + +void CDlgInput::OnBnClickedOk() +{ + // TODO: Add your control notification handler code here + wchar_t text[128] = { 0 }; + + ::GetDlgItemTextW(m_hWnd, IDC_EDIT1, text, _countof(text) - 1); + for (size_t i = 0; i < used_names_.size(); ++i) + { + if (used_names_[i] == text) + { + std::wstring t(used_names_[i] + L" is already used, choose another name, plz."); + ::MessageBoxW(m_hWnd, t.c_str(), L"Sorry", MB_OK); + return; + } + } + + CDialogEx::OnOK(); +} diff --git a/tools/apps/hgjson/DlgInput.h b/tools/apps/hgjson/DlgInput.h new file mode 100644 index 0000000..c3d4f1b --- /dev/null +++ b/tools/apps/hgjson/DlgInput.h @@ -0,0 +1,28 @@ +#pragma once + + +// CDlgInput dialog +#include +#include + +class CDlgInput : public CDialogEx +{ + DECLARE_DYNAMIC(CDlgInput) + +public: + CDlgInput(CWnd* pParent = NULL); // standard constructor + virtual ~CDlgInput(); + +// Dialog Data + enum { IDD = IDD_DIALOG1 }; + + std::vector used_names_; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + CString value_; + afx_msg void OnBnClickedOk(); +}; diff --git a/tools/apps/hgjson/ReadMe.txt b/tools/apps/hgjson/ReadMe.txt new file mode 100644 index 0000000..4c8675c --- /dev/null +++ b/tools/apps/hgjson/ReadMe.txt @@ -0,0 +1,99 @@ +================================================================================ + MICROSOFT FOUNDATION CLASS LIBRARY : hgjson Project Overview +=============================================================================== + +The application wizard has created this hgjson application for +you. This application not only demonstrates the basics of using the Microsoft +Foundation Classes but is also a starting point for writing your application. + +This file contains a summary of what you will find in each of the files that +make up your hgjson application. + +hgjson.vcxproj + This is the main project file for VC++ projects generated using an application wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + application wizard. + +hgjson.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +hgjson.h + This is the main header file for the application. It includes other + project specific headers (including Resource.h) and declares the + ChgjsonApp application class. + +hgjson.cpp + This is the main application source file that contains the application + class ChgjsonApp. + +hgjson.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. Your project resources are in 1033. + +res\hgjson.ico + This is an icon file, which is used as the application's icon. This + icon is included by the main resource file hgjson.rc. + +res\hgjson.rc2 + This file contains resources that are not edited by Microsoft + Visual C++. You should place all resources not editable by + the resource editor in this file. + + +///////////////////////////////////////////////////////////////////////////// + +The application wizard creates one dialog class: + +hgjsonDlg.h, hgjsonDlg.cpp - the dialog + These files contain your ChgjsonDlg class. This class defines + the behavior of your application's main dialog. The dialog's template is + in hgjson.rc, which can be edited in Microsoft Visual C++. + +///////////////////////////////////////////////////////////////////////////// + +Other Features: + +ActiveX Controls + The application includes support to use ActiveX controls. + +///////////////////////////////////////////////////////////////////////////// + +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named hgjson.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +hgjson.manifest + Application manifest files are used by Windows XP to describe an applications + dependency on specific versions of Side-by-Side assemblies. The loader uses this + information to load the appropriate assembly from the assembly cache or private + from the application. The Application manifest maybe included for redistribution + as an external .manifest file that is installed in the same folder as the application + executable or it may be included in the executable in the form of a resource. +///////////////////////////////////////////////////////////////////////////// + +Other notes: + +The application wizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +If your application uses MFC in a shared DLL, you will need +to redistribute the MFC DLLs. If your application is in a language +other than the operating system's locale, you will also have to +redistribute the corresponding localized resources mfc110XXX.DLL. +For more information on both of these topics, please see the section on +redistributing Visual C++ applications in MSDN documentation. + +///////////////////////////////////////////////////////////////////////////// diff --git a/tools/apps/hgjson/hgjson.cpp b/tools/apps/hgjson/hgjson.cpp new file mode 100644 index 0000000..b4c313c --- /dev/null +++ b/tools/apps/hgjson/hgjson.cpp @@ -0,0 +1,102 @@ + +// hgjson.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "hgjson.h" +#include "hgjsonDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// ChgjsonApp + +BEGIN_MESSAGE_MAP(ChgjsonApp, CWinApp) + ON_COMMAND(ID_HELP, &CWinApp::OnHelp) +END_MESSAGE_MAP() + + +// ChgjsonApp construction + +ChgjsonApp::ChgjsonApp() +{ + // support Restart Manager + m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; + + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + + +// The one and only ChgjsonApp object + +ChgjsonApp theApp; + + +// ChgjsonApp initialization + +BOOL ChgjsonApp::InitInstance() +{ + // InitCommonControlsEx() is required on Windows XP if an application + // manifest specifies use of ComCtl32.dll version 6 or later to enable + // visual styles. Otherwise, any window creation will fail. + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + // Set this to include all the common control classes you want to use + // in your application. + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + CWinApp::InitInstance(); + + + AfxEnableControlContainer(); + + // Create the shell manager, in case the dialog contains + // any shell tree view or shell list view controls. + CShellManager *pShellManager = new CShellManager; + + // Activate "Windows Native" visual manager for enabling themes in MFC controls + CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows)); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need + // Change the registry key under which our settings are stored + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + + ChgjsonDlg dlg; + m_pMainWnd = &dlg; + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + else if (nResponse == -1) + { + TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n"); + TRACE(traceAppMsg, 0, "Warning: if you are using MFC controls on the dialog, you cannot #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS.\n"); + } + + // Delete the shell manager created above. + if (pShellManager != NULL) + { + delete pShellManager; + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} + diff --git a/tools/apps/hgjson/hgjson.h b/tools/apps/hgjson/hgjson.h new file mode 100644 index 0000000..1a26657 --- /dev/null +++ b/tools/apps/hgjson/hgjson.h @@ -0,0 +1,32 @@ + +// hgjson.h : main header file for the PROJECT_NAME application +// + +#pragma once + +#ifndef __AFXWIN_H__ + #error "include 'stdafx.h' before including this file for PCH" +#endif + +#include "resource.h" // main symbols + + +// ChgjsonApp: +// See hgjson.cpp for the implementation of this class +// + +class ChgjsonApp : public CWinApp +{ +public: + ChgjsonApp(); + +// Overrides +public: + virtual BOOL InitInstance(); + +// Implementation + + DECLARE_MESSAGE_MAP() +}; + +extern ChgjsonApp theApp; \ No newline at end of file diff --git a/tools/apps/hgjson/hgjson.rc b/tools/apps/hgjson/hgjson.rc new file mode 100644 index 0000000..2c6e170 Binary files /dev/null and b/tools/apps/hgjson/hgjson.rc differ diff --git a/tools/apps/hgjson/hgjson.vcxproj b/tools/apps/hgjson/hgjson.vcxproj new file mode 100644 index 0000000..040a144 --- /dev/null +++ b/tools/apps/hgjson/hgjson.vcxproj @@ -0,0 +1,145 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5} + hgjson + MFCProj + 10.0 + + + + Application + true + v120 + Unicode + Dynamic + + + Application + false + v120 + true + Unicode + Dynamic + + + + + + + + + + + + + true + $(SolutionDir)..\sdk\Include\;$(IncludePath) + $(SolutionDir)..\sdk\lib\;$(LibraryPath) + $(OutDir)$(ProjectName)\ + + + false + $(SolutionDir)..\sdk\Include\;$(IncludePath) + $(SolutionDir)..\sdk\lib\;$(LibraryPath) + $(OutDir)$(ProjectName)\ + + + + Use + Level3 + Disabled + WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) + true + + + Windows + true + + + false + true + _DEBUG;%(PreprocessorDefinitions) + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + false + true + NDEBUG;%(PreprocessorDefinitions) + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/apps/hgjson/hgjson.vcxproj.filters b/tools/apps/hgjson/hgjson.vcxproj.filters new file mode 100644 index 0000000..04e1f9d --- /dev/null +++ b/tools/apps/hgjson/hgjson.vcxproj.filters @@ -0,0 +1,72 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/tools/apps/hgjson/hgjson.vcxproj.user b/tools/apps/hgjson/hgjson.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/tools/apps/hgjson/hgjson.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tools/apps/hgjson/hgjsonDlg.cpp b/tools/apps/hgjson/hgjsonDlg.cpp new file mode 100644 index 0000000..89484f8 --- /dev/null +++ b/tools/apps/hgjson/hgjsonDlg.cpp @@ -0,0 +1,1843 @@ + +// hgjsonDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "hgjson.h" +#include "hgjsonDlg.h" +#include "afxdialogex.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif +#pragma warning(disable: 4996) + +#include "DlgInput.h" + +#include +#include +#include + +#define TREE_ITEM_PRODUCT MAKELONG(MAKEWORD('P', 'R'), MAKEWORD('D', 'T')) +#define TREE_ITEM_GROUP MAKELONG(MAKEWORD('G', 'R'), MAKEWORD('U', 'P')) +#define TREE_ITEM_CONFIG MAKELONG(MAKEWORD('I', 'T'), MAKEWORD('E', 'M')) + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// sane data types: +typedef unsigned char SANE_Byte; +typedef int SANE_Word; +typedef SANE_Word SANE_Bool; +typedef SANE_Word SANE_Int; +typedef char SANE_Char; +typedef SANE_Char *SANE_String; +typedef const SANE_Char *SANE_String_Const; +typedef void *SANE_Handle; +typedef SANE_Word SANE_Fixed; + + +namespace coding +{ + INTER_MODULE_CALLBACK(get_string) + { + *((std::string*)param) += std::string(data, len); + + return inter_module_data::SET_RESULT_CONTINUE; + } + INTER_MODULE_CALLBACK(get_wstring) + { + *((std::wstring*)param) += std::wstring((const wchar_t*)data, len / 2); + + return inter_module_data::SET_RESULT_CONTINUE; + } + + int string_need_bytes(const wchar_t* str) + { + int len = lstrlenW(str) * 3; + + len += 7; + len /= 4; + len *= 4; + + return len; + } +} +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ChgjsonDlg dialog + + + +ChgjsonDlg::ChgjsonDlg(CWnd* pParent /*=NULL*/) + : CDialogEx(ChgjsonDlg::IDD, pParent) + , show_tree_tooltips_(true) + , show_list_tooltips_(true) +{ + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void ChgjsonDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_TREE1, tree_); + DDX_Control(pDX, IDC_LIST3, depends_); + DDX_Control(pDX, IDC_LIST_VALUES, constraint_list_); + DDX_Control(pDX, IDC_COMBO3, type_); + DDX_Control(pDX, IDC_COMBO4, constraint_); + DDX_Control(pDX, IDC_COMBO2, logic_); + DDX_Control(pDX, IDC_COMBO1, depend_item_); + DDX_Control(pDX, IDC_COMBO_DEFAULT, combo_default_); +} + +BEGIN_MESSAGE_MAP(ChgjsonDlg, CDialogEx) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_COMMAND(ID_TREE_ADDGROUP, &ChgjsonDlg::OnTreeAddGroup) + ON_COMMAND(ID_TREE_ADDITEM, &ChgjsonDlg::OnTreeAddItem) + ON_COMMAND(ID_TREE_DELITEM, &ChgjsonDlg::OnTreeDelItem) + ON_COMMAND(ID_TREE_ADDPRODUCT, &ChgjsonDlg::OnTreeAddProduct) + ON_BN_CLICKED(IDC_BUTTON3, &ChgjsonDlg::OnBnClickedButton3) + ON_BN_CLICKED(IDC_BUTTON1, &ChgjsonDlg::OnBnClickedButton1) + ON_BN_CLICKED(IDC_BUTTON2, &ChgjsonDlg::OnBnClickedButton2) + ON_CBN_SELCHANGE(IDC_COMBO3, &ChgjsonDlg::OnCbnSelchangeDataType) + ON_CBN_SELCHANGE(IDC_COMBO4, &ChgjsonDlg::OnCbnSelchangeConstraintType) + ON_CBN_SELCHANGE(IDC_COMBO1, &ChgjsonDlg::OnCbnSelchangeDependItem) + ON_CBN_SELCHANGE(IDC_COMBO2, &ChgjsonDlg::OnCbnSelchangeLogic) + ON_NOTIFY(LVN_ENDLABELEDIT, IDC_LIST_VALUES, &ChgjsonDlg::OnLvnEndlabeleditListValues) + ON_BN_CLICKED(IDC_CHECK1, &ChgjsonDlg::OnBnClickedDepend) + ON_BN_CLICKED(IDC_BUTTON4, &ChgjsonDlg::OnBnClickedButton4) + ON_NOTIFY(NM_RCLICK, IDC_TREE1, &ChgjsonDlg::OnNMRClickMfcshelltree1) + ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &ChgjsonDlg::OnTvnSelchangedTree1) + ON_COMMAND(ID_LISTMENU_SETDEFAULT, &ChgjsonDlg::OnListmenuSetdefault) + ON_COMMAND(ID_LISTMENU_DELETE, &ChgjsonDlg::OnListmenuDelete) + ON_NOTIFY(NM_RCLICK, IDC_LIST_VALUES, &ChgjsonDlg::OnNMRClickListValues) + ON_LBN_DBLCLK(IDC_LIST3, &ChgjsonDlg::OnLbnDblclkList3) + ON_WM_DROPFILES() + ON_COMMAND(ID_TREE_RENAME, &ChgjsonDlg::OnTreeRename) + ON_COMMAND(ID_TREE_LOADFILE, &ChgjsonDlg::OnTreeLoadfile) + ON_NOTIFY(LVN_KEYDOWN, IDC_LIST_VALUES, &ChgjsonDlg::OnLvnKeydownListValues) + ON_NOTIFY(TVN_KEYDOWN, IDC_TREE1, &ChgjsonDlg::OnTvnKeydownTree1) + ON_NOTIFY(TVN_GETINFOTIP, IDC_TREE1, &ChgjsonDlg::OnTvnGetInfoTipTree1) + ON_NOTIFY(LVN_GETINFOTIP, IDC_LIST_VALUES, &ChgjsonDlg::OnLvnGetInfoTipListValues) + ON_COMMAND(ID_TREE_TOOLTIPS, &ChgjsonDlg::OnTreeTooltips) + ON_COMMAND(ID_LISTMENU_TOOLTIPS, &ChgjsonDlg::OnListmenuTooltips) +END_MESSAGE_MAP() + + +// ChgjsonDlg message handlers +int get_cur_sel(CListCtrl* lc) +{ + POSITION pos = lc->GetFirstSelectedItemPosition(); + int sel = lc->GetNextSelectedItem(pos); + + return sel; +} +std::wstring get_tree_selected_item_text(CTreeCtrl* tree, HTREEITEM root) +{ + CString t(tree->GetItemText(root)); + std::wstring ret(t.GetBuffer()); + + t.ReleaseBuffer(); + + return ret; +} +std::wstring get_tree_selected_item_text(CTreeCtrl* tree, DWORD_PTR* data) +{ + HTREEITEM sel = tree->GetSelectedItem(); + + if (data) + *data = 0; + + if (sel) + { + if (data) + *data = tree->GetItemData(sel); + + return get_tree_selected_item_text(tree, sel); + } + else + return L""; +} +bool split(std::wstring str, ChgjsonDlg::DEPENDITEM* di) +{ + size_t pos = str.find(L"!"); + + if (pos == std::wstring::npos) + { + pos = str.find(L">"); + if (pos == std::wstring::npos) + { + pos = str.find(L"<"); + if (pos == std::wstring::npos) + { + pos = str.find(L"="); + } + } + } + + if (pos == std::wstring::npos) + return false; + + di->parent = str.substr(0, pos); + di->logic_values = str.substr(pos); + + return true; +} + +BOOL ChgjsonDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD); + constraint_list_.InsertColumn(0, TEXT("Value lists"), 0, 177); + constraint_list_.InsertColumn(1, TEXT("Default"), 0, 48); + type_.SetCurSel(0); + constraint_.SetCurSel(0); +// constraint_list_.ModifyStyleEx(0, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_INFOTIP); + constraint_list_.SetExtendedStyle(constraint_list_.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_INFOTIP); + constraint_list_.SetItemData(constraint_list_.InsertItem(constraint_list_.GetItemCount(), TEXT("click me to add value ...")), 1); + tree_menu_.LoadMenu(IDR_MENU1); + func_menu_.LoadMenu(IDR_MENU2); + + BITMAP bmi = { 0 }; + GetObject(LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1)), sizeof(bmi), &bmi); + tree_img_.Create(IDB_BITMAP1, bmi.bmWidth / 2, bmi.bmWidth / 2, RGB(255, 255, 255)); + tree_.SetImageList(&tree_img_, TVSIL_NORMAL); + init_control_statu(); + + return TRUE; // return TRUE unless you set the focus to a control +} + +void ChgjsonDlg::init_control_statu(void) +{ + HTREEITEM root = tree_.GetSelectedItem(); + BOOL valid = FALSE; + int type_ind = 0, constraint_ind = 0, default_ind = 1; + + GetDlgItem(IDC_STATIC_DEFAULT2)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_COMBO_DEFAULT)->ShowWindow(SW_HIDE); + + if (root) + { + DWORD_PTR ptr = NULL; + std::wstring t(get_tree_selected_item_text(&tree_, &ptr)); + DWORD data = (DWORD)ptr; + + if (data == TREE_ITEM_CONFIG) + { + std::vector::iterator it = std::find(hg_items_.begin(), hg_items_.end(), t.c_str()); + if (it != hg_items_.end()) + { + valid = TRUE; + set_control_status(*it); + } + } + } + + GetDlgItem(IDC_EDIT_DESC)->EnableWindow(valid); + GetDlgItem(IDC_CHECK_ADVANCED)->EnableWindow(valid); + constraint_.EnableWindow(valid); + depends_.EnableWindow(valid); + type_.EnableWindow(valid); + + GetDlgItem(IDC_RADIO_ALL)->EnableWindow(valid); + GetDlgItem(IDC_RADIO_ANY)->EnableWindow(valid); + depend_item_.EnableWindow(valid); + logic_.EnableWindow(valid); + GetDlgItem(IDC_EDIT_LOWER)->EnableWindow(valid); + GetDlgItem(IDC_BUTTON1)->EnableWindow(valid); + GetDlgItem(IDC_BUTTON2)->EnableWindow(valid); + GetDlgItem(IDC_BUTTON3)->EnableWindow(valid); + GetDlgItem(IDC_BUTTON4)->EnableWindow(valid); +} +void ChgjsonDlg::delete_tree_item(HTREEITEM root) +{ + HTREEITEM child = tree_.GetChildItem(root); + + while (child) + { + delete_tree_item(child); + child = tree_.GetChildItem(root); + } + + std::wstring name(get_tree_selected_item_text(&tree_, root)); + std::vector::iterator it = std::find(hg_items_.begin(), hg_items_.end(), name.c_str()); + + tree_.DeleteItem(root); + if (it != hg_items_.end()) + { + // delete depending items ... + for (size_t i = 0; i < hg_items_.size(); ++i) + { + if (i == it - hg_items_.begin()) + continue; + + std::vector::iterator d = std::find(hg_items_[i].depend.begin(), hg_items_[i].depend.end(), name.c_str()); + while (d != hg_items_[i].depend.end()) + { + hg_items_[i].depend.erase(d); + d = std::find(hg_items_[i].depend.begin(), hg_items_[i].depend.end(), name.c_str()); + } + } + hg_items_.erase(it); + } +} +int ChgjsonDlg::find_config_item(const wchar_t* item_name) +{ + std::vector::iterator it = std::find(hg_items_.begin(), hg_items_.end(), item_name); + + if (it == hg_items_.end()) + return -1; + else + return it - hg_items_.begin(); +} +int ChgjsonDlg::check_depend(const wchar_t* l, const wchar_t* r) +{ + // -1: l depends on r; 0: no depend; 1: r depends on l + int depend = 0; + std::vector::iterator il = std::find(hg_items_.begin(), hg_items_.end(), l), + ir = std::find(hg_items_.begin(), hg_items_.end(), r); + + if (il != hg_items_.end() && ir != hg_items_.end()) + { + std::vector::iterator it = std::find(il->depend.begin(), il->depend.end(), r); + if (it != il->depend.end()) + depend = -1; + else + { + it = std::find(ir->depend.begin(), ir->depend.end(), l); + if (it != ir->depend.end()) + depend = 1; + } + } + + return depend; +} +void ChgjsonDlg::set_control_status(const HGITEM& item) +{ + ::SetDlgItemTextW(m_hWnd, IDC_EDIT_DESC, item.desc.c_str()); + + if (item.type == L"bool") + type_.SetCurSel(0); + else if (item.type == L"int") + type_.SetCurSel(1); + else if (item.type == L"float") + type_.SetCurSel(2); + else if (item.type == L"string") + type_.SetCurSel(3); + else // if (item.type == L"button") + type_.SetCurSel(4); + + ((CButton*)GetDlgItem(IDC_CHECK_ADVANCED))->SetCheck(item.advanced ? BST_CHECKED : BST_UNCHECKED); + + // value ... + GetDlgItem(IDC_STATIC_FROM)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_TO)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_FROM)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_TO)->ShowWindow(SW_HIDE); + constraint_list_.ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_DEFAULT)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_COMBO_DEFAULT)->ShowWindow(SW_HIDE); + constraint_.SetCurSel(item.range.type); + if (item.range.type == RANGE_TYPE_NONE) + { + GetDlgItem(IDC_STATIC_DEFAULT)->ShowWindow(SW_SHOW); + if (item.type == L"bool") + { + GetDlgItem(IDC_COMBO_DEFAULT)->ShowWindow(SW_SHOW); + ((CComboBox*)GetDlgItem(IDC_COMBO_DEFAULT))->SetCurSel(item.init_val == L"true"); + } + else + { + GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); + ::SetDlgItemTextW(m_hWnd, IDC_EDIT_DEFAULT, item.init_val.c_str()); + } + } + else if (item.range.type == RANGE_TYPE_RANGE) + { + GetDlgItem(IDC_STATIC_DEFAULT)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); + ::SetDlgItemTextW(m_hWnd, IDC_EDIT_DEFAULT, item.init_val.c_str()); + + GetDlgItem(IDC_STATIC_FROM)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_STATIC_TO)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_FROM)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_TO)->ShowWindow(SW_SHOW); + + if (item.type == L"int") + { + SetDlgItemInt(IDC_EDIT_FROM, item.range.lower); + SetDlgItemInt(IDC_EDIT_TO, item.range.upper); + } + else + { + wchar_t buf[80] = { 0 }; + + swprintf_s(buf, _countof(buf) - 1, L"%f", item.range.lower); + ::SetDlgItemTextW(m_hWnd, IDC_EDIT_FROM, buf); + + swprintf_s(buf, _countof(buf) - 1, L"%f", item.range.upper); + ::SetDlgItemTextW(m_hWnd, IDC_EDIT_TO, buf); + } + } + else // list + { + constraint_list_.ShowWindow(SW_SHOW); + constraint_list_.DeleteAllItems(); + for (size_t i = 0; i < item.range.queue.size(); ++i) + { + int ind = constraint_list_.InsertItem(constraint_list_.GetItemCount(), item.range.queue[i].c_str()); + if (item.range.queue[i] == item.init_val) + constraint_list_.SetItemText(ind, 1, TEXT("yes")); + } + + int ind = constraint_list_.InsertItem(constraint_list_.GetItemCount(), TEXT("click me to add new item ...")); + constraint_list_.SetItemData(ind, 1); + } + + // depend + ((CButton*)GetDlgItem(IDC_CHECK1))->SetCheck(BST_UNCHECKED); + ((CButton*)GetDlgItem(IDC_RADIO_ANY))->SetCheck(BST_UNCHECKED); + ((CButton*)GetDlgItem(IDC_RADIO_ALL))->SetCheck(BST_UNCHECKED); + GetDlgItem(IDC_RADIO_ALL)->EnableWindow(FALSE); + GetDlgItem(IDC_RADIO_ANY)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_LOWER)->EnableWindow(FALSE); + GetDlgItem(IDC_COMBO_BOOL)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_AND)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_UPPER)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE); + GetDlgItem(IDC_LIST3)->EnableWindow(FALSE); + depends_.ResetContent(); + if (item.depend.size()) + { + ((CButton*)GetDlgItem(IDC_CHECK1))->SetCheck(BST_CHECKED); + OnBnClickedDepend(); + if (item.depend_or) + { + ((CButton*)GetDlgItem(IDC_RADIO_ANY))->SetCheck(BST_CHECKED); + ((CButton*)GetDlgItem(IDC_RADIO_ALL))->SetCheck(BST_UNCHECKED); + } + else + { + ((CButton*)GetDlgItem(IDC_RADIO_ANY))->SetCheck(BST_UNCHECKED); + ((CButton*)GetDlgItem(IDC_RADIO_ALL))->SetCheck(BST_CHECKED); + } + for (size_t i = 0; i < item.depend.size(); ++i) + { + depends_.AddString((item.depend[i].parent + item.depend[i].logic_values).c_str()); + } + } +} + +void* ChgjsonDlg::create_json(int item) +{ + known_file_util::IJsonW* jsn = known_file_util::create_jsonW(); + wchar_t buf[128] = { 0 }; + + jsn->set_value(L"category", hg_items_[item].advanced ? L"advanced" : L"base"); + swprintf_s(buf, _countof(buf) - 1, L"cfg-%d", hg_items_[item].index); + jsn->set_value(L"name", buf); + jsn->set_value(L"title", hg_items_[item].title.c_str()); + jsn->set_value(L"desc", hg_items_[item].desc.c_str()); + jsn->set_value(L"type", hg_items_[item].type.c_str()); + if (hg_items_[item].type == L"bool") + { + jsn->set_value(L"cur", hg_items_[item].init_val == L"true"); + jsn->set_value(L"default", hg_items_[item].init_val == L"true"); + } + else if (hg_items_[item].type == L"int") + { + jsn->set_value(L"cur", _wtoi(hg_items_[item].init_val.c_str())); + jsn->set_value(L"default", _wtoi(hg_items_[item].init_val.c_str())); + } + else if (hg_items_[item].type == L"float") + { + jsn->set_value(L"cur", _wtof(hg_items_[item].init_val.c_str())); + jsn->set_value(L"default", _wtof(hg_items_[item].init_val.c_str())); + } + else + { + jsn->set_value(L"cur", hg_items_[item].init_val.c_str()); + jsn->set_value(L"default", hg_items_[item].init_val.c_str()); + } + jsn->set_value(L"size", hg_items_[item].bytes); + + if (hg_items_[item].range.type == RANGE_TYPE_RANGE) + { + known_file_util::IJsonW *r = known_file_util::create_jsonW(); + if (hg_items_[item].type == L"int") + { + r->set_value(L"min", (int)hg_items_[item].range.lower); + r->set_value(L"max", (int)hg_items_[item].range.upper); + } + else + { + r->set_value(L"min", hg_items_[item].range.lower); + r->set_value(L"max", hg_items_[item].range.upper); + } + jsn->set_value(L"range", r); + r->release(); + } + else if (hg_items_[item].range.type == RANGE_TYPE_LIST) + { + known_file_util::IJsonW *r = known_file_util::create_jsonW(); + r->set_as_array(true); + if (hg_items_[item].type == L"int") + { + for (size_t i = 0; i < hg_items_[item].range.queue.size(); ++i) + { + *r += _wtoi(hg_items_[item].range.queue[i].c_str()); + } + } + else if (hg_items_[item].type == L"float") + { + for (size_t i = 0; i < hg_items_[item].range.queue.size(); ++i) + { + *r += _wtof(hg_items_[item].range.queue[i].c_str()); + } + } + else if (hg_items_[item].type == L"string") + { + int size = 0; + for (size_t i = 0; i < hg_items_[item].range.queue.size(); ++i) + { + *r += hg_items_[item].range.queue[i].c_str(); + if (size < coding::string_need_bytes(hg_items_[item].range.queue[i].c_str())) + size = coding::string_need_bytes(hg_items_[item].range.queue[i].c_str()); + } + if (hg_items_[item].bytes < size) + jsn->set_value(L"size", size); + } + jsn->set_value(L"range", r); + r->release(); + } + + if (hg_items_[item].depend.size()) + { + known_file_util::IJsonW *d = known_file_util::create_jsonW(); + d->set_as_array(true); + for (int i = 0; i < hg_items_[item].depend.size(); ++i) + { + int ind = find_config_item(hg_items_[item].depend[i].parent.c_str()); + if (ind != -1) + { + swprintf_s(buf, _countof(buf) - 1, L"%d", hg_items_[ind].index); + // d->set_value(i, (buf + hg_items_[item].depend[i].logic_values).c_str(), true); + *d += (buf + hg_items_[item].depend[i].logic_values).c_str(); + } + } + + if (hg_items_[item].depend_or) + jsn->set_value(L"depend_or", d); + else + jsn->set_value(L"depend_and", d); + d->release(); + } + + return jsn; +} +std::string ChgjsonDlg::to_json_text(void) +{ + known_file_util::IJsonW *jsn = known_file_util::create_jsonW(), *item = NULL; + HTREEITEM root = tree_.GetRootItem(), child = NULL; + std::wstring val(get_tree_selected_item_text(&tree_, root)); + int count = 1, group = 1, ind = 0; + wchar_t buf[128] = { 0 }; + + jsn->set_value(L"device_type", val.c_str()); + jsn->set_value(L"option_count", (int)hg_items_.size()); // occupy position + root = tree_.GetChildItem(root); + while (root) + { + if ((DWORD)tree_.GetItemData(root) == TREE_ITEM_CONFIG) + { + val = get_tree_selected_item_text(&tree_, root); + ind = find_config_item(val.c_str()); + if (ind != -1) + { + hg_items_[ind].index = count++; + item = (known_file_util::IJsonW*)create_json(ind); + swprintf_s(buf, _countof(buf) - 1, L"%d", hg_items_[ind].index); + jsn->set_value(buf, item); + item->release(); + item = NULL; + } + } + else + { + val = get_tree_selected_item_text(&tree_, root); + item = known_file_util::create_jsonW(); + item->set_value(L"category", L"base"); + swprintf_s(buf, _countof(buf) - 1, L"grp-%d", group++); + item->set_value(L"name", buf); + item->set_value(L"title", val.c_str()); + item->set_value(L"type", L"group"); + swprintf_s(buf, _countof(buf) - 1, L"%d", count++); + jsn->set_value(buf, item); + + child = tree_.GetChildItem(root); + while (child) + { + val = get_tree_selected_item_text(&tree_, child); + ind = find_config_item(val.c_str()); + if (ind != -1) + { + hg_items_[ind].index = count++; + if (item) + { + item->set_value(L"category", hg_items_[ind].advanced ? L"advanced" : L"base"); + item->release(); + } + item = (known_file_util::IJsonW*)create_json(ind); + + swprintf_s(buf, _countof(buf) - 1, L"%d", hg_items_[ind].index); + jsn->set_value(buf, item); + item->release(); + item = NULL; + } + child = tree_.GetNextSiblingItem(child); + } + if (item) + item->release(); + } + + root = tree_.GetNextSiblingItem(root); + } + + val = L""; + jsn->set_value(L"option_count", count); + jsn->to_string(coding::get_wstring, &val); + jsn->release(); + + std::string utf8(""); + coding_util::unicode_2_utf8(val.c_str(), coding::get_string, &utf8); + + return utf8; +} +void ChgjsonDlg::add_item(void* jsn_root, void* jsn_obj, HTREEITEM parent) +{ + known_file_util::IJsonW *jsn = (known_file_util::IJsonW*)jsn_obj, *child = NULL, + *root = (known_file_util::IJsonW*)jsn_root; + const wchar_t *val = NULL; + HGITEM item; + wchar_t buf[128] = { 0 }; + + jsn->get_value(L"title", &val); + if (!val) + return; + + item.title = val; + parent = add_tree_item(val, TREE_ITEM_CONFIG, parent); + + jsn->get_value(L"desc", &val); + if (val) + item.desc = val; + + jsn->get_value(L"type", &val); + if (val) + item.type = val; + + if (item.type == L"bool") + { + bool v = false; + jsn->get_value(L"default", v); + item.init_val = v ? L"true" : L"false"; + } + else if (item.type == L"int") + { + int v = 0; + jsn->get_value(L"default", v); + swprintf_s(buf, _countof(buf) - 1, L"%d", v); + item.init_val = buf; + } + else if (item.type == L"float") + { + double v = 0; + jsn->get_value(L"default", v); + swprintf_s(buf, _countof(buf) - 1, L"%f", v); + item.init_val = buf; + } + else + { + jsn->get_value(L"default", &val); + if (val) + item.init_val = val; + else + item.init_val = L""; + } + jsn->get_value(L"size", item.bytes); + + jsn->get_value(L"category", &val); + if (val && wcscmp(val, L"advanced") == 0) + item.advanced = true; + + jsn->get_value(L"depend_and", &child); + if (child) + { + item.depend_or = false; + } + else + { + jsn->get_value(L"depend_or", &child); + if (child) + item.depend_or = true; + } + if (child) + { + if (child->members()) + { + known_file_util::JSONMEMW m = child->first_member(known_file_util::JV_STRING); + DEPENDITEM di; + + if (split(m.str_val, &di)) + { + known_file_util::IJsonW *d = NULL; + root->get_value(di.parent.c_str(), &d); + if (d) + { + d->get_value(L"title", &val); + if (val) + { + di.parent = val; + item.depend.push_back(di); + } + d->release(); + } + } + for (int i = 1; i < child->members(); ++i) + { + m = child->next_member(); + if (split(m.str_val, &di)) + { + known_file_util::IJsonW *d = NULL; + root->get_value(di.parent.c_str(), &d); + if (d) + { + d->get_value(L"title", &val); + if (val) + { + di.parent = val; + item.depend.push_back(di); + } + d->release(); + } + } + } + } + child->release(); + } + + jsn->get_value(L"range", &child); + if (child) + { + if (item.type == L"int") + { + int l = 0, u = 0; + if (child->get_value(L"min", l)) + { + child->get_value(L"max", u); + item.range.lower = l; + item.range.upper = u; + item.range.type = RANGE_TYPE_RANGE; + } + else + { + item.range.type = RANGE_TYPE_LIST; + if (child->members()) + { + known_file_util::JSONMEMW m = child->first_member(known_file_util::JV_INT); + swprintf_s(buf, _countof(buf) - 1, L"%d", m.double_val); + item.range.queue.push_back(buf); + for (int i = 1; i < child->members(); ++i) + { + m = child->next_member(); + swprintf_s(buf, _countof(buf) - 1, L"%d", m.double_val); + item.range.queue.push_back(buf); + } + } + } + } + else if (item.type == L"float") + { + if (child->get_value(L"min", item.range.lower)) + { + child->get_value(L"max", item.range.upper); + item.range.type = RANGE_TYPE_RANGE; + } + else + { + item.range.type = RANGE_TYPE_LIST; + + if (child->members()) + { + known_file_util::JSONMEMW m = child->first_member(known_file_util::JV_FLOAT); + swprintf_s(buf, _countof(buf) - 1, L"%f", m.double_val); + item.range.queue.push_back(buf); + for (int i = 1; i < child->members(); ++i) + { + m = child->next_member(); + swprintf_s(buf, _countof(buf) - 1, L"%f", m.double_val); + item.range.queue.push_back(buf); + } + } + } + } + else if (item.type == L"string") + { + item.range.type = RANGE_TYPE_LIST; + if (child->members()) + { + known_file_util::JSONMEMW m = child->first_member(known_file_util::JV_STRING); + item.range.queue.push_back(m.str_val); + for (int i = 1; i < child->members(); ++i) + { + m = child->next_member(); + item.range.queue.push_back(m.str_val); + } + } + } + + child->release(); + } + else + item.range.type = RANGE_TYPE_NONE; + + hg_items_.push_back(item); +} +bool ChgjsonDlg::load_from_json_text(const wchar_t* txt) +{ + int pos = 0; + known_file_util::IJsonW *jsn = known_file_util::create_jsonW(txt, &pos), *child = NULL; + + if (!jsn) + return false; + + hg_items_.clear(); + tree_.DeleteAllItems(); + + const wchar_t* val = NULL; + HTREEITEM root = NULL, son = NULL; + int count = 0; + + jsn->get_value(L"device_type", &val); + if (val) + root = add_tree_item(val, TREE_ITEM_PRODUCT); + else + root = add_tree_item(L"Unkonwn Product", TREE_ITEM_PRODUCT); + son = root; + jsn->get_value(L"option_count", count); + + GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE); + GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE); + for (int i = 1; i < count; ++i) + { + wchar_t key[20] = { 0 }; + + swprintf_s(key, _countof(key) - 1, L"%d", i); + jsn->get_value(key, &child); + if (child) + { + child->get_value(L"type", &val); + if (val) + { + if (wcscmp(val, L"group") == 0) + { + child->get_value(L"title", &val); + if (!val) + { + val = key; + swprintf_s(key, _countof(key) - 1, L"group-%d", i); + } + son = add_tree_item(val, TREE_ITEM_GROUP, root); + } + else + { + add_item(jsn, child, son); + } + } + child->release(); + } + } + + jsn->release(); + tree_.Expand(root, TVE_EXPAND); + + return true; +} +bool ChgjsonDlg::load_from_file(const wchar_t* path_file) +{ + std::string cont(""); + std::wstring unic(L""); + bool ret = false; + + file_util::load_file(path_file, coding::get_string, &cont); + coding_util::bom::to_unicode(cont.c_str(), cont.length(), coding::get_wstring, &unic); + if (unic.length()) + { + if (!load_from_json_text(unic.c_str())) + { + unic = path_file; + unic.insert(0, L"Parse json file '"); + unic += L"' failed"; + ::MessageBoxW(m_hWnd, unic.c_str(), L"Error", MB_OK); + } + else + ret = true; + } + + return ret; +} +void ChgjsonDlg::get_all_names(HTREEITEM root, std::vector& names, DWORD mask) +{ + if (((DWORD)tree_.GetItemData(root) & mask) == mask) + names.push_back(get_tree_selected_item_text(&tree_, root)); + + HTREEITEM child = tree_.GetChildItem(root); + while (child) + { + get_all_names(child, names, mask); + + child = tree_.GetNextSiblingItem(child); + } +} +void ChgjsonDlg::on_config_name_changed(const wchar_t* prev, const wchar_t* now) +{ + for (size_t i = 0; i < hg_items_.size(); ++i) + { + if (hg_items_[i].title == prev) + { + hg_items_[i].title = now; + } + else + { + std::vector::iterator it = std::find(hg_items_[i].depend.begin(), hg_items_[i].depend.end(), prev); + while (it != hg_items_[i].depend.end()) + { + it->parent = now; + it = std::find(hg_items_[i].depend.begin(), hg_items_[i].depend.end(), prev); + } + } + } +} +HTREEITEM ChgjsonDlg::add_tree_item(const wchar_t* title, DWORD data, HTREEITEM parent, HTREEITEM after) +{ + HTREEITEM i = tree_.InsertItem(title, parent, after); + TVITEM item; + + item.mask = TVIF_SELECTEDIMAGE; + item.iSelectedImage = 1; + item.hItem = i; + tree_.SetItem(&item); + + tree_.SetItemData(i, (DWORD_PTR)data); + + return i; +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void ChgjsonDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialogEx::OnPaint(); + } +} + +// The system calls this function to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR ChgjsonDlg::OnQueryDragIcon() +{ + return static_cast(m_hIcon); +} + + + +void ChgjsonDlg::OnTreeAddProduct() +{ + // TODO: Add your command handler code here + CDlgInput input; + + get_all_names(tree_.GetRootItem(), input.used_names_); + if (input.DoModal() == IDOK) + { + add_tree_item(input.value_.GetBuffer(), TREE_ITEM_PRODUCT); + input.value_.ReleaseBuffer(); + } +} +void ChgjsonDlg::OnTreeAddGroup() +{ + // TODO: Add your command handler code here + HTREEITEM parent = tree_.GetSelectedItem(); + + if (parent) + { + CDlgInput input; + + get_all_names(tree_.GetRootItem(), input.used_names_); + if (input.DoModal() == IDOK) + { + HTREEITEM h = add_tree_item(input.value_.GetBuffer(), TREE_ITEM_GROUP, parent); + + tree_.SelectItem(h); + tree_.EnsureVisible(h); + input.value_.ReleaseBuffer(); + OnTvnSelchangedTree1(NULL, NULL); + } + } +} +void ChgjsonDlg::OnTreeAddItem() +{ + // TODO: Add your command handler code here + HTREEITEM parent = tree_.GetSelectedItem(); + + if (parent) + { + CDlgInput input; + + get_all_names(tree_.GetRootItem(), input.used_names_); + if (input.DoModal() == IDOK) + { + HTREEITEM h = add_tree_item(input.value_.GetBuffer(), TREE_ITEM_CONFIG, parent); + + input.value_.ReleaseBuffer(); + if (h) + { + HGITEM i(input.value_.GetBuffer()); + + input.value_.ReleaseBuffer(); + tree_.SelectItem(h); + tree_.EnsureVisible(h); + + hg_items_.push_back(i); + OnTvnSelchangedTree1(NULL, NULL); + } + } + } +} +void ChgjsonDlg::OnTreeDelItem() +{ + // TODO: Add your command handler code here + HTREEITEM parent = tree_.GetSelectedItem(); + if (parent) + { + delete_tree_item(parent); + OnTvnSelchangedTree1(NULL, NULL); + } +} +void ChgjsonDlg::OnTreeRename() +{ + // TODO: Add your command handler code here + DWORD_PTR ptr = NULL; + std::wstring t(get_tree_selected_item_text(&tree_, &ptr)); + CDlgInput input; + + get_all_names(tree_.GetRootItem(), input.used_names_); + std::vector::iterator it = std::find(input.used_names_.begin(), input.used_names_.end(), t); + if (it != input.used_names_.end()) + input.used_names_.erase(it); + + input.value_ = t.c_str(); + if (input.DoModal() == IDOK && input.value_.GetLength()) + { + std::wstring now(input.value_); + TVITEM item; + + item.mask = TVIF_TEXT; + item.pszText = &now[0]; + item.hItem = tree_.GetSelectedItem(); + tree_.SetItem(&item); + if ((DWORD)ptr == TREE_ITEM_CONFIG) + { + on_config_name_changed(t.c_str(), now.c_str()); + } + } +} + + +void ChgjsonDlg::OnBnClickedButton1() +{ + // TODO: Add your control notification handler code here + // export to file + std::string txt(to_json_text()); + + file_util::set_clipboard(txt.c_str(), txt.length()); + MessageBox(TEXT("JSON text has set to clipboard already")); +} +void ChgjsonDlg::OnBnClickedButton2() +{ + // TODO: Add your control notification handler code here + // export to code-text, replace '"' with '\"', '\' with '\\' + std::string txt(to_json_text()); + size_t pos = txt.find("\""); + + while (pos != std::string::npos) + { + txt.insert(pos, "\\"); + pos = txt.find("\"", pos + 2); + } + + pos = txt.find("\\u"); + while (pos != std::string::npos) + { + txt.insert(pos, "\\"); + pos = txt.find("\\u", pos + 3); + } + + file_util::set_clipboard(txt.c_str(), txt.length()); + MessageBox(TEXT("JSON text has set to clipboard already")); +} + + +void ChgjsonDlg::OnCbnSelchangeDataType() +{ + // TODO: Add your control notification handler code here + // bool;int;float;string; + wchar_t type[40] = { 0 }; + + ::GetWindowTextW(type_.m_hWnd, type, _countof(type) - 1); + constraint_.ResetContent(); + constraint_.AddString(TEXT("none")); + if (wcscmp(type, L"bool") == 0) + { + constraint_.SetCurSel(0); + combo_default_.SetCurSel(1); + } + else + { + constraint_.AddString(TEXT("range")); + constraint_.AddString(TEXT("list")); + + constraint_.SetCurSel(0); + combo_default_.ShowWindow(SW_HIDE); + } + OnCbnSelchangeConstraintType(); +} +void ChgjsonDlg::OnCbnSelchangeConstraintType() +{ + // TODO: Add your control notification handler code here + // none;range;list; + int sel = constraint_.GetCurSel(); + wchar_t type[40] = { 0 }; + + ::GetWindowTextW(type_.m_hWnd, type, _countof(type) - 1); + if (wcscmp(type, L"string") == 0 && sel == 1) + { + MessageBox(TEXT("'string' type cannot be in RANGE constraint.")); + constraint_.SetCurSel(0); + sel = 0; + } + + combo_default_.ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_DEFAULT)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_DEFAULT2)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_FROM)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_TO)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_FROM)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_TO)->ShowWindow(SW_HIDE); + constraint_list_.ShowWindow(SW_HIDE); + + if (sel == 0) + { + if (wcscmp(type, L"string") == 0) + GetDlgItem(IDC_STATIC_DEFAULT2)->ShowWindow(SW_SHOW); + else + GetDlgItem(IDC_STATIC_DEFAULT)->ShowWindow(SW_SHOW); + if (wcscmp(type, L"bool") == 0) + combo_default_.ShowWindow(SW_SHOW); + else + GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); + } + else if (sel == 1) + { + GetDlgItem(IDC_STATIC_FROM)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_STATIC_TO)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_FROM)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_TO)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_STATIC_DEFAULT)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); + } + else // if( sel == 2) + { + constraint_list_.ShowWindow(SW_SHOW); + } +} + + +void ChgjsonDlg::OnCbnSelchangeDependItem() +{ + // TODO: Add your control notification handler code here + int sel = depend_item_.GetCurSel(), d_ind = -1; + wchar_t name[128] = { 0 }, type[128] = { 0 }; + + ::GetWindowTextW(depend_item_.m_hWnd, name, _countof(name) - 1); + ::GetWindowTextW(type_.m_hWnd, type, _countof(type) - 1); + d_ind = find_config_item(name); + if (d_ind < 0) + { + std::wstring info(L"Depend item '"); + info += name; + info += L"' is not found!"; + ::MessageBoxW(m_hWnd, info.c_str(), L"Err", MB_OK); + return; + } + + // ==;!=;>;>=;<;<=;between;out of; + GetDlgItem(IDC_STATIC_AND)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_UPPER)->ShowWindow(SW_HIDE); + + logic_.ResetContent(); + logic_.AddString(L"=="); + logic_.AddString(L"!="); + if (hg_items_[d_ind].type == L"bool") + { + GetDlgItem(IDC_COMBO_BOOL)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_LOWER)->ShowWindow(SW_HIDE); + + CComboBox* val = (CComboBox*)GetDlgItem(IDC_COMBO_BOOL); + val->ResetContent(); + val->AddString(L"false"); + val->AddString(L"true"); + val->SetCurSel(1); + } + else if (hg_items_[d_ind].range.queue.size()) + { + GetDlgItem(IDC_COMBO_BOOL)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_LOWER)->ShowWindow(SW_HIDE); + + CComboBox* val = (CComboBox*)GetDlgItem(IDC_COMBO_BOOL); + val->ResetContent(); + for (int i = 0; i < hg_items_[d_ind].range.queue.size(); ++i) + { + val->AddString(hg_items_[d_ind].range.queue[i].c_str()); + } + val->SetCurSel(0); + } + else + { + if (hg_items_[d_ind].type == L"int" || hg_items_[d_ind].type == L"float") + { + logic_.AddString(L">"); + logic_.AddString(L">="); + logic_.AddString(L"<="); + logic_.AddString(L"<"); + logic_.AddString(L"between"); + logic_.AddString(L"out of"); + } + GetDlgItem(IDC_EDIT_LOWER)->ShowWindow(SW_SHOW); + } + logic_.SetCurSel(0); + OnCbnSelchangeLogic(); +} +void ChgjsonDlg::OnCbnSelchangeLogic() +{ + // TODO: Add your control notification handler code here + int count = logic_.GetCount(), + sel = logic_.GetCurSel(); + wchar_t text[128] = { 0 }; + + GetDlgItem(IDC_STATIC_AND)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_UPPER)->ShowWindow(SW_HIDE); + + ::GetWindowTextW(logic_.m_hWnd, text, _countof(text) - 1); + if (wcscmp(text, L"between") == 0 || wcscmp(text, L"out of") == 0) + { + GetDlgItem(IDC_STATIC_AND)->ShowWindow(SW_SHOW); + GetDlgItem(IDC_EDIT_UPPER)->ShowWindow(SW_SHOW); + } +} + + +void ChgjsonDlg::OnLvnEndlabeleditListValues(NMHDR *pNMHDR, LRESULT *pResult) +{ + NMLVDISPINFO *pDispInfo = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + *pResult = 0; + DWORD_PTR data = constraint_list_.GetItemData(pDispInfo->item.iItem); + + if (!pDispInfo->item.pszText || *pDispInfo->item.pszText == 0) + return; + + constraint_list_.SetItemText(pDispInfo->item.iItem, pDispInfo->item.iSubItem, pDispInfo->item.pszText); + constraint_list_.SetItemData(pDispInfo->item.iItem, 0); + if (constraint_list_.GetItemCount() == 1) + constraint_list_.SetItemText(pDispInfo->item.iItem, 1, TEXT("yes")); + + if (data) + { + int count = constraint_list_.GetItemCount(); + count = constraint_list_.InsertItem(count, TEXT("click me to add value ...")); + constraint_list_.SetItemData(count, 1); + } +} + + +void ChgjsonDlg::OnBnClickedDepend() +{ + // TODO: Add your control notification handler code here + // ---G100 + // | + // ---base + // | + // ---color-mode + // | + // ---scan-count + // + // ---advance + // | + // --- + HTREEITEM root = tree_.GetSelectedItem(); + BOOL enable = ((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck() == BST_CHECKED; + + if (root) + { + if (enable) + { + if ((DWORD)tree_.GetItemData(root) != TREE_ITEM_CONFIG) + { + ((CButton*)GetDlgItem(IDC_CHECK1))->SetCheck(BST_UNCHECKED); + MessageBox(TEXT("You must select a configuration item in the left tree first!"), NULL, MB_OK); + return; + } + + std::wstring name(get_tree_selected_item_text(&tree_, root)); + std::vector confs; + + get_all_names(tree_.GetRootItem(), confs, TREE_ITEM_CONFIG); + depends_.ResetContent(); + depend_item_.ResetContent(); + for (size_t i = 0; i < confs.size(); ++i) + { + if (confs[i] == name) + break; + + depend_item_.AddString(confs[i].c_str()); + } + } + + GetDlgItem(IDC_RADIO_ANY)->EnableWindow(enable); + GetDlgItem(IDC_RADIO_ALL)->EnableWindow(enable); + ((CButton*)GetDlgItem(IDC_RADIO_ANY))->SetCheck(BST_CHECKED); + depend_item_.EnableWindow(enable); + logic_.EnableWindow(enable); + GetDlgItem(IDC_EDIT_LOWER)->EnableWindow(enable); + GetDlgItem(IDC_BUTTON3)->EnableWindow(enable); + GetDlgItem(IDC_LIST3)->EnableWindow(enable); + } + else if (enable) + { + ((CButton*)GetDlgItem(IDC_CHECK1))->SetCheck(BST_UNCHECKED); + MessageBox(TEXT("You must select a configuration item in the left tree!"), NULL, MB_OK); + } +} + + +void ChgjsonDlg::OnBnClickedButton3() +{ + // TODO: Add your control notification handler code here + // add depend items + DEPENDITEM di; + wchar_t oper[128] = { 0 }; + bool or = ((CButton*)GetDlgItem(IDC_RADIO_ANY))->GetCheck() == BST_CHECKED; + DWORD_PTR data = NULL; + std::wstring name(get_tree_selected_item_text(&tree_, &data)); + std::vector::iterator it = std::find(hg_items_.begin(), hg_items_.end(), name.c_str()); + + if (it == hg_items_.end()) + { + name.insert(0, L"Not found the configuration named: "); + ::MessageBoxW(m_hWnd, name.c_str(), L"Error", MB_OK); + + return; + } + ::GetWindowTextW(depend_item_.m_hWnd, oper, _countof(oper) - 1); + di.parent = oper; + + // check recycle depend ... + std::vector::iterator dpn = std::find(hg_items_.begin(), hg_items_.end(), oper); + if (dpn != hg_items_.end()) + { + std::vector::iterator dpnd = std::find(dpn->depend.begin(), dpn->depend.end(), di.parent.c_str()); + if (dpnd != dpn->depend.end()) + { + name.insert(0, L" is already DEPEND on me("); + name.insert(0, oper); + name += L")! Delete me from it's depend queue first."; + ::MessageBoxW(m_hWnd, name.c_str(), L"Recycle Depending", MB_ICONSTOP | MB_OK); + return; + } + } + + ::GetWindowTextW(logic_.m_hWnd, oper, _countof(oper) - 1); + if (wcscmp(oper, L"between") == 0) + { + di.logic_values = L"==["; + ::GetWindowTextW(GetDlgItem(IDC_EDIT_LOWER)->m_hWnd, oper, _countof(oper) - 1); + di.logic_values += oper; + di.logic_values += L", "; + ::GetWindowTextW(GetDlgItem(IDC_EDIT_UPPER)->m_hWnd, oper, _countof(oper) - 1); + di.logic_values += oper; + di.logic_values += L"]"; + } + else if (wcscmp(oper, L"out of") == 0) + { + di.logic_values = L"!=["; + ::GetWindowTextW(GetDlgItem(IDC_EDIT_LOWER)->m_hWnd, oper, _countof(oper) - 1); + di.logic_values += oper; + di.logic_values += L", "; + ::GetWindowTextW(GetDlgItem(IDC_EDIT_UPPER)->m_hWnd, oper, _countof(oper) - 1); + di.logic_values += oper; + di.logic_values += L"]"; + } + else + { + di.logic_values = oper; + if (::IsWindowVisible(GetDlgItem(IDC_EDIT_LOWER)->m_hWnd)) + ::GetWindowTextW(GetDlgItem(IDC_EDIT_LOWER)->m_hWnd, oper, _countof(oper) - 1); + else + ::GetWindowTextW(GetDlgItem(IDC_COMBO_BOOL)->m_hWnd, oper, _countof(oper) - 1); + di.logic_values += oper; + } + + it->depend.push_back(di); + it->depend_or = or; +// if (depends_.FindString(-1, (di.parent + di.logic_values).c_str()) == -1) + depends_.AddString((di.parent + di.logic_values).c_str()); +} +void ChgjsonDlg::OnBnClickedButton4() +{ + // TODO: Add your control notification handler code here + // modify item attributes + DWORD_PTR data = NULL; + std::wstring name(get_tree_selected_item_text(&tree_, &data)); + + if ((DWORD)data != TREE_ITEM_CONFIG) + { + name += L" is not a configuration item."; + ::MessageBoxW(m_hWnd, name.c_str(), L"Err", MB_OK); + + return; + } + + std::vector::iterator it = std::find(hg_items_.begin(), hg_items_.end(), name.c_str()); + if (it == hg_items_.end()) + { + name += L" is not found."; + ::MessageBoxW(m_hWnd, name.c_str(), L"Err", MB_OK); + + return; + } + + wchar_t str[128] = { 0 }; + bool is_str = false; + + ::GetDlgItemTextW(m_hWnd, IDC_EDIT_DESC, str, _countof(str) - 1); + it->desc = str; + it->title = name; + + ::GetWindowTextW(type_.m_hWnd, str, _countof(str) - 1); + it->type = str; + it->advanced = ((CButton*)GetDlgItem(IDC_CHECK_ADVANCED))->GetCheck() == BST_CHECKED; + it->range.type = constraint_.GetCurSel(); + if (wcscmp(str, L"bool") == 0) + it->bytes = sizeof(SANE_Bool); + else if (wcscmp(str, L"int") == 0) + it->bytes = sizeof(SANE_Int); + else if (wcscmp(str, L"float") == 0) + it->bytes = sizeof(SANE_Fixed); + else // if (wcscmp(str, L"string") == 0) + { + it->bytes = GetDlgItemInt(IDC_EDIT_DEFAULT); + if (it->bytes <= 1 && it->range.type != RANGE_TYPE_LIST) + { + MessageBox(TEXT("Input max length in bytes of 'string' type")); + GotoDlgCtrl(GetDlgItem(IDC_EDIT_DEFAULT)); + return; + } + is_str = true; + } + + // constraints ... + it->range.queue.clear(); + if (it->range.type == RANGE_TYPE_LIST) + { + for (int i = 0; i < constraint_list_.GetItemCount(); ++i) + { + if (constraint_list_.GetItemData(i)) + continue; + + constraint_list_.GetItemText(i, 0, str, _countof(str) - 1); + it->range.queue.push_back(str); + if (is_str && it->bytes < coding::string_need_bytes(str)) // utf-8 need 3 bytes to present one char + it->bytes = coding::string_need_bytes(str); + constraint_list_.GetItemText(i, 1, str, _countof(str) - 1); + if (wcscmp(str, L"yes") == 0) + it->init_val = it->range.queue[it->range.queue.size() - 1]; + } + } + else + { + ::GetDlgItemTextW(m_hWnd, it->type == L"bool" ? IDC_COMBO_DEFAULT : IDC_EDIT_DEFAULT, str, _countof(str) - 1); + it->init_val = str; + + if (it->range.type == RANGE_TYPE_RANGE) + { + ::GetDlgItemTextW(m_hWnd, IDC_EDIT_FROM, str, _countof(str) - 1); + it->range.lower = _wtof(str); + ::GetDlgItemTextW(m_hWnd, IDC_EDIT_TO, str, _countof(str) - 1); + it->range.upper = _wtof(str); + } + } + + // depend ... + it->depend.clear(); + if (((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck() == BST_CHECKED) + { + it->depend_or = ((CButton*)GetDlgItem(IDC_RADIO_ANY))->GetCheck() == BST_CHECKED; + for (int i = 0; i < depends_.GetCount(); ++i) + { + DEPENDITEM di; + + depends_.GetText(i, str); + split(str, &di); + it->depend.push_back(di); + } + } +} + + +void ChgjsonDlg::OnNMRClickMfcshelltree1(NMHDR *pNMHDR, LRESULT *pResult) +{ + // TODO: Add your control notification handler code here + *pResult = 0; + POINT pt = { 0 }; + HTREEITEM hsel = tree_.GetSelectedItem(); + + tree_menu_.EnableMenuItem(ID_TREE_ADDGROUP, MF_DISABLED); + tree_menu_.EnableMenuItem(ID_TREE_ADDITEM, MF_DISABLED); + tree_menu_.EnableMenuItem(ID_TREE_ADDPRODUCT, MF_DISABLED); + tree_menu_.EnableMenuItem(ID_TREE_DELITEM, MF_DISABLED); + tree_menu_.EnableMenuItem(ID_TREE_RENAME, MF_DISABLED); + tree_menu_.CheckMenuItem(ID_TREE_TOOLTIPS, show_tree_tooltips_ ? MF_CHECKED : MF_UNCHECKED); + if (hsel) + { + DWORD data = (DWORD)tree_.GetItemData(hsel); + if (data == TREE_ITEM_PRODUCT) + { + tree_menu_.EnableMenuItem(ID_TREE_ADDGROUP, MF_ENABLED); + } + else if (data == TREE_ITEM_GROUP) + { + tree_menu_.EnableMenuItem(ID_TREE_ADDITEM, MF_ENABLED); + } + tree_menu_.EnableMenuItem(ID_TREE_DELITEM, MF_ENABLED); + tree_menu_.EnableMenuItem(ID_TREE_RENAME, MF_ENABLED); + } + else + tree_menu_.EnableMenuItem(ID_TREE_ADDPRODUCT, MF_ENABLED); + + GetCursorPos(&pt); + tree_menu_.GetSubMenu(0)->TrackPopupMenu(0, pt.x, pt.y, this); +} + + +void ChgjsonDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult) +{ + LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + if (pResult) + *pResult = 0; + + init_control_statu(); +} + + +void ChgjsonDlg::OnListmenuSetdefault() +{ + // TODO: Add your command handler code here + int sel = get_cur_sel(&constraint_list_); + + if (sel >= 0 && sel < constraint_list_.GetItemCount()) + { + for (int i = 0; i < constraint_list_.GetItemCount(); ++i) + { + if (constraint_list_.GetItemData(i)) + continue; + + constraint_list_.SetItemText(i, 1, i == sel ? TEXT("yes") : TEXT("")); + } + } +} + + +void ChgjsonDlg::OnListmenuDelete() +{ + // TODO: Add your command handler code here + int sel = get_cur_sel(&constraint_list_); + + if (sel >= 0 && sel < constraint_list_.GetItemCount()) + { + TCHAR buf[20] = { 0 }; + constraint_list_.GetItemText(sel, 1, buf, _countof(buf) - 1); + constraint_list_.DeleteItem(sel); + if (_tcscmp(buf, TEXT("yes")) == 0) + { + if (constraint_list_.GetItemCount() > 1) + constraint_list_.SetItemText(0, 1, TEXT("yes")); + } + } +} + + +void ChgjsonDlg::OnNMRClickListValues(NMHDR *pNMHDR, LRESULT *pResult) +{ + LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + *pResult = 0; + POINT pt = { 0 }; + int sel = get_cur_sel(&constraint_list_); + + func_menu_.CheckMenuItem(ID_LISTMENU_TOOLTIPS, show_list_tooltips_ ? MF_CHECKED : MF_UNCHECKED); + if (sel >= 0 && sel < constraint_list_.GetItemCount()) + { + if (constraint_list_.GetItemData(sel) == 0) + { + GetCursorPos(&pt); + func_menu_.GetSubMenu(0)->TrackPopupMenu(0, pt.x, pt.y, this); + } + } +} + + +void ChgjsonDlg::OnLbnDblclkList3() +{ + // TODO: Add your control notification handler code here + int sel = depends_.GetCurSel(); + + if (sel >= 0 && sel < depends_.GetCount()) + { + TCHAR text[128] = { 0 }; + + depends_.GetText(sel, text); + if (MessageBox(text, TEXT("Delete ?"), MB_YESNO) == IDYES) + depends_.DeleteString(sel); + } +} + + +void ChgjsonDlg::OnDropFiles(HDROP hDropInfo) +{ + // TODO: Add your message handler code here and/or call default + wchar_t path[MAX_PATH] = { 0 }; + + DragQueryFileW(hDropInfo, 0, path, _countof(path) - 1); + load_from_file(path); + + CDialogEx::OnDropFiles(hDropInfo); +} + +void ChgjsonDlg::OnTreeLoadfile() +{ + // TODO: Add your command handler code here + file_util::PATHFILE path = { 0 }; + + if (file_util::browser_file(m_hWnd, &path)) + { + load_from_file(path.path); + } +} + + +void ChgjsonDlg::OnLvnKeydownListValues(NMHDR *pNMHDR, LRESULT *pResult) +{ + LPNMLVKEYDOWN pLVKeyDow = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + *pResult = 0; + + if (GetKeyState(VK_CONTROL) < 0) + { + int sel = get_cur_sel(&constraint_list_), dir = 0; + TCHAR t0[200] = { 0 }, t1[20] = { 0 }; + + if (constraint_list_.GetItemData(sel) == 0) + { + if (pLVKeyDow->wVKey == VK_UP) + { + if (sel > 0) + dir = -1; + } + else if (pLVKeyDow->wVKey == VK_DOWN) + { + if (sel < constraint_list_.GetItemCount() - 1) + dir = 1; + } + } + if (dir) + { + constraint_list_.GetItemText(sel, 0, t0, _countof(t0) - 1); + constraint_list_.GetItemText(sel, 1, t1, _countof(t1) - 1); + constraint_list_.DeleteItem(sel); + sel += dir; + + sel = constraint_list_.InsertItem(sel, t0); + constraint_list_.SetItemText(sel, 1, t1); + + constraint_list_.SetItemState(sel - dir, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); + constraint_list_.SetSelectionMark(sel - dir); + } + } +} + + +void ChgjsonDlg::OnTvnKeydownTree1(NMHDR *pNMHDR, LRESULT *pResult) +{ + LPNMTVKEYDOWN pTVKeyDown = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + if (pResult) + *pResult = 0; + + if (pTVKeyDown->wVKey != VK_UP && pTVKeyDown->wVKey != VK_DOWN) + return; + if (GetKeyState(VK_CONTROL) >= 0) + return; + + HTREEITEM sel = tree_.GetSelectedItem(), next = NULL, parent = tree_.GetParentItem(sel); + DWORD_PTR data = NULL; + std::wstring name(get_tree_selected_item_text(&tree_, &data)); + + if ((DWORD)data != TREE_ITEM_CONFIG) + return; + + if (pTVKeyDown->wVKey == VK_DOWN) + { + next = tree_.GetNextSiblingItem(sel); + if (!next) + { + parent = tree_.GetNextSiblingItem(parent); + if (parent) + { + next = TVI_FIRST; + tree_.Expand(parent, TVIS_EXPANDED); + } + } + else + { + if ((DWORD)tree_.GetItemData(next) == TREE_ITEM_GROUP) + { + parent = next; + next = TVI_FIRST; + } + else if (check_depend(name.c_str(), get_tree_selected_item_text(&tree_, next).c_str()) == 1) + next = NULL; + } + } + else if (pTVKeyDown->wVKey == VK_UP) + { + next = tree_.GetPrevSiblingItem(sel); + if (!next) + { + if (parent != tree_.GetRootItem()) + { + parent = tree_.GetPrevSiblingItem(parent); + if (parent) + { + if ((DWORD)tree_.GetItemData(parent) == TREE_ITEM_CONFIG) + { + next = parent; + parent = tree_.GetParentItem(parent); + } + else + { + next = TVI_LAST; + tree_.Expand(parent, TVIS_EXPANDED); + } + } + else + { + parent = tree_.GetParentItem(tree_.GetParentItem(sel)); + next = TVI_FIRST; + } + } + } + else + { + if (check_depend(name.c_str(), get_tree_selected_item_text(&tree_, next).c_str()) == -1) + next = NULL; + else + { + next = tree_.GetPrevSiblingItem(next); + if (!next) + next = TVI_FIRST; + } + } + } + + if (next) + { + tree_.DeleteItem(sel); + sel = add_tree_item(name.c_str(), data, parent, next); + tree_.SelectItem(sel); + } +} + + +void ChgjsonDlg::OnTvnGetInfoTipTree1(NMHDR *pNMHDR, LRESULT *pResult) +{ + LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + *pResult = 0; + + if (show_tree_tooltips_) + _tcscpy(pGetInfoTip->pszText, TEXT("Ctrl + or can change the configuration item position.")); +} + + +void ChgjsonDlg::OnLvnGetInfoTipListValues(NMHDR *pNMHDR, LRESULT *pResult) +{ + LPNMLVGETINFOTIP pGetInfoTip = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + *pResult = 0; + + if (show_list_tooltips_) + _tcscpy(pGetInfoTip->pszText, TEXT("Ctrl + or can change the option position.")); +} + + +void ChgjsonDlg::OnTreeTooltips() +{ + // TODO: Add your command handler code here + show_tree_tooltips_ ^= true; +} + + +void ChgjsonDlg::OnListmenuTooltips() +{ + // TODO: Add your command handler code here + show_list_tooltips_ ^= true; +} diff --git a/tools/apps/hgjson/hgjsonDlg.h b/tools/apps/hgjson/hgjsonDlg.h new file mode 100644 index 0000000..8514257 --- /dev/null +++ b/tools/apps/hgjson/hgjsonDlg.h @@ -0,0 +1,151 @@ + +// hgjsonDlg.h : header file +// + +#pragma once +#include "afxshelltreectrl.h" +#include "afxwin.h" +#include "afxcmn.h" +#include +#include +#include + + +// ChgjsonDlg dialog +class ChgjsonDlg : public CDialogEx +{ +// Construction +public: + ChgjsonDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + enum { IDD = IDD_HGJSON_DIALOG }; + + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + +public: + typedef struct _depend_item + { + std::wstring parent; + std::wstring logic_values; // include logic operator: "==2" + + bool operator==(const wchar_t* name) + { + return wcscmp(name, parent.c_str()) == 0; + } + }DEPENDITEM; + enum range_type + { + RANGE_TYPE_NONE = 0, + RANGE_TYPE_RANGE, + RANGE_TYPE_LIST, + }; + typedef struct _range + { + int type; + double lower; + double upper; + std::vector queue; + }RANGE; + typedef struct _hg_item + { + std::wstring title; + std::wstring desc; + std::wstring type; + std::wstring init_val; + int index; + int bytes; + bool advanced; + bool depend_or; // or or and + std::vector depend; + RANGE range; + + bool operator==(const wchar_t* name) + { + return wcscmp(name, title.c_str()) == 0; + } + struct _hg_item(const wchar_t* ti= L"") + { + title = ti ? ti : L""; + desc = L""; + type = L"bool"; + init_val = L"true"; + bytes = 4; + advanced = false; + depend_or = true; + range.type = RANGE_TYPE_NONE; + } + }HGITEM; + std::vector hg_items_; + bool show_tree_tooltips_; + bool show_list_tooltips_; + +// Implementation +protected: + HICON m_hIcon; + CMenu tree_menu_; + CMenu func_menu_; + CImageList tree_img_; + + // Generated message map functions + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + DECLARE_MESSAGE_MAP() + + void init_control_statu(void); + void delete_tree_item(HTREEITEM root); + int find_config_item(const wchar_t* item_name); + int check_depend(const wchar_t* l, const wchar_t* r); // -1: l depends on r; 0: no depend; 1: r depends on l + void set_control_status(const HGITEM& item); + + void* create_json(int item); + std::string to_json_text(void); + void add_item(void* jsn_root, void* jsn_obj, HTREEITEM parent); + bool load_from_json_text(const wchar_t* txt); + bool load_from_file(const wchar_t* path_file); + void get_all_names(HTREEITEM root, std::vector& names, DWORD mask = 0); + void on_config_name_changed(const wchar_t* prev, const wchar_t* now); + HTREEITEM add_tree_item(const wchar_t* title, DWORD data, HTREEITEM parent = TVI_ROOT, HTREEITEM after = TVI_LAST); + +public: + afx_msg void OnTreeAddGroup(); + afx_msg void OnTreeAddItem(); + afx_msg void OnTreeDelItem(); + CTreeCtrl tree_; + afx_msg void OnTreeAddProduct(); + afx_msg void OnBnClickedButton3(); + afx_msg void OnBnClickedButton1(); + afx_msg void OnBnClickedButton2(); + CListBox depends_; + CListCtrl constraint_list_; + afx_msg void OnCbnSelchangeDataType(); + afx_msg void OnCbnSelchangeConstraintType(); + afx_msg void OnCbnSelchangeDependItem(); + afx_msg void OnCbnSelchangeLogic(); + afx_msg void OnLvnEndlabeleditListValues(NMHDR *pNMHDR, LRESULT *pResult); + CComboBox type_; + CComboBox constraint_; + afx_msg void OnBnClickedDepend(); + CComboBox logic_; + CComboBox depend_item_; + afx_msg void OnBnClickedButton4(); + afx_msg void OnNMRClickMfcshelltree1(NMHDR *pNMHDR, LRESULT *pResult); + CComboBox combo_default_; + afx_msg void OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnListmenuSetdefault(); + afx_msg void OnListmenuDelete(); + afx_msg void OnNMRClickListValues(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnLbnDblclkList3(); + afx_msg void OnDropFiles(HDROP hDropInfo); + afx_msg void OnTreeRename(); + afx_msg void OnTreeLoadfile(); + afx_msg void OnLvnKeydownListValues(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnTvnKeydownTree1(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnTvnGetInfoTipTree1(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnLvnGetInfoTipListValues(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnTreeTooltips(); + afx_msg void OnListmenuTooltips(); +}; + diff --git a/tools/apps/hgjson/res/bitmap1.bmp b/tools/apps/hgjson/res/bitmap1.bmp new file mode 100644 index 0000000..792cd46 Binary files /dev/null and b/tools/apps/hgjson/res/bitmap1.bmp differ diff --git a/tools/apps/hgjson/res/hgjson.ico b/tools/apps/hgjson/res/hgjson.ico new file mode 100644 index 0000000..d9c7466 Binary files /dev/null and b/tools/apps/hgjson/res/hgjson.ico differ diff --git a/tools/apps/hgjson/res/hgjson.rc2 b/tools/apps/hgjson/res/hgjson.rc2 new file mode 100644 index 0000000..3fecfc5 Binary files /dev/null and b/tools/apps/hgjson/res/hgjson.rc2 differ diff --git a/tools/apps/hgjson/resource.h b/tools/apps/hgjson/resource.h new file mode 100644 index 0000000..9398193 Binary files /dev/null and b/tools/apps/hgjson/resource.h differ diff --git a/tools/apps/hgjson/stdafx.cpp b/tools/apps/hgjson/stdafx.cpp new file mode 100644 index 0000000..c77c320 --- /dev/null +++ b/tools/apps/hgjson/stdafx.cpp @@ -0,0 +1,8 @@ + +// stdafx.cpp : source file that includes just the standard includes +// hgjson.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + diff --git a/tools/apps/hgjson/stdafx.h b/tools/apps/hgjson/stdafx.h new file mode 100644 index 0000000..3ace893 --- /dev/null +++ b/tools/apps/hgjson/stdafx.h @@ -0,0 +1,54 @@ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +#include "targetver.h" + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off MFC's hiding of some common and often safely ignored warning messages +#define _AFX_ALL_WARNINGS + +#include // MFC core and standard components +#include // MFC extensions + + +#include // MFC Automation classes + + + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC support for Internet Explorer 4 Common Controls +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include // MFC support for ribbons and control bars + + + + + + + + + +#ifdef _UNICODE +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#endif + + diff --git a/tools/apps/hgjson/targetver.h b/tools/apps/hgjson/targetver.h new file mode 100644 index 0000000..87c0086 --- /dev/null +++ b/tools/apps/hgjson/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/tools/sdk/include/coding/coding.h b/tools/sdk/include/coding/coding.h new file mode 100644 index 0000000..1019c61 --- /dev/null +++ b/tools/sdk/include/coding/coding.h @@ -0,0 +1,516 @@ + +// gb_base64.h : base64 encoding, allow you use your own BASE64 letter table +// +// Author: Gongbing +// +// Date: 2016-07-02 + +#pragma once +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + +#define MINI_BUF_LEN 40 + +// this MACRO should include and header files ... +#define STD_STR_TO_LOWER(str) std::transform((str).begin(), (str).end(), (str).begin(), tolower) + +namespace coding_util +{ + // all apis return error code, except commenting specially + + __declspec(novtable) struct IBase64 : public ref_util::IRef + { + COM_API_DECLARE(bool, init_table(const char* base64_table = 0)); + + // parameter: result((char*)data, ...) + // return: error code + COM_API_DECLARE(int, encode(const char* data, size_t len, inter_module_data::set_data result, void* param, unsigned int max_line_len = -1, bool need_padding = true)); + COM_API_DECLARE(int, decode(const char* data, size_t len, inter_module_data::set_data result, void* param)); + }; + __declspec(novtable) struct IBitsBuf : public ref_util::IRef + { + COM_API_DECLARE(bool, resize(int len, bool init_val = false)); + COM_API_DECLARE(void, reset(bool val = false)); + COM_API_DECLARE(void, set(int index, bool val)); + COM_API_DECLARE(bool, get(int index)); + + // following for two-dimension + COM_API_DECLARE(bool, resize(short row, short col, bool init_val = false)); + COM_API_DECLARE(void, set(short row, short col, bool val)); + COM_API_DECLARE(bool, get(short row, short col)); + }; + + // convert a hex letter to 4-bits integer. + // ch: to receive the result + // return whether the parameter 'hex' is a valid hex-letter + PORT_API(bool) hex_str_2_int(char hex, unsigned char* ch); + + /* commonplace code page: refer to https://www.cnblogs.com/answercard/p/10122434.html + GBK: 936 + BIG5: 950 + UTF-16: 1200 + unicode: 1201 + GB2312: 20936 + hz-gb-2312: 52936 + GB18030: 54936 + UTF-7: 65000 + UTF-8: 65001 + */ + // get code page of given charset name, 0 is failure + PORT_API(UINT) code_page_from_name(const char* name); + PORT_API(UINT) code_page_from_name(const wchar_t* name); + + // result((wchar_t*)data, ...); + // + // return: error code, 0 is success + PORT_API(int) ansi_2_unicode(const char* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP); + PORT_API(int) ansi_2_utf8(const char* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP); + PORT_API(int) unicode_2_ansi(const wchar_t* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP); + PORT_API(int) unicode_2_utf8(const wchar_t* data, inter_module_data::set_data result, void* param, int chars = -1); + PORT_API(int) utf8_2_ansi(const char* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP); + PORT_API(int) utf8_2_unicode(const char* data, inter_module_data::set_data result, void* param, int chars = -1); + + // case transfer, return changes + PORT_API(int) to_upper(char* str, int len = -1); + PORT_API(int) to_upper(wchar_t* str, int len = -1); + PORT_API(int) to_lower(char* str, int len = -1); + PORT_API(int) to_lower(wchar_t* str, int len = -1); + + // Function: transform string between unicode style as 0x1234 and web style such as \u1234, %12%34 ... + // result((wchar_t*)data, ...); + PORT_API(void) from_web_style(const wchar_t* data, inter_module_data::set_data result, void* param); + PORT_API(void) to_web_style(const wchar_t* data, inter_module_data::set_data result, void* param); + + namespace bom + { + PORT_API(bool) is_unicode(const char* bom_str, bool* big_ending); // bom_str must be great than 3 bytes, big_ending to receive whether the bom is a Big-Ending unicode + PORT_API(bool) is_utf8(const char* bom_str); // bom_str must be great than 3 bytes + + // result((char*)data, ...), maybe DATA_FLAG_ERROR + PORT_API(void) to_ansi(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param); + PORT_API(void) to_utf8(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param); + + // result((wchar_t*)data, ...), maybe DATA_FLAG_ERROR + PORT_API(void) to_unicode(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param, bool little_ending = true); + + // result((char*)data, ...), maybe DATA_FLAG_ERROR + PORT_API(void) from_ansi(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param); + PORT_API(void) from_unicode(const wchar_t* bom_str, size_t bytes, inter_module_data::set_data result, void* param, bool little_ending = true); + PORT_API(void) from_utf8(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param); + } + + PORT_API(int) trim_left(char* str, const char* trim_letter = " \t"); // return erased letters count + PORT_API(int) trim_left(wchar_t* str, const wchar_t* trim_letter = L" \t"); // return erased letters count + PORT_API(int) trim_right(char* str, const char* trim_letter = " \t"); // return erased letters count + PORT_API(int) trim_right(wchar_t* str, const wchar_t* trim_letter = L" \t"); // return erased letters count + + // return whether replaced, maybe DATA_FLAG_ERROR if 'old' is a sub-string in rep when 'all' is true + // all string should ended with '\0' + PORT_API(bool) replace(const char* str, const char* old, const char* rep, inter_module_data::set_data result, void* param, bool all = true); + PORT_API(bool) replace(const wchar_t* str, const wchar_t* old, const wchar_t* rep, inter_module_data::set_data result, void* param, bool all = true); + + // function: to pick the value between 'lead' and 'end' block. + // cont: the origin text + // lead: the leading mark + // end: the ending mark + // result: data - (const wchar_t*) or (const char*) value, without lead and rear mark + // len - data bytes + // total - found count + // flag - DATA_FLAG_FINAL + // param - same as the parameter 'param' + // first: to receive the beginning of the found value + // last: to receive the endding of the found value + // include_tag: picked result whether include the 'lead' and 'end' string + // case_sensitive: whether the lead and end are case sensitive + // + // return: found count, -1 is error + enum mark_layer + { + MARK_LAYER_FLAT = 1, // context formed as lead + val + end + ... + lead + val + end + ... + MARK_LAYER_EMBED, // context formed as lead + (lead + val + end) ... + end + ... + }; + PORT_API(int) pick_value(const char* cont, const char* lead, const char* end, inter_module_data::set_data result, void* param, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED); + PORT_API(int) pick_value(const char* cont, const char* lead, const char* end, int* first, int* last, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED); + PORT_API(int) pick_value(const wchar_t* cont, const wchar_t* lead, const wchar_t* end, inter_module_data::set_data result, void* param, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED); + PORT_API(int) pick_value(const wchar_t* cont, const wchar_t* lead, const wchar_t* end, int* first, int* last, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED); + PORT_API(int) pick_first_branch_in_if_else_endif(const wchar_t* cont, const wchar_t* lead, const wchar_t* elif, const wchar_t* end, int* first, int* last, bool include_tag = false, bool case_sensitive = true); + + // simple_line: consider followin lines + // line 1\ + // -line 2 + // true - return "line 1" + // false - return "line 1-line 2" + PORT_API(void) pick_line(const char* str, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false); + PORT_API(void) pick_line(const wchar_t* str, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false); + PORT_API(void) pick_whole_line(const char* cur, const char* bgn, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false); + PORT_API(void) pick_whole_line(const wchar_t* cur, const wchar_t* bgn, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false); + + enum num_format + { + NUM_FMT_DECIMAL, // float/double + NUM_FMT_INTEGER, // int in decimal + NUM_FMT_BIN, + NUM_FMT_OCT, + NUM_FMT_HEX, + }; + // function: to pick a number from string + // num_str: number string + // ret: to receive the ending point of the number + // nf: format of num_str + // + // return: all in double value, if nf is in BIN, OCT or HEX, this contains max 32-bits + // maybe return NON if num_str in DECIMAL or INTEGER + PORT_API(double) pick_number(const char* num_str, const char** ret = NULL, num_format nf = NUM_FMT_DECIMAL); + PORT_API(double) pick_number(const wchar_t* num_str, const wchar_t** ret = NULL, num_format nf = NUM_FMT_DECIMAL); + + // function: to pick an integer from a number string + // + // remarks: if all digit is in [0, 9], then consider it as a decimal + // 0xnnn or nnnh: heximal + // nnno: oct + // nnnb: binary + // other: decimal + // return: -1 if failed + PORT_API(unsigned long long) pick_integer(const char* num_str, size_t bytes = 4); + PORT_API(unsigned long long) pick_integer(const wchar_t* num_str, size_t bytes = 4); + + // following two apis replace the string in str buffer, and return ERROR_SUCCESS or ERROR_INSUFFICIENT_BUFFER + // all string should ended with '\0' + PORT_API(int) replace(char* str, size_t str_buf_len, const char* old, const char* _new, bool *rep); + PORT_API(int) replace(wchar_t* str, size_t str_buf_len, const wchar_t* old, const wchar_t* _new, bool *rep); + + PORT_API(IBase64*) create_base64(void); + PORT_API(IBitsBuf*) create_bits_buffer(void); + + // function: calculate md5 + // return: md5_val, may be empty if the path_file is not accessible + PORT_API(char*) md5(const char* data, size_t len, char md5_val[MINI_BUF_LEN]); + PORT_API(char*) md5(const wchar_t* path_file, char md5_val[MINI_BUF_LEN]); + + enum _aes_type_ + { + AES_ECB = 1, + AES_CBC, + AES_OFB, + AES_CFB, + }; + PORT_API(int) aes_encoding(const char* plain, size_t len, const char *iv, const char* pwd, inter_module_data::set_data result, void* param, int iv_len = 16, int pwd_len = 16, _aes_type_ type = AES_CBC); + PORT_API(int) aes_decoding(const char* cipher, size_t len, const char *iv, const char* pwd, inter_module_data::set_data result, void* param, int iv_len = 16, int pwd_len = 16, _aes_type_ type = AES_CBC); + + // return 0 if success + PORT_API(int) lzw_encoding(const char* plain, size_t len, inter_module_data::set_data result, void* param); + PORT_API(int) lzw_decoding(const char* cipher, size_t len, inter_module_data::set_data result, void* param); + + // wildcard matching ... + // str: to be compared string + // pattern: include '*' or '?', e.g. "*.bat" + PORT_API(bool) is_wildcard_match(const char* str, const char* pattern, int str_len = -1, int patt_len = -1); + PORT_API(bool) is_wildcard_match(const wchar_t* str, const wchar_t* pattern, int str_len = -1, int patt_len = -1); + + // convert time to string like: "yyyy-mm-dd hh:mm:ss" + // NOTE: parameter 'tmprc' is valid only when 't' is ZERO + enum _time_precision + { + TIME_PRECISION_SECOND = 0, + TIME_PRECISION_MILLISECOND, + TIME_PRECISION_ms = TIME_PRECISION_MILLISECOND, + TIME_PRECISION_MICROSECOND, + TIME_PRECISION_us = TIME_PRECISION_MICROSECOND, + TIME_PRECISION_NANOSECOND, + TIME_PRECISION_ns = TIME_PRECISION_NANOSECOND, + }; + enum _week + { + WEEK_DAY_NO = 0, + WEEK_DAY_CN, + WEEK_DAY_EN, + }; + PORT_API(bool) local_time_2_string(char tm_str[MINI_BUF_LEN], _time_precision tmprc = TIME_PRECISION_SECOND, _week week = WEEK_DAY_NO, time_t t = 0); + PORT_API(bool) local_time_2_string(wchar_t tm_str[MINI_BUF_LEN], _time_precision tmprc = TIME_PRECISION_SECOND, _week week = WEEK_DAY_NO, time_t t = 0); + PORT_API(const wchar_t*) get_week_string(int day_of_week, bool chinese); + + // convert string like "yyyy-mm-dd hh:mm:ss" to local time, return -1 is error + PORT_API(time_t) time_str_2_date_time(const char* tm_str); + PORT_API(time_t) time_str_2_date_time(const wchar_t* tm_str); + + // version ... + // function: convert version '1.2.3.4' to 0x01020304 + PORT_API(UINT64) version_string_2_int(const char* dot_version); + PORT_API(UINT64) version_string_2_int(const wchar_t* dot_version); + + // return ver_buf + PORT_API(char*) version_string_from_int(UINT64 val, char ver_buf[MINI_BUF_LEN]); + PORT_API(wchar_t*) version_string_from_int(UINT64 val, wchar_t ver_buf[MINI_BUF_LEN]); + + // return: 0 - equal; 1 - dot_version1 > dot_version2; -1 - dot_version1 < dot_version2 + PORT_API(int) compare_version(const char* dot_version1, const char* dot_version2); + PORT_API(int) compare_version(const wchar_t* dot_version1, const wchar_t* dot_version2); + + // file time + PORT_API(bool) file_time_2_time(FILETIME ft, time_t* t); + PORT_API(bool) file_time_from_time(time_t t, FILETIME* ft); + + // convert the hex-string '12cdef' to [0x12, 0xcd, 0xef] + // return: ending position in hex_str after this + PORT_API(int) hex_string_2_bytes_seq(const char* hex_str, inter_module_data::set_data result, void* param, const char* omit = " \t\r\n"); + PORT_API(int) hex_string_2_bytes_seq(const wchar_t* hex_str, inter_module_data::set_data result, void* param, const wchar_t* omit = L" \t\r\n"); + + // transferred char like '\r', '\n' ... 'ok' to receive whether transfered + PORT_API(char*) to_transfer_text(char trans_char, bool* ok); // return "\n" for '\n' + PORT_API(wchar_t*) to_transfer_text(wchar_t trans_char, bool* ok); // return L"\n" for L'\n + PORT_API(char) from_transfer_text(const char* trans_char, int* used_bytes, bool* ok); // return '\n' for "\n" + PORT_API(wchar_t) from_transfer_text(const wchar_t* trans_char, int* used_bytes, bool* ok); // return L'\n' for L"\n" + + // create guid as "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}", return buf + wchar_t* create_guid(wchar_t buf[MINI_BUF_LEN * 2]); +}; + +namespace cxx_code +{ + // function: to check a character is space or not + // + // parameter: ch - the character to be check + // + // return: whether the character 'ch' is a space + // + // NOTE: we assume the following characters spaces: + // ' ', '\r', '\n', '\t' + PORT_API(bool) is_space_char(wchar_t ch); + + // function: skip the space character until valid character or ending + // + // parameter: codes - the cxx codes string + // + // pos - [in] starting pos to skip, [out] - the first none-space character position + // + // has_lrn - whether the spaces has '\n' + // + // return: whether any spaces has been skipped, i.e. the out pos is greater than in pos + // + // NOTE: space characters: ' '; '\t'; '\r'; '\n' + PORT_API(bool) skip_space(const wchar_t* codes, int* pos, bool *has_lrn = NULL); + + // function: to check the character 'ch' is whether a valid leading character of a variable + PORT_API(bool) is_var_leading_char(wchar_t ch); + + // function: to check the character 'ch' is whether a valid character of a variable + PORT_API(bool) is_var_char(wchar_t ch); + + // return the line ending char '\n' position or ending position if no, support multi-line joint by '\\' + // str[ret] = L'\n' || str[ret] = 0 + PORT_API(long) line_ending(const wchar_t* str, int bgn); + + // find the next 'key' position in 'str', omit those in quotes or comments, return -1 when not found + PORT_API(long) next_key(const wchar_t* str, const wchar_t* key, int bgn = 0); + + // return comment block beginning position (str[ret] = L'/'), -1 if not a comment block, start from *pos and set ending in pos when return + // + // pos when out will be the line ending (str[*pos] = L'\n') or the last '/' character of "/**/" block (str[*pos] = L'/') + PORT_API(long) comment_block(const wchar_t* str, int* pos); + + // function: erase the comments in "/**/" or after "//" + // + // parameter: codes - the cxx codes string + // + // notify - data: (const wchar_t*)the codes string after erasing comments + // + // len: unused + // + // total: unused + // + // flag: always be DATA_FLAG_FINAL + // + // param: same as the parameter 'param' you passed in the function + // + // param - for callback 'notify' using + // + // return: nonsence + // + // NOTE: the last '\n' after the comments will be reserved + PORT_API(void) erase_comments(const wchar_t* codes, INTER_MODULE_CALLBACK_VAR(notify), void* param); + + // function: pick a variable or function name + // + // parameter: codes - the cxx codes string + // + // pos - [in] starting pos, [out] - ending position after the last name character, or error position when failed + // + // digit - true to pick a digit, false to pick a variable + // + // return: the beginning of the name, -1 for error + PORT_API(int) pick_variable(const wchar_t* codes, int* pos, bool digit = false); + + // function: pick a block between characters 'bgn_ch' and 'end_ch' + // + // parameter: codes - the cxx codes string + // + // pos - [in] starting pos, [out] - ending position after the last name character(codes[*pos] == 'end_ch'), or error position when failed + // + // bgn_ch - the beginning character of the block, e.g. '(' + // + // end_ch - the ending character of the block, e.g. ')' + // + // single_line - whether the block will be a single line in commonplace, or else with '\\' at the line ending + // + // other_comment_leading_char - other sinle line comment leading character + // + // return: the beginning of the block (codes[ret] == 'bgn_ch'), -1 for error. + // failed also when single_line was true and meeting line-endig before 'end_ch' + // + // NOTE: this function will ommit the 'bgn_ch' and 'end_ch' which is after '\\' or in quotes "" or '' + PORT_API(int) pick_block(const wchar_t* codes, int* pos, wchar_t bgn_ch, wchar_t end_ch, bool single_line = false, wchar_t other_comment_leading_char = 0); + + // function: pick a if-else codes block + // + // parameter: codes - the cxx codes string + // + // pos - [in] starting pos, [out] - ending position after the last name character, or error position when failed + // + // notify - to notify a picked branch + // + // data: (const wchar_t*)condition, "(...)", empty string if the last 'else' branch + // + // len: (const wchar_t*)entity, "{...}" + // + // total: unused, always be ZERO + // + // flag: always be DATA_FLAG_FINAL. no invoking if error occurs + // + // param: same as the parameter 'param' you passed in the function + // + // return: SET_RESULT_CONTINUE to continue, SET_RESULT_STOP to stop this invoking + // + // param - for callback 'notify' using + // + // other_comment_leading_char - other sinle line comment leading character + // + // return: the beginning of the block, -1 for error + // + // NOTE: first word must be "if" + PORT_API(int) pick_if_else_block(const wchar_t* codes, int* pos, INTER_MODULE_CALLBACK_VAR(notify), void* param, wchar_t other_comment_leading_char = 0); + + // function: pick a #if-#endif codes block + // + // parameter: codes - the cxx codes string + // + // pos - [in] starting pos, [out] - ending position after the last name character, or error position when failed + // + // notify - to notify a picked branch + // + // data: (const wchar_t*)condition, empty string if the last 'else' branch + // + // len: (const wchar_t*)entity + // + // total: unused, always be ZERO + // + // flag: always be DATA_FLAG_FINAL. no invoking if error occurs + // + // param: same as the parameter 'param' you passed in the function + // + // return: SET_RESULT_CONTINUE to continue, SET_RESULT_STOP to stop this invoking + // + // param - for callback 'notify' using + // + // return: the beginning of the block, -1 for error + // + // NOTE: first word must be "#if" + PORT_API(int) pick_macro_if_else_block(const wchar_t* codes, int* pos, INTER_MODULE_CALLBACK_VAR(notify), void* param); + + // function: pick a function block + // + // parameter: codes - the cxx codes string + // + // pos - [in] starting pos, [out] - ending position after the last '}', or error position when return false + // + // notify - data: (const wchar_t*)function name and pre_leading declaration + // + // len: parameters ending with double '\0' + // + // total: (const wchar_t*)function entity, leading with '{' and ending with '}' + // + // flag: always be DATA_FLAG_FINAL. no invoking if error occurs + // + // param: same as the parameter 'param' you passed in the function + // + // param - for callback 'notify' using + // + // other_comment_leading_char - other sinle line comment leading character + // + // return: true when success, and then the function elements is passed back by 'notify' + // + // NOTE: it will be without entity if it was a function invoking + PORT_API(bool) pick_function(const wchar_t* codes, int* pos, INTER_MODULE_CALLBACK_VAR(notify), void* param, wchar_t other_comment_leading_char = 0); + + // function: to get the line number from offset 'pos' + // + PORT_API(unsigned) line_from_pos(const wchar_t* cont, unsigned pos); + + // Function: to save and calculate a logical action result + // + // e.g.: set 'is_win' is 'true, then check 'is_win' will return true and '!is_win' is false + // + // NOTE: now support '||', '&&' and '!' operator and consider expression like 'i >= 0' as ONE variable + // this means every expression between '&&' and '||' will consider as ONE variable + // + __declspec(novtable) struct ILogicAction : public ref_util::IRef + { + // Function: to set the callback to query value when a variable is unknown + // + // get_variable_val: data - see 'inter_module_data::DATA_FLAG_GET_VAL' + // + // len - see 'inter_module_data::DATA_FLAG_GET_VAL' + // + // total - see 'inter_module_data::DATA_FLAG_GET_VAL' + // + // flag - always be DATA_FLAG_GET_VAL + // + // param - the same as 'param' in this function + // + // NOTE: all unknown variable would be considered as 'false' if you did not set the callback + // variable values has multi-strings format, and end with '\0' per value, double '\0' for all values + COM_API_DECLARE(void, set_callback(inter_module_data::set_data get_variable_val, void* param)); + + // Function: add or modify known boolean value + // + // var: boolean variable, multi-vars divided by ';' + // + COM_API_DECLARE(void, set_variable_value(const wchar_t* var, const wchar_t* val, int bytes = 0)); + COM_API_DECLARE(void, set_variable_value(const wchar_t* var, bool val)); + COM_API_DECLARE(void, remove_variable(const wchar_t* var)); + COM_API_DECLARE(void, clear(void)); + + // Function: calculate logical expression such as 'is_win && is_android' ... + // + // logic_exp: logical expression, like 'is_win && is_android', '!is_win' ... + // + // supported: to receive whether the logic_exp is valid/supported now, return value would be nonsence if this was false + // + // return: boolean result. SEE 'supported' !!! + // + COM_API_DECLARE(bool, logic_expression_result(const wchar_t* logic_exp, bool* supported)); + + // Function: to query an logical expression value without user interacting + // + // Parameter: logic_expression - logical expression, like 'is_win && is_android', '!is_win' ... + // + // val - to receive the expression value if it was existing + // + // Return: whether the 'logic_expression' all are existing already (until calculate the result) + COM_API_DECLARE(bool, query_existing_value(const wchar_t* logic_exp, bool* val)); + + COM_API_DECLARE(inter_module_data::set_result, last_input_result(void)); + + // Function: get symbol's value. e.g. return L"1" of symbol_value(L"BUILD_TYPE", ...) if L"BUILD_TYPE=1" was existed + // + // return: value, NULL if not found. you should use it immediately, and need not free it. + COM_API_DECLARE(const wchar_t*, symbol_value(const wchar_t* symbol)); + + // save the logical-expressions to path_file which it is 'true' + COM_API_DECLARE(int, save(const wchar_t* path_file)); + }; + + // logical action + PORT_API(ILogicAction*) create_logical_action(void); +} diff --git a/tools/sdk/include/coding/math_util.h b/tools/sdk/include/coding/math_util.h new file mode 100644 index 0000000..2706316 Binary files /dev/null and b/tools/sdk/include/coding/math_util.h differ diff --git a/tools/sdk/include/db/database.h b/tools/sdk/include/db/database.h new file mode 100644 index 0000000..b70d628 --- /dev/null +++ b/tools/sdk/include/db/database.h @@ -0,0 +1,70 @@ + +// database.h: simple database interface +// +// Author: Gongbing +// +// Date: 2020-09-11 + +#pragma once +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif +#include // for VARIANT + +#define MAX_TABLE_FIELD_NAME_LEN 20 + +namespace db_util +{ + enum // Driver type + { + DBDRIVER_ODBC_DBASE = 533, + DBDRIVER_ODBC_EXCEL = 790, + DBDRIVER_ODBC_ACCESS = 25, + DBDRIVER_ODBC_VFDB, + DBDRIVER_ODBC_VFTABLE, + DBDRIVER_FILE_SQLITE = 1000, + }; + typedef struct _table_fields + { + wchar_t name[MAX_TABLE_FIELD_NAME_LEN]; + VARIANT default_val; // the field 'type' is defining the field type too. + // NOW support VT_BOOL, VT_BSTR, VT_DATE, VT_I1(to VT_I8), VT_R4, VT_R8 + // VT_DATE use function VariantTimeToSystemTime to convert !!! + int length; // 0 is not set, always for TEXT field + bool unique; + bool not_null; + bool primary_key; + bool foreign_key; + bool use_default_val; // whether use the 'default_val' in table as the field's default value + }TBLFLD; + + __declspec(novtable) struct IRecordset : public ref_util::IRef + { + COM_API_DECLARE(int, get_rows(void)); // get count of records + COM_API_DECLARE(int, get_cols(void)); // get count of record fields + COM_API_DECLARE(bool, get_value(int row, int col, bool* boolean)); + COM_API_DECLARE(bool, get_value(int row, int col, int* integer)); + COM_API_DECLARE(bool, get_value(int row, int col, double* decimal)); + COM_API_DECLARE(bool, get_value(int row, int col, wchar_t* buf, int* words/*[in] - words in buf; [out] - real length of the value. you should provide greater buffer if it was greater than in*/)); + COM_API_DECLARE(bool, get_value(int row, int col, inter_module_data::set_data set_val/*data: pointed to an unicode string*/, void* param)); + }; + + __declspec(novtable) struct IDatabase : public ref_util::IRef + { + COM_API_DECLARE(int, open(const wchar_t* db_name, const wchar_t* user_name = 0, const wchar_t* password = 0)); + COM_API_DECLARE(int, create_table(const wchar_t* table_name, db_util::TBLFLD* fields, int fields_num, int *composed_primary_key_index = NULL)); + COM_API_DECLARE(int, close(void)); + COM_API_DECLARE(int, execute_sql(const wchar_t* sql, IRecordset** record = 0)); + COM_API_DECLARE(int, get_error_msg(inter_module_data::set_data set_msg/*data: pointed to an unicode string*/, void* param)); // return error code + }; + + // exports ... + PORT_API(bool) add_database(const wchar_t* db_name, const wchar_t* db_file, int driver_type); + PORT_API(bool) del_database(const wchar_t* db_name, int driver_type = DBDRIVER_ODBC_ACCESS); + PORT_API(IDatabase*) create_database_instance(int driver_type = DBDRIVER_ODBC_ACCESS); + PORT_API(bool) create_table_sql(const wchar_t* table_name, TBLFLD* fields, int fields_num + , inter_module_data::set_data set_msg/*data: pointed to an unicode string*/, void* param + , int *composed_primary_key_index = NULL); // -1 is over +}; + diff --git a/tools/sdk/include/file/file_util.h b/tools/sdk/include/file/file_util.h new file mode 100644 index 0000000..c087616 --- /dev/null +++ b/tools/sdk/include/file/file_util.h @@ -0,0 +1,230 @@ +// folder_util.h : include utilities for manage folders +// +// Author: Gongbing +// +// Date: 2016-09-21 + +#pragma once +#include +#include +#include +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + +namespace file_util +{ + // 1 - all paths returned by these apis ended with '\\' + typedef struct _path_file + { + wchar_t path[MAX_PATH]; + }PATHFILE, *LPPATHFILE; + + enum file_coding + { + FILE_CODING_ANSI = 1, + FILE_CODING_UTF8, + FILE_CODING_UNICODE, + }; + __declspec(novtable) struct IFileFinder : public ref_util::IRef + { + // found_file: to receive the found file with full path + // NOTE: child folder will always be in the found queue wherever you given the 'mark' !!! + // filter '*.*' will not match the file which without extension, so use '*' as default filter for mark + COM_API_DECLARE(int, find_first(const wchar_t* dir, LPPATHFILE found_file, const wchar_t* mark = L"*", bool recursive = true, bool depth_first = true, bool ignore_dot_folder = true)); + COM_API_DECLARE(int, find_next(LPPATHFILE found_file)); + COM_API_DECLARE(int, current_file_attr(WIN32_FILE_ATTRIBUTE_DATA* attr)); // return file attributes, -1 is error + COM_API_DECLARE(int, current_root(LPPATHFILE root)); // root: full path with last '\\' of current finding path + COM_API_DECLARE(int, stop_find(void)); + + COM_API_DECLARE(bool, is_current_folder(void)); + }; + __declspec(novtable) struct ISimpleShareMemory : public ref_util::IRef + { + // for monitor using, called should before write_result + COM_API_DECLARE(int, wait_result(const wchar_t* id, inter_module_data::set_data notify, void* notify_param, DWORD wait_milliseconds = -1, size_t max_size = -1/*one page*/)); + + // for notifier using + COM_API_DECLARE(int, write_result(const wchar_t* id, const char* data, size_t data_bytes)); + }; + __declspec(novtable) struct IGroupFile : public ref_util::IRef // to write grp_0000.txt, grp_0001.txt, ... files + { + COM_API_DECLARE(int, set_read_param(inter_module_data::set_data set_d, file_coding fc = FILE_CODING_ANSI)); + COM_API_DECLARE(int, to_line(int line/*ZERO-based*/, int file_ind = -1)); // locate in read, return ERROR_SUCCESS in success + COM_API_DECLARE(int, read_line(void* param, bool next = true)); // param is used in the set_d callback; get the first line if next was true + COM_API_DECLARE(int, write(const char* data, size_t len)); + COM_API_DECLARE(int, next_file(void)); + COM_API_DECLARE(DWORD, cur_size(void)); + COM_API_DECLARE(DWORD, cur_index(void)); // return current file index + COM_API_DECLARE(DWORD, cur_line(void)); // return current line in file + }; + __declspec(novtable) struct IOvlHandler : public ref_util::IRef + { + COM_API_DECLARE(long, on_data_arrived(const char* data, size_t bytes, void* user_key)); // return how many bytes used, -1 to stop receiving !!! + COM_API_DECLARE(bool, on_data_sent(char* data, size_t bytes, size_t data_buf_len/*for reuse inner_buffer*/, void* user_key)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it + COM_API_DECLARE(void, on_error(int err)); + }; + __declspec(novtable) struct IPipe : public ref_util::IRef + { + COM_API_DECLARE(int, read(void)); // data returned by IOvlHandler::on_data_arrived + COM_API_DECLARE(int, write(const char* data, size_t bytes, bool inner_buf/*whether the 'data' is returned by get_write_buf*/)); + COM_API_DECLARE(int, close(void)); + + COM_API_DECLARE(char*, get_write_buf(size_t bytes)); + COM_API_DECLARE(void, free_got_write_buf(void* buf/*returned by get_write_buf*/)); + }; + + PORT_API(int) get_special_folder(int clsidl, LPPATHFILE path); + PORT_API(int) desktop(bool current_user, LPPATHFILE path); + PORT_API(int) start_menu(bool current_user, LPPATHFILE path); + PORT_API(int) start_menu_program(bool current_user, LPPATHFILE path); + PORT_API(int) start_menu_startup(bool current_user, LPPATHFILE path); + PORT_API(int) start_menu_recently(LPPATHFILE path); + PORT_API(int) application_data(bool current_user, LPPATHFILE path); + PORT_API(int) my_documents(bool current_user, LPPATHFILE path); + PORT_API(int) self_path(LPPATHFILE path); + PORT_API(int) local_application_data(LPPATHFILE path); + PORT_API(int) program_files(LPPATHFILE path); + PORT_API(int) windows(LPPATHFILE path); + PORT_API(int) system(LPPATHFILE path); + PORT_API(int) start_menu_program(LPPATHFILE path); + PORT_API(int) quick_launch(bool current_user, LPPATHFILE path, LPPATHFILE path_pin = NULL/*full path*/); + PORT_API(int) temporary_file(LPPATHFILE path, const wchar_t* prefix = NULL); + PORT_API(int) get_currentLoginUser_AppdataPath(LPPATHFILE path);//add by weidongli on 2019-6-3 + + PORT_API(void) simplify_path(wchar_t* path, size_t path_buf_len = 0/*as lstrlenW(path) + 1*/); + PORT_API(void) to_absolute_path(LPPATHFILE path); // convert './', '%WINDOWS%', '%SYSTEM%', ... to absolute path + PORT_API(void) to_relative_path(const wchar_t* path_file_base, const wchar_t* path_file_tobe, LPPATHFILE rel_path); + PORT_API(void) to_known_path(LPPATHFILE path); // convert absolute path to './', '%WINDOWS%', '%SYSTEM%', ... + PORT_API(void) append_name(const wchar_t* path_file, const wchar_t* append, LPPATHFILE result); // to insert string 'append' before extension name + PORT_API(bool) is_file_existing(const wchar_t* path_file); + PORT_API(bool) is_valid_file_name_character(wchar_t file_name_char); + PORT_API(int) force_rename_file(const wchar_t* from, const wchar_t* to); + PORT_API(int) force_copy_file(const wchar_t* from, const wchar_t* to); + PORT_API(int) force_move_file(const wchar_t* from, const wchar_t* to); + PORT_API(int) force_delete_file(const wchar_t* file); + PORT_API(int) force_create_file(const wchar_t* path_file, HANDLE* ret, DWORD acc = GENERIC_WRITE | GENERIC_READ, DWORD share = 0, DWORD method = CREATE_ALWAYS + , DWORD attr = FILE_ATTRIBUTE_NORMAL, LPSECURITY_ATTRIBUTES psa = NULL); + PORT_API(int) force_create_folder(const wchar_t* path_folder, SECURITY_ATTRIBUTES* psa = NULL, bool default_psa = true); + PORT_API(bool) initialize_commonplace_security(SECURITY_ATTRIBUTES* psa); + PORT_API(bool) is_valid_path(const wchar_t* path); + PORT_API(bool) is_dir(DWORD attr); + PORT_API(bool) is_dir(const wchar_t* path); + PORT_API(int) get_file_attributes(const wchar_t* path_file, WIN32_FILE_ATTRIBUTE_DATA* attr); + PORT_API(bool) get_file_version(const wchar_t* path_file, WORD* lpver_hh, WORD* lpver_hl, WORD* lpver_lh, WORD* lpver_ll, bool file_ver = true/*false is product version*/); + PORT_API(UINT64) get_file_size(const wchar_t* path_file); + PORT_API(UINT64) get_disk_available_space(const wchar_t* disk_path); + + // when return false, 'err' can be: + // + // 1: ERROR_DISK_FULL - the free space in 'disk' is not enough + // + // 2: ERROR_FILE_SYSTEM_LIMITATION - 'bytes' exceedes the maximum of the file-system's limitation + // + PORT_API(bool) is_disk_space_enough_for_single_file(const wchar_t* disk, UINT64 bytes, int* err = NULL); + PORT_API(bool) is_parent_path(const wchar_t* path_to_check, const wchar_t* file); // to check whether the path 'path_to_check' is the parent path of 'file' + PORT_API(int) parent_folder(const wchar_t* path_file, LPPATHFILE path); // without last '\\' + PORT_API(int) common_parent_folder(const wchar_t* path_file1, const wchar_t* path_file2, LPPATHFILE parent); + PORT_API(int) file_name(const wchar_t* path_file, LPPATHFILE path, bool with_ext = NULL); + PORT_API(int) file_extension(const wchar_t* path_file, LPPATHFILE path); // without '.' + + PORT_API(int) load_file(const wchar_t* file, inter_module_data::set_data result, void* param); + PORT_API(int) save_2_file(const char* data, size_t len, const wchar_t* file); + PORT_API(void*) map_file_to_memory(const wchar_t* path_file, bool read_only = true, DWORD expand_size = 0, HANDLE *file_handle = NULL, HANDLE *map_handle = NULL); + + // clipboard + PORT_API(int) set_clipboard(const void* data, size_t bytes, int format = CF_TEXT, HWND owner = NULL); + PORT_API(int) set_clipboard_directly(HANDLE data, int format = CF_TEXT, HWND owner = NULL); + PORT_API(int) get_clipboard(void* buf, size_t* bytes/*[in]-bytes of buf, [out]-content bytes in clipboard*/, int format = CF_TEXT, HWND owner = NULL); + + // parameter of result: + // + // data: real data of the clipboard format + // + // len: bytes of the data + // + // total: clipboard fromat, support CF_TEXT - (char*)data + // CF_UNICODETEXT - (wchar_t*)data + // CF_BITMAP - 'data' contains contents of PNG file + // CF_DIB - 'data' contains contents of BMP file + // CF_HDROP - (wchar_t*)data, copying files list, separated by "\r\n" + // + // flag: DATA_FLAG_FINAL + // + // param: same as 'user' + // + PORT_API(int) get_clipboard(inter_module_data::set_data result, void* user); + + PORT_API(bool) browser_file(HWND owner, LPPATHFILE file, const wchar_t *filter = L"All Files(*.*)\0\0", bool open = true, const wchar_t* title = NULL, WNDPROC cust_proc = NULL, LPARAM proc_param = NULL); + + // function: monitor file & folder + // + // path: full path, can be a folder or a file + // + // mask: FILE_NOTIFY_CHANGE_FILE_NAME FILE_NOTIFY_CHANGE_DIR_NAME FILE_NOTIFY_CHANGE_ATTRIBUTES FILE_NOTIFY_CHANGE_SIZE FILE_NOTIFY_CHANGE_LAST_WRITE FILE_NOTIFY_CHANGE_LAST_ACCESS FILE_NOTIFY_CHANGE_CREATION FILE_NOTIFY_CHANGE_SECURITY + // + // result: data - (const wchar_t*)path_file_name + // len - bytes of data + // total - unused + // flag - DATA_FLAG_FINAL + // param - the same as 'param' of this function + // + // return: monitor key , NULL if failed. should call un_monitor to free the return value + // + PORT_API(void*) monitor_files(const wchar_t* path, int mask, bool sub_dir, inter_module_data::set_data result, void* param); + PORT_API(void) un_monitor(void* key); + PORT_API(void) display_file_in_explorer(const wchar_t* path_file); + PORT_API(UINT64) get_filesystem_maximum_file_bytes(const wchar_t* disk, wchar_t* fs_name = NULL/*provids NULL or not less than "MAX_PATH + 2"*/); + + PORT_API(IFileFinder*) create_file_finder(void); + PORT_API(ISimpleShareMemory*) create_simple_share_memory(void); + PORT_API(IGroupFile*) create_group_files(const wchar_t* first_file, bool for_read, int sn_digits = 4, DWORD limit_bytes = 0); // the limit_bytes would be ommited if fro_read was true + + PORT_API(IPipe*) open_pipe(IOvlHandler* handler, const wchar_t* name); +} + +#define STR_SIMPLIFY_PATH(str) \ + { \ + file_util::PATHFILE pf = { 0 }; \ + wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \ + file_util::simplify_path(pf.path); \ + (str) = pf.path; \ + } + +#define STR_TO_ABSOLUTE_PATH(str) \ + { \ + file_util::PATHFILE pf = { 0 }; \ + wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \ + file_util::to_absolute_path(&pf); \ + (str) = pf.path; \ + } + +#define STR_TO_KNOWN_PATH(str) \ + { \ + file_util::PATHFILE pf = { 0 }; \ + wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \ + file_util::to_known_path(&pf); \ + (str) = pf.path; \ + } + +#define STR_PARENT_FOLDER(str) \ + { \ + file_util::PATHFILE pf = { 0 }; \ + file_util::parent_folder((str).c_str(), &pf); \ + (str) = pf.path; \ + } + +#define STR_FILE_NAME(str, with_ext) \ + { \ + file_util::PATHFILE pf = { 0 }; \ + file_util::file_name((str).c_str(), &pf, with_ext); \ + (str) = pf.path; \ + } + +#define STR_FILE_EXTENSION(str) \ + { \ + file_util::PATHFILE pf = { 0 }; \ + file_util::file_extension((str).c_str(), &pf); \ + (str) = pf.path; \ + } diff --git a/tools/sdk/include/log/log.h b/tools/sdk/include/log/log.h new file mode 100644 index 0000000..0191b31 --- /dev/null +++ b/tools/sdk/include/log/log.h @@ -0,0 +1,75 @@ +// log.h : log utility +// +// Author: Gongbing +// +// Create: 2019-08-07 + +#pragma once +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// level +enum _log_level +{ + LOG_LEVEL_ALL = 1, + LOG_LEVEL_PART, + LOG_LEVEL_IMPORTANT, + LOG_LEVEL_VERY_IMPORTANT, + LOG_LEVEL_NONE = INT_MAX, +}; +enum _log_type +{ + LOG_TYPE_NONE, + LOG_TYPE_CONSOLE_OUT, + LOG_TYPE_OUTPUTDBG, + LOG_TYPE_WRITE_FILE, + LOG_TYPE_USER_CUSTOM, +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// macros +#ifndef UNICODE_STR +#define _TO_UNICODE(str) L##str +#define UNICODE_STR(str) _TO_UNICODE(str) +#define MAKE_UNICODE(str) UNICODE_STR(str) +#endif + +#define LOG_API_PROTO(name) void(__stdcall *name)(const wchar_t* info, size_t words, void* user) +#define LOG_API_INSTANCE(name) void __stdcall name(const wchar_t* info, size_t words, void* user) + +namespace log_util +{ + ////////////////////////////////////////////////////////////////////////////////////////// + // log interface + typedef LOG_API_PROTO(real_log); + + __declspec(novtable) struct ILog : public ref_util::IRef + { + // param0: (const wchar_t*)path file when type is LOG_TYPE_WRITE_FILE, real_log when type is LOG_TYPE_USER_CUSTOM. otherwise always be ZERO + // param1: for parameter 'user' of real_log when type is LOG_TYPE_USER_CUSTOM, otherwise always be ZERO + COM_API_DECLARE(int, set_log_level(_log_level level)); + COM_API_DECLARE(int, set_log_type(_log_type type, void* param0 = NULL, void* param1 = NULL)); // return type after this oper + COM_API_DECLARE(void, write_log(const wchar_t* info, size_t bytes, _log_level level)); + COM_API_DECLARE(bool, is_level_enabled(_log_level level)); // whether the message of level can be logged + COM_API_DECLARE(void, set_prefix(const wchar_t* pref)); // default is without prefix + COM_API_DECLARE(void, enable_time_stamp(bool enable)); // default is without timestamp + }; + + // use inner log_util + // param0: (const wchar_t*)path file when type is LOG_TYPE_WRITE_FILE, real_log when type is LOG_TYPE_USER_CUSTOM. otherwise always be ZERO + // param1: for parameter 'user' of real_log when type is LOG_TYPE_USER_CUSTOM, otherwise always be ZERO + PORT_API(ILog*) start_log(_log_type type = LOG_TYPE_OUTPUTDBG, _log_level level = LOG_LEVEL_ALL, void* param0 = NULL, void* param1 = NULL); + PORT_API(ILog*) get_cur_log_util(void); + + // set an external log_util, NULL to stop current log, will invoke log->add_ref() if log is valid + PORT_API(void) set_log_util(ILog* log); + + + // invoke log + PORT_API(bool) is_logging_enable(_log_level level); + PORT_API_CALL(void, __cdecl) log(_log_level level, size_t estimate_bytes, const wchar_t* format, ...); + PORT_API_CALL(void, __cdecl) log(_log_level level, size_t estimate_bytes, const char* format, ...); +} diff --git a/tools/sdk/include/net/net_app.h b/tools/sdk/include/net/net_app.h new file mode 100644 index 0000000..a8a6914 --- /dev/null +++ b/tools/sdk/include/net/net_app.h @@ -0,0 +1,259 @@ +// net_app.h : network applications +// +// Author: Gongbing +// +// Create: 2019-07-22 + +#pragma once + +#include "net_base.h" + +//typedef struct ip_option_information { +// UCHAR Ttl; +// UCHAR Tos; +// UCHAR Flags; +// UCHAR OptionsSize; +// PUCHAR OptionsData; +//} IP_OPTION_INFORMATION, *PIP_OPTION_INFORMATION; +//typedef struct icmp_echo_reply { +// struct sockaddr_in Address; +// ULONG Status; +// ULONG RoundTripTime; +// USHORT DataSize; +// USHORT Reserved; +// PVOID Data; +// struct ip_option_information Options; +//} ICMP_ECHO_REPLY, *PICMP_ECHO_REPLY; +//#define IPAddr struct sockaddr_in + +namespace net_app +{ + enum web_format + { + WEB_FMT_UNKNOWN = 0, + WEB_FMT_STREAM, // binary stream ... + WEB_FMT_ANSI, + WEB_FMT_UTF8, + WEB_FMT_UNICODE, + WEB_FMT_DECIDE_BY_CONTENT, // text/html should decide by content + }; + __declspec(novtable) struct IAcceptClient : public ref_util::IRef + { + COM_API_DECLARE(long, client_accepted(SOCKET s, const char* ip, unsigned port)); + COM_API_DECLARE(void, on_server_exited(unsigned exit_code)); + }; + __declspec(novtable) struct ITcpSvrSocket : public ref_util::IRef + { + COM_API_DECLARE(long, listen_at(unsigned short port, const char* ip = NULL/*INADDR_ANY*/, bool reuse_addr = true)); + COM_API_DECLARE(long, stop(void)); + COM_API_DECLARE(long, listen_port(void)); + COM_API_DECLARE(SOCKET, listen_socket(void)); + }; + __declspec(novtable) struct IAsyncTcpSvr : public ITcpSvrSocket + { + // following two functions return ERROR_FILE_HANDLE_REVOKED if the peer is used in transmit file + COM_API_DECLARE(long, read_from_peer(void* peer_key)); // DO NOT call this until you stop the read with return -1 in IPeerManager::on_data_arrived, server will invoke this automately + COM_API_DECLARE(long, write_2_peer(void* peer_key, const char* data, size_t data_len, bool inner_buffer = false/*whether the data buffer is returned by request_sent_buffer, if failed and iner_buffer is 'true', the 'data' would be freed !!!*/)); + COM_API_DECLARE(long, close_peer(void* peer_key, int* peer_ref)); + COM_API_DECLARE(long, set_peer_data(void* peer_key, int index, void* data)); + COM_API_DECLARE(long, get_peer_data(void* peer_key, int index, void** data)); + COM_API_DECLARE(long, peer_address(void* peer_key, char ip_buf[IP_BUF_LEN], unsigned* port)); + COM_API_DECLARE(long, send_file_content(void* peer_key, HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!! + COM_API_DECLARE(size_t, io_buffer_size(bool in_buf)); + + // add on 2017-08-26 for add an existing connecting into client queue (DO NOT add it which is already in queue !!!) + // after this, you should operate the peer in IPeerManager. + // following two apis return peer_key + COM_API_DECLARE(void*, add_2_client_queue(SOCKET s)); + COM_API_DECLARE(void*, create_async_tcp_client(const char* ip, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0)); + + // for reducing the times of memory copying, request memory from inner - added on 2019-07-28 + COM_API_DECLARE(char*, request_sent_buffer(size_t bytes)); + COM_API_DECLARE(void, free_unsent_buffer(void* buf)); // free the returned value of request_sent_buffer which has NOT called write_2_peer with inner_buffer is 'true' yet!!! + }; + __declspec(novtable) struct IAsyncTcpHatcher : public ref_util::IRef + { + COM_API_DECLARE(void*, connect(const char* ip, int port, const char* reuse_ip = NULL, unsigned reuse_port = 0)); + COM_API_DECLARE(int, write(void* client, const char* buf, size_t data_len, bool inner_buf)); + //COM_API_DECLARE(void*, add_2_client_queue(SOCKET s)); + COM_API_DECLARE(int, close_client(void* client)); + COM_API_DECLARE(int, destroy(void)); + COM_API_DECLARE(long, send_file_content(void* client, HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!! + COM_API_DECLARE(bool, get_address(void* client, char* ip/*at least with 40 bytes!!!*/, int* port, bool svr = true)); + }; + __declspec(novtable) struct IAsyncTcpHandler : public ref_util::IRef + { + COM_API_DECLARE(long, on_data_arrived(void* client, const char* data, size_t data_len, bool* rcv_file/*[in] - whether in receiving file for transmit_file, [out] - stop(true) or continue(true) receiving file*/)); // return how many bytes used, -1 to stop receiving !!! + COM_API_DECLARE(bool, on_data_sent(void* client, char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it + COM_API_DECLARE(void, on_closed(void* client, int err)); + COM_API_DECLARE(void, on_file_content_sent(void* client, HANDLE file, ULONGLONG bytes, int error)); // response for IAsyncTcpSvr::send_file_content + }; + __declspec(novtable) struct IPeerManager : public ref_util::IRef + { + COM_API_DECLARE(void, on_peer_connected(void* peer_key)); + COM_API_DECLARE(void, on_server_exited(unsigned exit_code)); + COM_API_DECLARE(long, on_data_arrived(void* peer_key, const char* data, size_t data_len, bool* rcv_file/*[in] - whether in receiving file for transmit_file, [out] - stop(true) or continue(true) receiving file*/)); // return how many bytes used, -1 to stop receiving !!! + COM_API_DECLARE(bool, on_data_sent(void* peer_key, char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it + COM_API_DECLARE(void, on_peer_error(void* peer_key, unsigned err_code)); + COM_API_DECLARE(void, on_peer_closed(void* peer_key)); + COM_API_DECLARE(bool, is_peer_timeout(void* peer_key, int elapsed_seconds/*elapsed seconds from last active*/)); + COM_API_DECLARE(void, on_file_content_sent(void* peer_key, HANDLE file, ULONGLONG bytes, int error)); // response for IAsyncTcpSvr::send_file_content + }; + __declspec(novtable) struct IBlockTcp : public ref_util::IRef + { + COM_API_DECLARE(SOCKET, attach(SOCKET s)); + COM_API_DECLARE(SOCKET, detach(void)); + COM_API_DECLARE(SOCKET, socket_handle(void)); + COM_API_DECLARE(int, re_connect(const char* dot_ip = NULL, unsigned short port = 0)); + COM_API_DECLARE(int, set_timeout(unsigned *read_timeout/*milliseconds*/, unsigned *write_timeout/*milliseconds*/)); + COM_API_DECLARE(int, read(char* buf, size_t buf_len, size_t* read_bytes)); + COM_API_DECLARE(int, write(const char* buf, size_t data_len, size_t* wrote)); + COM_API_DECLARE(int, last_error(void)); + COM_API_DECLARE(long, send_file_content(HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!! + COM_API_DECLARE(void, get_address(char* ip/*at least with 40 bytes!!!*/, int* port, bool svr = true)); + COM_API_DECLARE(int, close(void)); + }; + + __declspec(novtable) struct IUdpSvrHandler : public ref_util::IRef + { + COM_API_DECLARE(size_t,on_udp_data_arrived(const char* data, size_t data_len, const char* ip, unsigned port)); // return used data bytes + COM_API_DECLARE(bool, on_udp_data_sent(char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/, const char* ip, unsigned port)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it + COM_API_DECLARE(void, on_udp_server_exit(unsigned err)); + }; + __declspec(novtable) struct IUdpServer : public ref_util::IRef + { + COM_API_DECLARE(int, start(unsigned short port)); + COM_API_DECLARE(int, send_to(const char* buf, size_t len, const char* ip, unsigned port, bool inner_buffer = false/*whether the data buffer is returned by request_sent_buffer*/)); + COM_API_DECLARE(int, broad_cast(const char* buf, size_t len, unsigned short port, bool inner_buffer = false, const char* broad_ip_seg = NULL)); + COM_API_DECLARE(int, stop(void)); + + // for reducing the times of memory copying, request memory from inner - added on 2019-07-28 + COM_API_DECLARE(char*, request_sent_buffer(size_t bytes)); + COM_API_DECLARE(void, free_unsent_buffer(void* buf)); // free the returned value of request_sent_buffer which has NOT called write_2_peer with inner_buffer is 'true' yet!!! + }; + + typedef struct _set_cookie // all members and its' buffers will be in the same buffer with the head + { + char *name; + char *val; + char *path; + char *expire; + char *domain; + bool http_only; + bool https_only; // true - secure 1; false - secure 0 + }SETCOOKIE, *LPSETCOOKIE; + enum _add_head_flag + { + ADD_HEAD_ADD = 1, // new item added if the key was not existing, or else failed + ADD_HEAD_NEW, // new item added however the key is existing already + ADD_HEAD_REPLACE, // new item added if the key was not existing, or else replace it with new val + ADD_HEAD_APPEND_COMMA, // like ADD_HEAD_REPLACE but append new val to rear with comma(,) if the key was existing + ADD_HEAD_APPEND_SEMIC, // like ADD_HEAD_REPLACE but append new val to rear with semicolon(;) if the key was existing + }; + enum _cookie_index + { + COOKIE_INDEX_ALL = -1, + }; +#ifdef _USE_HTTP_CALLBACK_ + __declspec(novtable) struct IHttpCallback : public ref_util::IRef + { + COM_API_DECLARE(void, on_response_header_ok(int response_code, unsigned __int64 cont_len, bool cont_chunked, bool cont_zipped)); + COM_API_DECLARE(int, on_response_content(const char* content, size_t len)); // return 0 to continue, other to stop + COM_API_DECLARE(int, on_url_jump(int jump_code, const char* utf8_new_url)); // return 0 to continue, other to stop + }; +#endif + __declspec(novtable) struct IHttp : public ref_util::IRef // all methods are thread unsafe, all history cookies will occur in last request + { +#ifndef _USE_HTTP_CALLBACK_ + COM_API_DECLARE(void, set_response_data_callback(inter_module_data::set_data setdata, void* param)); +#endif + COM_API_DECLARE(int, add_header(const char* utf8_key, const char* utf8_val, _add_head_flag flag = ADD_HEAD_REPLACE)); // 0 - ok; ERROR_ALREADY_EXISTS. must call before open_url or post_data + COM_API_DECLARE(int, remove_header(const char* utf8_key/*NULL to clear all extra headers*/)); // 0 - ok; ERROR_NOT_FOUND. must call before open_url or post_data + COM_API_DECLARE(int, clear_cookie(void)); // all history cookies would be added on the last request, call this to clear all cookies + COM_API_DECLARE(int, open_url(const char* url, const char* cookie, const char* agent, bool get = true, const char* content = NULL, size_t content_len = 0)); + COM_API_DECLARE(int, post_data(const char* url, const char* data, unsigned __int64 data_len, const char* utf8_file_tag, const char* utf8_file_name, const char* cookie, const char* agent)); + COM_API_DECLARE(int, get_response_code(void)); + COM_API_DECLARE(int, get_set_cookie(LPSETCOOKIE buf/*format: cookie1\0cookie2\0\0*/, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/ + , int index = 0/*if index == COOKIE_INDEX_ALL, then return all cookies in ONE string and put it in buf*/)); // 0 - ok; ERROR_NOT_FOUND + COM_API_DECLARE(int, get_jump_url(char* buf, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/)); // 0 - ok; ERROR_NOT_FOUND + COM_API_DECLARE(int, get_response_all_header(char* buf, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/)); // 0 - ok; ERROR_NOT_FOUND + COM_API_DECLARE(unsigned __int64, get_response_content_length(void)); + COM_API_DECLARE(enum web_format, get_content_format(void)); + COM_API_DECLARE(void, close(void)); + }; + + PORT_API(ITcpSvrSocket*) create_tcp_server_socket(IAcceptClient* ac, bool ipv6 = false); + enum _svr_ip_type + { + SVR_TYPE_NONE = 0, + SVR_TYPE_IPV4_ONLY = 1, + SVR_TYPE_IPV6_ONLY, + SVR_TYPE_IPV4_AND_IPV6, + }; + PORT_API(IAsyncTcpSvr*) create_async_tcp_server(IPeerManager* peer, _svr_ip_type svr_type = SVR_TYPE_IPV4_ONLY, int buf_size_in = 0, int buf_size_out = 0, int desired_threads = 0, unsigned allow_cpu_mask = -1); + + // for blocking tcp would blocks following operation, this function will set r/w timeout to be 9 seconds; + PORT_API(IBlockTcp*) connect_2_server(const char* ip, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0); + PORT_API(IBlockTcp*) connect_2_server_by_host(const char* host, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0); + PORT_API(IAsyncTcpHatcher*) create_async_tcp_hatcher(IAsyncTcpHandler* handler); + PORT_API(IUdpServer*) create_udp_server(IUdpSvrHandler* handler, _svr_ip_type type = SVR_TYPE_IPV4_ONLY); +#ifdef _USE_HTTP_CALLBACK_ + PORT_API(IHttp*) create_http(IHttpCallback* cb); +#else + PORT_API(IHttp*) create_http(void); +#endif + + // trace route by ICMPxxx function, to be completed ... + // parameter of result: + // data: ip, NULL when over + // len: milliseconds, -1 is timeout, or error code when over + // total: hops count, unused when over + // flag: DATA_FLAG_FINAL in hops, DATA_FLAG_INSTAR in beginning information, and DATA_FLAG_OVER for over + // param: 'param' + PORT_API(int) trace_route(const char* www, inter_module_data::set_data result, void* param, int max_hops = 30); + PORT_API(int) get_default_gateway(char gateway[IP_BUF_LEN]); + PORT_API(int) get_mac(const char* dot_ip, char *mac, int* mac_bytes/*in - bytes of 'mac', out - result bytes in 'mac'*/); + + // enum all ips in given subnet ... + // parameter of result: + // data: ip, NULL when over + // len: bytes of 'data' + // total: unused + // flag: DATA_FLAG_FINAL + // param: same as 'param' + PORT_API(int) enum_all_ips_in_subnet(const char* dot_ip, const char* dot_subnet, inter_module_data::set_data result, void* param); + + PORT_API(int) parse_cookie(const char* cookie_str, LPSETCOOKIE lpcookie, size_t size/*size of lpcookie must great than sizeof(SETCOOKIE) + lstrlenA(cookie_str) * 2*/); + PORT_API(int) cookie_for_url(LPSETCOOKIE lpcookie, const char* url, char* cookie, size_t* len); + PORT_API(int) http_post(const char* url, const char* content, size_t length, const char* utf8_file_tag, const char* utf8_file_name = NULL, const char* cookie = NULL, const char* agent = NULL); + PORT_API(int) http_download(const char* url, inter_module_data::set_data setdata, void* param, const char* cookie = NULL, const char* agent = NULL, const char* extra_data = 0, size_t extra_data_len = 0); + PORT_API(enum web_format) web_content_format(const char* web_cont, size_t bytes, UINT* cp = NULL/*to receive the code page*/); + + // function: send file by 'TransmitFile' for more efficiency, the function is blocked until all content transfered or error happens if parameter 'lpovl' was NULL + // file: an openning file handle, suggest use flag with 'FILE_FLAG_SEQUENTIAL_SCAN' + // s: an connection socket + // packet_size: bytes of every packet + // lpovl: asynchronous OVERLAPPED data. if you bind the socket on an IOCP, the IOCP will receive a write complete notify + // pre: the content sent to remote before the file content + // pre_bytes: bytes of 'pre' content + // rear: the content sent to remote after all file contents transfered + // rear_bytes: bytes of 'rear' content + // + // return: error code. + PORT_API(int) transmit_file(HANDLE file, SOCKET s, size_t bytes_to_sent = 0/*max up to INT_MAX - 1*/, size_t packet_size = 4096, LPOVERLAPPED lpovl = NULL, void* pre = NULL, size_t pre_bytes = 0, void* rear = NULL, size_t rear_bytes = 0); + PORT_API(HANDLE) open_file_for_sending(const wchar_t* local_file); + + enum + { + NIC_CHANGED = 0, // MibParameterNotification, + NIC_ADDED = 1, // MibAddInstance, + NIC_DELETED = 2, // MibDeleteInstance, + }; + // parameter of notify: + // data: ip, this is the final ip + // len: index of network interface + // total_len: NIC_CHANGED - parameter changed; NIC_ADDED - new NIC added; NIC_DELETED - NIC deleted + // flag: be inter_module_data::DATA_FLAG_FINAL always + PORT_API(void*) reg_interface_notification(inter_module_data::set_data notify, void* param); // free the returned object by unreg_interface_notification + PORT_API(void) unreg_interface_notification(void* key/*returned by reg_interface_notification()*/); +} diff --git a/tools/sdk/include/net/net_base.h b/tools/sdk/include/net/net_base.h new file mode 100644 index 0000000..dbf2d1d --- /dev/null +++ b/tools/sdk/include/net/net_base.h @@ -0,0 +1,332 @@ +// net_base.h : network utility +// +// Author: Gongbing +// +// Create: 2019-07-18 + +#pragma once + +////////////////////////////////////////////////////////////////////////////////////////// +// module type and global definition +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif +#ifndef SOCKET +#define SOCKET unsigned int +#endif + + +////////////////////////////////////////////////////////////////////////////////////////// +// import headers + + +////////////////////////////////////////////////////////////////////////////////////////// +// structures && enumerations +#define IP_BUF_LEN 48 + +typedef struct _ip_info +{ + int index; // NIC index + char ip[IP_BUF_LEN]; + char gateway[IP_BUF_LEN]; + char subnet[IP_BUF_LEN]; +}IPINFO, *LPIPINFO; + +enum firewall_port_cat +{ + FWPORT_UNKNOWN = 0, + FWPORT_TCP, + FWPORT_UDP, + FWPORT_ALL, +}; + +#pragma pack(push) +#pragma pack(1) +typedef struct _ip_pack +{ + // all in net-sn, i.e. big-endian + unsigned long ver : 4; // version of the ip-datagram + unsigned long head_len : 4; // length in four-bytes of this head, unit as long + unsigned long service : 8; // service type ... + unsigned long total_len : 16; // total bytes of this datagram, include this header + unsigned long mark : 16; + unsigned long flag : 3; + unsigned long offset : 13; // offet of part data in whole data + unsigned long ttl : 8; // living time, as hops + unsigned long protocol : 8; // protocol type, see IPPROTO_ICMP ... + unsigned long checksum : 16; // + unsigned long src_ip; + unsigned long dst_ip; + unsigned char head_data[0]; + + void from_buffer(const unsigned char* buf) + { + ver = *buf >> 4; + head_len = *buf++; + service = *buf++; + total_len = *buf++; + total_len <<= 8; + total_len |= *buf++; + mark = *buf++; + mark <<= 8; + mark |= *buf++; + flag = *buf >> 5; + + offset = *buf & 0x1f; + offset <<= 8; + offset |= buf[1]; + buf += 2; + + ttl = *buf++; + protocol = *buf++; + checksum = *buf++; + checksum <<= 8; + checksum |= *buf++; + + src_ip = *buf++; + src_ip <<= 8; + src_ip |= *buf++; + src_ip <<= 8; + src_ip |= *buf++; + src_ip <<= 8; + src_ip |= *buf++; + + dst_ip = *buf++; + dst_ip <<= 8; + dst_ip |= *buf++; + dst_ip <<= 8; + dst_ip |= *buf++; + dst_ip <<= 8; + dst_ip |= *buf++; + + // data, you should ensure enough buffer to contains it !!! + int rest = head_len * 4 - sizeof(*this); + if (rest > 0) + memcpy(head_data, buf, rest); + } + unsigned long calc_checksum(void) + { + unsigned long chk = 0; + + // 1 - fixed fields: + chk = (ver << 12) | (head_len << 8) | service; + chk += total_len; + chk += mark; + chk += (flag << 13) | offset; + chk += (ttl << 8) | protocol; + chk += src_ip & 0x0ffff; + chk += src_ip >> 16; + chk += dst_ip & 0x0ffff; + chk += dst_ip >> 16; + + // 2 - appendix data in header: + unsigned short *d = (unsigned short*)head_data; + int num = (head_len * 4 - sizeof(*this)) / 2; + for (int i = 0; i < num; ++i) + chk += *d++; + + // 3 - add the overflow of short + chk = (chk & 0x0ffff) + (chk >> 16); + chk = (chk & 0x0ffff) + (chk >> 16); + + // 4 - NOT + checksum = ~chk; + + return checksum; + } + int to_buffer(unsigned char* buf) + { + calc_checksum(); + + *buf++ = (ver << 4) | head_len; + *buf++ = service; + *buf++ = total_len >> 8; + *buf++ = total_len; + *buf++ = mark >> 8; + *buf++ = mark; + *buf++ = (flag << 5) | (offset >> 8); + *buf++ = offset; + *buf++ = ttl; + *buf++ = protocol; + *buf++ = checksum >> 8; + *buf++ = checksum; + *buf++ = src_ip >> 24; + *buf++ = src_ip >> 16; + *buf++ = src_ip >> 8; + *buf++ = src_ip; + *buf++ = dst_ip >> 24; + *buf++ = dst_ip >> 16; + *buf++ = dst_ip >> 8; + *buf++ = dst_ip; + + int rest = head_len * 4 - sizeof(*this); + if (rest > 0) + memcpy(buf, head_data, rest); + + return head_len * 4; + } +}IPPACK, *LPIPPACK; + +enum _icmp_type +{ + ICMP_TYPE_TERM_UNREACHABLE = 3, // the terminal is unreachable + ICMP_TYPE_RESTRICT_SOURCE, + ICMP_TYPE_MODIFY_ROUTER, + ICMP_TYPE_TIMEOUT = 11, // when ttl == 0, send back this type by router + ICMP_TYPE_INVALID_PARAMETER, + + ICMP_TYPE_ECHO_ANSWER = 0, // answer for query request + ICMP_TYPE_ECHO_REQUEST = 8, + ICMP_TYPE_TIMESTAMP_REQUEST = 13, + ICMP_TYPE_TIMESTAMP_ANSWER, +}; +enum _term_unrechable_code +{ + TERM_UNREACHABLE_NETWORK = 0, + TERM_UNREACHABLE_TERMINAL, + TERM_UNREACHABLE_PROTOCOL, + TERM_UNREACHABLE_PORT, + TERM_UNREACHABLE_DATA_SEGMENT, // data should divided into several segments + TERM_UNREACHABLE_SOURCE_ROUTER, // source router cannot complete + TERM_UNREACHABLE_UNKNOWN_DST_NET, // destination network is unknown + TERM_UNREACHABLE_UNKNOWN_TERMINAL, + TERM_UNREACHABLE_SOURCE_DISABLED, // source host is disabled + TERM_UNREACHABLE_DISABLE_NETWORK, // disabled with network by policy + TERM_UNREACHABLE_DISABLE_TERM, // disabled with destion terminal by policy + TERM_UNREACHABLE_SERVICE_NETWORK, // network cannot support the service + TERM_UNREACHABLE_SERVICE_TERM, // destion terminal cannot support the service + TERM_UNREACHABLE_TERM_FILTER, // destion terminal has filter + TERM_UNREACHABLE_TERM_PRIORITY, // confilict with priority policy + TERM_UNREACHABLE_PRIORITY_DISABLED, // +}; +enum _modi_router_code +{ + MODI_ROUTER_FOR_NETWORK = 0, // modify the router-table for given network + MODI_ROUTER_FOR_TERM, // modify the router-table for given terminal + MODI_ROUTER_FOR_SERVICE_NETWORK, // modify the router-table for given network on given service + MODI_ROUTER_FOR_SERVICE_TERM, // modify the router-table for given termina on given service +}; +typedef struct _icmp_pack +{ + unsigned char type; + unsigned char code; + unsigned short checksum; + unsigned short mark; + unsigned short seq; + + void from_buffer(const unsigned char* buf) + { + type = *buf++; + code = *buf++; + checksum = (buf[0] << 8) | buf[1]; + buf += 2; + mark = (buf[0] << 8) | buf[1]; + buf += 2; + seq = (buf[0] << 8) | buf[1]; + } + void to_buffer(unsigned char* buf) + { + *buf++ = type; + *buf++ = code; + *buf++ = checksum >> 8; + *buf++ = checksum; + *buf++ = mark >> 8; + *buf++ = mark; + *buf++ = seq >> 8; + *buf++ = seq; + } +}ICMPPACK, *LPICMPPACK; +#pragma pack(pop) +////////////////////////////////////////////////////////////////////////////////////////// +// apis + +namespace net_base_util +{ + PORT_API(void) free_sock_addr(void* sockaddr); + PORT_API(void*) init_sock_addr(const char* ip, unsigned port, int* addrlen, int family = /*AF_INET*/2, int type = /*SOCK_STREAM*/1, int proto = /*IPPROTO_TCP*/6); // return sockaddr_in* type. call net_base_util::free_sock_addr to free the returned value !!! + PORT_API(void) ipv4_broadcast_address(unsigned self_ip, unsigned subnet, char ipbuf[IP_BUF_LEN]); + PORT_API(bool) ip_from_sockaddr_storage(const void/*sockaddr_storage*/* sockaddr_storage_, char ipbuf[IP_BUF_LEN], unsigned* port); + PORT_API(bool) is_ip_equal(const void/*sockaddr_storage*/* sockaddr_storage1_, const void/*sockaddr_storage*/* sockaddr_storage2_, bool compare_port = false); + + // following apis return as base-socket api + PORT_API(int) init_network(unsigned min_ver = 2, unsigned max_ver = 2); + PORT_API(int) cleanup_network(void); + PORT_API(SOCKET) raw_socket(int raw_proto, bool overlapped = false, bool ipv6 = false); + PORT_API(SOCKET) tcp_socket(bool overlapped = false, bool ipv6 = false); + PORT_API(SOCKET) udp_socket(bool overlapped = false, bool ipv6 = false, bool broadcast = false); + PORT_API(int) close_socket(SOCKET s); + PORT_API(int) bind_socket(SOCKET s, bool ipv6_socket, const char* ip, unsigned port); + PORT_API(int) ip_from_domain(const char* domain, char ipbuf[IP_BUF_LEN]); + PORT_API(int) get_local_ip(LPIPINFO ips, size_t* count/*[in] - count of ips; [out] - ip numbers in ips*/); + PORT_API(int) get_ipv6_addrress(LPIPINFO ips, size_t* count/*[in] - count of ips; [out] - ip numbers in ips*/, const char* hostname = NULL/*local ipv6 when NULL*/); + PORT_API(int) set_socket_block(SOCKET s, bool blocked); + PORT_API(int) set_socket_buffer(SOCKET s, int buf_size, bool in_buf/*true for in buffer and false for out buffer*/); + PORT_API(int) set_socket_keepalive(SOCKET s, bool keep_alive); + PORT_API(int) set_socket_keepalive_detect(SOCKET s, bool detect_on, int alive_heart_milliseconds = 0, int retry_heart_milliseconds = 0); + PORT_API(int) set_socket_timeout(SOCKET s, int milliseconds = 0/*no timeout*/, bool rcv_timeout = true); + PORT_API(int) get_socket_timeout(SOCKET s, int *milliseconds, bool rcv_timeout); + PORT_API(int) set_socket_nagle(SOCKET s, bool nagle_on); // if nagle_on is true, then the packet maybe sent delayed + PORT_API(int) set_socket_ttl(SOCKET s, unsigned short ttl); + PORT_API(int) set_reused_address(SOCKET s, bool reused); + PORT_API(int) set_broadcast(SOCKET s, bool enabled); + PORT_API(int) connect_with_timeout(SOCKET s, const char* ip, unsigned port, unsigned timeout_seconds, bool return_block_socket = false); + PORT_API(SOCKET) connect_2_server(const char* ip, unsigned short port, unsigned timeout_seconds = 0/*0 to blocked*/, bool return_block_socket = false, const char* bind_ip = NULL, unsigned bind_port = 0); + + // following apis return 0 for success otherwise error code + PORT_API(int) ipv4_broadcast_address(const char* self_ip, const char* subnet, char ip_buf[IP_BUF_LEN]); + PORT_API(int) get_peer_address(SOCKET s, bool remote, unsigned* port, char ip_buf[IP_BUF_LEN]); + PORT_API(int) ipv4_address(unsigned addr, char ip_buf[IP_BUF_LEN]); + PORT_API(unsigned) ipv4_address(const char* ipv4); + PORT_API(bool) is_in_same_ipv4_subnet(const char* ip1, const char* ip2, const char* subnet); + + // parameters of result: + // data: (const char*)adapter_name + // data_len: (const char*)adapter_description + // total_len: IPINFO* + // flag: inter_module_data::DATA_FLAG_FINAL + // param: the same as 'param' + PORT_API(int) enum_network_adapters(inter_module_data::set_data result, void* param); + + // parameters of result: + // data: (const char*)local address + // data_len: (const char*)remote address + // total_len: HIDWORD = state, LODWORD = owning pid + // flag: inter_module_data::DATA_FLAG_FINAL + // param: the same as 'param' + PORT_API(int) enum_sockets(bool tcp, inter_module_data::set_data result, void* param); + + // trace route by raw socket with ICMP + // parameter of result: + // data: ip, NULL when over + // len: milliseconds, -1 is timeout, or error code when over + // total: hops count, unused when over + // flag: DATA_FLAG_FINAL in hops, DATA_FLAG_INSTAR in beginning information, and DATA_FLAG_OVER for over + // param: 'param' + // PORT_API(int) trace_route(const char* www, inter_module_data::set_data result, void* param, int max_hops = 30); // commented, use net_app::trace_route + PORT_API(unsigned) proto_default_port(const char* proto); + + // function: get the next hop, generally as gateway + // for_ip: in multi-network-card, get the the next hop for given ip, if was NULL, return the first + PORT_API(int) get_next_hop(char next_hop[IP_BUF_LEN], const char* for_ip = NULL); + + // Note: the buffer length of proto(proto_buf_len) must be double of url!!! for host and page would use the buffer + // and need not free host and page + PORT_API(bool) parse_url(const char* url, char* proto, size_t proto_buf_len, char** host, char** page, unsigned* port, bool* port_from_host = NULL); + PORT_API(bool) parse_url(const wchar_t* url, wchar_t* proto, size_t proto_buf_len, wchar_t** host, wchar_t** page, unsigned* port, bool* port_from_host = NULL); + + PORT_API(unsigned short) calculate_ip_datagram_checksum(const unsigned char* buf, int bytes, bool* ok = NULL); + PORT_API(unsigned short) calculate_icmp_checksum(LPICMPPACK pack, int bytes, bool* ok = NULL); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // windows firewall + PORT_API(bool) firewall_is_on(void); + PORT_API(bool) firewall_is_app_enabled(const wchar_t* app_pe_name); + PORT_API(bool) firewall_is_port_enabled(unsigned port, firewall_port_cat fpc); + PORT_API(int) firewall_turn_on(void); + PORT_API(int) firewall_turn_off(void); + PORT_API(int) firewall_enable_app(const wchar_t* name/*display name in firewall*/, const wchar_t* pe/*pe-image file name*/, bool enable); + PORT_API(int) firewall_enable_port(unsigned port, firewall_port_cat fpc, bool enable, const wchar_t* name/*display name in firewall*/ = NULL); +} + + diff --git a/tools/sdk/include/process/pe_util.h b/tools/sdk/include/process/pe_util.h new file mode 100644 index 0000000..457702a --- /dev/null +++ b/tools/sdk/include/process/pe_util.h @@ -0,0 +1,223 @@ +// process_util.h : include utilities for manage folders +// +// Author: Gongbing +// +// Date: 2016-09-25 + +#pragma once +#include +#include +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + + + +// hook utils +namespace pe_util +{ + __declspec(novtable) struct IObscurityCall : public ref_util::IRef + { + // params must not be NULL but the API was no parameter + COM_API_DECLARE(long, invoke(void** params, int* ret_val = NULL)); // return error code + }; +#pragma pack(push) +#pragma pack(1) + typedef struct _hook_instruction_info + { + // e.g. in instruction 'E912345678', then bytes = 5, rel_addr_off = 1, rel_addr_size = 4 + unsigned long bytes : 6; // all bytes in this instruction + unsigned long far_bytes : 3; // the far jumping instruction bytes if this was a near jumping instruction + unsigned long rel_addr_off : 3; // relative address offset to instruction in this + unsigned long rel_addr_size : 3; // relative address size of this instruction, ZERO is none + unsigned char far_instruction[8]; // far jumping instruction, relative address size always be 4 bytes (int) + unsigned long far_adden; // the jumping offset should added this value for converting near jumping to far jumping + }HOOKII, *LPHOOKII; + + typedef struct _group_icon_entry + { + unsigned char width; + unsigned char height; + unsigned char color_count; + unsigned char reserved; + unsigned short planes; + unsigned short bits_per_pixel; + unsigned long bytes; + unsigned short id; + }GROUPICONENTRY, *LPGROUPICONENTRY; + typedef struct _group_icon // for RT_GROUP_ICON + { + unsigned short reserved; + unsigned short res_type; // 1 for icon + unsigned short entries; + GROUPICONENTRY entry[1]; + }GROUPICON, *LPGROUPICON; +#pragma pack(pop) + + PORT_API(LPVOID) allocate_code_buffer(size_t size); + PORT_API(void) free_code_buffer(LPVOID code_buf); + PORT_API(int) get_min_code_buffer_bytes(void); + + // function: calculate hooking info at hook_addr + // hook_addr: the address will be hooked + // lphii: the hooking instruction info, at least 6 elements + // size: [in] - count of lphii, [out] - valid elements in lphii + // bytes: to receive the minimum bytes to be moved for hooking + // return: error code + PORT_API(int) calculate_hook_bytes(const BYTE* hook_addr, LPHOOKII lphii, int* size, int* bytes); + PORT_API(LPVOID) move_src_code_for_hook(LPVOID src_code, LPHOOKII lphii, int count, LPVOID given_buf = NULL, int bytes = 0); + + // hook_addr: the instruction address which you should hooking at + // new_addr: your hooking codes which would jump from hood_addr + // origin_code: to receive origin codes at hook_addr. or the given address for hook junk if was not NULL, then the moved_bytes contains the size of the buffer when in + // moved_bytes: to receive copied bytes from hook_addr. it can contains the origin_code buffer bytes if origin_code is not NULL + PORT_API(int) hook_at(DWORD_PTR hook_addr, FARPROC new_addr, DWORD_PTR *origin_code, int *moved_bytes); + PORT_API(int) hook_at(const char* module_name, const char* api, FARPROC new_addr, DWORD_PTR *origin_code, int *moved_bytes, int api_offset = 0); + PORT_API(int) hook_with_shellcode(DWORD_PTR hook_addr, unsigned char* shellcodes, size_t shell_codes_bytes); // // RVA in shellcodes will not be handled !!! + PORT_API(int) unhook_at(DWORD_PTR unhook_addr, DWORD_PTR* origin_code, int bytes_moved); + PORT_API(int) unhook_at(const char* module_name, const char* api, DWORD_PTR *origin_code, int bytes_moved, int api_offset = 0); + + // hook_bef: call method must be '__stdcall', and the parameters are pointers that points to the parameter of the origin api + // hook_after: call method must be '__stdcall', and the first parameter is the return value of origin api whenever the origin api return value or not + // and following the parameters is the same as origin api + // + // e.g. system api: HANDLE WINAPI CreateFileW(_In_ LPCWSTR lpFileName, + // _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, + // _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + // _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, + // _In_opt_ HANDLE hTemplateFile); + // hook_bef: void __stdcall hook_bef(LPCWSTR* lpFileName, + // DWORD* dwDesiredAccess, DWORD* dwShareMode, + // LPSECURITY_ATTRIBUTES* lpSecurityAttributes, + // DWORD* dwCreationDisposition, DWORD* dwFlagsAndAttributes, + // HANDLE* hTemplateFile + // void* user_data); + // or can be void __stdcall hook_bef(void* user_data) if no_param_for_hook_before was true; + // + // hook_after: void __stdcall hook_after(HANDLE* ret, LPCWSTR lpFileName, + // DWORD dwDesiredAccess, DWORD dwShareMode, + // LPSECURITY_ATTRIBUTES lpSecurityAttributes, + // DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, + // HANDLE hTemplateFile + // void* user_data); + // + // + PORT_API(void*) any_hook_at(FARPROC api, size_t param_count, bool stdcall, FARPROC hook_bef = NULL, bool hook_bef_without_param = false, FARPROC hook_after = NULL, void* user_data = NULL); + PORT_API(void) free_any_hook(void* any_hook); + + PORT_API(IObscurityCall*) create_obscurity_caller(const wchar_t* module, const char* api, int api_params, bool stdcall); + PORT_API(IObscurityCall*) create_obscurity_caller(HMODULE module, const char* api, int api_params, bool stdcall); + + // pe parsing ... + enum pe_address_type + { + PE_ADDR_RELATIVE_TO_FILE = 0, + PE_ADDR_RELATIVE_TO_MEM, + PE_ADDR_ABSOLUTE_ON_DEFAULT_BASE, + }; + __declspec(novtable) struct IPe : public ref_util::IRef + { + // params must not be NULL but the API was no parameter + COM_API_DECLARE(long, load_pe(const wchar_t* path_pe)); // return error code + COM_API_DECLARE(long, close(void)); // return error code, owner MUST call this before 'release' when you never use this !!! + COM_API_DECLARE(long, attach(unsigned char* buf, UINT64 bytes)); // return error code + COM_API_DECLARE(long, detach(unsigned char** buf)); // return error code + + // cb: data - (const char*)dll_name if flag was DATA_FLAG_FINAL or (const char*)err_msg if flag was DATA_FLAG_ERROR + // or "IAT" if flag was DATA_FLAG_INSTAR + // len - (const char*)api_name + // or IAT sector info(void*[2]) if flag was DATA_FLAG_INSTAR: [0] - (char*)section name, [1] - (UINT64) offset to file + // total - UINT64[2]: [0] - hint, [2] - offset in file(EAT only), [1] - offset in mem set to be '0' if 'only_dll' was true if flag was DATA_FLAG_FINAL or unused if flag was DATA_FLAG_ERROR + // or IAT table info(UINT64[3]) if flag was DATA_FLAG_INSTAR: [0] - offset to file, [1] - offset in memory, [2] - table bytes + // flag - DATA_FLAG_FINAL or DATA_FLAG_INSTAR or DATA_FLAG_ERROR + // + // param - same as the paramenter you passed 'param' + // + // return non 'SET_RESULT_CONTINUE' to stop working + COM_API_DECLARE(long, dump_iat(INTER_MODULE_CALLBACK_VAR(cb), void* param, bool only_dll = false)); + COM_API_DECLARE(long, dump_eat(INTER_MODULE_CALLBACK_VAR(cb), void* param)); + + // cb: data - (const char*)section name + // + // len - bytes of section name + // + // total - UINT64 pos[3]: pos[0] - offset in file, pos[1] - offset in memory, pos[2] - section size in bytes + // + // flag - DATA_FLAG_FINAL + // + // param - same as the paramenter you passed 'param' + COM_API_DECLARE(long, dump_sections(INTER_MODULE_CALLBACK_VAR(cb), void* param)); + + // cb: data - (const char*)resource name + // + // len - UINT64[2]: [0] - bytes of resource; [1] - (void*)resource_data + // + // total - UINT64[4]: [0] - id; [1] - memory offset; [2] - file offset, [3] - codepage + // + // flag - DATA_FLAG_FINAL + // + // param - same as the paramenter you passed 'param' + COM_API_DECLARE(long, dump_resources(INTER_MODULE_CALLBACK_VAR(cb), void* param)); + + // function: convert RVA between memory offset and file offset + // + // parameter: from - source address; + // + // to - to receive the target address + // + // off2rva - true: file offset to memory offset; false: memory offset to file offset + COM_API_DECLARE(long, rva(UINT64 from, UINT64* to, bool off2rva)); + + // cb: data - (const char*)assembly + // + // len - bytes of assembly + // + // total - UINT[2]: 0 - offset in file of the code, 1 - offset in memory of the assembly + // + // flag - DATA_FLAG_FINAL + // + // param - same as the paramenter you passed 'param' + COM_API_DECLARE(long, find_address_ref(UINT64 addr, INTER_MODULE_CALLBACK_VAR(cb), void* param, short addr_bytes = 4)); + COM_API_DECLARE(long, find_iat_ref(const char* dll_name, const char* api_name/*consider as hint if less than 0x10000*/, INTER_MODULE_CALLBACK_VAR(cb), void* param)); + COM_API_DECLARE(long, find_string_ref(const char* str, INTER_MODULE_CALLBACK_VAR(cb), void* param)); + COM_API_DECLARE(long, find_string_ref(const wchar_t* str, INTER_MODULE_CALLBACK_VAR(cb), void* param)); + + // function: un-assembly given function begin from 'addr' and ENDING at instruction 'ret' or 'cb' return SET_RESULT_STOP + // + // parameter: addr - given address + // + // addr_type - how to use the address 'addr' + // + // cb - data: (const char*) assembly + // len: bytes of data + // total: UINT64[4]: 0 - file offset; 1 - instruction absolute address; 2 - bytes; [3] - (unsigned char*) codes + // flag: DATA_FLAG_FINAL + // param: same as the paramenter you passed 'param' + // return SET_RESULT_CONTINUE to work until 'ret', or SET_RESULT_STOP to stop immediately + // + // param - parameter for 'cb' + // + // img_base - specify the image base. use default base if it was '0' + COM_API_DECLARE(long, un_assembly(UINT64 addr, enum pe_address_type addr_type, INTER_MODULE_CALLBACK_VAR(cb), void* param, UINT64 img_base = 0)); + COM_API_DECLARE(long, un_assembly(const char* export_api_name, INTER_MODULE_CALLBACK_VAR(cb), void* param)); + + // function: to change content at given file offset + // + // cb - data: (const wchar_t*) target file after changed + // len: bytes of data + // total: unused + // flag: DATA_FLAG_FINAL + // param: same as the parameter you passed 'param' + // return: omitted + COM_API_DECLARE(long, change(UINT64 file_off, const unsigned char* data, size_t bytes, INTER_MODULE_CALLBACK_VAR(cb), void* param)); + + COM_API_DECLARE(bool, is_pe_64(void)); // whether the PE is a 64-bits module + COM_API_DECLARE(long, get_entry_point(UINT64* off)); // get offset of entry-point in memory + COM_API_DECLARE(long, get_image_base_addr(UINT64* addr)); // get offset of entry-point in memory + COM_API_DECLARE(long, get_file_time(UINT64* file_time)); // get file compiled time + }; + + PORT_API(IPe*) create_pe_parser(void); +}; + diff --git a/tools/sdk/include/process/process_util.h b/tools/sdk/include/process/process_util.h new file mode 100644 index 0000000..184f077 --- /dev/null +++ b/tools/sdk/include/process/process_util.h @@ -0,0 +1,171 @@ +// process_util.h : include utilities for manage folders +// +// Author: Gongbing +// +// Date: 2016-09-25 + +#pragma once +#include +#include +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + +#define STATUS_SUCCESS 0x00000000 +#define STATUS_BUFFER_OVERFLOW 0x80000005 +#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 + +// process utils +namespace process_util +{ + PORT_API(int) start_program(const wchar_t* prog_file, const wchar_t* param, bool show_wnd, DWORD* pid = NULL, bool as_admin = false, const wchar_t* path_dll = NULL); + PORT_API(bool) is_me_in_admin(void); + PORT_API(int) try_me_in_admin(bool show_wnd, DWORD *pid = NULL, const wchar_t* append_param = NULL); + PORT_API(int) start_program_as_current_user(const wchar_t* prog_file, const wchar_t* param, bool show_wnd, unsigned* proc_id = NULL, bool merge_pe_2_param = true, const wchar_t* path_dll = NULL); + PORT_API(bool) start_program_by_cmd(const wchar_t* prog_file, const wchar_t* param); + PORT_API(bool) query_acting_user_token(HANDLE* aut); + PORT_API(int) enable_privilege(const wchar_t* privilege_name, bool enabled); + PORT_API(bool) kill_process_by_name(const wchar_t* proc_name, const wchar_t* taskkill_path = NULL); + PORT_API(bool) is_process_living(const wchar_t* proc_name, DWORD* pid = NULL); + + // parameter of result: + // data: (wchar_t*)pe_path_file + // len: process id + // total: parent process id + PORT_API(void) enum_processes(inter_module_data::set_data result, void* param); + + // parameter of result: + // data: (wchar_t*)module path file + // len: base address + // total: module size + PORT_API(void) enum_modules(DWORD proc_id, inter_module_data::set_data result, void* param); + PORT_API(bool) module_pe_from_run_address(void* addr, wchar_t path_name[MAX_PATH], void** base_addr = NULL); + + PORT_API(int) find_resource(HINSTANCE inst, const wchar_t* res_type, UINT res_id, inter_module_data::set_data result, void* param); + PORT_API(bool) is_pe_checksum_ok(const wchar_t* pe_path_file, DWORD* lppe_chksum = NULL, DWORD* lpfile_chksum = NULL); + PORT_API(bool) get_module_info(HMODULE module, void** base, void** entry, size_t* size); + PORT_API(bool) get_process_time(DWORD proc_id, LPFILETIME start = NULL, LPFILETIME kern = NULL, LPFILETIME user = NULL); + PORT_API(DWORD) get_parent_process(DWORD proc_id); + PORT_API(int) get_process_name(DWORD proc_id, wchar_t path_name[MAX_PATH]); + PORT_API(int) get_self_pathname(wchar_t path_name[MAX_PATH], bool call_module = false/*default to get exe pathname*/); + PORT_API(void) quit_and_delete_self(void); + PORT_API(char*) set_command_lineA(char* cmda); // the return buffer need not free + PORT_API(wchar_t*) set_command_lineW(wchar_t* cmda, bool is_setpeb); // the return buffer need not free + PORT_API(void) set_peb_command_lineW(wchar_t* cmda); + + PORT_API(HANDLE) get_file_handle_by_name(const wchar_t* filename, ULONG *pid = NULL); + PORT_API(BOOL) is_wow64_process(DWORD proc_id); + PORT_API(HMODULE) load_system_dll(const wchar_t* dll); + + PORT_API(void*) write_to_process(HANDLE proc, const void* src, int bytes); + PORT_API(void*) write_to_process(DWORD proc_id, const void* src, int bytes); + PORT_API(int) read_process_memory(DWORD proc_id, void* base_addr, int read_bytes, unsigned char* buf); // read proc_id [base_addr, base_addr] contents into buf, return error code, 0 is success + + // function: create a remote thread in given process + // proc_id: the target process ID + // code_bytes: remote thread code size in bytes + // susbend: whether to supspend this thread when create it + // parameter_size: remote thread parameter size + // tid: to receive the remote thread id + // thread: to receive the remote thread handle + // fill: to fill the thread code and parameter in this callback + // data: unused, always be NULL + // len: (LPVOID), the memory address in process proc_id + // total: (unsigned char*), to receive the content + // flag: write code when DATA_FLAG_REMOTE_THREAD_INSTRUCT, or parameter when DATA_FLAG_REMOTE_THREAD_PARAMETER if parameter_bytes was great than ZERO + // param: the same as 'param' + // param: parameter 'param' of callback fill + // return: error code, 0 is success + PORT_API(int) create_remote_thread(DWORD proc_id, int code_bytes, inter_module_data::set_data fill, void* param, bool suspend = false + , int parameter_bytes = 0, DWORD* tid = NULL, HANDLE* thread = NULL); + + // code and param: [in] - the source code or parameter buffer; [out] - remote code or parameter buffer + PORT_API(int) create_remote_thread(DWORD proc_id, const unsigned char **code, int code_bytes, bool suspend = false + , const unsigned char** param = NULL, int param_bytes = 0, DWORD* tid = NULL, HANDLE* thread = NULL); + PORT_API(bool) get_api_in_process(DWORD proc_id, const wchar_t* dll, const char* apis/*GetTickCount\0CreateFileW\0\0*/, FARPROC* api_addrs/*length as same as apis*/); + PORT_API(HMODULE) load_dll_in_process(DWORD proc_id, const wchar_t* path_dll); // return the loaded dll handle in the process + PORT_API(HMODULE) free_dll_in_process(DWORD proc_id, const wchar_t* path_dll); // return the dll in the process + + enum _inst_statu + { + INST_STATU_FIRST = 0, // 0 - I am the FIRST instance + INST_STATU_FAILED_CREATE, // 1 - no instance existing and failed to create the singleton instance + INST_STATU_INFO_FIRST, // 2 - an instance is already existing and informed my parameter + INST_STATU_FAILED_INFO_FIRST, // 3 - an instance is already existing and failed in informing my parameter + INST_STATU_ID_USED, // 4 - the name is used by other object + + INST_STATU_UNKNOWN = 10, // unknown error + }; + __declspec(novtable) struct ISingleton : public ref_util::IRef + { + COM_API_DECLARE(_inst_statu, statu(void)); + COM_API_DECLARE(bool, set_max_run_seconds(DWORD seconds = -1)); // quit after seconds when not -1 + }; + __declspec(novtable) struct ICmd : public ref_util::IRef + { + COM_API_DECLARE(void, reset(const wchar_t* cmdline = NULL)); // reset command line string, use GetCommandLineW if cmd_line was NULL + COM_API_DECLARE(long, count(void)); // return parameter count, if has key-val pair, then count them as 2 + + // function: whether the command line has 'param' + // case_sens: is case sensitive + // ind: to receive the index in command line if has + COM_API_DECLARE(bool, has(const wchar_t* param, bool case_sens = false, int *ind = NULL)); + COM_API_DECLARE(bool, is_first_main_pe(void)); // return whether the first parameter is main-pe + COM_API_DECLARE(const wchar_t*, parameter(int index)); // ZERO-based index, should not free the return buffer but use it immediately + + // key: the key for the parameter + // case_sens: whether the 'key' is case sensitive + // return: return im.exe of key '/im' in "taskkill /f /im im.exe", should not free but use it immediately + COM_API_DECLARE(const wchar_t*, parameter(const wchar_t* key, bool case_sens = false)); + COM_API_DECLARE(const wchar_t*, main_pe(void)); // DO NOT free the return buffer but use it immediately + + COM_API_DECLARE(int, add(const wchar_t* param, bool case_sens = false, int index = -1)); + COM_API_DECLARE(int, add(const wchar_t* key, const wchar_t* val, bool case_sens = false, int index = -1)); + + // if as_key was true, then remove param and the next item to it + COM_API_DECLARE(int, remove(const wchar_t* param, bool case_sens = false, bool as_key = false)); + COM_API_DECLARE(int, remove(int index)); + + // function: convert to a command line string + // buf: to receive the string, can be NULL + // len: [in] - count of buf, [out] - content length in buf, if buf was NULL or len is small, then contains the minimum length and return ERROR_INSUFFICIENT_BUFFER + // return: ERROR_SUCCESS if buf is length enough, or ERROR_INSUFFICIENT_BUFFER if len was less than required, + COM_API_DECLARE(int, to_command_line(wchar_t* buf, int* len)); + + // data: (const wchar_t*) + // len: bytes of 'data' + // total: unused, be ZERO + // flag: inter_module_data::DATA_FLAG_FINAL + // param: same as 'user' + COM_API_DECLARE(int, to_command_line(INTER_MODULE_CALLBACK_VAR(got_result), void* user)); + }; + + PORT_API(long) invoke_api(FARPROC func, bool stdcall_, int param_count, void** params, int* ret_val = NULL); + PORT_API(long) invoke_api(const wchar_t* path_module, const char* api, bool stdcall_, int param_count, void** params, int* ret_val = NULL); + + // parameter of result: + // data: (const wchar_t*)command line + // len: length of (const wchar_t*)data + // total: as same as len + // flag: DATA_FLAG_FINAL in commonplace, or DATA_FLAG_UNKNOWN to quit + // param: like 'param' + PORT_API(ISingleton*) create_singleton(const wchar_t* inst_id, inter_module_data::set_data result, void* param); + PORT_API(ICmd*) create_command_line(const wchar_t* cmd = NULL); + enum _console_attr + { + CA_FOREGROUND_BLUE = FOREGROUND_BLUE, + CA_FOREGROUND_GREEN = FOREGROUND_GREEN, + CA_FOREGROUND_RED = FOREGROUND_RED, + CA_FOREGROUND_INTENSITY = FOREGROUND_INTENSITY, + CA_BACKGROUND_BLUE = BACKGROUND_BLUE, + CA_BACKGROUND_GREEN = BACKGROUND_GREEN, + CA_BACKGROUND_RED = BACKGROUND_RED, + CA_BACKGROUND_INTENSITY = BACKGROUND_INTENSITY, + }; + PORT_API(WORD) set_console_attribute(WORD attr); + PORT_API(ICmd*) from_console(const wchar_t* tips = L"input"); + PORT_API(ICmd*) from_console(const char* tips = "input"); +} + + diff --git a/tools/sdk/include/process/un_asm.h b/tools/sdk/include/process/un_asm.h new file mode 100644 index 0000000..0f8ea03 --- /dev/null +++ b/tools/sdk/include/process/un_asm.h @@ -0,0 +1,126 @@ +// un_asm.h : include utilities for unassembly +// +// Author: Gongbing +// +// Date: 2020-03-19 + +#pragma once +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + + +namespace ia_asm +{ + // unassembly utils + enum ia_arch + { + IA_ARCHITECTURE_32 = 1, + IA_ARCHITECTURE_64, + }; + const UINT64 REGISTER_BMP_RAX = (UINT64)1 << 0; const UINT64 REGISTER_BMP_EAX = (UINT64)1 << 0; + const UINT64 REGISTER_BMP_RCX = (UINT64)1 << 1; const UINT64 REGISTER_BMP_ECX = (UINT64)1 << 1; + const UINT64 REGISTER_BMP_RDX = (UINT64)1 << 2; const UINT64 REGISTER_BMP_EDX = (UINT64)1 << 2; + const UINT64 REGISTER_BMP_RBX = (UINT64)1 << 3; const UINT64 REGISTER_BMP_EBX = (UINT64)1 << 3; + const UINT64 REGISTER_BMP_RSP = (UINT64)1 << 4; const UINT64 REGISTER_BMP_ESP = (UINT64)1 << 4; + const UINT64 REGISTER_BMP_RBP = (UINT64)1 << 5; const UINT64 REGISTER_BMP_EBP = (UINT64)1 << 5; + const UINT64 REGISTER_BMP_RSI = (UINT64)1 << 6; const UINT64 REGISTER_BMP_ESI = (UINT64)1 << 6; + const UINT64 REGISTER_BMP_RDI = (UINT64)1 << 7; const UINT64 REGISTER_BMP_EDI = (UINT64)1 << 7; + const UINT64 REGISTER_BMP_R08 = (UINT64)1 << 8; + const UINT64 REGISTER_BMP_R09 = (UINT64)1 << 9; + const UINT64 REGISTER_BMP_R10 = (UINT64)1 << 10; + const UINT64 REGISTER_BMP_R11 = (UINT64)1 << 11; + const UINT64 REGISTER_BMP_R12 = (UINT64)1 << 12; + const UINT64 REGISTER_BMP_R13 = (UINT64)1 << 13; + const UINT64 REGISTER_BMP_R14 = (UINT64)1 << 14; + const UINT64 REGISTER_BMP_R15 = (UINT64)1 << 15; + const UINT64 REGISTER_BMP_MM0 = (UINT64)1 << 16; + const UINT64 REGISTER_BMP_MM1 = (UINT64)1 << 17; + const UINT64 REGISTER_BMP_MM2 = (UINT64)1 << 18; + const UINT64 REGISTER_BMP_MM3 = (UINT64)1 << 19; + const UINT64 REGISTER_BMP_MM4 = (UINT64)1 << 20; + const UINT64 REGISTER_BMP_MM5 = (UINT64)1 << 21; + const UINT64 REGISTER_BMP_MM6 = (UINT64)1 << 22; + const UINT64 REGISTER_BMP_MM7 = (UINT64)1 << 23; + const UINT64 REGISTER_BMP_XMM0 = (UINT64)1 << 24; + const UINT64 REGISTER_BMP_XMM1 = (UINT64)1 << 25; + const UINT64 REGISTER_BMP_XMM2 = (UINT64)1 << 26; + const UINT64 REGISTER_BMP_XMM3 = (UINT64)1 << 27; + const UINT64 REGISTER_BMP_XMM4 = (UINT64)1 << 28; + const UINT64 REGISTER_BMP_XMM5 = (UINT64)1 << 29; + const UINT64 REGISTER_BMP_XMM6 = (UINT64)1 << 30; + const UINT64 REGISTER_BMP_XMM7 = (UINT64)1 << 31; + const UINT64 REGISTER_BMP_FLAG = (UINT64)1 << 32; + +#pragma pack(push) +#pragma pack(1) + typedef struct _instruction_data + { + unsigned long long address; // instruction address + unsigned long bytes; // all bytes of this instruction + unsigned long cycle; // cpu cycle + UINT64 reg_chg_bmp; // changed register bit-map mask + struct _rel_addr + { + union + { + unsigned char rel_byte; + struct + { + unsigned char offset : 5; // the offest to codes[0] of the relative address, ZERO means no + unsigned char size : 3; // bytes of the relative address, ZERO means no + }; + }; + }rel_addr[4]; // relative address in this instruction, max up to 4 + struct + { + unsigned char bytes[4]; // bytes for val, ZERO means no imm val, often be 1, 2, 4, 8 + UINT64 val[4]; // imm value + }imm; + char codes[20]; // instruction code bytes + char assembly[84]; // instruction text + + struct _instruction_data() + { + clear(); + } + void clear(void) + { + memset(this, 0, sizeof(struct _instruction_data)); + } + void copy(struct _instruction_data* r) + { + memcpy(this, r, sizeof(struct _instruction_data)); + } + }INSTRUCTION, *LPINSTRUCTION; +#pragma pack(pop) + + // function: to un-assembly the codes + // + // return: error codes, ZERO is success + PORT_API(int) unasm(const unsigned char* codes // code stream + , LPINSTRUCTION lpasm // to receive the assembly text + , unsigned long long address = 0 // instruction address, use address 'codes' if this was ZERO + , ia_arch ia32 = IA_ARCHITECTURE_32); // intel architecture + + // function: to convert near instruction to far instruction + // + // return: ZERO - have far instruction; 1 - no far instruction + PORT_API(int) far_instruction(const LPINSTRUCTION near + , LPINSTRUCTION far // to receive the far instruction + , unsigned long long far_instruction_addr = 0 // the address of the far instruction, use near's address if was ZERO + , ia_arch ia32 = IA_ARCHITECTURE_32); // intel architecture); + + // function: compile single instruction + // + // return: error codes, ZERO is success + PORT_API(int) compile(const char* assembly // assembly text such as 'mov eax, ebp' + , unsigned long long *address // [in] - address of this assembly, [out] - address of the next statement, commonly [in] add lpasm->bytes + , LPINSTRUCTION lpasm // instruction array to receive the result + , inter_module_data::set_data label // label callback. see DATA_FLAG_UNASM_SET_LABEL && DATA_FLAG_UNASM_GET_LABEL + , ia_arch ia32 = IA_ARCHITECTURE_32); // assembly architecture + PORT_API(int) compile_one(const char* assembly + , unsigned char *code // minimum length with 40 bytes. [bytes]codes[bytes]codes[0] + , unsigned long long address = 0); +} diff --git a/tools/sdk/include/ref/ref.h b/tools/sdk/include/ref/ref.h new file mode 100644 index 0000000..75c4ef6 --- /dev/null +++ b/tools/sdk/include/ref/ref.h @@ -0,0 +1,208 @@ +// ref.h : the base utility for life-cycle control by reference +// +// Author: Gongbing +// +// Create: 2017-05-20 + +#pragma once + +#ifdef _AS_DLL_ +#ifdef _NET_EXPORTS_ +#define PORT_API(ret) __declspec(dllexport) ret __stdcall +#define PORT_API_CALL(ret, call_) __declspec(dllexport) ret call_ +#else +#define PORT_API(ret) __declspec(dllimport) ret __stdcall +#define PORT_API_CALL(ret, call_) __declspec(dllimport) ret call_ +#ifdef _DEBUG +#pragma comment(lib, "./Debug/base_util.lib") +#else +#pragma comment(lib, "./Release/base_util.lib") +#endif +#endif +#else +#define PORT_API(ret) ret __stdcall +#define PORT_API_CALL(ret, call_) ret call_ +#ifndef _BASE_EXPORTS_ +#ifdef _DEBUG +#pragma comment(lib, "./Debug/base_util.lib") +#else +#pragma comment(lib, "./Release/base_util.lib") +#endif +#endif +#endif + +//#define STRUCT_ALIGN(bytes) \ +// #pragma pack(push) \ +// #pragma pack(bytes) +//#define STRUCT_ALIGN_END \ +// #pragma pack(pop) + +#define COM_API_DECLARE(ret, decl) virtual ret __stdcall decl = 0 +#define COM_API_DECLARE_NON_PURE(ret, decl) virtual ret __stdcall decl +#define COM_API_OVERRIDE(ret, decl) virtual ret __stdcall decl override +#define COM_API_IMPLEMENT(cls, ret, decl) ret __stdcall cls##::decl + +#define ALIGN_MEMORY(n, align) ((n + align - 1) / (align) * (align)) +#define _TO_UNICODE_(str) L##str +#define UNICODE_STR(str) _TO_UNICODE_(str) + +// refferer simulating-COM +namespace ref_util +{ + // + // rule: + // + // if a member of container owns the container pointer, the member should release the container pointer + // in an explicit function like 'stop'; the container could release the member pointer in destructor!!! + // + __declspec(novtable) struct IRef + { + COM_API_DECLARE(long, add_ref(void)); + COM_API_DECLARE(long, release(void)); + }; + + class refer : public IRef + { + volatile long m_ref; + + public: + refer() : m_ref(1) + {} + + protected: + virtual ~refer() + {} + + public: + COM_API_OVERRIDE(long, add_ref(void)) + { + return InterlockedIncrement(&m_ref); + } + COM_API_OVERRIDE(long, release(void)) + { + long ref = InterlockedDecrement(&m_ref); + + if (ref <= 0) delete this; + + return ref; + } + }; + + template + class auto_pointer + { + T* m_ptr; + + public: + auto_pointer() : m_ptr(NULL) + {} + auto_pointer(T* ptr) : m_ptr(ptr) + {} + auto_pointer(const auto_pointer& r) + { + m_ptr = r.m_ptr; + if (m_ptr) m_ptr->add_ref(); + } + ~auto_pointer() + { + if (m_ptr) m_ptr->release(); + } + + public: + auto_pointer& operator=(T* ptr) + { + if (m_ptr) m_ptr->release(); + m_ptr = ptr; + + return *this; + } + auto_pointer& operator=(const auto_pointer& r) + { + if (m_ptr) m_ptr->release(); + m_ptr = r.m_ptr; + if (m_ptr) m_ptr->add_ref(); + + return *this; + } + T* ptr(void) + { + return m_ptr; + } + T* operator->(void) + { + return m_ptr; + } + bool is_empty(void) + { + return m_ptr == NULL; + } + }; + +} + +#define IMPL_REF_BY_REFER() \ + COM_API_OVERRIDE(long, add_ref(void)) \ + { \ + return ref_util::refer::add_ref(); \ + } \ + COM_API_OVERRIDE(long, release(void)) \ + { \ + return ref_util::refer::release(); \ + } + +// inter-module data +namespace inter_module_data +{ + enum data_flag + { + // commonly + DATA_FLAG_UNKNOWN = 0, + DATA_FLAG_ERROR, // the parameter 'len' is contains the error code, total is extension info for 'len' + DATA_FLAG_FINAL, // data is final result for the api which you called + DATA_FLAG_INSTAR, // data is instar for your api, and finally will notified with flag DATA_TYPE_FINAL + DATA_FLAG_OVER, // all data has been transfered, parameter data, len and total are all invalid + + DATA_FLAG_GET_VAL, // (const wchar_t*)data, 'len' is bytes of data, 'total' is set_data + // call (set_data)total(const wchar_t* data, bytes of 'data', 0, DATA_FLAG_FINAL, param) + DATA_FLAG_DEBUG_INFO, + + // for http data + DATA_FLAG_HTTP_HEAD = 100, // http(s) response head + DATA_FLAG_302, // 301 or 302 to new url, the data contains the url. in this case, return SET_RESULT_CONTINUE to jump, SET_RESULT_DISCARD to stop jumping + + // for remote thread + DATA_FLAG_REMOTE_THREAD_INSTRUCT = 200, // to fill the remote thread code in given address + DATA_FLAG_REMOTE_THREAD_PARAMETER, // to fill the remote thread parameter in given address + + // the parameter data, len and total will be all set to ZERO if unused + DATA_FALG_SVC_ENTER = 300, // service callback, called when initailizing, parameter 'data' is pointing to proc_util::ICmd* + DATA_FALG_SVC_TIMER, // service callback, called when timer is set, parameter 'len' is the count base from ZERO + DATA_FALG_SVC_CONTROL, // service callback, called when service control is invoked, parameter 'len' is the control code + DATA_FALG_SVC_EXIT, // service callback, called when service exiting + + // for un-assembly + DATA_FLAG_UNASM_SET_LABEL = 1000, // set the label address, data is label, len is address, other has no mean + DATA_FLAG_UNASM_GET_LABEL, // query the label address. data is label, param is a pointer points to the UINT64 variable to receive the address + }; + + // return true to continue, false to stop + enum set_result + { + SET_RESULT_CONTINUE = ERROR_SUCCESS, // continue doing the task of the calling api + SET_RESULT_UNKNOWN = -100, // omit this value + SET_RESULT_DISCARD, // discard this data handling. i.e. it will stop jump to new url if flag is DATA_FLAG_302 + SET_RESULT_STOP, // this will stop all operations of the api you calling + }; + + // real usage of these parameters, see the API which use this callback ... + typedef set_result(__stdcall* set_data)(const char* data // data buffer + , UINT64 len // bytes of data in data-buffer or error code if flag was DATA_FLAG_ERROR + , UINT64 total // total bytes of the data for the api which you called + , data_flag flag // data flag + , void* param); // user defined data, and passing it when call the callback +} + +#define INTER_MODULE_CALLBACK(name) \ + inter_module_data::set_result __stdcall name(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param) +#define INTER_MODULE_CALLBACK_VAR(name) \ + inter_module_data::set_result (__stdcall *name)(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param) diff --git a/tools/sdk/include/sys/sys_util.h b/tools/sdk/include/sys/sys_util.h new file mode 100644 index 0000000..de6bf05 --- /dev/null +++ b/tools/sdk/include/sys/sys_util.h @@ -0,0 +1,242 @@ +// utility for registery operation +// +// Date: 2019-10-30 +// +#pragma once + +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// export interface for other modules on 2017-08-23 by GB +namespace sys_util +{ + ///////////////////////////////////////////////////////////////////////////////////////////// + // registry utilities ... + enum _wow_type + { + WOW_TYPE_DEFAULT = 0, // both given path and the Wow6432Node path in 32-bits app + WOW_TYPE_32_BITS, // the same as WOW_TYPE_DEFAULT in 32-bits app + WOW_TYPE_64_BITS, // no affect on registry in 32-bits app + }; + + // if parameter 'temporary' is true, then the key you created would lost after the system restart !!! + PORT_API(long) reg_create_key(const wchar_t* path, HKEY* ret = NULL, HKEY root = HKEY_LOCAL_MACHINE, _wow_type type = WOW_TYPE_DEFAULT, bool temporary = false); + PORT_API(long) reg_close_key(HKEY key); + PORT_API(long) reg_remove_key(const wchar_t* path, HKEY root = HKEY_LOCAL_MACHINE, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_remove_value(const wchar_t* path, const wchar_t* val_name, HKEY root = HKEY_LOCAL_MACHINE, _wow_type type = WOW_TYPE_DEFAULT); + + // parameter of cb + // data: (const wchar_t*) + // len: bytes of data + // total: unused + // flag: inter_module_data::DATA_FLAG_FINAL + // param: the same as the parameter 'param' + // + // return: error code + PORT_API(long) reg_get_string(HKEY root, const wchar_t* path, const wchar_t* name, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_get_binary(HKEY root, const wchar_t* path, const wchar_t* name, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_get_integer(HKEY root, const wchar_t* path, const wchar_t* name, int* val, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_get_integer(HKEY root, const wchar_t* path, const wchar_t* name, unsigned long long* val, _wow_type type = WOW_TYPE_DEFAULT); + + // parameter of cb + // data: (const wchar_t*)key_name + // len: (const wchar_t*)path + // total: unused + // flag: inter_module_data::DATA_FLAG_FINAL + // param: the same as the parameter 'param' + // + // return: error code + PORT_API(long) reg_enum_key(HKEY root, const wchar_t* path, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT); + + // parameter of cb + // data: (const wchar_t*) reg_value name + // len: (HIDWORD): type - REG_SZ, (wchar_t*)total; REG_DWORD/REG_QWORD, (DWORD/UINT64)total; REG_BINARY, (unsigned char*)total + // (LODWORD): bytes of data + // total: value + // flag: inter_module_data::DATA_FLAG_FINAL + // param: the same as the parameter 'param' + // + // return: error code + PORT_API(long) reg_enum_value(HKEY root, const wchar_t* path, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT); + + // function: set string value + // val: can be multi-string fromat such as "123\0456\0789\0\0", in this circumstance, caller must provides val_bytes + // val_bytes: length of val, in bytes. will consider as single string if it was 0 + // + // NOTE: this api would not support REG_EXPAND_SZ that with unexpanded string such as %systemroot% + PORT_API(long) reg_set_string(HKEY root, const wchar_t* path, const wchar_t* name, const wchar_t* val, int val_bytes = 0, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_set_integer(HKEY root, const wchar_t* path, const wchar_t* name, unsigned val, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_set_integer(HKEY root, const wchar_t* path, const wchar_t* name, unsigned long long val, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_set_binary(HKEY root, const wchar_t* path, const wchar_t* name, unsigned char* val, int val_bytes, _wow_type type = WOW_TYPE_DEFAULT); + + // function: to find the default opener of given file type + // file_ext: the extension name of the file, such as ".txt", lead with '.' + // cb: data - (const wchar_t*)path_opener + PORT_API(long) reg_get_file_opener(const wchar_t* file_ext/*.txt*/, inter_module_data::set_data cb, void* param); + + // function: enumerate installed service + // cb: data - (const wchar_t*) reg_service name + // len - (const wchar_t*) reg_service path file + // total - (const wchar_t*) reg_service description + // flag - inter_module_data::DATA_FLAG_FINAL + PORT_API(long) reg_enum_service(inter_module_data::set_data cb, void* param); + + // function: enumerate the auto starting program when system power on + // cb: data - (const wchar_t*) reg_program name + // len - (const wchar_t*) reg_program path file + // total - (const wchar_t*) reg_startup parameter + // flag - inter_module_data::DATA_FLAG_FINAL + PORT_API(long) reg_enum_program_on_system_poweron(inter_module_data::set_data cb, void* param); + PORT_API(long) reg_remove_program_on_system_poweron(const wchar_t* name); // the name should be the same as in enum_program_on_system_poweron + + // function: enumerate installed service + // cb: data - (const wchar_t*) reg_software display name + // len - (const wchar_t*) reg_uninstaller path file + // total - (const wchar_t*) reg_publisher + // flag - inter_module_data::DATA_FLAG_FINAL + PORT_API(long) reg_enum_uninstaller(inter_module_data::set_data cb, void* param); + PORT_API(long) reg_reg_uninstaller(const wchar_t* app_name, const wchar_t* display_name, const wchar_t* uninstall_pe, const wchar_t* uninstall_param = NULL + , const wchar_t* publisher = NULL, const wchar_t* version = NULL, unsigned size_in_bytes = 0, _wow_type type = WOW_TYPE_DEFAULT); + PORT_API(long) reg_del_uninstaller(const wchar_t* app_name, _wow_type type = WOW_TYPE_DEFAULT); + + ///////////////////////////////////////////////////////////////////////////////////////////// + // wmi utilities ... + // initialize a WMI object, use wmi_free to free the returned object + PORT_API(void*) wmi_initialize(void); + + // because WMI is query system database, so consider it as registry and provides here ... + // function: query system configuration through by WMI + // win32_cls: the class name like Win32_xxxx, e.g. "Win32_NetworkAdapterConfiguration" + // attr_name: the attribute name in the win32_cls, e.g. "IPAddress" of "Win32_NetworkAdapterConfiguration" + // cb: data - value depends on len, see comments of parameter 'len' + // len - value type: VT_BSTR(const wchar_t*), VT_I1~8(char*, short*, int*, longlong*), VT_R4/8(float*, double*), VT_BOOL(bool*) + // total - unused + // flag - inter_module_data::DATA_FLAG_INSTAR in enumeration, and inter_module_data::DATA_FLAG_FINAL at over, then the data is invalid + // param - the same as parameter 'param' + PORT_API(HRESULT) wmi_query(const wchar_t* win32_cls, const wchar_t* attr_name, inter_module_data::set_data cb, void* param, void* wmi = NULL/*returned by wmi_initialize*/); + PORT_API(void) wmi_free(void* wmi/*returned by wmi_initialize*/); + + + ///////////////////////////////////////////////////////////////////////////////////////////// + // service utilities ... + enum _svc_state + { + SVC_STATE_UNKNOWN = 0, + SVC_STATE_STOPPED, + SVC_STATE_STARTING, + SVC_STATE_STOPPING, + SVC_STATE_RUNNING, + SVC_STATE_RESUMING, + SVC_STATE_PAUSING, + SVC_STATE_PAUSED, + }; + PORT_API(long) svc_install(const wchar_t* svc_file, const wchar_t* svc_name, const wchar_t* svc_desc, const wchar_t* display_name = NULL); + PORT_API(long) svc_uninstall(const wchar_t* svc_name); + PORT_API(long) svc_start(const wchar_t* svc_name, DWORD wait_running_timeout = 0/*milliseconds*/); + PORT_API(long) svc_pause(const wchar_t* svc_name); + PORT_API(long) svc_resume(const wchar_t* svc_name); + PORT_API(long) svc_enable(const wchar_t* svc_name, bool enable); + PORT_API(long) svc_stop(const wchar_t* svc_name, DWORD wait_stopped_timeout = 0/*milliseconds*/); + PORT_API(long) svc_change_pe_file(const wchar_t* svc_name, const wchar_t* to_pe_file); + PORT_API(long) svc_change_description(const wchar_t* svc_name, const wchar_t* description); + PORT_API(bool) svc_is_running(const wchar_t* svc_name); + PORT_API(long) svc_pe_file(const wchar_t* svc_name, inter_module_data::set_data cb, void* param); // NOTE: DLL service will return "%system%\svchost.exe -k name" !!! + + // function: handle the service common command, supporting following commands: + // --install: install self, or other service if with "-pe given service file" parameter + // --uninstall: uninstall self + // --restart: restart self + // --start: start self + // --stop: stop self + // --pause: pause self + // --resume: resume self + // + // return: whether handled the command + // + // NOTE: this API's codes must be in the service module; if with parameter "-pe given service file" then all operation are both on the given service + PORT_API(bool) svc_handle_common_command(const wchar_t* svc_name, const wchar_t* svc_desc, long* err); + + // function: service enter, call this in main() for exe service.... support --install, --uninstall and --restart startup parameter + // parameter of cb: see the comment of DATA_FALG_SVC_xxx + PORT_API(long) start_as_service(const wchar_t* svc_name, const wchar_t* svc_desc, inter_module_data::set_data cb, void* param, DWORD timer_elapse = 0/*millisecond*/); + + + ///////////////////////////////////////////////////////////////////////////////////////////// + // shortcut utilities ... + // + // lnk_file: the file which with '.lnk' extension name + // target_file: the final file linked by lnk_file + // + PORT_API(HRESULT) link_create(const wchar_t* lnk_file, const wchar_t* target_file, const wchar_t* start_arguments + , const wchar_t* icon_path_file = NULL, int icon_index = 0, const wchar_t* lnk_desc = NULL); + + // icon_index: change the icon in target file of icon index; or not change the icon if it was -1, you can call link_change_icon to change it later + PORT_API(HRESULT) link_change_target_file(const wchar_t* lnk_file, const wchar_t* target_file, int icon_index = 0); + PORT_API(HRESULT) link_change_icon(const wchar_t* lnk_file, const wchar_t* file_ico, int index = 0); + PORT_API(HRESULT) link_change_startup_arguments(const wchar_t* lnk_file, const wchar_t* start_arguments); + PORT_API(HRESULT) link_change_description(const wchar_t* lnk_file, const wchar_t* description); + PORT_API(long) link_pin_to_taskbar(const wchar_t* lnk_file, bool pin = true); + + // flag: DATA_FLAG_INSTAR for startup arguments, DATA_FLAG_FINAL for the target pe file + PORT_API(HRESULT) link_get_target_file(const wchar_t* lnk_file, inter_module_data::set_data cb, void* param); + + /////////////////////////////////////////////////////////////////////////////////////// + // hardware info + enum cpu_cache_type + { + CPU_CACHE_NULL = 0, // 0 = Null - No more caches. + CPU_CACHE_DATA, // 1 = Data Cache. + CPU_CACHE_INSTRUCTION, // 2 = Instruction Cache. + CPU_CACHE_UNIFIED, // 3 = Unified Cache. + CPU_CACHE_COUNT, + }; + typedef struct _cpu_cache + { + cpu_cache_type type; + int level; + UINT64 bytes; + }CPUCACHE, *LPCPUCACHE; + typedef struct _cpu_info + { + int max_cpuid; + int cores; + int speed_base; // in MHz, 0 - not got; < 0 is unreliable + int speed_max; // in MHz, 0 - not got; < 0 is unreliable + char *manufactor; + char *product; + int cache_num; + CPUCACHE caches[4]; + }CPUINFO, *LPCPUINFO; + typedef struct _bios_info + { + char *base_board_manufactor; + char *base_board_product_name; + char *base_board_version; + char *bios_vendor; + char *bios_version; + char *bios_release_date; + char bios_major_release; + char bios_minor_release; + char controller_major_release; + char controller_minor_release; + }BIOSINFO, *LPBIOSINFO; + + // result: data - LPCPUINFO + // len - error code, 0 is success + // total - unused, always be ZERO + // flag - DATA_FLAG_FINAL + // param - same as the parameter 'param' + PORT_API(bool) get_cpu_info(inter_module_data::set_data result, void* param); + + // result: data - LPBIOSINFO + // len - error code, 0 is success + // total - unused, always be ZERO + // flag - DATA_FLAG_FINAL + // param - same as the parameter 'param' + PORT_API(bool) get_bios_info(inter_module_data::set_data result, void* param); +}; + + diff --git a/tools/sdk/include/threads/thread.h b/tools/sdk/include/threads/thread.h new file mode 100644 index 0000000..0fa8023 --- /dev/null +++ b/tools/sdk/include/threads/thread.h @@ -0,0 +1,224 @@ +// thread.h : the base utility for thread pool management +// +// Author: Gongbing +// +// Create: 2017-05-20 + +#pragma once +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif +#pragma warning(disable: 4996) + +//////////////////////////////////////////////////////////////////////////////////////////// +// thread ... +// +// purpose: if you CreateThrad and TerminateThread then, the new thread maybe occupying the global +// RTL_CRITICAL_SECTION variable in ntdll.dll module. In this situation, all threads that +// created by CreateThread will no longer have opportunity to run!!! +// This class is providing you to TerminateThread safely + +namespace thread_util +{ + enum _io_direction + { + IO_WRITE = 1, + IO_READ, + IO_CONTROL, + IO_USER_TYPE_BASE = 10, + }; +#pragma pack(push) +#pragma pack(1) + typedef struct _ovl_extension : OVERLAPPED + { + int io_direction; // _io_direction + size_t buf_len; // bytes of payload buffer + size_t data_len; // valid bytes of payload + size_t io_pos; // current IO position + char payload[8]; // payload data buffer + + char* user_payload(void) + { + return payload; + } + }OVLEX, *LPOVLEX; +#pragma pack(pop) + + __declspec(novtable) struct ILock : public ref_util::IRef + { + COM_API_DECLARE(void, lock(void)); + COM_API_DECLARE(bool, try_lock(void)); + COM_API_DECLARE(void, unlock(void)); + }; + __declspec(novtable) struct IThreadWorker : public ref_util::IRef + { + COM_API_DECLARE(void*/*void* tls*/, thread_enter(void)); // you can initialize tls in this method + COM_API_DECLARE(void, thread_work(void*/*bind data*/ task_key, LPOVLEX task_data, unsigned data_size, DWORD err_code, void* enter_data)); + COM_API_DECLARE(void, thread_exit(void* enter_data/*tls*/)); + }; + __declspec(novtable) struct IThreadPool : public ref_util::IRef + { + COM_API_DECLARE(long, add_task(void* task_key, void* task_data, unsigned data_size)); // return 0 when success + COM_API_DECLARE(long, stop(void)); + + COM_API_DECLARE(long, worker_threads(void)); + COM_API_DECLARE(long, busy_threads(void)); + COM_API_DECLARE(long, waiting_task(void)); + }; + __declspec(novtable) struct IEventDispatchThreadPool : public IThreadPool // dispach thread pool through by hardware-event mechanism + { + COM_API_DECLARE(long, bind_object(void* object, void* bind_key)); + COM_API_DECLARE(long, remove_object(void* object, void* bind_key)); + }; + + class simple_lock + { + ILock *lck_; + + public: + simple_lock(ILock* lck) + { + lck_ = lck; + if (lck_) + { + //lck_->add_ref(); + lck_->lock(); + } + } + ~simple_lock() + { + if (lck_) + { + lck_->unlock(); + //lck_->release(); + } + } + }; + + // for reducing the times of memory copying, request memory from inner - added on 2019-07-28 + PORT_API(LPOVLEX) inner_buffer_to_OVLEX_head(void* buf/*'buf' is returned by request_inner_buffer*/); + PORT_API(char*) request_inner_buffer(size_t bytes); + PORT_API(void) free_inner_buffer(void* buf); // free the buffer returned by 'request_inner_buffer' + PORT_API(void) free_inner_buffer(LPOVLEX buf); // free the buffer returned by 'request_inner_buffer' + + PORT_API(HANDLE) create_thread(unsigned(__stdcall* thread)(void*), void* param, bool suspend = false, unsigned allow_cpu_mask = -1); // return thread id + PORT_API(ILock*) create_lock(void); + PORT_API(IThreadPool*) create_thread_pool(IThreadWorker* worker, int desired_threads = 0, unsigned cpu_allow_mask = -1); + PORT_API(IEventDispatchThreadPool*) create_event_thread_pool(IThreadWorker* worker, int desired_threads = 0, unsigned cpu_allow_mask = -1); + + // parameter of result: + // data: (wchar_t*)thread name, maybe null + // len: thread id + // total: start address + PORT_API(void) enum_threads(DWORD proc_id, inter_module_data::set_data result, void* param); + PORT_API(LPVOID) get_thread_start_address(DWORD thread_id); + PORT_API(DWORD) get_call_stack(DWORD ebp, DWORD *stack/*caller allocate the buffer*/, int depth = 6, void* ensure_module = NULL/*ensure the module which contains the address ensure_module in the stack, omit if stack_data was valid*/ + , unsigned char* stack_data = NULL, int stack_bytes = 0); // return depth in stack + PORT_API(DWORD) get_thread_call_stack(DWORD thread_id, DWORD *stack/*caller allocate the buffer*/, int depth = 6, void* ensure_module = NULL/*ensure the module which contains the address ensure_module in the stack*/); // return depth in stack + PORT_API(void) set_thread_name(DWORD thread_id, const char* thread_name); + + // the parameter 'allow_cpu_mask' is is a bit vector in which each bit represents the processors that a thread is allowed to run on + // 1 represent CPU0, 5 represent CPU0 and CPU2, and so on... + enum _ict_state + { + ICT_STATE_NONE = 0, + ICT_STATE_START_FAIL, + ICT_STATE_RUNNING, + ICT_STATE_COMPLETE, + }; + template // NOTE: class T must derived from ref_util::IRef !!! + class invoke_class_thread : public ref_util::refer + { + void(__stdcall T::* handle_func)(void*); + void *param_; // dynamic parameter should free in handle_func !!! + T *obj_; + HANDLE wait_; + HANDLE thread_; + unsigned thread_id_; + unsigned affinity_mask_; + + _ict_state state_; + unsigned start_tick_; // elapse milliseconds if state_ == ICT_STATE_COMPLETE, start time tick counts in others + + public: + invoke_class_thread(T* obj, void(__stdcall T::* thread_func)(void*), void* param, unsigned allow_cpu_mask = -1) : state_(ICT_STATE_NONE), start_tick_(0) + { + if (obj) obj->add_ref(); + obj_ = obj; + param_ = param; + handle_func = thread_func; + + wait_ = CreateEvent(NULL, TRUE, FALSE, NULL); + thread_ = thread_util::create_thread(invoke_thread, this, false, allow_cpu_mask); + if (thread_ == NULL) state_ = ICT_STATE_START_FAIL; + else + { + thread_id_ = GetThreadId(thread_); + WaitForSingleObject(wait_, INFINITE); + } + CloseHandle(wait_); + wait_ = NULL; + } + + protected: + ~invoke_class_thread() + { + if (thread_) CloseHandle(thread_); + if (obj_) obj_->release(); + } + + private: + static unsigned WINAPI invoke_thread(void* lp) + { + invoke_class_thread *obj = (invoke_class_thread*)lp; + + obj->add_ref(); + obj->state_ = ICT_STATE_RUNNING; + obj->start_tick_ = GetTickCount(); + SetEvent(obj->wait_); + (obj->obj_->*obj->handle_func)(obj->param_); + obj->state_ = ICT_STATE_COMPLETE; + obj->start_tick_ = GetTickCount() - obj->start_tick_; + obj->release(); + + return 0; + } + + public: + unsigned thread_id(void) + { + return thread_id_; + } + HANDLE thread(bool take = false) + { + HANDLE h = thread_; + + if (take) + thread_ = NULL; + + return h; + } + enum _ict_state thread_state(void) + { + return state_; + } + unsigned start_tick_count(bool elapse = false) + { + return elapse && state_ != ICT_STATE_COMPLETE ? GetTickCount() - start_tick_ : start_tick_; + } + int terminate(int reason = 0) + { + HANDLE h = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id_); + int err = GetLastError(); + if (h) + { + err = TerminateThread(h, reason) ? ERROR_SUCCESS : GetLastError(); + CloseHandle(h); + } + + return err; + } + }; + +} diff --git a/tools/sdk/include/utility/known_file.h b/tools/sdk/include/utility/known_file.h new file mode 100644 index 0000000..1ebc300 Binary files /dev/null and b/tools/sdk/include/utility/known_file.h differ diff --git a/tools/sdk/include/vs_tool/vs_tool.h b/tools/sdk/include/vs_tool/vs_tool.h new file mode 100644 index 0000000..f71c4e2 Binary files /dev/null and b/tools/sdk/include/vs_tool/vs_tool.h differ diff --git a/tools/sdk/include/win/ui/ui_util.h b/tools/sdk/include/win/ui/ui_util.h new file mode 100644 index 0000000..7e794fa Binary files /dev/null and b/tools/sdk/include/win/ui/ui_util.h differ diff --git a/tools/sdk/include/win/win_util.h b/tools/sdk/include/win/win_util.h new file mode 100644 index 0000000..83f0e08 Binary files /dev/null and b/tools/sdk/include/win/win_util.h differ diff --git a/tools/sdk/include/zip/zip_util.h b/tools/sdk/include/zip/zip_util.h new file mode 100644 index 0000000..cde2db1 --- /dev/null +++ b/tools/sdk/include/zip/zip_util.h @@ -0,0 +1,152 @@ +// zip_util.h : include utilities for manage zip/unzip +// +// Author: Gongbing +// +// Date: 2016-09-25 + +#pragma once +#ifndef _INCLUDED_REF_ +#define _INCLUDED_REF_ +#include "../ref/ref.h" +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// + + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// +#pragma pack(push) +#pragma pack(1) +typedef struct zip_local_file_header +{ + unsigned signature; // 0x04034B50 + unsigned short ver; + unsigned short flag; + unsigned short compression; + unsigned short last_modify_time; + unsigned short last_modify_date; + unsigned crc; + unsigned compressed_size; + unsigned uncompressed_size; + unsigned short name_len; + unsigned short ext_len; + char name[0]; + + char* extension() + { + char *ext = NULL; + + if (ext_len) + { + ext = (char*)this; + ext += sizeof(struct zip_local_file_header); + ext += name_len; + } + + return ext; + } +}ZIPLFH, *LPZIPLFH; + +typedef struct zip_centeral_file_header +{ + unsigned signature; // 0x02014B50 + unsigned short ver_zip; + unsigned short ver_unzip; + unsigned short flag; + unsigned short compression; + unsigned short last_modify_time; + unsigned short last_modify_date; + unsigned crc; + unsigned compressed_size; + unsigned uncompressed_size; + unsigned short name_len; + unsigned short ext_len; + unsigned short comment_len; + unsigned short start_disk_number; + unsigned short inter_file_attr; + unsigned outer_file_attr; + unsigned lfh_rva; + char file_name[0]; // follwing by extra & comment +}ZIPCFH, *LPZIPCFH; +#pragma pack(pop) + + +namespace zip_util +{ + __declspec(novtable) struct IUnzipPack : public ref_util::IRef + { + // open a local packet file + COM_API_DECLARE(int, open(const wchar_t* path_file, const char* pwd = NULL)); + + // open a memory packet content + COM_API_DECLARE(int, open(void* data, size_t len, const char* pwd = NULL)); + + // files: to receive all items include folder + // folders: to receive folders in this packet + // total_size: to receive every file size(exclude folder) + // return: result statu code, ERROR_SUCCESS or other error code + COM_API_DECLARE(int, get_files(int *files, int* folders, UINT64* total_size)); + + // index: ZERO-based index in this packet + // size: to receive the item bytes data in returned buffer + // name: to receive the item name, maybe with relative path. call free_zip_buffer to free it + // cont: to receive the content, call free_zip_buffer to free it + // attr: to receive the item attribute + // create_time: to receive the item created time + // modi_time: to receive the item last modified time + // acc_time: to receive the item last accessed time + COM_API_DECLARE(int, get_item(int index, DWORD* attr, wchar_t** name = NULL, char** cont = NULL, UINT64* size = NULL + , FILETIME* create_time = NULL, FILETIME* modi_time = NULL, FILETIME* acc_time = NULL)); + + // Function: unzip this packet to an existing local directory. caller should ensure the path local_dir is existing already + // prog: data - points to a wchar_t* buffer contains the current file path + // len - current file bytes of data if flag was DATA_FLAG_FINAL, when flag is DATA_FLAG_ERROR then contains error: + // ERROR_ALREADY_EXISTS, return SET_RESULT_DISCARD to reserve the file; SET_RESULT_CONTINUE to overwrite + // ERROR_CREATE_FAILED, create local file failed, parameter 'total' is GetLastError + // ERROR_DATA_CHECKSUM_ERROR, unzip the file failed, the (wchar_t*)data is unreliable + // total- all data bytes to be unzipped + // flag - be DATA_FLAG_FINAL always in normal or DATA_FLAG_ERROR if error occurs + // param- be prog_param always + COM_API_DECLARE(int, unzip_to(const wchar_t* local_dir, inter_module_data::set_data prog, void* prog_param)); + COM_API_DECLARE(int, close(void)); + }; + __declspec(novtable) struct IZipPack : public ref_util::IRef + { + // add a local file or directory into the packet, rel_path is relative to the packet + // rel_path: relative to the packet, only file name if NULL. e.g. 'first\\data.txt' or 'data.txt' + COM_API_DECLARE(int, add_local_file(const wchar_t* path_file, const wchar_t* rel_path = NULL)); + + // add memory data into the packet, rel_path_name is relative to the packet + // rel_path_name: e.g. 'first\\data.txt' or 'data.txt' + COM_API_DECLARE(int, add_data(void* data, size_t len, const wchar_t* rel_path_name)); + + // add a folder into the packet, only folder, no data. path is relative to the packet + // add local directory into the packet, use add_local_file + // folder_rel_path_name: e.g. 'folder' or 'top\\folder' + COM_API_DECLARE(int, add_folder(const wchar_t* folder_rel_path_name)); + + // if you create a memory packet, this will return the start buffer and data length. + // the buffer 'data' is caller passed in + COM_API_DECLARE(int, get_memory_data(void** data, UINT64* len)); + + COM_API_DECLARE(int, close(void)); + }; + + // Function: zip data into stream which leading by 0x1f, 0x8b, ... + // data: should be zipped data + // len: bytes of data + // return: error code + PORT_API(int) gzip_zip(const char* data, ULONGLONG len, inter_module_data::set_data result, void* result_param); + + // Function: unzip the gzip data which leading by 0x1f, 0x8b, ... + // data: should be unzipped data + // len: bytes of data + // return: error code + PORT_API(int) gzip_unzip(const char* data, ULONGLONG len, inter_module_data::set_data result, void* result_param); + + PORT_API(IZipPack*) create_zip_file(const wchar_t* local_file, const char* pwd = NULL); + PORT_API(IZipPack*) create_zip_memory(void* buf, UINT64 len, const char* pwd = NULL); + PORT_API(IUnzipPack*) open_zip(const wchar_t* local_file, const char* pwd = NULL); + PORT_API(IUnzipPack*) open_zip(void* buf, UINT64 len, const char* pwd = NULL); +}; diff --git a/tools/sdk/lib/Debug/base_util.lib b/tools/sdk/lib/Debug/base_util.lib new file mode 100644 index 0000000..5d76f95 Binary files /dev/null and b/tools/sdk/lib/Debug/base_util.lib differ diff --git a/tools/sdk/lib/Release/base_util.lib b/tools/sdk/lib/Release/base_util.lib new file mode 100644 index 0000000..473d4c0 Binary files /dev/null and b/tools/sdk/lib/Release/base_util.lib differ diff --git a/tools/solution/Release/cvstr.exe b/tools/solution/Release/cvstr.exe new file mode 100644 index 0000000..f1e89f8 Binary files /dev/null and b/tools/solution/Release/cvstr.exe differ diff --git a/tools/solution/Release/hgjson.exe b/tools/solution/Release/hgjson.exe new file mode 100644 index 0000000..e5cce0f Binary files /dev/null and b/tools/solution/Release/hgjson.exe differ diff --git a/tools/solution/sane_tools.sln b/tools/solution/sane_tools.sln new file mode 100644 index 0000000..1d79cf7 --- /dev/null +++ b/tools/solution/sane_tools.sln @@ -0,0 +1,63 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32106.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{434BA17E-2347-4C76-97A2-DF9940EEB9FC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hgjson", "..\apps\hgjson\hgjson.vcxproj", "{D3579C48-F5AB-4F15-9B49-A2970FBA76C5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cvstr", "..\apps\cvstr\cvstr.vcxproj", "{758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Debug|Win32.ActiveCfg = Debug|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Debug|Win32.Build.0 = Debug|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Debug|x64.ActiveCfg = Debug|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Debug|x86.ActiveCfg = Debug|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Debug|x86.Build.0 = Debug|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Release|Mixed Platforms.Build.0 = Release|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Release|Win32.ActiveCfg = Release|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Release|Win32.Build.0 = Release|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Release|x64.ActiveCfg = Release|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Release|x86.ActiveCfg = Release|Win32 + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5}.Release|x86.Build.0 = Release|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Debug|Win32.ActiveCfg = Debug|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Debug|Win32.Build.0 = Debug|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Debug|x64.ActiveCfg = Debug|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Debug|x86.ActiveCfg = Debug|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Debug|x86.Build.0 = Debug|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Release|Mixed Platforms.Build.0 = Release|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Release|Win32.ActiveCfg = Release|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Release|Win32.Build.0 = Release|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Release|x64.ActiveCfg = Release|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Release|x86.ActiveCfg = Release|Win32 + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D3579C48-F5AB-4F15-9B49-A2970FBA76C5} = {434BA17E-2347-4C76-97A2-DF9940EEB9FC} + {758032ED-6FB3-4E7F-AA8F-A463C2B5D91E} = {434BA17E-2347-4C76-97A2-DF9940EEB9FC} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8F4909F0-C507-4210-A730-BFFBF9773850} + EndGlobalSection +EndGlobal