1 /**
2  * WinPR: Windows Portable Runtime
3  * Print Utils
4  *
5  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <errno.h>
28 
29 #include <winpr/crt.h>
30 #include <winpr/print.h>
31 
32 #include "trio.h"
33 
34 #include "../log.h"
35 
winpr_HexDump(const char * tag,UINT32 level,const BYTE * data,size_t length)36 void winpr_HexDump(const char* tag, UINT32 level, const BYTE* data, size_t length)
37 {
38 	wLog* log = WLog_Get(tag);
39 	winpr_HexLogDump(log, level, data, length);
40 }
41 
winpr_HexLogDump(wLog * log,UINT32 lvl,const BYTE * data,size_t length)42 void winpr_HexLogDump(wLog* log, UINT32 lvl, const BYTE* data, size_t length)
43 {
44 	const BYTE* p = data;
45 	size_t i, line, offset = 0;
46 	const int maxlen = 20; /* 64bit SIZE_MAX as decimal */
47 	/* String line length:
48 	 * prefix          '[1234] '
49 	 * hexdump         '01 02 03 04'
50 	 * separator       '   '
51 	 * ASIC line       'ab..cd'
52 	 * zero terminator '\0'
53 	 */
54 	const size_t blen =
55 	    ((size_t)maxlen + 3) + (WINPR_HEXDUMP_LINE_LENGTH * 3) + 3 + WINPR_HEXDUMP_LINE_LENGTH + 1;
56 	size_t pos = 0;
57 
58 	char* buffer;
59 
60 	if (!log || (maxlen < 0))
61 		return;
62 
63 	buffer = malloc(blen);
64 
65 	if (!buffer)
66 	{
67 		WLog_Print(log, WLOG_ERROR, "malloc(%" PRIuz ") failed with [%" PRIuz "] %s", blen, errno,
68 		           strerror(errno));
69 		return;
70 	}
71 
72 	while (offset < length)
73 	{
74 		int rc = trio_snprintf(&buffer[pos], blen - pos, "%04" PRIuz " ", offset);
75 
76 		if (rc < 0)
77 			goto fail;
78 
79 		pos += (size_t)rc;
80 		line = length - offset;
81 
82 		if (line > WINPR_HEXDUMP_LINE_LENGTH)
83 			line = WINPR_HEXDUMP_LINE_LENGTH;
84 
85 		for (i = 0; i < line; i++)
86 		{
87 			rc = trio_snprintf(&buffer[pos], blen - pos, "%02" PRIx8 " ", p[i]);
88 
89 			if (rc < 0)
90 				goto fail;
91 
92 			pos += (size_t)rc;
93 		}
94 
95 		for (; i < WINPR_HEXDUMP_LINE_LENGTH; i++)
96 		{
97 			rc = trio_snprintf(&buffer[pos], blen - pos, "   ");
98 
99 			if (rc < 0)
100 				goto fail;
101 
102 			pos += (size_t)rc;
103 		}
104 
105 		for (i = 0; i < line; i++)
106 		{
107 			rc = trio_snprintf(&buffer[pos], blen - pos, "%c",
108 			                   (p[i] >= 0x20 && p[i] < 0x7F) ? (char)p[i] : '.');
109 
110 			if (rc < 0)
111 				goto fail;
112 
113 			pos += (size_t)rc;
114 		}
115 
116 		WLog_Print(log, lvl, "%s", buffer);
117 		offset += line;
118 		p += line;
119 		pos = 0;
120 	}
121 
122 	WLog_Print(log, lvl, "[length=%" PRIuz "] ", length);
123 fail:
124 	free(buffer);
125 }
126 
winpr_CArrayDump(const char * tag,UINT32 level,const BYTE * data,int length,int width)127 void winpr_CArrayDump(const char* tag, UINT32 level, const BYTE* data, int length, int width)
128 {
129 	const BYTE* p = data;
130 	int i, line, offset = 0;
131 	const size_t llen = ((length > width) ? width : length) * 4 + 1;
132 	size_t pos;
133 	char* buffer = malloc(llen);
134 
135 	if (!buffer)
136 	{
137 		WLog_ERR(tag, "malloc(%" PRIuz ") failed with [%d] %s", llen, errno, strerror(errno));
138 		return;
139 	}
140 
141 	while (offset < length)
142 	{
143 		line = length - offset;
144 
145 		if (line > width)
146 			line = width;
147 
148 		pos = 0;
149 
150 		for (i = 0; i < line; i++)
151 			pos += trio_snprintf(&buffer[pos], llen - pos, "\\x%02" PRIX8 "", p[i]);
152 
153 		WLog_LVL(tag, level, "%s", buffer);
154 		offset += line;
155 		p += line;
156 	}
157 
158 	free(buffer);
159 }
160 
winpr_BinToHexString(const BYTE * data,int length,BOOL space)161 char* winpr_BinToHexString(const BYTE* data, int length, BOOL space)
162 {
163 	size_t i;
164 	int n;
165 	char* p;
166 	const char bin2hex[] = "0123456789ABCDEF";
167 	n = space ? 3 : 2;
168 	p = (char*)malloc((length + 1ULL) * n);
169 
170 	if (!p)
171 		return NULL;
172 
173 	for (i = 0; i < length; i++)
174 	{
175 		int ln = data[i] & 0xF;
176 		int hn = (data[i] >> 4) & 0xF;
177 		p[i * n] = bin2hex[hn];
178 		p[(i * n) + 1] = bin2hex[ln];
179 
180 		if (space)
181 			p[(i * n) + 2] = ' ';
182 	}
183 
184 	p[length * n] = '\0';
185 	return p;
186 }
187 
wvprintfx(const char * fmt,va_list args)188 int wvprintfx(const char* fmt, va_list args)
189 {
190 	return trio_vprintf(fmt, args);
191 }
192 
wprintfx(const char * fmt,...)193 int wprintfx(const char* fmt, ...)
194 {
195 	va_list args;
196 	int status;
197 	va_start(args, fmt);
198 	status = trio_vprintf(fmt, args);
199 	va_end(args);
200 	return status;
201 }
202 
wvsnprintfx(char * buffer,size_t bufferSize,const char * fmt,va_list args)203 int wvsnprintfx(char* buffer, size_t bufferSize, const char* fmt, va_list args)
204 {
205 	return trio_vsnprintf(buffer, bufferSize, fmt, args);
206 }
207