1 1.1 christos # Registry.pm 2 1.1 christos # A perl module provided easy Windows Registry access 3 1.1 christos # 4 1.1 christos # Author: Shu-Min Chang 5 1.1 christos # 6 1.1 christos # Copyright(c) 2002 Intel Corporation. All rights reserved 7 1.1 christos # 8 1.1 christos # Redistribution and use in source and binary forms, with or without 9 1.1 christos # modification, are permitted provided that the following conditions are met: 10 1.1 christos # 11 1.1 christos # 1. Redistributions of source code must retain the above copyright notice, 12 1.1 christos # this list of conditions and the following disclaimer. 13 1.1 christos # 2. Redistributions in binary form must reproduce the above copyright notice 14 1.1 christos # this list of conditions and the following disclaimer in the documentation 15 1.1 christos # and/or other materials provided with the distribution 16 1.1 christos # 3. Neither the name of Intel Corporation nor the names of its contributors 17 1.1 christos # may be used to endorse or promote products derived from this software 18 1.1 christos # without specific prior written permission. 19 1.1 christos # 20 1.1 christos # THIS SOFTWARE IS PROVIDED BY THE INTEL CORPORATION AND CONTRIBUTORS "AS IS" 21 1.1 christos # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 1.1 christos # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 1.1 christos # ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE 24 1.1 christos # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL EXEMPLARY, OR 25 1.1 christos # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO PROCUREMENT OF SUBSTITUE 26 1.1 christos # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 christos # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 christos # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29 1.1 christos # OF THE USE OF THIS SOFTWARE, EVEN IF ADVICED OF THE POSSIBILITY OF SUCH 30 1.1 christos # DAMAGE. 31 1.1 christos 32 1.1 christos package Registry; 33 1.1 christos use strict; 34 1.1 christos use Win32API::Registry 0.21 qw( :ALL ); 35 1.1 christos 36 1.1 christos 37 1.1 christos ############################################################################### 38 1.1 christos 39 1.1 christos #----------------------------------------- 40 1.1 christos sub GetRegKeyVal($*) { 41 1.1 christos my ($FullRegPath, $value) = @_; 42 1.1 christos #----------------------------------------- 43 1.1 christos # Purpose: uses Win32API to get registry information from a given server 44 1.1 christos # 45 1.1 christos # WARNING: this procedure is VERY Win32 specific, you'll need a Win32 manual 46 1.1 christos # to figure out why something is done. 47 1.1 christos # input: $FullRegPath: a MS specific way of fully qualifying a registry path 48 1.1 christos # \\Server\RootKey\Path\ValueName 49 1.1 christos # output: *value: the value of the registry key of $FullRegPath 50 1.1 christos # 51 1.1 christos 52 1.1 christos my ($RemoteMachine, $RootKey, $RegPath, $KeyName, $i); 53 1.1 christos 54 1.1 christos #print "in sub:GetRegKeyVal:Parameters:", @_, "\n"; 55 1.1 christos 56 1.1 christos # Check the for valid fully qualified registry path 57 1.1 christos return -1 if (! ($FullRegPath =~ /\\.+\\.+/)) && (!($FullRegPath =~ /\\\\.+\\.+\\.+/)); 58 1.1 christos 59 1.1 christos 60 1.1 christos $RemoteMachine = (index($FullRegPath, "\\\\") == $[ ? substr($FullRegPath, $[+2, index($FullRegPath, "\\", $[+2)-2):0); 61 1.1 christos 62 1.1 christos #print "RemoteMachine = $RemoteMachine\n"; 63 1.1 christos 64 1.1 christos $i = $RemoteMachine ? $[+3+length($RemoteMachine) : $[+1; 65 1.1 christos $RootKey = substr ($FullRegPath, $i, index($FullRegPath, "\\", $i)-$i); 66 1.1 christos 67 1.1 christos $KeyName = $FullRegPath; 68 1.1 christos $KeyName =~ s/.*\\(.+)/$1/; 69 1.1 christos #print "KeyName = $KeyName\n"; 70 1.1 christos 71 1.1 christos $i = index($FullRegPath, $RootKey, $[+length($RemoteMachine)) + $[ + length($RootKey)+1; 72 1.1 christos $RegPath = substr ($FullRegPath, $i, length($FullRegPath) - length($KeyName) -$i - 1); 73 1.1 christos #print "RegPath = $RegPath\n"; 74 1.1 christos 75 1.1 christos my ($RootKeyHandle, $handle, $key, $type); 76 1.1 christos 77 1.1 christos if ($RemoteMachine) { 78 1.1 christos $RootKeyHandle = regConstant($RootKey); 79 1.1 christos 80 1.1 christos if (!RegConnectRegistry ($RemoteMachine, $RootKeyHandle, $handle)) { 81 1.1 christos $$value = regLastError(); 82 1.1 christos return -2; 83 1.1 christos } 84 1.1 christos } else { # not valid actually because I can't find the mapping table of default 85 1.1 christos # local handle mapping. Should always pass in the Machine name to use for now 86 1.1 christos $handle = $RootKey; 87 1.1 christos } 88 1.1 christos 89 1.1 christos if (!RegOpenKeyEx ($handle, $RegPath, 0, KEY_READ, $key)) { 90 1.1 christos $$value = regLastError(); 91 1.1 christos #print "regLastError = $$value\n"; 92 1.1 christos return -3; 93 1.1 christos } 94 1.1 christos if (!RegQueryValueEx( $key, $KeyName, [], $type, $$value, [] )) { 95 1.1 christos $$value = regLastError(); 96 1.1 christos #print "regLastError = $$value\n"; 97 1.1 christos return -4; 98 1.1 christos } 99 1.1 christos 100 1.1 christos #print "RegType=$type\n"; # Perl doesn't fetch type, at this in this 101 1.1 christos # ActiveState 5.6.0 that I'm using 102 1.1 christos #print "RegValue=$$value\n"; 103 1.1 christos RegCloseKey ($key); 104 1.1 christos RegCloseKey ($handle); 105 1.1 christos 106 1.1 christos return 0; 107 1.1 christos } 108 1.1 christos 109 1.1 christos ############################################################################### 110 1.1 christos 111 1.1 christos #----------------------------------------- 112 1.1 christos sub GetRegSubkeyList($*) { 113 1.1 christos my ($FullKeyRegPath, $Subkeys) = @_; 114 1.1 christos #----------------------------------------- 115 1.1 christos # Purpose: uses Win32API to get registry subkey list from a given server 116 1.1 christos # 117 1.1 christos # WARNING: this procedure is VERY Win32 specific, you'll need a Win32 manual 118 1.1 christos # to figure out why something is done. 119 1.1 christos # input: $FullKeyRegPath: a MS specific way of fully qualifying a registry path 120 1.1 christos # \\Server\RootKey\Path\KeyName 121 1.1 christos # output: *Subkeys: the list of subkeys in array of the registry key of 122 1.1 christos # $FullKeyRegPath 123 1.1 christos # 124 1.1 christos 125 1.1 christos my ($RemoteMachine, $RootKey, $RegPath, $KeyName, $i); 126 1.1 christos 127 1.1 christos #print "in sub:GetRegSubkeyList:Parameters:", @_, "\n"; 128 1.1 christos 129 1.1 christos # Check the for valid registry key path 130 1.1 christos return -1 if (! ($FullKeyRegPath =~ /\\.+\\.+/)) && (!($FullKeyRegPath =~ /\\\\.+\\.+\\.+/)); 131 1.1 christos 132 1.1 christos 133 1.1 christos $RemoteMachine = (index($FullKeyRegPath, "\\\\") == $[ ? substr($FullKeyRegPath, $[+2, index($FullKeyRegPath, "\\", $[+2)-2):0); 134 1.1 christos 135 1.1 christos #print "RemoteMachine = $RemoteMachine\n"; 136 1.1 christos 137 1.1 christos $i = $RemoteMachine ? $[+3+length($RemoteMachine) : $[+1; 138 1.1 christos $RootKey = substr ($FullKeyRegPath, $i, index($FullKeyRegPath, "\\", $i)-$i); 139 1.1 christos 140 1.1 christos $i = index($FullKeyRegPath, $RootKey, $[+length($RemoteMachine)) + $[ + length($RootKey)+1; 141 1.1 christos $RegPath = substr ($FullKeyRegPath, $i); 142 1.1 christos 143 1.1 christos #print "RegPath = $RegPath\n"; 144 1.1 christos 145 1.1 christos my ($RootKeyHandle, $handle, $key, $type); 146 1.1 christos 147 1.1 christos if ($RemoteMachine) { 148 1.1 christos $RootKeyHandle = regConstant($RootKey); 149 1.1 christos 150 1.1 christos if (!RegConnectRegistry ($RemoteMachine, $RootKeyHandle, $handle)) { 151 1.1 christos @$Subkeys[0]= regLastError(); 152 1.1 christos return -2; 153 1.1 christos } 154 1.1 christos } else { # not valid actually because I can't find the mapping table of default 155 1.1 christos # local handle mapping. Should always pass in the Machine name to use for now 156 1.1 christos $handle = $RootKey; 157 1.1 christos } 158 1.1 christos 159 1.1 christos if (!RegOpenKeyEx ($handle, $RegPath, 0, KEY_READ, $key)) { 160 1.1 christos @$Subkeys[0] = regLastError(); 161 1.1 christos #print "regLastError = @$Subkeys[0]\n"; 162 1.1 christos return -3; 163 1.1 christos } 164 1.1 christos 165 1.1 christos my $tmp; 166 1.1 christos # For some reason, the regLastError() stays at ERROR_NO_MORE_ITEMS 167 1.1 christos # in occasional call sequence, so I'm resetting the error code 168 1.1 christos # before entering the loop 169 1.1 christos regLastError(0); 170 1.1 christos for ($i=0; regLastError()==regConstant("ERROR_NO_MORE_ITEMS"); $i++) { 171 1.1 christos #print "\nERROR: error enumumerating reg\n"; 172 1.1 christos if (RegEnumKeyEx ($key, $i, $tmp, [], [], [], [], [])) { 173 1.1 christos @$Subkeys[$i] = $tmp; 174 1.1 christos } 175 1.1 christos } 176 1.1 christos 177 1.1 christos #print "RegType=$type\n"; 178 1.1 christos #print "RegValue=@$Subkeys\n"; 179 1.1 christos RegCloseKey ($key); 180 1.1 christos RegCloseKey ($handle); 181 1.1 christos 182 1.1 christos return 0; 183 1.1 christos } 184 1.1 christos 185 1.1 christos ##################################################### 186 1.1 christos 187 1.1 christos sub ExtractOptionIps ($) { 188 1.1 christos my ($MSDHCPOption6Value) = @_; 189 1.1 christos my @ip; 190 1.1 christos # purpose: DHCP registry specific; to return the extracted IP addresses from 191 1.1 christos # the input variable 192 1.1 christos # input: 193 1.1 christos # $MSDHCPOption6Value: Option 6 was used to develop, but it works for any 194 1.1 christos # other options of the same datatype. 195 1.1 christos # output: none 196 1.1 christos # return: 197 1.1 christos # @ip: an arry of IP addresses in human readable format. 198 1.1 christos 199 1.1 christos 200 1.1 christos # First extract the size of the option 201 1.1 christos my ($byte, $size, $ind1, $ind2, @octet) = unpack("VVVV", $MSDHCPOption6Value); 202 1.1 christos # print "byte = $byte\nsize=$size\nind1=$ind1\nind2=$ind2\n"; 203 1.1 christos 204 1.1 christos # Calculate total number of bytes that IP addresses occupy 205 1.1 christos my $number = $size * $ind1; 206 1.1 christos ($byte, $size, $ind1, $ind2, @octet) = unpack("VVVVC$number", $MSDHCPOption6Value); 207 1.1 christos 208 1.1 christos for (my $i=0; $i<$#octet; $i=$i+4) { 209 1.1 christos $ip[$i/4] = "$octet[$i+3]\.$octet[$i+2]\.$octet[$i+1]\.$octet[$i]"; 210 1.1 christos } 211 1.1 christos 212 1.1 christos return @ip; 213 1.1 christos } 214 1.1 christos 215 1.1 christos ##################################################### 216 1.1 christos 217 1.1 christos sub ExtractOptionStrings ($) { 218 1.1 christos my ($MSDHCPOption15Value) = @_; 219 1.1 christos my @string; 220 1.1 christos # purpose: DHCP registry specific; to return the extracted string from 221 1.1 christos # the input variable 222 1.1 christos # input: 223 1.1 christos # $MSDHCPOption15Value: Option 15 was used to develop, but it works for any 224 1.1 christos # other options of the same datatype. 225 1.1 christos # output: none 226 1.1 christos # return: 227 1.1 christos # @string: an arry of strings in human readable format. 228 1.1 christos 229 1.1 christos 230 1.1 christos # First extract the size of the option 231 1.1 christos my ($byte, $start, $ind1, $ind2, $size, @data) = unpack("VVVVV", $MSDHCPOption15Value); 232 1.1 christos # print "byte = $byte\nstart=$start\nind1=$ind1\nind2=$ind2\nsize=$size\n"; 233 1.1 christos 234 1.1 christos # Calculate total number of bytes that IP addresses occupy 235 1.1 christos my $number = $size * $ind1; 236 1.1 christos ($byte, $start, $ind1, $ind2, $size, @data) = unpack("VVVVVC$number", $MSDHCPOption15Value); 237 1.1 christos 238 1.1 christos for (my $i=0; $i<$ind1; $i++) { 239 1.1 christos # actually this is only programmed to do one string, until I see 240 1.1 christos # example of how the multiple strings are represented, I don't have a 241 1.1 christos # guess to how to program them properly. 242 1.1 christos for (my $j=0; $j<$#data & $data[$j]!=0; $j+=2) { 243 1.1 christos $string[$i] = $string[$i].chr($data[$j]); 244 1.1 christos } 245 1.1 christos } 246 1.1 christos 247 1.1 christos return @string; 248 1.1 christos } 249 1.1 christos 250 1.1 christos ##################################################### 251 1.1 christos 252 1.1 christos sub ExtractOptionHex ($) { 253 1.1 christos my ($MSDHCPOption46Value) = @_; 254 1.1 christos my @Hex; 255 1.1 christos # purpose: DHCP registry specific; to return the extracted hex from the input 256 1.1 christos # variable 257 1.1 christos # input: 258 1.1 christos # $MSDHCPOption46Value: Option 46 was used to develop, but it works for any 259 1.1 christos # other options of the same datatype. 260 1.1 christos # output: none 261 1.1 christos # return: 262 1.1 christos # @Hex: an arry of hex strings in human readable format. 263 1.1 christos my $Temp; 264 1.1 christos 265 1.1 christos 266 1.1 christos # First extract the size of the option 267 1.1 christos my ($byte, $unknown, $ind1, $ind2, @data) = unpack("VVVV", $MSDHCPOption46Value); 268 1.1 christos # print "byte=$byte\nunknown=$unknown\nind1=$ind1\nind2=$ind2\n"; 269 1.1 christos 270 1.1 christos # Calculate total number of bytes that IP addresses occupy 271 1.1 christos my $number = $byte - 15; 272 1.1 christos ($byte, $unknown, $ind1, $ind2, @data) = unpack("VVVVC$number", $MSDHCPOption46Value); 273 1.1 christos 274 1.1 christos # printf "data=%4x\n", $data[0]; 275 1.1 christos 276 1.1 christos for (my $i=0; $i<$ind1; $i++) { 277 1.1 christos # actually this is only programmed to do one Hex, until I see 278 1.1 christos # example of how the multiple Hexes are represented, I don't have a 279 1.1 christos # guess to how to program them properly. 280 1.1 christos for (my $j=3; $j>=0; $j--) { 281 1.1 christos $Hex[$i] = $Hex[$i].sprintf ("%x", $data[$j+$i*4]); 282 1.1 christos } 283 1.1 christos } 284 1.1 christos 285 1.1 christos return @Hex; 286 1.1 christos } 287 1.1 christos 288 1.1 christos ##################################################### 289 1.1 christos 290 1.1 christos sub ExtractExclusionRanges ($) { 291 1.1 christos my ($MSDHCPExclusionRanges) = @_; 292 1.1 christos my @RangeList; 293 1.1 christos # purpose: DHCP registry specific; to return the extracted exclusion ranges 294 1.1 christos # from the input variable 295 1.1 christos # input: 296 1.1 christos # $MSDHCPExclusionRanges: Exclusion range as DHCP server returns them 297 1.1 christos # output: none 298 1.1 christos # return: 299 1.1 christos # @RangeList: an arry of paird IP addresses strings in human readable format. 300 1.1 christos 301 1.1 christos 302 1.1 christos # First extract the size of the option 303 1.1 christos my ($paircount, @data) = unpack("V", $MSDHCPExclusionRanges); 304 1.1 christos # print "paircount = $paircount\n"; 305 1.1 christos 306 1.1 christos # Calculate total number of bytes that IP addresses occupy 307 1.1 christos # my $number = $paircount * 4*2; 308 1.1 christos # ($paircount, @data) = unpack("VC$number", $MSDHCPExclusionRanges); 309 1.1 christos # 310 1.1 christos # for (my $i=0; $i<$#data; $i=$i+4) { 311 1.1 christos # $ip[$i/4] = "$data[$i+3]\.$data[$i+2]\.$data[$i+1]\.$data[$i]"; 312 1.1 christos # } 313 1.1 christos # 314 1.1 christos my $number = $paircount * 2; 315 1.1 christos ($paircount, @data) = unpack("VL$number", $MSDHCPExclusionRanges); 316 1.1 christos 317 1.1 christos for (my $i=0; $i<=$#data; $i++) { 318 1.1 christos $RangeList[$i] = pack ("L", $data[$i]); 319 1.1 christos # print "extracted", ExtractIp ($RangeList[$i]), "\n"; 320 1.1 christos } 321 1.1 christos 322 1.1 christos return @RangeList; 323 1.1 christos } 324 1.1 christos ##################################################### 325 1.1 christos 326 1.1 christos sub ExtractIp ($) { 327 1.1 christos my ($octet) = @_; 328 1.1 christos # purpose: to return the registry saved IP address in a readable form 329 1.1 christos # input: 330 1.1 christos # $octet: a 4 byte data storing the IP address as the registry save it as 331 1.1 christos # output: none 332 1.1 christos # return: anonymous variable of a string of IP address 333 1.1 christos 334 1.1 christos my (@data) = unpack ("C4", $octet); 335 1.1 christos 336 1.1 christos return "$data[3]\.$data[2]\.$data[1]\.$data[0]"; 337 1.1 christos 338 1.1 christos } 339 1.1 christos ##################################################### 340 1.1 christos 341 1.1 christos sub ExtractHex ($) { 342 1.1 christos my ($HexVal) = @_; 343 1.1 christos my @Hex; 344 1.1 christos # purpose: to return the registry saved hex number in a readable form 345 1.1 christos # input: 346 1.1 christos # $octet: a 4 byte data storing the hex number as the registry save it as 347 1.1 christos # output: none 348 1.1 christos # return: 349 1.1 christos # $Hex: string of hex digit 350 1.1 christos 351 1.1 christos 352 1.1 christos # First extract the size of the option 353 1.1 christos my (@data) = unpack("C4", $HexVal); 354 1.1 christos 355 1.1 christos for (my $i=3; $i>=0; $i--) { 356 1.1 christos $Hex[0] = $Hex[0] . sprintf ("%x", $data[$i]); 357 1.1 christos } 358 1.1 christos 359 1.1 christos return @Hex; 360 1.1 christos } 361 1.1 christos 1; 362