Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS test application * FILE: apps/net/netreg/netreg.cpp * PURPOSE: HTTP Registry Server * PROGRAMMERS: Art Yerkes (arty@users.sf.net) * REVISIONS: * 01-17-2005 arty -- initial */#include <windows.h>#include <stdlib.h>#include <stdio.h>#include <map>#include <string>#include <sstream>#include <iomanip>
using std::hex;using std::setw;using std::setfill;using std::map;using std::string;using std::ostringstream;
const char *root_entries[] = { "HKEY_LOCAL_MACHINE", "HKEY_CURRENT_USER", "HKEY_CLASSES_ROOT", "HKEY_CURRENT_CONFIG", "HKEY_USERS", 0};
const HKEY root_handles[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, HKEY_CLASSES_ROOT, HKEY_CURRENT_CONFIG, HKEY_USERS};
class RequestHandler {public: RequestHandler( SOCKET s ) : socket( s ), state( NO_REQUEST_YET ) {} ~RequestHandler() { closesocket( socket ); } void RecvData( string input ) { full_input += input; if( full_input.find( "\r\n\r\n" ) != string::npos ) { // Full request received... size_t space_pos = full_input.find( ' ' ); if( space_pos == string::npos ) { state = SHOULD_DIE; return; } string method = full_input.substr( 0, space_pos ); if( method != "GET" ) { state = SHOULD_DIE; return; } space_pos++; if( full_input[space_pos] != '/' ) { state = SHOULD_DIE; return; } space_pos++; string reg_key_and_remainder = full_input.substr( space_pos, full_input.size() - space_pos ); space_pos = reg_key_and_remainder.find( ' ' ); if( space_pos == string::npos ) { state = SHOULD_DIE; return; } string reg_key_name = reg_key_and_remainder.substr( 0, space_pos ); process_request( urldec( reg_key_name ) ); state = REQUEST_RECVD_SENDING_REPLY; } } void OkToSend() { int rv = send( socket, remaining_output.c_str(), remaining_output.size(), 0 ); if( rv < 0 ) { state = SHOULD_DIE; return; } else { remaining_output = remaining_output.substr( rv, remaining_output.size() - rv ); if( remaining_output.size() == 0 ) { state = SHOULD_DIE; } } }
SOCKET GetSocket() const { return socket; }
bool ShouldDie() const { return state == SHOULD_DIE; }
bool WantPollout() const { return state == REQUEST_RECVD_SENDING_REPLY; }
private: string urlenc( string in ) { ostringstream out;
for( string::iterator i = in.begin(); i != in.end(); i++ ) { if( isalnum( *i ) || *i == '/' ) out << *i; else { char minibuf[10]; sprintf( minibuf, "%02x", *i ); out << "%" << minibuf; } }
return out.str(); }
string urldec( string in ) { string out;
for( string::iterator i = in.begin(); i != in.end(); i++ ) { if( *i == '%' ) { char buf[3]; int res = ' ';
i++; if( i != in.end() ) { buf[0] = *i; i++; if( i != in.end() ) { buf[1] = *i; buf[2] = 0; sscanf( buf, "%x", &res ); fprintf( stderr, "Interpreting %c%c as %02x\n", buf[0], buf[1], res ); out += (char)res; } } } else out += *i; }
return out; }
string dump_one_line( const char *data, int llen, int len, int addr ) { ostringstream out; int i;
out << setw( 8 ) << setfill( '0' ) << hex << addr << ": ";
for( i = 0; i < llen; i++ ) { if( i < len ) out << setw( 2 ) << setfill( '0' ) << hex << (data[i] & 0xff) << " "; else out << " "; }
out << " : ";
for( i = 0; i < llen; i++ ) { if( i < len && i < llen && data[i] >= ' ' && data[i] < 0x7f ) out << data[i]; else out << '.'; }
out << "\n";
return out.str(); }
string bindump( const char *data, int len ) { const char *end = data + len; string out; int addr = 0;
out += "<pre>";
while( data < end ) { out += dump_one_line( data, 16, end - data, addr ); addr += 16; data += 16; }
out += "</pre>";
return out; }
string present_value( DWORD type, const char *data, DWORD len ) { //switch( type ) { //default: return bindump( data, len ); //} }
void process_valid_request( HKEY open_reg_key, string key_name ) { size_t ending_slash; string up_level; ostringstream text_out;
DWORD num_sub_keys; DWORD max_subkey_len; DWORD num_values; DWORD max_value_name_len; DWORD max_value_len;
char *value_name_buf; char *value_buf; char *key_name_buf;
if( RegQueryInfoKey( open_reg_key, NULL, NULL, NULL, &num_sub_keys, &max_subkey_len, NULL, &num_values, &max_value_name_len, &max_value_len, NULL, NULL ) != ERROR_SUCCESS ) { process_invalid_request( key_name ); return; }
value_name_buf = new char [max_value_name_len+1]; value_buf = new char [max_value_len+1]; key_name_buf = new char [max_subkey_len+1];
ending_slash = key_name.rfind( '/' ); if( ending_slash != string::npos ) up_level = key_name.substr( 0, ending_slash );
text_out << "HTTP/1.0 200 OK\r\n" << "Content-Type: text/html\r\n" << "\r\n" << "<html><head><title>Registry Key `" << key_name << "'</title></head><body>\r\n" << "<h1>Registry Key `" << key_name << "'</h1>\r\n" << "<a href='/" << urlenc(up_level) << "'>(Up one level)</a><p>\r\n" << "<h2>Subkeys:</h2><table border='1'>\r\n";
DWORD which_index; DWORD key_name_size;
for( which_index = 0; which_index < num_sub_keys; which_index++ ) { key_name_size = max_subkey_len+1; RegEnumKeyEx( open_reg_key, which_index, key_name_buf, &key_name_size, NULL, NULL, NULL, NULL ); text_out << "<tr><td><a href='/" << urlenc(key_name) << "/" << urlenc(string(key_name_buf,key_name_size)) << "'>" << string(key_name_buf,key_name_size) << "</a></td></tr>\r\n"; }
text_out << "</table><h2>Values:</h2><table border='1'>\r\n";
DWORD value_name_size; DWORD value_data_size; DWORD value_type;
for( which_index = 0; which_index < num_values; which_index++ ) { value_name_size = max_value_name_len+1; value_data_size = max_value_len+1;
RegEnumValue( open_reg_key, which_index, value_name_buf, &value_name_size, NULL, &value_type, (BYTE *)value_buf, &value_data_size );
text_out << "<tr><td><b>" << string(value_name_buf,value_name_size) << "</b></td><td>" << present_value( value_type, value_buf, value_data_size ) << "</td></tr>"; }
text_out << "</ul></body></html>\r\n";
delete [] key_name_buf; delete [] value_name_buf; delete [] value_buf;
remaining_output = text_out.str(); }
void process_invalid_request( string reg_key ) { ostringstream text_out; text_out << "HTTP/1.0 404 Not Found\r\n" << "Content-Type: text/html\r\n" << "\r\n" << "<html><head><title>Can't find registry key `" << reg_key << "'</title></head><body>\r\n" << "<H1>Can't find registry key `" << reg_key << "'</H1>\r\n" << "The registry key doesn't exist in the local registry.\r\n" << "</body></html>\r\n";
remaining_output = text_out.str(); }
void process_root_request() { ostringstream text_out; int i;
text_out << "HTTP/1.0 200 OK\r\n" << "Content-Type: text/html\r\n" << "\r\n" << "<html><head><title>Registry Browser</title></head>\r\n" << "<body>\r\n" << "<H1>Registry Browser</H1>" << "You can use this interface to browse the registry." << "You will be presented with one registry key at a time and " << "the decendents.\r\n" << "<h2>Root Level</h2>\r\n" << "Subkeys:<ul>\r\n";
for( i = 0; root_entries[i]; i++ ) text_out << "<li>" << "<a href='/" << urlenc(root_entries[i]) << "'>" << root_entries[i] << "</a></li>\r\n";
text_out << "</ul></body></html>\r\n";
remaining_output = text_out.str(); }
void process_request( string reg_key ) { int i; bool is_predefined_key = true;
if( reg_key == "" ) { process_root_request(); return; } HKEY hRegKey = 0;
// Parse the key name... size_t slash = reg_key.find( '/' ); string reg_initial = "";
if( slash == string::npos ) // A root key... reg_initial = reg_key; else // Any other key reg_initial = reg_key.substr( 0, slash );
fprintf( stderr, "reg_init = %s, reg_key = %s\n", reg_initial.c_str(), reg_key.c_str() );
for( i = 0; root_entries[i]; i++ ) if( reg_initial == root_entries[i] ) hRegKey = root_handles[i];
if( hRegKey != 0 && reg_initial != reg_key ) { size_t start_of_reg_path = reg_initial.size() + 1; string reg_path = reg_key.substr( start_of_reg_path, reg_key.size() - start_of_reg_path );
string reg_open_path = reg_path; do { slash = reg_open_path.find( '/' ); string reg_single_key = reg_open_path;
if( slash != string::npos ) { reg_single_key = reg_open_path.substr( 0, slash ); reg_open_path = reg_open_path.substr( slash+1, reg_open_path.size() ); }
HKEY oldKey = hRegKey;
fprintf( stderr, "Opening %s\n", reg_single_key.c_str() );
if( RegOpenKey( hRegKey, reg_single_key.c_str(), &hRegKey ) != ERROR_SUCCESS ) { hRegKey = 0; break; } else RegCloseKey( oldKey );
is_predefined_key = false; } while( slash != string::npos ); }
if( hRegKey == 0 ) process_invalid_request( reg_key ); else { process_valid_request( hRegKey, reg_key ); if( !is_predefined_key ) RegCloseKey( hRegKey ); } }
typedef enum _RHState { NO_REQUEST_YET, REQUEST_RECVD_SENDING_REPLY, SHOULD_DIE } RHState;
string full_input; string remaining_output; SOCKET socket; RHState state;};
SOCKET make_listening_socket( int port ) { struct sockaddr_in sa;
ZeroMemory( &sa, sizeof( sa ) );
sa.sin_family = PF_INET; sa.sin_port = ntohs( port );
fprintf( stderr, "Creating the listener\n" ); SOCKET l = socket( PF_INET, SOCK_STREAM, 0 ); fprintf( stderr, "Socket %Ix\n", l );
if( l == INVALID_SOCKET ) return l; if( bind( l, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 ) { fprintf( stderr, "Bad response from bind: %d\n", WSAGetLastError() ); closesocket( l ); return INVALID_SOCKET; } if( listen( l, 5 ) < 0 ) { fprintf( stderr, "Listening: %d\n", WSAGetLastError() ); closesocket( l ); return INVALID_SOCKET; }
return l;}
int main( int argc, char **argv ) { WSADATA wdWinsockData; map<SOCKET,RequestHandler *> requests; fd_set pollin,pollout,pollerr; SOCKET listen_socket; int i; int port_to_listen = 80; unsigned int active_fds = 0;
for( i = 1; i < argc; i++ ) { if( string( "-p" ) == argv[i] ) { i++; if( i < argc ) port_to_listen = atoi( argv[i] ); } }
WSAStartup( 0x0101, &wdWinsockData );
listen_socket = make_listening_socket( port_to_listen ); if( listen_socket == INVALID_SOCKET ) return 1;
while( true ) { FD_ZERO( &pollin ); FD_ZERO( &pollout ); FD_ZERO( &pollerr ); active_fds = listen_socket + 1;
for( std::map<SOCKET,RequestHandler *>::iterator i = requests.begin(); i != requests.end(); i++ ) { if( i->second->ShouldDie() ) { delete i->second; requests.erase( i ); i = requests.begin(); break; }
FD_SET(i->first,&pollin); FD_SET(i->first,&pollerr);
if( i->first > active_fds ) active_fds = i->first + 1;
if( i->second->WantPollout() ) FD_SET(i->first,&pollout); }
FD_SET(listen_socket,&pollin);
active_fds = select( active_fds, &pollin, &pollout, &pollerr, NULL );
if( active_fds > 0 ) { if( FD_ISSET(listen_socket,&pollin) ) { SOCKET ns = accept( listen_socket, NULL, NULL ); if( ns != INVALID_SOCKET ) { requests.insert( std::make_pair( ns, new RequestHandler( ns ) ) ); } }
for( std::map<SOCKET,RequestHandler *>::iterator i = requests.begin(); i != requests.end(); i++ ) { if( FD_ISSET(i->first,&pollin) ) { char inbuf[1024]; int rv = recv(i->first,inbuf,1024,0); if( rv < 0 ) { delete i->second; requests.erase( i ); i = requests.begin(); break; } else i->second->RecvData( string( inbuf, rv ) ); } if( FD_ISSET(i->first,&pollout) ) { i->second->OkToSend(); } if( FD_ISSET(i->first,&pollerr) ) { delete i->second; requests.erase( i ); i = requests.begin(); break; } } } }
WSACleanup();}