win: fix incomplete VSCEIP, location scripts
This commit improves the validation logic in parser, corrects Windows collection files to adhere to expected structure. This validation helps catch errors that previously led to incomplete generated code in scripts for disabling VSCEIP and location settings. Changes: - Add type validation for function call structures in the parser/compiler. This helps prevent runtime errors by ensuring that only correctly structured data is processed. - Fix scripts in the Windows collection that previoulsy had incomplete `code` or `revertCode` values. These corrections ensure that the scripts function as intended. - Refactor related logic within the compiler/parser to improve testability and maintainability.
This commit is contained in:
@@ -18,7 +18,10 @@ export const createCollectionUtilities: CategoryCollectionSpecificUtilitiesFacto
|
||||
) => {
|
||||
const syntax = syntaxFactory.create(scripting.language);
|
||||
return {
|
||||
compiler: new ScriptCompiler(functionsData ?? [], syntax),
|
||||
compiler: new ScriptCompiler({
|
||||
functions: functionsData ?? [],
|
||||
syntax,
|
||||
}),
|
||||
syntax,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,27 +1,50 @@
|
||||
import type { FunctionCallData, FunctionCallsData, FunctionCallParametersData } from '@/application/collections/';
|
||||
import { isArray, isPlainObject } from '@/TypeHelpers';
|
||||
import { createTypeValidator, type TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
||||
import { FunctionCallArgumentCollection } from './Argument/FunctionCallArgumentCollection';
|
||||
import { FunctionCallArgument } from './Argument/FunctionCallArgument';
|
||||
import { ParsedFunctionCall } from './ParsedFunctionCall';
|
||||
import type { FunctionCall } from './FunctionCall';
|
||||
|
||||
export function parseFunctionCalls(calls: FunctionCallsData): FunctionCall[] {
|
||||
const sequence = getCallSequence(calls);
|
||||
return sequence.map((call) => parseFunctionCall(call));
|
||||
export interface FunctionCallsParser {
|
||||
(
|
||||
calls: FunctionCallsData,
|
||||
validator?: TypeValidator,
|
||||
): FunctionCall[];
|
||||
}
|
||||
|
||||
function getCallSequence(calls: FunctionCallsData): FunctionCallData[] {
|
||||
export const parseFunctionCalls: FunctionCallsParser = (
|
||||
calls,
|
||||
validator = createTypeValidator(),
|
||||
) => {
|
||||
const sequence = getCallSequence(calls, validator);
|
||||
return sequence.map((call) => parseFunctionCall(call, validator));
|
||||
};
|
||||
|
||||
function getCallSequence(calls: FunctionCallsData, validator: TypeValidator): FunctionCallData[] {
|
||||
if (!isPlainObject(calls) && !isArray(calls)) {
|
||||
throw new Error('called function(s) must be an object or array');
|
||||
}
|
||||
if (isArray(calls)) {
|
||||
validator.assertNonEmptyCollection({
|
||||
value: calls,
|
||||
valueName: 'function call sequence',
|
||||
});
|
||||
return calls as FunctionCallData[];
|
||||
}
|
||||
const singleCall = calls as FunctionCallData;
|
||||
return [singleCall];
|
||||
}
|
||||
|
||||
function parseFunctionCall(call: FunctionCallData): FunctionCall {
|
||||
function parseFunctionCall(
|
||||
call: FunctionCallData,
|
||||
validator: TypeValidator,
|
||||
): FunctionCall {
|
||||
validator.assertObject({
|
||||
value: call,
|
||||
valueName: 'function call',
|
||||
allowedProperties: ['function', 'parameters'],
|
||||
});
|
||||
const callArgs = parseArgs(call.parameters);
|
||||
return new ParsedFunctionCall(call.function, callArgs);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import type { FunctionData } from '@/application/collections/';
|
||||
import type { ILanguageSyntax } from '@/application/Parser/Executable/Script/Validation/Syntax/ILanguageSyntax';
|
||||
import type { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||
|
||||
export interface ISharedFunctionsParser {
|
||||
parseFunctions(
|
||||
functions: readonly FunctionData[],
|
||||
syntax: ILanguageSyntax,
|
||||
): ISharedFunctionCollection;
|
||||
}
|
||||
@@ -12,50 +12,52 @@ import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/
|
||||
import { createFunctionWithInlineCode, createCallerFunction } from './SharedFunction';
|
||||
import { SharedFunctionCollection } from './SharedFunctionCollection';
|
||||
import { FunctionParameter } from './Parameter/FunctionParameter';
|
||||
import { parseFunctionCalls } from './Call/FunctionCallParser';
|
||||
import { parseFunctionCalls, type FunctionCallsParser } from './Call/FunctionCallsParser';
|
||||
import { createFunctionParameterCollection, type FunctionParameterCollectionFactory } from './Parameter/FunctionParameterCollectionFactory';
|
||||
import type { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||
import type { ISharedFunctionsParser } from './ISharedFunctionsParser';
|
||||
import type { IReadOnlyFunctionParameterCollection } from './Parameter/IFunctionParameterCollection';
|
||||
import type { ISharedFunction } from './ISharedFunction';
|
||||
|
||||
const DefaultSharedFunctionsParsingUtilities: SharedFunctionsParsingUtilities = {
|
||||
export interface SharedFunctionsParser {
|
||||
(
|
||||
functions: readonly FunctionData[],
|
||||
syntax: ILanguageSyntax,
|
||||
utilities?: SharedFunctionsParsingUtilities,
|
||||
): ISharedFunctionCollection;
|
||||
}
|
||||
|
||||
export const parseSharedFunctions: SharedFunctionsParser = (
|
||||
functions: readonly FunctionData[],
|
||||
syntax: ILanguageSyntax,
|
||||
utilities = DefaultUtilities,
|
||||
) => {
|
||||
const collection = new SharedFunctionCollection();
|
||||
if (!functions.length) {
|
||||
return collection;
|
||||
}
|
||||
ensureValidFunctions(functions);
|
||||
return functions
|
||||
.map((func) => parseFunction(func, syntax, utilities))
|
||||
.reduce((acc, func) => {
|
||||
acc.addFunction(func);
|
||||
return acc;
|
||||
}, collection);
|
||||
};
|
||||
|
||||
const DefaultUtilities: SharedFunctionsParsingUtilities = {
|
||||
wrapError: wrapErrorWithAdditionalContext,
|
||||
createParameter: (...args) => new FunctionParameter(...args),
|
||||
codeValidator: CodeValidator.instance,
|
||||
createParameterCollection: createFunctionParameterCollection,
|
||||
parseFunctionCalls,
|
||||
};
|
||||
|
||||
export class SharedFunctionsParser implements ISharedFunctionsParser {
|
||||
public static readonly instance: ISharedFunctionsParser = new SharedFunctionsParser();
|
||||
|
||||
constructor(
|
||||
private readonly utilities = DefaultSharedFunctionsParsingUtilities,
|
||||
) { }
|
||||
|
||||
public parseFunctions(
|
||||
functions: readonly FunctionData[],
|
||||
syntax: ILanguageSyntax,
|
||||
): ISharedFunctionCollection {
|
||||
const collection = new SharedFunctionCollection();
|
||||
if (!functions.length) {
|
||||
return collection;
|
||||
}
|
||||
ensureValidFunctions(functions);
|
||||
return functions
|
||||
.map((func) => parseFunction(func, syntax, this.utilities))
|
||||
.reduce((acc, func) => {
|
||||
acc.addFunction(func);
|
||||
return acc;
|
||||
}, collection);
|
||||
}
|
||||
}
|
||||
|
||||
interface SharedFunctionsParsingUtilities {
|
||||
readonly wrapError: ErrorWithContextWrapper;
|
||||
readonly createParameter: FunctionParameterFactory;
|
||||
readonly codeValidator: ICodeValidator;
|
||||
readonly createParameterCollection: FunctionParameterCollectionFactory;
|
||||
readonly parseFunctionCalls: FunctionCallsParser;
|
||||
}
|
||||
|
||||
export type FunctionParameterFactory = (
|
||||
@@ -74,7 +76,7 @@ function parseFunction(
|
||||
return createFunctionWithInlineCode(name, parameters, data.code, data.revertCode);
|
||||
}
|
||||
// Has call
|
||||
const calls = parseFunctionCalls(data.call);
|
||||
const calls = utilities.parseFunctionCalls(data.call);
|
||||
return createCallerFunction(name, parameters, calls);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,28 +6,46 @@ import { NoEmptyLines } from '@/application/Parser/Executable/Script/Validation/
|
||||
import type { ICodeValidator } from '@/application/Parser/Executable/Script/Validation/ICodeValidator';
|
||||
import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
||||
import { createScriptCode, type ScriptCodeFactory } from '@/domain/Executables/Script/Code/ScriptCodeFactory';
|
||||
import { SharedFunctionsParser } from './Function/SharedFunctionsParser';
|
||||
import { FunctionCallSequenceCompiler } from './Function/Call/Compiler/FunctionCallSequenceCompiler';
|
||||
import { parseFunctionCalls } from './Function/Call/FunctionCallParser';
|
||||
import { parseFunctionCalls } from './Function/Call/FunctionCallsParser';
|
||||
import { parseSharedFunctions, type SharedFunctionsParser } from './Function/SharedFunctionsParser';
|
||||
import type { CompiledCode } from './Function/Call/Compiler/CompiledCode';
|
||||
import type { IScriptCompiler } from './IScriptCompiler';
|
||||
import type { ISharedFunctionCollection } from './Function/ISharedFunctionCollection';
|
||||
import type { FunctionCallCompiler } from './Function/Call/Compiler/FunctionCallCompiler';
|
||||
import type { ISharedFunctionsParser } from './Function/ISharedFunctionsParser';
|
||||
|
||||
interface ScriptCompilerUtilities {
|
||||
readonly sharedFunctionsParser: SharedFunctionsParser;
|
||||
readonly callCompiler: FunctionCallCompiler;
|
||||
readonly codeValidator: ICodeValidator;
|
||||
readonly wrapError: ErrorWithContextWrapper;
|
||||
readonly scriptCodeFactory: ScriptCodeFactory;
|
||||
}
|
||||
|
||||
const DefaultUtilities: ScriptCompilerUtilities = {
|
||||
sharedFunctionsParser: parseSharedFunctions,
|
||||
callCompiler: FunctionCallSequenceCompiler.instance,
|
||||
codeValidator: CodeValidator.instance,
|
||||
wrapError: wrapErrorWithAdditionalContext,
|
||||
scriptCodeFactory: createScriptCode,
|
||||
};
|
||||
|
||||
interface CategoryCollectionDataContext {
|
||||
readonly functions: readonly FunctionData[];
|
||||
readonly syntax: ILanguageSyntax;
|
||||
}
|
||||
|
||||
export class ScriptCompiler implements IScriptCompiler {
|
||||
private readonly functions: ISharedFunctionCollection;
|
||||
|
||||
constructor(
|
||||
functions: readonly FunctionData[],
|
||||
syntax: ILanguageSyntax,
|
||||
sharedFunctionsParser: ISharedFunctionsParser = SharedFunctionsParser.instance,
|
||||
private readonly callCompiler: FunctionCallCompiler = FunctionCallSequenceCompiler.instance,
|
||||
private readonly codeValidator: ICodeValidator = CodeValidator.instance,
|
||||
private readonly wrapError: ErrorWithContextWrapper = wrapErrorWithAdditionalContext,
|
||||
private readonly scriptCodeFactory: ScriptCodeFactory = createScriptCode,
|
||||
categoryContext: CategoryCollectionDataContext,
|
||||
private readonly utilities: ScriptCompilerUtilities = DefaultUtilities,
|
||||
) {
|
||||
this.functions = sharedFunctionsParser.parseFunctions(functions, syntax);
|
||||
this.functions = this.utilities.sharedFunctionsParser(
|
||||
categoryContext.functions,
|
||||
categoryContext.syntax,
|
||||
);
|
||||
}
|
||||
|
||||
public canCompile(script: ScriptData): boolean {
|
||||
@@ -40,14 +58,14 @@ export class ScriptCompiler implements IScriptCompiler {
|
||||
throw new Error('Script does include any calls.');
|
||||
}
|
||||
const calls = parseFunctionCalls(script.call);
|
||||
const compiledCode = this.callCompiler.compileFunctionCalls(calls, this.functions);
|
||||
validateCompiledCode(compiledCode, this.codeValidator);
|
||||
return this.scriptCodeFactory(
|
||||
const compiledCode = this.utilities.callCompiler.compileFunctionCalls(calls, this.functions);
|
||||
validateCompiledCode(compiledCode, this.utilities.codeValidator);
|
||||
return this.utilities.scriptCodeFactory(
|
||||
compiledCode.code,
|
||||
compiledCode.revertCode,
|
||||
);
|
||||
} catch (error) {
|
||||
throw this.wrapError(error, `Failed to compile script: ${script.name}`);
|
||||
throw this.utilities.wrapError(error, `Failed to compile script: ${script.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4362,9 +4362,10 @@ actions:
|
||||
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
|
||||
-
|
||||
function: RunInlineCode
|
||||
code: reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}" /v "SensorPermissionState" /d "0" /t REG_DWORD /f
|
||||
revertCode: >- # Default value is `1` since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
|
||||
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}" /v "SensorPermissionState" /d "1" /t REG_DWORD /f
|
||||
parameters:
|
||||
code: reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}" /v "SensorPermissionState" /d "0" /t REG_DWORD /f
|
||||
revertCode: >- # Default value is `1` since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
|
||||
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}" /v "SensorPermissionState" /d "1" /t REG_DWORD /f
|
||||
-
|
||||
name: Disable device sensors
|
||||
recommend: standard
|
||||
@@ -5764,30 +5765,31 @@ actions:
|
||||
-
|
||||
# Using OS keys
|
||||
function: RunInlineCode
|
||||
code: |-
|
||||
if %PROCESSOR_ARCHITECTURE%==x86 ( REM is 32 bit?
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
) else (
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
)
|
||||
revertCode: |-
|
||||
if %PROCESSOR_ARCHITECTURE%==x86 ( REM is 32 bit?
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
) else (
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
)
|
||||
parameters:
|
||||
code: |-
|
||||
if %PROCESSOR_ARCHITECTURE%==x86 ( REM is 32 bit?
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
) else (
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 0 /f
|
||||
)
|
||||
revertCode: |-
|
||||
if %PROCESSOR_ARCHITECTURE%==x86 ( REM is 32 bit?
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
) else (
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\14.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\15.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\16.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\VSCommon\17.0\SQM" /v "OptIn" /t REG_DWORD /d 1 /f
|
||||
)
|
||||
-
|
||||
function: SetRegistryValue
|
||||
parameters:
|
||||
|
||||
Reference in New Issue
Block a user