Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

859 lines
28 KiB

  1. #-----------------------------------------------------------------//
  2. # Script: WMIFE.pm
  3. #
  4. # (c) 2001,2002 Microsoft Corporation. All rights reserved.
  5. #
  6. # addresses the generic OLE->WMI interface to test various stuff
  7. # defined on the given remote box
  8. #
  9. # Version: <2.01> 06/11/2002 : Serguei Kouzmine
  10. #
  11. #-----------------------------------------------------------------//
  12. package WMIFE;
  13. use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
  14. use lib $ENV{RAZZLETOOLPATH};
  15. use PbuildEnv;
  16. use Logmsg;
  17. require Exporter;
  18. use vars qw( @ISA @EXPORT_OK );
  19. @ISA = ( 'Exporter' );
  20. @EXPORT_OK = qw( $verbose );
  21. my $hPrivileges = {"SeBackupPrivilege" => "Backup",
  22. "SeSecurityPrivilege" => "Security",
  23. "SeRestorePrivilege" => "Restore",
  24. "SeShutdownPrivilege" => "ShutDown",
  25. "SeRemoteShutdownPrivilege" => "RemoteShutdown"
  26. };
  27. use strict;
  28. no strict 'refs';
  29. use Win32::OLE qw(in with);
  30. use Win32::OLE::Variant;
  31. # use 'in' loop for retrieve WQL cursors
  32. use vars qw( $verbose
  33. $NameSpace
  34. $impersonationLevel
  35. $authLevel
  36. $Privileges
  37. $ComputerName
  38. $MasterData
  39. $Provider
  40. $Query
  41. $DisplayFields
  42. $User
  43. $Password
  44. $DEBUG
  45. $TIMEOUT
  46. $sRootKey
  47. $sBootTestDataSubKey
  48. $sLogonUserDataSubKey
  49. );
  50. my $VERSION = "1.1";
  51. $TIMEOUT = 60;
  52. $DEBUG = 0;
  53. $verbose = ["NO","YES"];
  54. my $SEPARATOR = "\n". join("", map{chr(61)} 0..79). "\n";
  55. $NameSpace = "root\\cimv2";
  56. $sRootKey = "HKEY_LOCAL_MACHINE";
  57. $sBootTestDataSubKey = "SOFTWARE\\MICROSOFT\\BOOTTEST";
  58. $sLogonUserDataSubKey = "SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\WINLOGON";
  59. $impersonationLevel = "impersonate";
  60. $authLevel = "pktPrivacy";
  61. $Privileges = join(",", values(%$hPrivileges));
  62. $Provider = q(WbemScripting.SWbemLocator);
  63. $MasterData=
  64. q(winmgmts:{impersonationLevel=$impersonationLevel,authenticationLevel=$authLevel, ($Privileges)}!
  65. \\\\$ComputerName\\$NameSpace);
  66. sub ObjectExecMethod{
  67. my ($WbemObjClassName, $MethodName, $ComputerName, $ParameterName, $ParameterValue, $User, $Password) = @_;
  68. # play with the command line expansion
  69. # here.
  70. $DEBUG and print STDERR
  71. "ObjectExecMethod: using PROVIDER: ", $Provider, " " , $User, "\n";
  72. my $WbemLocator = Win32::OLE->new($Provider);
  73. OLEerrmsg("Could not instatiate $Provider") unless defined $WbemLocator;
  74. my $SWbemServices = ($User =~ /\*/) ?
  75. $WbemLocator->ConnectServer( $ComputerName, $NameSpace) :
  76. $WbemLocator->ConnectServer( $ComputerName, $NameSpace, $User, $Password );
  77. defined $SWbemServices or
  78. OLEerrmsg("Cannot connect: $ComputerName, $NameSpace");
  79. # Make sure we are using the appropriate security level
  80. OLEerrmsg("Error setting security level")
  81. if ( !($SWbemServices->{Security_}->{ImpersonationLevel} = 3) );
  82. map {
  83. $SWbemServices->{Security_}->{Privileges}->AddAsString($_)
  84. or OLEerrmsg( "Error setting $hPrivileges->$_ privileges");
  85. } keys %$hPrivileges;
  86. # Get the process object on the remote machine
  87. my $WbemObject = $SWbemServices->Get($WbemObjClassName);
  88. my $Result = $WbemObject->SetProperty($ParameterName, $ParameterValue) unless !defined($ParameterName);
  89. my $ProcessId = \0;
  90. #~ $REALDEBUG and
  91. #~ print $SEPARATOR , $WbemObject->Invoke("GetObjectText_"), $SEPARATOR;
  92. #~ too much info here
  93. my $ResultArrayRef = [(in $WbemObject->Invoke("Methods_"))];
  94. $DEBUG and print STDERR
  95. "$WbemObjClassName: METHODS_:\n";
  96. $DEBUG and
  97. map {&FormatDebugMsg($_->{"Name"}, $_->{"value"})} @$ResultArrayRef;
  98. OLEerrmsg("undefined method: $MethodName") unless grep {/$MethodName/i}
  99. map {$_->{"Name"}} @$ResultArrayRef;
  100. defined $WbemObject or
  101. OLEerrmsg("Could not create remote $WbemObjClassName");
  102. # Now invoke the method
  103. $DEBUG and
  104. print STDERR $WbemObject->{CommandLine}, "\n";
  105. OLEerrmsg("At $ComputerName, $ParameterName($ParameterValue) => $Result" )
  106. if ($Result = $WbemObject->Invoke($MethodName,
  107. $WbemObject->{CommandLine},
  108. undef,
  109. undef,
  110. $ProcessId)); # ):- $ProcessId not filled up :-(
  111. undef $WbemLocator;
  112. undef $SWbemServices;
  113. undef $WbemObject;
  114. Win32::OLE->Uninitialize();
  115. $DEBUG and print STDERR "OK\n";
  116. 0;
  117. }
  118. sub ExecQuery{
  119. local ($ComputerName, $Query, $DisplayFields, $User, $Password) = @_;
  120. # the "local" keyword is necessary to get search/replace able to do /e switch
  121. my @MasterData = split (/\n/, $MasterData);
  122. my %Caption = map {$_=> $_} @$DisplayFields;
  123. # The values of %Caption must not be identical to the retrieved field names
  124. my $Caption = \%Caption;
  125. grep {s/\$\{?(\w+)\}?/${$1}/ge} @MasterData, $Query;
  126. # here we replace all the vars with their values
  127. $MasterData = join("", @MasterData);
  128. $Query =~ s/([^\\])\\([^\\])/$1\\\\$2/g;
  129. my $ResultSet = undef;
  130. $DEBUG and print STDERR
  131. "ExecQuery: using PROVIDER: ", $Provider, " " , $User, "\n";
  132. my $WbemLocator = Win32::OLE->new($Provider);
  133. OLEerrmsg("Could not instatiate $Provider") unless defined $WbemLocator;
  134. my $SWbemServices = ($User =~ /\*/) ?
  135. $WbemLocator->ConnectServer( $ComputerName, $NameSpace) :
  136. $WbemLocator->ConnectServer( $ComputerName, $NameSpace, $User, $Password );
  137. defined $SWbemServices or
  138. OLEerrmsg("Cannot connect: $ComputerName, $NameSpace");
  139. # Make sure we are using the appropriate security level
  140. OLEerrmsg("Error setting security level")
  141. if ( !($SWbemServices->{Security_}->{ImpersonationLevel} = 3) );
  142. map {
  143. $SWbemServices->{Security_}->{Privileges}->AddAsString($_)
  144. or OLEerrmsg( "Error setting $hPrivileges->$_ privileges");
  145. } keys %$hPrivileges;
  146. $DEBUG and print STDERR
  147. "\$Query: ", qq($Query), "\n";
  148. ###
  149. ### eval { $ResultSet = Win32::OLE->GetObject($MasterData)->ExecQuery($Query); };
  150. ### $DEBUG and $Query = ""
  151. eval { $ResultSet = $SWbemServices->ExecQuery($Query); };
  152. #
  153. #
  154. my $ResultArrayRef = [(in $ResultSet)] unless ($@);
  155. $ResultArrayRef or
  156. print STDERR "Win32::OLE::LastError ", Win32::OLE::LastError, "\n";
  157. my @ResultCursor;
  158. # pack ResultSet -> ResultCursor;
  159. map {map {push @ResultCursor, {$Caption->{$_} => $ResultArrayRef->[0]->{$_}}}
  160. @$DisplayFields and shift @$ResultArrayRef}
  161. (0..$#$ResultArrayRef);
  162. Win32::OLE->Uninitialize();
  163. \@ResultCursor;
  164. }
  165. # &IsRunning($ProcMask, $runAtHost);
  166. # lists processes on the host $runAtHost to
  167. # find pattern $ProcMask.
  168. # for all process found, collect the
  169. # $1 of the search
  170. # e.g. you get language of the running postbuiild with
  171. # the pattern:
  172. # "\\\\POSTBUILDSCRIPTS\\\\PBUILD\\\.CMD\\\"\\s\+\\\-l[: ]\(\\w\{3\}\)";
  173. #
  174. # plus some properties of the $ProcessSet
  175. # return value: array pointer. The arguments are filtered out by default:
  176. # (/S:\\BLD_WNXF1\RELEASE\GER\3562.X86FRE.MAIN.011002-1901\PRO /TEMPDRIVE:D /#T:7)
  177. # PID= 00220
  178. # NAME= winnt32.exe
  179. # CMD= \\bld_wnxf1\release\ger\3562.x86fre.main.011002-1901\pro\i386\winnt32.exe /s:\\bld_wnxf1\release\ger\3562.x86fre.main.011002-1901\pro /tempdrive:d /#t:7
  180. sub IsRunning{
  181. my (
  182. $WMIclass, $ProcMask, $Field, $Fields, $runAtHost) = @_;
  183. # filter out arguments
  184. $ProcMask = $ProcMask."\\\"\? \(\.\+\)\$" unless $ProcMask=~/\(/;
  185. $DEBUG and print STDERR $ProcMask, "\n";
  186. my $ProcessSet;
  187. my @result;
  188. my $Moniker = "winmgmts:{impersonationLevel=impersonate}!\\\\HOST\\root\\cimv2";
  189. $Moniker =~ s/HOST/$runAtHost/;
  190. $DEBUG and print STDERR
  191. "using MONIKER: ", $Moniker, "\n";
  192. eval {
  193. $ProcessSet = Win32::OLE->GetObject($Moniker)->InstancesOf ($WMIclass); };
  194. unless($@){
  195. foreach my $ProcessInst (in $ProcessSet){
  196. push @result, join("\n",
  197. uc($1), map {"$_=".$ProcessInst->{$_}} @$Fields),
  198. if $ProcessInst->{$Field} =~ m/$ProcMask/gi;
  199. }
  200. }else{
  201. print STDERR Win32::OLE->LastError, "\n";
  202. }
  203. $DEBUG and print STDERR join ("\n", @result) , "\n";
  204. \@result;
  205. }
  206. # supplyRegData
  207. # usage:
  208. # $defaultData = {
  209. # "DEBUG" => $DEBUG,
  210. # "Lang" => $Lang ,
  211. # ...
  212. # }
  213. # $volatileData = {}
  214. #
  215. # &supplyRegData($sTargetcomputer, $REGISTRY_KEY,
  216. # $defaultData, $volatileData , $FovWrite);
  217. #
  218. #
  219. sub supplyRegData{
  220. my ($sTargetcomputer, $sBootTestDataSubKey, $defaultData, $volatileData, $FovWrite) = @_;
  221. use strict;
  222. use Win32API::Registry 0.21 qw(HKEY_LOCAL_MACHINE
  223. REG_OPTION_VOLATILE
  224. REG_OPTION_NON_VOLATILE
  225. KEY_ALL_ACCESS
  226. KEY_READ
  227. REG_SZ
  228. regLastError
  229. RegConnectRegistry
  230. RegOpenKeyEx
  231. RegEnumValue
  232. RegQueryInfoKey
  233. RegQueryValueEx
  234. RegCreateKeyEx
  235. RegSetValueEx
  236. RegDeleteValue
  237. RegCloseKey
  238. );
  239. # This provides fairly low-level access to the Win32 System API calls
  240. # dealing with the Registry [mostly from WINREG.H]. This is mostly
  241. my $hRootKey = $sRootKey;
  242. { no strict 'refs';
  243. $hRootKey =~ s/(\w+)/$1/eeg;
  244. use strict 'refs';
  245. }
  246. my $sStatusSubKey = "STATUS";
  247. my $ohKey = undef;
  248. my $ohSubKey = undef;
  249. my $ohStatusSubKey = undef;
  250. my $ocValues;
  251. my $olValName;
  252. my $olValData;
  253. my $olSecDesc;
  254. my $opValData;
  255. my $osValName;
  256. my $sValueNames = [];
  257. my $sValueName;
  258. my $nStatus = undef;
  259. $DEBUG and print STDERR
  260. "COMPUTER: ".uc($sTargetcomputer)."\n";
  261. &RegConnectRegistry( $sTargetcomputer,
  262. $hRootKey,
  263. $ohKey )
  264. or die "Can't open $hRootKey: ", regLastError(),"\n";
  265. $DEBUG and print STDERR
  266. "Registry Key: ".$sRootKey."\\$sBootTestDataSubKey\n";
  267. $nStatus = &RegOpenKeyEx( $ohKey,
  268. $sBootTestDataSubKey ."\\". $sStatusSubKey,
  269. 0,
  270. KEY_READ,
  271. $ohStatusSubKey );
  272. if (scalar(keys(%$volatileData))){
  273. $sValueName = (keys(%$volatileData))[0];
  274. $opValData = undef;
  275. if ($nStatus){
  276. &RegQueryValueEx( $ohStatusSubKey,
  277. $sValueName ,
  278. [],
  279. [],
  280. $opValData,
  281. [] );
  282. # error is ignored.
  283. $opValData = "(undef)" unless $opValData;
  284. &RegCloseKey($ohStatusSubKey);
  285. }
  286. if ($nStatus ){
  287. $DEBUG and print STDERR
  288. "\\\\$sTargetcomputer\\$sRootKey\\$sBootTestDataSubKey\\$sStatusSubKey\\$sValueName: ",$opValData, "\n";
  289. $FovWrite or return 1;
  290. }
  291. }
  292. RegCreateKeyEx($ohKey,
  293. $sBootTestDataSubKey,
  294. 0,
  295. "",
  296. REG_OPTION_NON_VOLATILE,
  297. KEY_ALL_ACCESS,
  298. [],
  299. $ohSubKey,
  300. []);
  301. RegCloseKey($ohSubKey);
  302. &RegOpenKeyEx( $ohKey,
  303. $sBootTestDataSubKey ,
  304. 0,
  305. KEY_ALL_ACCESS,
  306. $ohSubKey )
  307. or die "Can't open $sBootTestDataSubKey: \n", regLastError(),"\n";
  308. &RegQueryInfoKey($ohSubKey,
  309. [],
  310. [],
  311. [],
  312. [],
  313. [],
  314. [],
  315. $ocValues,
  316. $olValName,
  317. $olValData,
  318. [],
  319. []
  320. )
  321. or die "Can't query $sBootTestDataSubKey: ", regLastError(),"\n";
  322. $DEBUG and print STDERR
  323. $ocValues, " values found\n";
  324. foreach my $Data (keys(%$defaultData)){
  325. if ($FovWrite){
  326. # tsanders: existing values do not get overwritten.
  327. &RegDeleteValue($ohSubKey,
  328. $Data);
  329. $DEBUG and print STDERR
  330. "\t\tDeleting Default Data: \"$Data\"\n\t\t$^E\n";
  331. #ignore the "$^E" here.
  332. }
  333. &RegSetValueEx($ohSubKey,
  334. $Data,
  335. 0,
  336. REG_SZ,
  337. $defaultData->{$Data},
  338. 0
  339. )
  340. or die "Can't RegSetValueEx($Data,...$defaultData->{$Data}: ", regLastError(),"\n";
  341. }
  342. foreach my $nCnt (0..$ocValues-1){
  343. &RegEnumValue($ohSubKey,
  344. $nCnt,
  345. $osValName,
  346. 0,
  347. [],
  348. [],
  349. $opValData,
  350. 0 );
  351. push @$sValueNames, $osValName;
  352. }
  353. foreach $sValueName (@$sValueNames){
  354. &RegQueryValueEx( $ohSubKey,
  355. $sValueName ,
  356. [],
  357. [],
  358. $opValData,
  359. [] )
  360. or die "Can't read $sValueName: ", regLastError(),"\n";
  361. $DEBUG and print STDERR
  362. "$sValueName=$opValData\n";
  363. }
  364. RegCreateKeyEx($ohSubKey,
  365. $sStatusSubKey,
  366. 0,
  367. "",
  368. REG_OPTION_VOLATILE,
  369. KEY_ALL_ACCESS,
  370. [],
  371. $ohStatusSubKey,
  372. []);
  373. foreach my $Data (keys(%$volatileData)){
  374. &RegSetValueEx($ohStatusSubKey,
  375. $Data,
  376. 0,
  377. REG_SZ,
  378. $volatileData->{$Data},
  379. 0
  380. )
  381. or die "Can't RegSetValueEx($Data,...$volatileData->{$Data}: ",
  382. regLastError(),"\n";
  383. }
  384. map {defined($_) and RegCloseKey($_)} ($ohSubKey, $ohKey, $ohStatusSubKey);
  385. 0;
  386. }
  387. sub OLEerrmsg($)
  388. {
  389. my $text = shift;
  390. errmsg( "$text (". Win32::OLE->LastError(). ")" );
  391. exit 1;
  392. }
  393. sub ScheduleTime{
  394. use Time::localtime;
  395. my $shiftTime = shift;
  396. my $tNow = time();
  397. $DEBUG and print STDERR
  398. "Current time: " , &localtime->hour(), ":", &localtime->min(), "\n";
  399. $tNow += $shiftTime;
  400. my @result = map {sprintf("%02d", $_)} (&localtime($tNow)-> hour(),
  401. &localtime($tNow)-> min(),
  402. &localtime($tNow)-> sec(),
  403. &localtime($tNow)-> mon() + 1,
  404. &localtime($tNow)-> mday(),
  405. &localtime($tNow)-> year() + 1900
  406. );
  407. $DEBUG and print STDERR
  408. "Schedule time: " , $result[0], ":",
  409. $result[1], ":",
  410. $result[2], " ",
  411. $result[3], "/",
  412. $result[4], "/",
  413. $result[5], "\n";
  414. \@result;
  415. }
  416. sub FormatDebugMsg{
  417. format STDERR =
  418. # field name field value
  419. @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  420. $_[0] $_[1]
  421. .
  422. write STDERR;
  423. }
  424. # BackTick
  425. # sample usage: &BackTick("dir");
  426. # &BackTick(<<BLOCKBOUNDARY);
  427. # ...cmd code...
  428. # BLOCKBOUNDARY
  429. # passes block of code to the cmd interpreter.
  430. # lines are concatenated
  431. # comments thrown away
  432. # useful stuff when the code is already
  433. # developed and just needs to be inserted in place
  434. # has limitations.
  435. sub BackTick{
  436. my ($cmd) = @_;
  437. my $res = undef;
  438. $DEBUG and
  439. print STDERR join(" &", grep (!/^:|REM/i, ($cmd =~ /^(.+)/gm)));
  440. $cmd = join(" &", grep (!/^:|REM/i, ($cmd =~ /^(.+)/gm)));
  441. $res=qx ($cmd);
  442. $res;
  443. }
  444. sub pPpPinfo{
  445. my @infa = @_;
  446. my $opBrws = Win32::OLE->new("WScript.Shell");
  447. $opBrws->Popup(join("\n", @infa), $TIMEOUT ,
  448. ref($opBrws) . "<- $0,". $VERSION,
  449. 0 + 64);
  450. undef($opBrws);
  451. Win32::OLE->FreeUnusedLibraries();
  452. Win32::OLE->Uninitialize();
  453. 1;
  454. }
  455. 1;
  456. __END__
  457. #-------------------------------------------------------------//
  458. =head1 NAME
  459. B<WMIFE> - Interface the query engine exposed by WMI
  460. =head1 SYNOPSIS
  461. use WMIFE;
  462. &WMIFE::ExecQuery($ComputerName, $Query, [@Fields]);
  463. &WMIFE::FormatDebugMsg($Comment, $Field);
  464. =head1 DESCRIPTION
  465. Generates the WQL (A.K.A. WMI SQL) query on the remote machine against
  466. its namespace.
  467. Sample objects that reside on the remote box $ComputerName are:
  468. * local files [/.//ROOT/CIMV2/CIM_DATAFILE],
  469. * running processes [/.//ROOT/CIMV2/WIN32_PROCESSES],
  470. * registry entries [/.//ROOT/DEFAULT/STDREGPROV].
  471. The WMI is functional even in the absence of logon sessions on $ComputerName.
  472. =head1 METHODS
  473. =head2 FormatDebugMsg($fieldName, $FieldValue)
  474. Nice (?) formatting of the RDB like table field output (A.K.A. browse view):
  475. Name perl.exe
  476. Description perl.exe
  477. ProcessID 2920
  478. ParentProce 2692
  479. ExecutableP d:\ntt\tools\perl\bin\perl.exe
  480. ...
  481. =head2 ExecQuery($ComputerName, $Query, $DisplayFields)
  482. Execute the WMI WQL query against the namespace of the remote machine
  483. where
  484. $ComputerName is the name of the machine which namespaces are about to be queried.
  485. $Query the string representing the query, with the dollarsigned names placeholders for parameters
  486. $DisplayFields reference to the field list to retusn the result
  487. The return value is a reference to the like the RDB cursor.
  488. (array of hashes where keys are described in $DisplayFields array).
  489. If no data is returned from the query the returned value is a reference to undefined value.
  490. =head2 ObjectExecMethod($MethodName, $ComputerName, $ParameterName, $ParameterValue, $User, $Password
  491. Access the namespace on the remote box $ComputerName, and execute the method $MethodName of the class
  492. $WbemObjClassName (currently only for Win32_Process). Supply the parameter(s) via name/value.
  493. PErfurm the call under $User account, proving the password.
  494. =head2 Sample calls:
  495. =head2 To list files in the root directory of the logical disk labeled $Drive of the machine $Machine
  496. $Results = &WMIFE::ExecQuery($Machine,
  497. qq(SELECT * FROM cim_Datafile WHERE Drive="$Drive" AND Path="\\\\" "),
  498. [qw(Drive Path Name)]);
  499. =head2 To list logical disks of the machine $Machine
  500. $Results = &WMIFE::ExecQuery($Machine,
  501. qq(SELECT * FROM Win32_LogicalDisk WHERE DriveType=3),
  502. [qw(Name Description)]);
  503. =head2 To list the running processes
  504. $Results = &WMIFE::ExecQuery($ComputerName,
  505. qq(SELECT * FROM Win32_Process),
  506. [qw(Name Description ProcessID ParentProcessId ExecutablePath )]);
  507. =head2 To view installed software
  508. $Results = &WMIFE::ExecQuery($ComputerName,
  509. qq(SELECT * FROM Win32_Product),
  510. [qw(Name Vendor Version)]);
  511. =head2 To verify administrators group
  512. $Results = &WMIFE::ExecQuery($ComputerName,
  513. qq(SELECT * FROM Win32_GroupUser WHERE GroupComponent="Win32_Group.Domain=\\"$ComputerName\\",Name=\\"Administrators\\""),
  514. [qw(GroupComponent)]);
  515. =head2 To browse the process dependency hierarchy
  516. $Results = &WMIFE::ExecQuery($ComputerName,
  517. qq(SELECT * FROM CIM_ProcessExecutable),
  518. [qw(Antecedent Dependent)]);
  519. =head2 Query who is currently logged to somewhere.
  520. $Results =
  521. &WMIFE::ExecQuery($ENV{"COMPUTERNAME"}, # interactive session
  522. qq(SELECT * FROM Win32_LogonSession WHERE LogonType=2),
  523. [qw(LogonId LogonType)]);
  524. foreach my $Result (@$Results){
  525. $DEBUG and
  526. map {&WMIFE::FormatDebugMsg($_, $Result->{$_})} keys (%$Result);
  527. push @Ids, $Result->{"LogonId"};
  528. }
  529. $Results =
  530. &WMIFE::ExecQuery($ENV{"COMPUTERNAME"}, # Difficult to build the WHERE condition.
  531. qq(SELECT * FROM Win32_LoggedOnUser),
  532. [qw(Antecedent Dependent)]);
  533. my @Users = ();
  534. my $User = undef;
  535. my $LoggedUser = undef;
  536. my @LoggedUsers = ();
  537. # a little bit ugly.
  538. foreach my $Id (grep {/\d+/} @Ids){
  539. foreach my $Result (@$Results){
  540. $User = $Result->{"Antecedent"};
  541. if ($User =~ /\S/){
  542. push @Users, $User;
  543. }
  544. if ((grep {/\b$Id\b/} $Result->{"Dependent"})){
  545. $LoggedUser = pop @Users;
  546. push @LoggedUsers, $LoggedUser;
  547. $DEBUG and &WMIFE::FormatDebugMsg("win32_user", $LoggedUser);
  548. $DEBUG and &WMIFE::FormatDebugMsg("win32_logonSession", $Id);
  549. }
  550. }
  551. }
  552. map {($user, $domain) = (/Win32_Account.Domain=\"(\w+)\",Name=\"(\w+)\"/);
  553. $DEBUG and
  554. print $user, "\t" , $domain,"\n"; } @LoggedUsers;
  555. =head2 To list the $Result contents, the following framework may be used:
  556. use WMIFE;
  557. &WMIFE::ExecQuery($ENV{"COMPUTERNAME"},
  558. qq(SELECT * FROM Win32_BootConfiguration),
  559. [qw(Caption BootDirectory Description)]);
  560. foreach my $Result (@$Results){
  561. map {&WMIFE::FormatDebugMsg($_, $Result->{$_})} keys (%$Result);
  562. }
  563. =head2 To design the new query
  564. please use the %WINDIR%\SYSTEM32\WBEM\wbemtest.exe vendor shell for accessing and
  565. querying the WMI classes and then use the query string designed in that shell as an argument to the Perl qq()
  566. [double backslashes]
  567. Some queries may take long time to execute, before being sufficiently refined.
  568. =head1 SEE ALSO
  569. Whole bunch of tools interfacing WMI is in progress. Note that the Perl interface to WMI is not as powerful as
  570. VBSCRIPT/JSCRIPT since there is no working examples for P/P (A.K.A. object sinking) and in general any
  571. interface(s) other than SQL. the design of such sample code might prove to be complicated indeed.
  572. =head2 supplyRegData($sTargetcomputer, $Lang, $BldNum, $Sku, $Drive, $BuildName, $Unattend, $FovWrite)
  573. Write the data to the REGISTRY of the Boot test machine to start the execution
  574. of test build installation.
  575. The REGISTRY path where the data is stored is:
  576. HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\BOOTTEST
  577. The data includes the following fields:
  578. -------------+-----------------------------------------------------------
  579. $Lang | fields are used to find the test bits, in the form:
  580. $BuildName | $Drive\$Lang\$BuildName
  581. $BldNum | $BldNum, $Sku and $Lang are used to verify the
  582. $Sku | REGISTRY data is actual for the build being installed.
  583. $Drive | target drive for winnt32.exe
  584. $Unattend | location of the answer file
  585. The data is written by the postbuild on the build machine (NTDEV\NTBUILD),
  586. and is later consumed from boot machine side by (NTDEV\<AUTOGENERATED> user).
  587. The registry access across the network hence the use of HKEY_LOCAL_MACHINE.
  588. The default REGISTRY key names are:
  589. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\_BldNum => $BldNum
  590. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\_BuildArch => $_BuildArch
  591. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\LANG => $Lang
  592. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\_BldSku => $Sku
  593. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\_BuildType => $_BuildType
  594. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\_BldDrive => $Drive
  595. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\Unattend => $Unattend
  596. HKLM\SOFTWARE\MICROSOFT\BOOTTEST\_BldName => $BuildName
  597. Running regedit.exe will show the following data:
  598. +-----------------------------------------------
  599. |Windows Registry Editor Version 5.00
  600. |
  601. |[HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\BOOTTEST]
  602. |"_BuildArch"="x86"
  603. |"_BuildType"="fre"
  604. |"_BldSku"="SRV"
  605. |"_BldName"="3615.x86fre.main.020306-1639"
  606. |"_BldDrive"="D"
  607. |"Unattend"="unattend.txt"
  608. |"LANG"="GER"
  609. |"_BldNum"="3615"
  610. |
  611. |[HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\BOOTTEST\Status]
  612. |"COMPUTERNAME"="BLD_WNXF1"
  613. +-----------------------------------------------
  614. The Status subkey is to prevent concurrent execution of the more than one
  615. test build install on the single test machine. The function will return
  616. the data observed e.g.
  617. \\sergueik4\HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\BOOTTEST\STATUS\COMPUTERNAME: SERGUEIK2
  618. To ignore the presence of the Status set $FovWrite = 1.
  619. Booting test machine (but not logging off of the user) will cause Status
  620. key to disappear.
  621. =head2 &ScheduleTime($Delay)
  622. Calculate the time/date for execution of the scheduled tasks in
  623. $Delay secs from NOW.
  624. Example usage:
  625. use WMIFE;
  626. $WMIFE::DEBUG = 1;
  627. my $DELAY1 = 1800; # delay in 1800 secs = 30 min
  628. my $string = "/st %HH%:%MM%:%SS% /sd %mm%/%dd%/%yyyy%" ;
  629. my $marker = ["HH" , "MM", "SS", "mm", "dd", "yyyy"];
  630. # this is the way to set the date/time of scheduled task
  631. my $ScheduleTime = &WMIFE::ScheduleTime($DELAY1);
  632. print STDERR "\"$string\"\t";
  633. map {$string =~ s/\%$marker->[$_]\%/$ScheduleTime->[$_]/g;}
  634. (0..$#$marker);
  635. print STDERR "\"$string\"\n";
  636. Current time: 15:51
  637. Schedule time: 16:21:32 03/25/2002
  638. "/st %HH%:%MM%:%SS% /sd %mm%/%dd%/%yyyy%"
  639. "/st 16:21:32 /sd 03/25/2002"
  640. =head1 AUTHOR
  641. Serguei Kouzmine sergueik@microsoft.com
  642. =cut
  643. 1;