{*******************************************************} { } { Tocsg.WscApi } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit Tocsg.WscApi; interface uses WinApi.Windows, Vcl.OleServer, System.Generics.Collections; const strIID_IWscProduct = '{8C38232E-3A45-4A27-92B0-1A16A975F669}'; strIID_IWSCProductList = '{722A338C-6E8E-4E72-AC27-1417FB0C81C2}'; strCLASS_WSCProductList = '{17072F7B-9ABE-4A74-A261-1EB76B55107A}'; IID_IWscProduct: TGUID = strIID_IWscProduct; IID_IWSCProductList: TGUID = strIID_IWSCProductList; CLASS_WSCProductList: TGUID = strCLASS_WSCProductList; WSC_SECURITY_PRODUCT_STATE_ON = 0; WSC_SECURITY_PRODUCT_STATE_OFF = 1; WSC_SECURITY_PRODUCT_STATE_SNOOZED = 2; WSC_SECURITY_PRODUCT_STATE_EXPIRED = 3; WSC_SECURITY_PRODUCT_OUT_OF_DATE = 0; WSC_SECURITY_PRODUCT_UP_TO_DATE = 1; WSC_SECURITY_PROVIDER_NONE = 0; WSC_SECURITY_PROVIDER_FIREWALL = $1; WSC_SECURITY_PROVIDER_AUTOUPDATE_SETTINGS = $2; WSC_SECURITY_PROVIDER_ANTIVIRUS = $4; WSC_SECURITY_PROVIDER_ANTISPYWARE = $8; WSC_SECURITY_PROVIDER_INTERNET_SETTINGS = $10; WSC_SECURITY_PROVIDER_USER_ACCOUNT_CONTROL = $20; WSC_SECURITY_PROVIDER_SERVICE = $40; WSC_SECURITY_PROVIDER_ALL = WSC_SECURITY_PROVIDER_FIREWALL or WSC_SECURITY_PROVIDER_AUTOUPDATE_SETTINGS or WSC_SECURITY_PROVIDER_ANTIVIRUS or WSC_SECURITY_PROVIDER_ANTISPYWARE or WSC_SECURITY_PROVIDER_INTERNET_SETTINGS or WSC_SECURITY_PROVIDER_USER_ACCOUNT_CONTROL or WSC_SECURITY_PROVIDER_SERVICE; type IWscProduct = interface(IDispatch) [strIID_IWscProduct] function get_ProductName(var sVal: PChar): Integer; stdcall; function get_ProductState(var nVal: Integer): Integer; stdcall; function get_SignatureStatus(var nVal: Integer): Integer; stdcall; function get_RemediationPath(var sVal: PChar): Integer; stdcall; function get_ProductStateTimestamp(var sVal: PChar): Integer; stdcall; function get_ProductGuid(var sVal: PChar): Integer; stdcall; function get_ProductIsDefault(var bVal: Boolean): Integer; stdcall; end; IWSCProductList = interface(IDispatch) [strIID_IWSCProductList] function Initialize(dwProvider: DWORD): Integer; stdcall; function get_Count(var nVal: Integer): Integer; stdcall; function get_Item(nIdx: Integer; var pVal: IWscProduct): Integer; stdcall; end; PWSCProductEnt = ^TWSCProductEnt; TWSCProductEnt = record sName, sGuid, sStateTimestamp, sRemediationPath: String; bIsDefault: Boolean; nState, nStatus: Integer; end; TWSCProductEntList = class(TList) protected nProvider_: Integer; procedure Notify(const Item: PWSCProductEnt; Action: TCollectionNotification); override; public property Provider: Integer read nProvider_; end; function GetWscSecurityInfo(nProvider: Integer; aList: TWSCProductEntList): Integer; implementation uses Tocsg.Exception, Winapi.ActiveX, System.SysUtils; { TWSCProductEntList } procedure TWSCProductEntList.Notify(const Item: PWSCProductEnt; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; function GetWscSecurityInfo(nProvider: Integer; aList: TWSCProductEntList): Integer; var ProductList: IWSCProductList; Product: IWscProduct; nProductCnt: Integer; i, nVal: Integer; sData: PChar; bVal: Boolean; pEnt: PWSCProductEnt; PdEnt: TWSCProductEnt; begin Result := 0; aList.Clear; aList.nProvider_ := nProvider; try ProductList := nil; if FAILED(CoCreateInstance(CLASS_WSCProductList, nil, CLSCTX_INPROC_SERVER, IID_IWSCProductList, ProductList)) then exit; if ProductList = nil then exit; if FAILED(ProductList.Initialize(nProvider)) then exit; if FAILED(ProductList.get_Count(nProductCnt)) then exit; // 구버전 윈도우 10에서 SysFreeString() 하면 프로그램이 크러쉬 된다.... 22_0620 17:16:55 kku for i := 0 to nProductCnt - 1 do begin ZeroMemory(@PdEnt, SizeOf(PdEnt)); if not FAILED(ProductList.get_Item(i, Product)) then begin if not FAILED(Product.get_ProductName(sData)) then begin PdEnt.sName := String(sData); // SysFreeString(sData); end else continue; if not FAILED(Product.get_ProductGuid(sData)) then begin PdEnt.sGuid := String(sData); // SysFreeString(sData); end; if not FAILED(Product.get_ProductStateTimestamp(sData)) then begin PdEnt.sStateTimestamp := String(sData); // SysFreeString(sData); end; if not FAILED(Product.get_RemediationPath(sData)) then begin PdEnt.sRemediationPath := String(sData); // SysFreeString(sData); end; if not FAILED(Product.get_ProductIsDefault(bVal)) then PdEnt.bIsDefault := bVal; if not FAILED(Product.get_ProductState(nVal)) then PdEnt.nState := nVal; if not FAILED(Product.get_SignatureStatus(nVal)) then PdEnt.nStatus := nVal; New(pEnt); pEnt^ := PdEnt; aList.Add(pEnt); Finalize(PdEnt); Inc(Result); end; end; except on E: Exception do ETgException.TraceException(E, 'Fail .. GetWscSecurityInfo()'); end; end; end.