| 1 | /* |
| 2 | Copyright 2019-2020 Intel Corporation |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | var promise = require('promise'); |
| 18 | |
| 19 | // We use the environment variable directly or the standard Windows path |
| 20 | var psPath = (process.env['SystemRoot'] ? process.env['SystemRoot'] : 'C:\\Windows') + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'; |
| 21 | |
| 22 | function qfe() |
| 23 | { |
| 24 | try { |
| 25 | var tokens = require('win-wmi').query('ROOT\\CIMV2', 'SELECT * FROM Win32_QuickFixEngineering'); |
| 26 | if (tokens[0]){ |
| 27 | for (var index = 0; index < tokens.length; index++) { |
| 28 | for (var key in tokens[index]) { |
| 29 | if (key.startsWith('__')) delete tokens[index][key]; |
| 30 | } |
| 31 | } |
| 32 | return (tokens); |
| 33 | } else { |
| 34 | return ([]); |
| 35 | } |
| 36 | } catch (ex) { |
| 37 | return ([]); |
| 38 | } |
| 39 | } |
| 40 | function av() |
| 41 | { |
| 42 | var result = []; |
| 43 | try { |
| 44 | var tokens = require('win-wmi-fixed').query('ROOT\\SecurityCenter2', 'SELECT * FROM AntiVirusProduct'); |
| 45 | if (tokens.length == 0) { return ([]); } |
| 46 | // Process each antivirus product |
| 47 | for (var i = 0; i < tokens.length; ++i) { |
| 48 | var product = tokens[i]; |
| 49 | var modifiedPath = product.pathToSignedProductExe || ''; |
| 50 | // Expand environment variables (e.g., %ProgramFiles%) |
| 51 | var regex = /%([^%]+)%/g; |
| 52 | var match; |
| 53 | while ((match = regex.exec(product.pathToSignedProductExe)) !== null) { |
| 54 | var envVar = match[1]; |
| 55 | var envValue = process.env[envVar] || ''; |
| 56 | if (envValue) { |
| 57 | modifiedPath = modifiedPath.replace(match[0], envValue); |
| 58 | } |
| 59 | } |
| 60 | // Check if the executable exists (unless it's Windows Defender pseudo-path) |
| 61 | var flag = true; |
| 62 | if (modifiedPath !== 'windowsdefender://') { |
| 63 | try { |
| 64 | if (!require('fs').existsSync(modifiedPath)) { |
| 65 | flag = false; |
| 66 | } |
| 67 | } catch (ex) { |
| 68 | flag = false; |
| 69 | } |
| 70 | } |
| 71 | // Only include products with valid executables |
| 72 | if (flag) { |
| 73 | var status = {}; |
| 74 | status.product = product.displayName || ''; |
| 75 | status.updated = (parseInt(product.productState) & 0x10) == 0; |
| 76 | status.enabled = (parseInt(product.productState) & 0x1000) == 0x1000; |
| 77 | result.push(status); |
| 78 | } |
| 79 | } |
| 80 | return (result); |
| 81 | } catch (ex) { |
| 82 | return ([]); |
| 83 | } |
| 84 | } |
| 85 | function defrag(options) |
| 86 | { |
| 87 | var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; }); |
| 88 | var path = ''; |
| 89 | |
| 90 | switch(require('os').arch()) |
| 91 | { |
| 92 | case 'x64': |
| 93 | if (require('_GenericMarshal').PointerSize == 4) |
| 94 | { |
| 95 | // 32 Bit App on 64 Bit Windows |
| 96 | ret._rej('Cannot defrag volume on 64 bit Windows from 32 bit application'); |
| 97 | return (ret); |
| 98 | } |
| 99 | else |
| 100 | { |
| 101 | // 64 Bit App |
| 102 | path = process.env['windir'] + '\\System32\\defrag.exe'; |
| 103 | } |
| 104 | break; |
| 105 | case 'ia32': |
| 106 | // 32 Bit App on 32 Bit Windows |
| 107 | path = process.env['windir'] + '\\System32\\defrag.exe'; |
| 108 | break; |
| 109 | default: |
| 110 | ret._rej(require('os').arch() + ' not supported'); |
| 111 | return (ret); |
| 112 | break; |
| 113 | } |
| 114 | |
| 115 | ret.child = require('child_process').execFile(process.env['windir'] + '\\System32\\defrag.exe', ['defrag', options.volume + ' /A']); |
| 116 | ret.child.promise = ret; |
| 117 | ret.child.promise.options = options; |
| 118 | ret.child.stdout.str = ''; ret.child.stdout.on('data', function (c) { this.str += c.toString(); }); |
| 119 | ret.child.stderr.str = ''; ret.child.stderr.on('data', function (c) { this.str += c.toString(); }); |
| 120 | ret.child.on('exit', function (code) |
| 121 | { |
| 122 | var lines = this.stdout.str.trim().split('\r\n'); |
| 123 | var obj = { volume: this.promise.options.volume }; |
| 124 | for (var i in lines) |
| 125 | { |
| 126 | var token = lines[i].split('='); |
| 127 | if(token.length == 2) |
| 128 | { |
| 129 | switch(token[0].trim().toLowerCase()) |
| 130 | { |
| 131 | case 'volume size': |
| 132 | obj['size'] = token[1]; |
| 133 | break; |
| 134 | case 'free space': |
| 135 | obj['free'] = token[1]; |
| 136 | break; |
| 137 | case 'total fragmented space': |
| 138 | obj['fragmented'] = token[1]; |
| 139 | break; |
| 140 | case 'largest free space size': |
| 141 | obj['largestFragment'] = token[1]; |
| 142 | break; |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | this.promise._res(obj); |
| 147 | }); |
| 148 | return (ret); |
| 149 | } |
| 150 | function regQuery(H, Path, Key) |
| 151 | { |
| 152 | try |
| 153 | { |
| 154 | return(require('win-registry').QueryKey(H, Path, Key)); |
| 155 | } |
| 156 | catch(e) |
| 157 | { |
| 158 | return (null); |
| 159 | } |
| 160 | } |
| 161 | function pendingReboot() |
| 162 | { |
| 163 | var tmp = null; |
| 164 | var ret = null; |
| 165 | var HKEY = require('win-registry').HKEY; |
| 166 | if(regQuery(HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing', 'RebootPending') !=null) |
| 167 | { |
| 168 | ret = 'Component Based Servicing'; |
| 169 | } |
| 170 | else if(regQuery(HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate', 'RebootRequired')) |
| 171 | { |
| 172 | ret = 'Windows Update'; |
| 173 | } |
| 174 | else if ((tmp=regQuery(HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager', 'PendingFileRenameOperations'))!=null && tmp != 0 && tmp != '') |
| 175 | { |
| 176 | ret = 'File Rename'; |
| 177 | } |
| 178 | else if (regQuery(HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName', 'ComputerName') != regQuery(HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName', 'ComputerName')) |
| 179 | { |
| 180 | ret = 'System Rename'; |
| 181 | } |
| 182 | return (ret); |
| 183 | } |
| 184 | |
| 185 | function installedApps() { |
| 186 | var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; }); |
| 187 | var registry = require('win-registry'); |
| 188 | var HKEY = registry.HKEY; |
| 189 | var results = []; |
| 190 | var registryPaths = [ |
| 191 | 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall', |
| 192 | 'SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall' |
| 193 | ]; |
| 194 | try { |
| 195 | for (var i in registryPaths) { |
| 196 | var path = registryPaths[i]; |
| 197 | var keyInfo = registry.QueryKey(HKEY.LocalMachine, path); |
| 198 | if (!keyInfo || !keyInfo.subkeys) continue; |
| 199 | for (var j = 0; j < keyInfo.subkeys.length; j++) { |
| 200 | var subPath = path + '\\' + keyInfo.subkeys[j]; |
| 201 | var name = regQuery(HKEY.LocalMachine, subPath, 'DisplayName'); |
| 202 | if (name && name != '') { |
| 203 | results.push({ |
| 204 | name: name, |
| 205 | version: regQuery(HKEY.LocalMachine, subPath, 'DisplayVersion') || '', |
| 206 | publisher: regQuery(HKEY.LocalMachine, subPath, 'Publisher') || '', |
| 207 | uninstall: regQuery(HKEY.LocalMachine, subPath, 'QuietUninstallString') || regQuery(HKEY.LocalMachine, subPath, 'UninstallString') || '', |
| 208 | location: regQuery(HKEY.LocalMachine, subPath, 'InstallLocation') || '', |
| 209 | date: regQuery(HKEY.LocalMachine, subPath, 'InstallDate') || '' |
| 210 | }); |
| 211 | } |
| 212 | } |
| 213 | } |
| 214 | } catch (e) { |
| 215 | ret._rej(e); |
| 216 | return (ret); |
| 217 | } |
| 218 | ret._res(results); |
| 219 | return (ret); |
| 220 | } |
| 221 | |
| 222 | function installedStoreApps() { |
| 223 | var ret = new promise(function (a, r) { this._resolve = a; this._reject = r; }); |
| 224 | |
| 225 | // Basierend auf deiner funktionierenden Version + Scope-Erkennung |
| 226 | var psCommand = [ |
| 227 | "$ErrorActionPreference = 'SilentlyContinue'", |
| 228 | "$allUsersApps = @(Get-AppxPackage -AllUsers)", |
| 229 | "$allUsersPkgNames = @($allUsersApps | Select-Object -ExpandProperty PackageFullName)", |
| 230 | "$userOnlyApps = @(Get-AppxPackage | Where-Object { $allUsersPkgNames -notcontains $_.PackageFullName })", |
| 231 | "$provPkgs = @(Get-AppxProvisionedPackage -Online | Select-Object -ExpandProperty DisplayName)", |
| 232 | "$results = @()", |
| 233 | "foreach ($app in $allUsersApps) {", |
| 234 | " if ($app.Name -and $app.Name -notlike 'Microsoft.Windows.*' -and $app.Name -notlike 'windows.*' -and $app.Name -notlike '*_neutral_*') {", |
| 235 | " $scope = 'System'", |
| 236 | " if ($provPkgs -contains $app.Name) { $scope = 'System+Prov' }", |
| 237 | " $results += [PSCustomObject]@{ Name=$app.Name; Version=[string]$app.Version; PackageFullName=$app.PackageFullName; Publisher=$app.Publisher; Scope=$scope }", |
| 238 | " }", |
| 239 | "}", |
| 240 | "foreach ($app in $userOnlyApps) {", |
| 241 | " if ($app.Name -and $app.Name -notlike 'Microsoft.Windows.*' -and $app.Name -notlike 'windows.*' -and $app.Name -notlike '*_neutral_*') {", |
| 242 | " $scope = 'User'", |
| 243 | " if ($provPkgs -contains $app.Name) { $scope = 'User+Prov' }", |
| 244 | " $results += [PSCustomObject]@{ Name=$app.Name; Version=[string]$app.Version; PackageFullName=$app.PackageFullName; Publisher=$app.Publisher; Scope=$scope }", |
| 245 | " }", |
| 246 | "}", |
| 247 | "$results | Sort-Object Name -Unique | ConvertTo-Json -Compress" |
| 248 | ].join("; "); |
| 249 | |
| 250 | try { |
| 251 | var psPath = (process.env['SystemRoot'] || 'C:\\Windows') + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'; |
| 252 | |
| 253 | ret.child = require('child_process').execFile( |
| 254 | psPath, |
| 255 | ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', psCommand], |
| 256 | { timeout: 60000, maxBuffer: 10 * 1024 * 1024 } |
| 257 | ); |
| 258 | |
| 259 | ret.child.promise = ret; |
| 260 | ret.child.stdout.str = ''; |
| 261 | ret.child.stdout.on('data', function (chunk) { this.str += chunk.toString(); }); |
| 262 | |
| 263 | ret.child.on('exit', function (code) { |
| 264 | try { |
| 265 | var output = this.stdout.str.trim(); |
| 266 | |
| 267 | if (output === '' || output === 'null' || output === '[]') { |
| 268 | this.promise._resolve([]); |
| 269 | return; |
| 270 | } |
| 271 | |
| 272 | var data = JSON.parse(output); |
| 273 | if (!Array.isArray(data)) { data = [data]; } |
| 274 | |
| 275 | var apps = data.map(function(app) { |
| 276 | return { |
| 277 | name: app.Name || '', |
| 278 | version: app.Version || '', |
| 279 | publisher: app.Publisher || '', |
| 280 | packageFullName: app.PackageFullName || '', |
| 281 | scope: app.Scope || '', |
| 282 | uninstall: 'Remove-AppxPackage -Package "' + (app.PackageFullName || '') + '" -AllUsers' |
| 283 | }; |
| 284 | }); |
| 285 | |
| 286 | this.promise._resolve(apps); |
| 287 | } catch (e) { |
| 288 | this.promise._resolve([]); |
| 289 | } |
| 290 | }); |
| 291 | |
| 292 | ret.child.on('error', function (err) { |
| 293 | this.promise._resolve([]); |
| 294 | }); |
| 295 | } catch (ex) { |
| 296 | ret._resolve([]); |
| 297 | } |
| 298 | |
| 299 | return (ret); |
| 300 | } |
| 301 | |
| 302 | function defender(){ |
| 303 | try { |
| 304 | var tokens = require('win-wmi').query('ROOT\\Microsoft\\Windows\\Defender', 'SELECT * FROM MSFT_MpComputerStatus', ['RealTimeProtectionEnabled','IsTamperProtected','AntivirusSignatureVersion','AntivirusSignatureLastUpdated']); |
| 305 | if (tokens[0]){ |
| 306 | var info = { RealTimeProtection: tokens[0].RealTimeProtectionEnabled, TamperProtected: tokens[0].IsTamperProtected }; |
| 307 | if (tokens[0].AntivirusSignatureVersion) { info.AntivirusSignatureVersion = tokens[0].AntivirusSignatureVersion; } |
| 308 | if (tokens[0].AntivirusSignatureLastUpdated) { info.AntivirusSignatureLastUpdated = tokens[0].AntivirusSignatureLastUpdated; } |
| 309 | return (info); |
| 310 | } else { |
| 311 | return ({}); |
| 312 | } |
| 313 | } catch (ex) { |
| 314 | return ({}); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | if (process.platform == 'win32') |
| 319 | { |
| 320 | module.exports = { qfe: qfe, av: av, defrag: defrag, pendingReboot: pendingReboot, installedApps: installedApps, installedStoreApps: installedStoreApps, defender: defender }; |
| 321 | } |
| 322 | else |
| 323 | { |
| 324 | var not_supported = function () { throw (process.platform + ' not supported'); }; |
| 325 | module.exports = { qfe: not_supported, av: not_supported, defrag: not_supported, pendingReboot: not_supported, installedApps: not_supported, installedStoreApps: not_supported, defender: not_supported }; |
| 326 | } |