ReactOS 0.4.16-dev-401-g45b008d
netreg.cpp
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS test application
4 * FILE: apps/net/netreg/netreg.cpp
5 * PURPOSE: HTTP Registry Server
6 * PROGRAMMERS: Art Yerkes (arty@users.sf.net)
7 * REVISIONS:
8 * 01-17-2005 arty -- initial
9 */
10#include <windows.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <map>
14#include <string>
15#include <sstream>
16#include <iomanip>
17
18using std::hex;
19using std::setw;
20using std::setfill;
21using std::map;
22using std::string;
23using std::ostringstream;
24
25const char *root_entries[] = {
26 "HKEY_LOCAL_MACHINE",
27 "HKEY_CURRENT_USER",
28 "HKEY_CLASSES_ROOT",
29 "HKEY_CURRENT_CONFIG",
30 "HKEY_USERS",
31 0
32};
33
34const HKEY root_handles[] = {
40};
41
43public:
46 void RecvData( string input ) {
48 if( full_input.find( "\r\n\r\n" ) != string::npos ) {
49 // Full request received...
50 size_t space_pos = full_input.find( ' ' );
51 if( space_pos == string::npos ) { state = SHOULD_DIE; return; }
52 string method = full_input.substr( 0, space_pos );
53 if( method != "GET" ) { state = SHOULD_DIE; return; }
54 space_pos++;
55 if( full_input[space_pos] != '/' ) { state = SHOULD_DIE; return; }
56 space_pos++;
57 string reg_key_and_remainder =
58 full_input.substr( space_pos, full_input.size() - space_pos );
59 space_pos = reg_key_and_remainder.find( ' ' );
60 if( space_pos == string::npos ) { state = SHOULD_DIE; return; }
61 string reg_key_name = reg_key_and_remainder.substr( 0, space_pos );
62 process_request( urldec( reg_key_name ) );
64 }
65 }
66 void OkToSend() {
67 int rv = send( socket,
70 if( rv < 0 ) {
72 return;
73 } else {
76 if( remaining_output.size() == 0 ) {
78 }
79 }
80 }
81
82 SOCKET GetSocket() const { return socket; }
83
84 bool ShouldDie() const {
85 return state == SHOULD_DIE;
86 }
87
88 bool WantPollout() const {
90 }
91
92
93private:
94 string urlenc( string in ) {
96
97 for( string::iterator i = in.begin();
98 i != in.end();
99 i++ ) {
100 if( isalnum( *i ) || *i == '/' )
101 out << *i;
102 else {
103 char minibuf[10];
104 sprintf( minibuf, "%02x", *i );
105 out << "%" << minibuf;
106 }
107 }
108
109 return out.str();
110 }
111
112 string urldec( string in ) {
113 string out;
114
115 for( string::iterator i = in.begin();
116 i != in.end();
117 i++ ) {
118 if( *i == '%' ) {
119 char buf[3];
120 int res = ' ';
121
122 i++;
123 if( i != in.end() ) {
124 buf[0] = *i;
125 i++;
126 if( i != in.end() ) {
127 buf[1] = *i;
128 buf[2] = 0;
129 sscanf( buf, "%x", &res );
130 fprintf( stderr, "Interpreting %c%c as %02x\n",
131 buf[0], buf[1],
132 res );
133 out += (char)res;
134 }
135 }
136 } else out += *i;
137 }
138
139 return out;
140 }
141
142 string dump_one_line( const char *data, int llen, int len, int addr ) {
144 int i;
145
146 out << setw( 8 ) << setfill( '0' ) << hex << addr << ": ";
147
148 for( i = 0; i < llen; i++ ) {
149 if( i < len ) out << setw( 2 ) << setfill( '0' ) << hex <<
150 (data[i] & 0xff) << " ";
151 else out << " ";
152 }
153
154 out << " : ";
155
156 for( i = 0; i < llen; i++ ) {
157 if( i < len && i < llen &&
158 data[i] >= ' ' && data[i] < 0x7f ) out << data[i]; else out << '.';
159 }
160
161 out << "\n";
162
163 return out.str();
164 }
165
166 string bindump( const char *data, int len ) {
167 const char *end = data + len;
168 string out;
169 int addr = 0;
170
171 out += "<pre>";
172
173 while( data < end ) {
174 out += dump_one_line( data, 16, end - data, addr );
175 addr += 16;
176 data += 16;
177 }
178
179 out += "</pre>";
180
181 return out;
182 }
183
184 string present_value( DWORD type, const char *data, DWORD len ) {
185 //switch( type ) {
186 //default:
187 return bindump( data, len );
188 //}
189 }
190
191 void process_valid_request( HKEY open_reg_key, string key_name ) {
192 size_t ending_slash;
193 string up_level;
194 ostringstream text_out;
195
196 DWORD num_sub_keys;
197 DWORD max_subkey_len;
198 DWORD num_values;
199 DWORD max_value_name_len;
200 DWORD max_value_len;
201
202 char *value_name_buf;
203 char *value_buf;
204 char *key_name_buf;
205
206 if( RegQueryInfoKey( open_reg_key,
207 NULL,
208 NULL,
209 NULL,
210 &num_sub_keys,
211 &max_subkey_len,
212 NULL,
213 &num_values,
214 &max_value_name_len,
215 &max_value_len,
216 NULL,
217 NULL ) != ERROR_SUCCESS ) {
219 return;
220 }
221
222 value_name_buf = new char [max_value_name_len+1];
223 value_buf = new char [max_value_len+1];
224 key_name_buf = new char [max_subkey_len+1];
225
226 ending_slash = key_name.rfind( '/' );
227 if( ending_slash != string::npos )
228 up_level = key_name.substr( 0, ending_slash );
229
230 text_out << "HTTP/1.0 200 OK\r\n"
231 << "Content-Type: text/html\r\n"
232 << "\r\n"
233 << "<html><head><title>Registry Key `"
234 << key_name
235 << "'</title></head><body>\r\n"
236 << "<h1>Registry Key `" << key_name << "'</h1>\r\n"
237 << "<a href='/" << urlenc(up_level)
238 << "'>(Up one level)</a><p>\r\n"
239 << "<h2>Subkeys:</h2><table border='1'>\r\n";
240
241 DWORD which_index;
242 DWORD key_name_size;
243
244 for( which_index = 0; which_index < num_sub_keys; which_index++ ) {
245 key_name_size = max_subkey_len+1;
246 RegEnumKeyEx( open_reg_key,
247 which_index,
248 key_name_buf,
249 &key_name_size,
250 NULL,
251 NULL,
252 NULL,
253 NULL );
254 text_out << "<tr><td><a href='/" << urlenc(key_name) << "/"
255 << urlenc(string(key_name_buf,key_name_size)) << "'>"
256 << string(key_name_buf,key_name_size)
257 << "</a></td></tr>\r\n";
258 }
259
260 text_out << "</table><h2>Values:</h2><table border='1'>\r\n";
261
262 DWORD value_name_size;
263 DWORD value_data_size;
264 DWORD value_type;
265
266 for( which_index = 0; which_index < num_values; which_index++ ) {
267 value_name_size = max_value_name_len+1;
268 value_data_size = max_value_len+1;
269
270 RegEnumValue( open_reg_key,
271 which_index,
272 value_name_buf,
273 &value_name_size,
274 NULL,
275 &value_type,
276 (BYTE *)value_buf,
277 &value_data_size );
278
279 text_out << "<tr><td><b>" << string(value_name_buf,value_name_size)
280 << "</b></td><td>"
281 << present_value( value_type, value_buf, value_data_size )
282 << "</td></tr>";
283 }
284
285 text_out << "</ul></body></html>\r\n";
286
287 delete [] key_name_buf;
288 delete [] value_name_buf;
289 delete [] value_buf;
290
291 remaining_output = text_out.str();
292 }
293
294 void process_invalid_request( string reg_key ) {
295 ostringstream text_out;
296 text_out << "HTTP/1.0 404 Not Found\r\n"
297 << "Content-Type: text/html\r\n"
298 << "\r\n"
299 << "<html><head><title>Can't find registry key `"
300 << reg_key
301 << "'</title></head><body>\r\n"
302 << "<H1>Can't find registry key `"
303 << reg_key
304 << "'</H1>\r\n"
305 << "The registry key doesn't exist in the local registry.\r\n"
306 << "</body></html>\r\n";
307
308 remaining_output = text_out.str();
309 }
310
312 ostringstream text_out;
313 int i;
314
315 text_out << "HTTP/1.0 200 OK\r\n"
316 << "Content-Type: text/html\r\n"
317 << "\r\n"
318 << "<html><head><title>Registry Browser</title></head>\r\n"
319 << "<body>\r\n"
320 << "<H1>Registry Browser</H1>"
321 << "You can use this interface to browse the registry."
322 << "You will be presented with one registry key at a time and "
323 << "the decendents.\r\n"
324 << "<h2>Root Level</h2>\r\n"
325 << "Subkeys:<ul>\r\n";
326
327 for( i = 0; root_entries[i]; i++ )
328 text_out << "<li>"
329 << "<a href='/" << urlenc(root_entries[i])
330 << "'>" << root_entries[i]
331 << "</a></li>\r\n";
332
333 text_out << "</ul></body></html>\r\n";
334
335 remaining_output = text_out.str();
336 }
337
338 void process_request( string reg_key ) {
339 int i;
340 bool is_predefined_key = true;
341
342 if( reg_key == "" ) { process_root_request(); return; }
343 HKEY hRegKey = 0;
344
345 // Parse the key name...
346 size_t slash = reg_key.find( '/' );
347 string reg_initial = "";
348
349 if( slash == string::npos ) // A root key...
350 reg_initial = reg_key;
351 else // Any other key
352 reg_initial = reg_key.substr( 0, slash );
353
354 fprintf( stderr, "reg_init = %s, reg_key = %s\n",
355 reg_initial.c_str(),
356 reg_key.c_str() );
357
358 for( i = 0; root_entries[i]; i++ )
359 if( reg_initial == root_entries[i] ) hRegKey = root_handles[i];
360
361 if( hRegKey != 0 && reg_initial != reg_key ) {
362 size_t start_of_reg_path = reg_initial.size() + 1;
363 string reg_path = reg_key.substr( start_of_reg_path,
364 reg_key.size() - start_of_reg_path );
365
366 string reg_open_path = reg_path;
367 do {
368 slash = reg_open_path.find( '/' );
369 string reg_single_key = reg_open_path;
370
371 if( slash != string::npos ) {
372 reg_single_key = reg_open_path.substr( 0, slash );
373 reg_open_path = reg_open_path.substr( slash+1,
374 reg_open_path.size() );
375 }
376
377 HKEY oldKey = hRegKey;
378
379 fprintf( stderr, "Opening %s\n", reg_single_key.c_str() );
380
381 if( RegOpenKey( hRegKey, reg_single_key.c_str(), &hRegKey ) !=
382 ERROR_SUCCESS ) {
383 hRegKey = 0;
384 break;
385 } else RegCloseKey( oldKey );
386
387 is_predefined_key = false;
388 } while( slash != string::npos );
389 }
390
391 if( hRegKey == 0 ) process_invalid_request( reg_key );
392 else {
393 process_valid_request( hRegKey, reg_key );
394 if( !is_predefined_key ) RegCloseKey( hRegKey );
395 }
396 }
397
398 typedef enum _RHState {
403
408};
409
411 struct sockaddr_in sa;
412
413 ZeroMemory( &sa, sizeof( sa ) );
414
415 sa.sin_family = PF_INET;
416 sa.sin_port = ntohs( port );
417
418 fprintf( stderr, "Creating the listener\n" );
420 fprintf( stderr, "Socket %Ix\n", l );
421
422 if( l == INVALID_SOCKET ) return l;
423 if( bind( l, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 ) {
424 fprintf( stderr, "Bad response from bind: %d\n", WSAGetLastError() );
425 closesocket( l ); return INVALID_SOCKET;
426 }
427 if( listen( l, 5 ) < 0 ) {
428 fprintf( stderr, "Listening: %d\n", WSAGetLastError() );
429 closesocket( l );
430 return INVALID_SOCKET;
431 }
432
433 return l;
434}
435
436int main( int argc, char **argv ) {
437 WSADATA wdWinsockData;
439 fd_set pollin,pollout,pollerr;
440 SOCKET listen_socket;
441 int i;
442 int port_to_listen = 80;
443 unsigned int active_fds = 0;
444
445 for( i = 1; i < argc; i++ ) {
446 if( string( "-p" ) == argv[i] ) {
447 i++;
448 if( i < argc ) port_to_listen = atoi( argv[i] );
449 }
450 }
451
452 WSAStartup( 0x0101, &wdWinsockData );
453
454 listen_socket = make_listening_socket( port_to_listen );
455 if( listen_socket == INVALID_SOCKET ) return 1;
456
457 while( true ) {
458 FD_ZERO( &pollin );
459 FD_ZERO( &pollout );
460 FD_ZERO( &pollerr );
461 active_fds = listen_socket + 1;
462
463 for( std::map<SOCKET,RequestHandler *>::iterator i = requests.begin();
464 i != requests.end();
465 i++ ) {
466 if( i->second->ShouldDie() ) {
467 delete i->second;
468 requests.erase( i );
469 i = requests.begin();
470 break;
471 }
472
473 FD_SET(i->first,&pollin);
474 FD_SET(i->first,&pollerr);
475
476 if( i->first > active_fds ) active_fds = i->first + 1;
477
478 if( i->second->WantPollout() ) FD_SET(i->first,&pollout);
479 }
480
481 FD_SET(listen_socket,&pollin);
482
483 active_fds = select( active_fds, &pollin, &pollout, &pollerr, NULL );
484
485 if( active_fds > 0 ) {
486 if( FD_ISSET(listen_socket,&pollin) ) {
487 SOCKET ns = accept( listen_socket, NULL, NULL );
488 if( ns != INVALID_SOCKET ) {
489 requests.insert( std::make_pair( ns, new RequestHandler( ns ) ) );
490 }
491 }
492
493 for( std::map<SOCKET,RequestHandler *>::iterator i = requests.begin();
494 i != requests.end();
495 i++ ) {
496 if( FD_ISSET(i->first,&pollin) ) {
497 char inbuf[1024];
498 int rv = recv(i->first,inbuf,1024,0);
499 if( rv < 0 ) {
500 delete i->second;
501 requests.erase( i );
502 i = requests.begin();
503 break;
504 } else i->second->RecvData( string( inbuf, rv ) );
505 }
506 if( FD_ISSET(i->first,&pollout) ) {
507 i->second->OkToSend();
508 }
509 if( FD_ISSET(i->first,&pollerr) ) {
510 delete i->second;
511 requests.erase( i );
512 i = requests.begin();
513 break;
514 }
515 }
516 }
517 }
518
519 WSACleanup();
520}
static int argc
Definition: ServiceArgs.c:12
_STLP_PRIV _Ios_Manip_1< streamsize > _STLP_CALL setw(int __n)
Definition: _iomanip.h:125
_STLP_PRIV _Setfill_Manip< _CharT > _STLP_CALL setfill(_CharT __c)
Definition: _iomanip.h:160
static int inbuf
Definition: adnsresfilter.c:73
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define RegCloseKey(hKey)
Definition: registry.h:49
r l[0]
Definition: byte_order.h:168
string full_input
Definition: netreg.cpp:404
void process_valid_request(HKEY open_reg_key, string key_name)
Definition: netreg.cpp:191
enum RequestHandler::_RHState RHState
string dump_one_line(const char *data, int llen, int len, int addr)
Definition: netreg.cpp:142
SOCKET socket
Definition: netreg.cpp:406
RHState state
Definition: netreg.cpp:407
bool WantPollout() const
Definition: netreg.cpp:88
string present_value(DWORD type, const char *data, DWORD len)
Definition: netreg.cpp:184
string urldec(string in)
Definition: netreg.cpp:112
RequestHandler(SOCKET s)
Definition: netreg.cpp:44
void OkToSend()
Definition: netreg.cpp:66
string remaining_output
Definition: netreg.cpp:405
string bindump(const char *data, int len)
Definition: netreg.cpp:166
bool ShouldDie() const
Definition: netreg.cpp:84
SOCKET GetSocket() const
Definition: netreg.cpp:82
@ REQUEST_RECVD_SENDING_REPLY
Definition: netreg.cpp:400
string urlenc(string in)
Definition: netreg.cpp:94
void process_request(string reg_key)
Definition: netreg.cpp:338
void RecvData(string input)
Definition: netreg.cpp:46
void process_root_request()
Definition: netreg.cpp:311
void process_invalid_request(string reg_key)
Definition: netreg.cpp:294
_String str() const
Definition: _sstream.h:184
_Self substr(size_type __pos=0, size_type __n=npos) const
Definition: _string.h:1022
const _CharT * c_str() const
Definition: _string.h:949
size_type find(const _Self &__s, size_type __pos=0) const
Definition: _string.h:953
size_type size() const
Definition: _string.h:400
Definition: _map.h:48
pair< iterator, bool > insert(const value_type &__x)
Definition: _map.h:188
iterator end()
Definition: _map.h:165
iterator begin()
Definition: _map.h:163
void erase(iterator __pos)
Definition: _map.h:203
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
USHORT port
Definition: uri.c:228
unsigned char
Definition: typeof.h:29
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
method
Definition: dragdrop.c:54
int main()
Definition: test.c:6
#define SOCK_STREAM
Definition: tcpip.h:118
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint res
Definition: glext.h:9613
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
GLenum GLenum GLenum input
Definition: glext.h:9031
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int hex(char ch)
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define ntohs(x)
Definition: module.h:210
char string[160]
Definition: util.h:11
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define argv
Definition: mplay32.c:18
#define closesocket
Definition: ncftp.h:477
SOCKET make_listening_socket(int port)
Definition: netreg.cpp:410
const HKEY root_handles[]
Definition: netreg.cpp:34
const char * root_entries[]
Definition: netreg.cpp:25
static FILE * out
Definition: regtests2xml.c:44
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
Definition: winsock.h:66
Definition: mxnamespace.c:45
#define ZeroMemory
Definition: winbase.h:1737
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_CONFIG
Definition: winreg.h:15
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define RegOpenKey
Definition: winreg.h:519
#define RegEnumValue
Definition: winreg.h:511
#define RegEnumKeyEx
Definition: winreg.h:510
#define RegQueryInfoKey
Definition: winreg.h:521
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define HKEY_USERS
Definition: winreg.h:13
#define FD_ISSET(fd, set)
Definition: winsock.h:100
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
#define FD_ZERO(set)
Definition: winsock.h:96
int PASCAL FAR WSACleanup(void)
Definition: startup.c:60
#define INVALID_SOCKET
Definition: winsock.h:332
#define PF_INET
Definition: winsock.h:373
UINT_PTR SOCKET
Definition: winsock.h:47
#define FD_SET(fd, set)
Definition: winsock.h:89
unsigned char BYTE
Definition: xxhash.c:193