mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Support Windows 98 Resource Kit REG.EXE in test suite.
This commit is contained in:
parent
623d2c3df4
commit
f20261dfa5
2
Makefile
2
Makefile
@ -51,7 +51,7 @@ TESTS := tests/addr.exe tests/addrcache.exe tests/ethernet.exe tools/fionread.ex
|
||||
# Tools to compile before running the test suite.
|
||||
TOOLS := tools/socket.exe tools/list-interfaces.exe tools/bind.exe tools/ipx-send.exe \
|
||||
tools/ipx-recv.exe tools/spx-server.exe tools/spx-client.exe tools/ipx-isr.exe \
|
||||
tools/dptool.exe
|
||||
tools/dptool.exe tools/osversion.exe tools/reg-set-bin.exe
|
||||
|
||||
# DLLs to copy to the tools/ directory before running the test suite.
|
||||
TOOL_DLLS := tools/ipxwrapper.dll tools/wsock32.dll tools/mswsock.dll tools/dpwsockx.dll
|
||||
|
103
tests/lib/IPXWrapper/Tool/OSVersion.pm
Normal file
103
tests/lib/IPXWrapper/Tool/OSVersion.pm
Normal file
@ -0,0 +1,103 @@
|
||||
# IPXWrapper test suite
|
||||
# Copyright (C) 2024 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 as published by
|
||||
# the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package IPXWrapper::Tool::OSVersion;
|
||||
|
||||
use IPC::Open3;
|
||||
use Test::Spec;
|
||||
|
||||
my %os_version_cache = ();
|
||||
|
||||
sub get
|
||||
{
|
||||
my ($class, $host) = @_;
|
||||
|
||||
if(defined $os_version_cache{$host})
|
||||
{
|
||||
return $os_version_cache{$host};
|
||||
}
|
||||
|
||||
my @command = ("ssh", $host, "Z:\\tools\\osversion.exe");
|
||||
|
||||
note(join(" ", @command));
|
||||
|
||||
# No need for error checking here - open3 throws on failure.
|
||||
my $pid = open3(my $in, my $out, undef, @command);
|
||||
|
||||
my $output = do {
|
||||
local $/;
|
||||
<$out>;
|
||||
};
|
||||
|
||||
if($output =~ m/^(\d+).(\d+)\r?\n(\d+)\r?\n(\w+)\r?\n(.*)\r?\n$/)
|
||||
{
|
||||
my $self = bless({
|
||||
major => $1,
|
||||
minor => $2,
|
||||
build => $3,
|
||||
platform => $4,
|
||||
extra => $5,
|
||||
}, $class);
|
||||
|
||||
$os_version_cache{$host} = $self;
|
||||
|
||||
return $self;
|
||||
}
|
||||
else{
|
||||
die("Didn't get expected output from osversion.exe:\n$output");
|
||||
}
|
||||
}
|
||||
|
||||
sub major
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{major};
|
||||
}
|
||||
|
||||
sub minor
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{minor};
|
||||
}
|
||||
|
||||
sub build
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{build};
|
||||
}
|
||||
|
||||
sub platform
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{platform};
|
||||
}
|
||||
|
||||
sub platform_is_win9x
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{platform} eq "VER_PLATFORM_WIN32_WINDOWS";
|
||||
}
|
||||
|
||||
sub platform_is_winnt
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{platform} eq "VER_PLATFORM_WIN32_NT";
|
||||
}
|
||||
|
||||
1;
|
@ -1,5 +1,5 @@
|
||||
# IPXWrapper test suite
|
||||
# Copyright (C) 2014-2017 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
# Copyright (C) 2014-2024 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 as published by
|
||||
@ -55,6 +55,8 @@ use Net::Libdnet::Eth;
|
||||
use NetPacket::IPX;
|
||||
use NetPacket::IPXWrapper;
|
||||
|
||||
use IPXWrapper::Tool::OSVersion;
|
||||
|
||||
sub run_remote_cmd
|
||||
{
|
||||
my ($host_ip, $exe_name, @exe_args) = @_;
|
||||
@ -78,7 +80,21 @@ sub reg_set_dword
|
||||
{
|
||||
my ($host_ip, $key, $value, $data) = @_;
|
||||
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/v", $value, "/t", "REG_DWORD", "/d", $data, "/f");
|
||||
if(IPXWrapper::Tool::OSVersion->get($host_ip)->platform_is_winnt())
|
||||
{
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/v", $value, "/t", "REG_DWORD", "/d", $data, "/f");
|
||||
}
|
||||
else{
|
||||
eval { run_remote_cmd($host_ip, "REG", "QUERY", "$key\\$value"); };
|
||||
|
||||
if($@)
|
||||
{
|
||||
run_remote_cmd($host_ip, "REG", "ADD", "$key\\$value=$data", "REG_DWORD");
|
||||
}
|
||||
else{
|
||||
run_remote_cmd($host_ip, "REG", "UPDATE", "$key\\$value=$data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub reg_set_addr
|
||||
@ -86,33 +102,71 @@ sub reg_set_addr
|
||||
my ($host_ip, $key, $value, $data) = @_;
|
||||
|
||||
$data =~ s/://g;
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/v", $value, "/t", "REG_BINARY", "/d", $data, "/f");
|
||||
|
||||
if(IPXWrapper::Tool::OSVersion->get($host_ip)->platform_is_winnt())
|
||||
{
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/v", $value, "/t", "REG_BINARY", "/d", $data, "/f");
|
||||
}
|
||||
else{
|
||||
run_remote_cmd($host_ip, "Z:\\tools\\reg-set-bin.exe", $key, $value, $data);
|
||||
}
|
||||
}
|
||||
|
||||
sub reg_set_string
|
||||
{
|
||||
my ($host_ip, $key, $value, $data) = @_;
|
||||
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/v", $value, "/t", "REG_SZ", "/d", $data, "/f");
|
||||
if(IPXWrapper::Tool::OSVersion->get($host_ip)->platform_is_winnt())
|
||||
{
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/v", $value, "/t", "REG_SZ", "/d", $data, "/f");
|
||||
}
|
||||
else{
|
||||
eval { run_remote_cmd($host_ip, "REG", "QUERY", "$key\\$value"); };
|
||||
|
||||
if($@)
|
||||
{
|
||||
run_remote_cmd($host_ip, "REG", "ADD", "$key\\$value=$data", "REG_SZ");
|
||||
}
|
||||
else{
|
||||
run_remote_cmd($host_ip, "REG", "UPDATE", "$key\\$value=$data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub reg_delete_key
|
||||
{
|
||||
my ($host_ip, $key) = @_;
|
||||
|
||||
# Attempting to delete a key which doesn't exist is considered to be an
|
||||
# error, so we touch the key beforehand.
|
||||
eval { run_remote_cmd($host_ip, "REG", "QUERY", $key); };
|
||||
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/f");
|
||||
run_remote_cmd($host_ip, "REG", "DELETE", $key, "/f");
|
||||
unless($@)
|
||||
{
|
||||
if(IPXWrapper::Tool::OSVersion->get($host_ip)->platform_is_winnt())
|
||||
{
|
||||
run_remote_cmd($host_ip, "REG", "DELETE", $key, "/f");
|
||||
}
|
||||
else{
|
||||
run_remote_cmd($host_ip, "REG", "DELETE", $key, "/FORCE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub reg_delete_value
|
||||
{
|
||||
my ($host_ip, $key, $value) = @_;
|
||||
|
||||
run_remote_cmd($host_ip, "REG", "ADD", $key, "/v", $value, "/t", "REG_SZ", "/f");
|
||||
run_remote_cmd($host_ip, "REG", "DELETE", $key, "/v", $value, "/f");
|
||||
eval { run_remote_cmd($host_ip, "REG", "QUERY", "$key\\$value"); };
|
||||
|
||||
unless($@)
|
||||
{
|
||||
if(IPXWrapper::Tool::OSVersion->get($host_ip)->platform_is_winnt())
|
||||
{
|
||||
run_remote_cmd($host_ip, "REG", "DELETE", $key, "/v", $value, "/f");
|
||||
}
|
||||
else{
|
||||
run_remote_cmd($host_ip, "REG", "DELETE", "$key\\$value", "/FORCE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub send_ipx_over_udp
|
||||
|
61
tools/osversion.c
Normal file
61
tools/osversion.c
Normal file
@ -0,0 +1,61 @@
|
||||
/* IPXWrapper test tools
|
||||
* Copyright (C) 2024 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
OSVERSIONINFO osver;
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
|
||||
if(!GetVersionEx(&osver))
|
||||
{
|
||||
fprintf(stderr, "GetVersionEx: %u\n", (unsigned)(GetLastError()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *platform;
|
||||
|
||||
switch(osver.dwPlatformId)
|
||||
{
|
||||
case VER_PLATFORM_WIN32s:
|
||||
platform = "VER_PLATFORM_WIN32s";
|
||||
break;
|
||||
|
||||
case VER_PLATFORM_WIN32_WINDOWS:
|
||||
platform = "VER_PLATFORM_WIN32_WINDOWS";
|
||||
break;
|
||||
|
||||
case VER_PLATFORM_WIN32_NT:
|
||||
platform = "VER_PLATFORM_WIN32_NT";
|
||||
break;
|
||||
|
||||
default:
|
||||
platform = "VER_PLATFORM_UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%u.%u\n%u\n%s\n%s\n",
|
||||
(unsigned)(osver.dwMajorVersion),
|
||||
(unsigned)(osver.dwMinorVersion),
|
||||
(unsigned)(osver.dwBuildNumber),
|
||||
platform,
|
||||
osver.szCSDVersion);
|
||||
|
||||
return 0;
|
||||
}
|
140
tools/reg-set-bin.c
Normal file
140
tools/reg-set-bin.c
Normal file
@ -0,0 +1,140 @@
|
||||
/* IPXWrapper test tools
|
||||
* Copyright (C) 2024 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* "Why do you have a standalone program specifically for storing binary
|
||||
* registry values rather than using REG.EXE like you do for everything else?"
|
||||
*
|
||||
* "I'm so glad you asked that, hypothetical voice in my head, BEHOLD."
|
||||
*
|
||||
* > REG ADD HKCU\Software\IPXWrapper\08:00:27:C3:6A:E6\net=00000001 REG_BINARY
|
||||
* > Adding Binary Format Data is not Supported.
|
||||
* > The operation completed successfully.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static unsigned char hex_nibble_to_bin(char hex)
|
||||
{
|
||||
if(hex >= '0' && hex <= '9')
|
||||
{
|
||||
return 0x0 + (hex - '0');
|
||||
}
|
||||
else if(hex >= 'A' && hex <= 'F')
|
||||
{
|
||||
return 0xA + (hex - 'A');
|
||||
}
|
||||
else if(hex >= 'a' && hex <= 'f')
|
||||
{
|
||||
return 0xA + (hex - 'a');
|
||||
}
|
||||
else{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if(argc != 4)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <key path> <value name> <hex string>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *key_path = argv[1];
|
||||
const char *value_name = argv[2];
|
||||
const char *value_hex = argv[3];
|
||||
|
||||
HKEY root_key;
|
||||
|
||||
if(strncmp(key_path, "HKLM", 4) == 0 && (key_path[4] == '\\' || key_path[4] == '\0'))
|
||||
{
|
||||
root_key = HKEY_LOCAL_MACHINE;
|
||||
key_path += 4;
|
||||
}
|
||||
else if(strncmp(key_path, "HKCU", 4) == 0 && (key_path[4] == '\\' || key_path[4] == '\0'))
|
||||
{
|
||||
root_key = HKEY_CURRENT_USER;
|
||||
key_path += 4;
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "Key path must begin with HKLM or HKCU\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key_path[0] == '\\')
|
||||
{
|
||||
++key_path;
|
||||
}
|
||||
|
||||
size_t hex_len = strlen(value_hex);
|
||||
|
||||
if((hex_len % 2) != 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid byte string\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char *data = malloc(hex_len / 2);
|
||||
if(hex_len > 0 && data == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t data_len = hex_len / 2;
|
||||
|
||||
for(size_t i = 0; i < hex_len; i += 2)
|
||||
{
|
||||
char hex1 = value_hex[i];
|
||||
char hex2 = value_hex[i + 1];
|
||||
|
||||
if(isxdigit(hex1) && isxdigit(hex2))
|
||||
{
|
||||
data[i / 2] = (hex_nibble_to_bin(hex1) << 4) | hex_nibble_to_bin(hex2);
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "Invalid byte string\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
HKEY key;
|
||||
DWORD error = RegCreateKeyEx(root_key, key_path, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &key, NULL);
|
||||
if(error != ERROR_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Error opening/creating registry key (error code %u)\n", (unsigned)(error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
error = RegSetValueEx(key, value_name, 0, REG_BINARY, (BYTE*)(data), data_len);
|
||||
|
||||
RegCloseKey(key);
|
||||
free(data);
|
||||
|
||||
if(error == ERROR_SUCCESS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "Error code %u when writing registry value\n", (unsigned)(error));
|
||||
return 1;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user