//**************************************************** // IE-Guid * // For Delphi * // Freeware Component * // by * // * // Per Lindsų Larsen * // http://www.euromind.com/iedelphi * // * // Contributor: * // Eran Bodankin (bsalsa) - D2005 update and bug fix * // bsalsa@gmail.com * // * // Documentation and updated versions: * // http://www.bsalsa.com * //**************************************************** {*******************************************************************************} {LICENSE: THIS SOFTWARE IS PROVIDED TO YOU "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED INCLUDING BUT NOT LIMITED TO THE APPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. YOU ASSUME THE ENTIRE RISK AS TO THE ACCURACY AND THE USE OF THE SOFTWARE AND ALL OTHER RISK ARISING OUT OF THE USE OR PERFORMANCE OF THIS SOFTWARE AND DocUMENTATION. BSALSA PRODUCTIONS DOES NOT WARRANT THAT THE SOFTWARE IS ERROR-FREE OR WILL OPERATE WITHOUT INTERRUPTION. THE SOFTWARE IS NOT DESIGNED, INTENDED OR LICENSED FOR USE IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE CONTROLS, INCLUDING WITHOUT LIMITATION, THE DESIGN, CONSTRUCTION, MAINTENANCE OR OPERATION OF NUCLEAR FACILITIES, AIRCRAFT NAVIGATION OR COMMUNICATION SystemS, AIR TRAFFIC CONTROL, AND LIFE SUPPORT OR WEAPONS SystemS. BSALSA PRODUCTIONS SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR SUCH PURPOSE. You may use, change or modify the component under 3 conditions: 1. In your website, add a Link to "http://www.bsalsa.com" 2. In your application, add credits to "Embedded Web Browser" 3. Mail me (bsalsa@gmail.com) any code change in the unit for the benefit of the other users. 4. You may consider donation in our web site! {*******************************************************************************} //$Id: IEGuid.pas,v 1.2 2006/11/15 21:01:42 sergev Exp $ unit IEGuid; interface uses Mshtml_Ewb, Clipbrd, Comobj, Activex, Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs; type TIEGuid = class(TObject) private function LoadList(Fname: string): Integer; public Names: TStringlist; Guids: TStringlist; function NameFromGuid(Guid: TGUID): string; function NameFromGuidStr(GuidStr: string): string; function CopyToClipboard(GuidName: string): HResult; function GetInterfaces(Unk: IUnknown; const S: TStrings): HResult; function GetServices(Unk: IUnknown; rsid: string; const S: TStrings): HResult; function GetConnectionPoints(Unk: IUnknown; const S: TStrings; ShowIDispatch: Boolean): HResult; procedure GetPropertyList(const Obj: IDispatch; const S: TStrings); function GetDispatchFromName(const Disp: IDispatch; const PropertyName: WideString): OleVariant; function GetInterfacesEx(Unk: IUnknown; const S: TStrings; ShowIUnknown, ShowIDispatch, ShowIDispatchEx, ShowDispinterfaces: Boolean): HResult; destructor Destroy; override; constructor Create(const fname: string); end; function CreateIEGuid(HeadersDir, GuidFile: string): Integer; function CreateIEList(Guidfile, IEList: string): Integer; implementation { TIEGuid } function TIEGuid.GetDispatchFromName(const Disp: IDispatch; const PropertyName: WideString): OleVariant; var PName: PWideChar; DispID: Integer; ExcepInfo: TExcepInfo; DispParams: TDispParams; Status: HResult; begin Result := disp <> nil; if Result then begin PName := PWideChar(PropertyName); if PName <> 'parentDocument' then begin if PropertyName = '' then Result := DISPID_UNKNOWN else Disp.GetIDsOfNames(GUID_NULL, @PName, 1, GetThreadLocale, @DispID); FillChar(DispParams, SizeOf(DispParams), 0); Status := Disp.Invoke(DispID, GUID_NULL, 0, DISPATCH_PROPERTYGET, DispParams, @Result, @ExcepInfo, nil); if Status <> S_OK then DispatchInvokeError(Status, ExcepInfo); end; end; end; procedure TIEGuid.GetPropertyList(const Obj: IDispatch; const S: TStrings); var i: Integer; TI: ITypeInfo; TA: PTypeAttr; FD: PFuncDesc; aName: WideString; vt: Integer; begin OleCheck(Obj.GetTypeInfo(0, 0, TI)); OleCheck(TI.GetTypeAttr(TA)); for i := 0 to TA.cFuncs - 1 do begin OleCheck(TI.GetFuncDesc(i, FD)); if (FD.invkind = INVOKE_PROPERTYGET) then begin TI.GetDocumentation(FD.memid, @aName, nil, nil, nil); vt := fd.elemdescFunc.tdesc.vt; if (vt = VT_DISPATCH) or (vt = VT_PTR) then S.add(aName); end; TI.ReleaseFuncDesc(FD); end; TI.ReleaseTypeAttr(TA); end; // Create list of .h-files in Headers directory function GetFileList(const Path: string; var FileList: TStringList): Boolean; var SearchRec: TSearchRec; ff: Integer; begin GetFileList := False; ff := FindFirst(Path + '\*.*', faAnyFile, SearchRec); if ff = 0 then begin GetFileList := True; if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then begin if (SearchRec.Attr and $10 <> $10) then if Pos('.h', SearchRec.Name) > 0 then FileList.Add(Path + '\' + SearchRec.Name); end; repeat ff := FindNext(SearchRec); if ff = 0 then begin if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then begin if (SearchRec.Attr and $10 <> $10) then FileList.Add(Path + '\' + SearchRec.Name); end; end; until ff <> 0; end; end; function FindStr(S: string; I: Integer; Token: string): string; var counter, t, t1, t2: Shortint; begin S := Token + S + Token; counter := 1; t := 0; while t < I do begin if Copy(S, counter, 1) = Token then Inc(t); inc(counter); end; t1 := counter; if Copy(S, counter, 1) = token then Result := '' else begin Inc(Counter); while Copy(S, counter, 1) <> Token do Inc(counter); t2 := counter - t1; Result := copy(S, t1, t2); end; end; function ExtractDefineGuid(GuidStr: string): string; var o, Temp, s, G: string; X: Integer; begin GuidStr := Trim(StringReplace(GuidStr, ' ', '', [rfReplaceAll, rfIgnoreCase])); Guidstr := Stringreplace(GuidStr, Chr($09), '', [rfReplaceAll]); g := Copy(GuidStr, 13, Pos(',', GuidStr) - 13); S := Uppercase(Copy(GuidStr, Pos('0x', GuidStr), 255)); S := Trim(StringReplace(S, ');', '', [rfReplaceAll, rfIgnoreCase])); S := StringReplace(S, '0x', '', [rfReplaceAll, rfIgnoreCase]); S := StringReplace(S, 'L', '', [rfReplaceAll, rfIgnoreCase]); X := 1; o := ''; repeat Temp := Findstr(S, X, ','); if (Length(Temp) = 1) or (Length(temp) = 3) or (Length(temp) = 7) then o := o + '0' + temp else o := o + temp; Inc(x); until Temp = ''; s := o; S := StringReplace(S, ',', '', [rfReplaceAll, rfIgnoreCase]); s := Trim('{' + Copy(s, 1, 8) + '-' + Copy(S, 9, 4) + '-' + Copy(s, 13, 4) + '-' + Copy(s, 17, 4) + '-' + Copy(s, 21, 12) + '}'); if (Length(s) <> 38) or (Pos('name', g) > 0) or (Pos('DEFINE_', S) > 0) then Result := '' else Result := g + '=' + S; end; //Extract GUIDS Registry: HKEY_CLASSES_ROOT\Interfaces procedure GetGuidsFromRegistry(Guids: TStringList); var dwIndex: DWORD; cb: Integer; szIID: array[0..80] of char; szvalue: array[0..256] of char; hk: HKEY; Str: string; begin cb := SizeOf(szValue); RegOpenKey(HKEY_CLASSES_ROOT, 'Interface', hk); dwIndex := 0; while RegEnumKey(hk, dwindex, szIID, SizeOf(szIID)) = ERROR_SUCCESS do begin szValue := ''; RegQueryValue(hk, szIID, szvalue, cb); if (szValue <> '') then begin str := string(szvalue) + '=' + szIID; if Guids.IndexOf(str) = -1 then Guids.Add(str); end; inc(dwIndex); end; end; function CreateIEGuid(HeadersDir, GuidFile: string): Integer; var files, lines, Guids: TStringlist; S, n, g: string; X, Fcounter, Lcounter: Integer; begin Files := TStringlist.Create; Lines := TStringlist.Create; Guids := TStringlist.Create; Guids.Sorted := True; GetFileList(HeadersDir, Files); for FCounter := 0 to Files.Count - 1 do begin Lines.LoadFromFile(Files[FCounter]); for LCounter := 0 to Lines.Count - 1 do begin if Pos('MIDL_INTERFACE("', Lines[LCounter]) > 0 then //(1) Extract GUIDS from MIDL_INTERFACE("... lines in header files begin g := UpperCase('{' + Copy(Trim(Lines[LCounter]), 17, 36) + '}'); n := Copy(Trim(Lines[LCounter + 1]), 1, 255); if n = '' then N := Copy(Trim(Lines[LCounter + 2]), 1, 255); n := Copy(n, 1, Pos(' ', n) - 1); S := n + '=' + g; if (Guids.IndexOf(S) < 0) and (n <> '') then Guids.Add(S); end else if Pos('DEFINE_GUID(', Trim(Lines[LCounter])) = 1 then begin //(2) Extract GUIDS from DEFINE_GUID("... lines in header files n := Lines[LCounter]; x := LCounter; while (pos(');', n) = 0) and (x < lines.count) do begin Inc(x); n := n + Lines[x]; end; S := ExtractDefineGuid(n); if s <> '' then if Guids.IndexOf(s) < 0 then Guids.Add(s); end else if (pos('__declspec(uuid("', Lines[LCounter]) > 0) and (Pos(';', Lines[LCounter]) > 0) then begin // (3) Extract GUIDS from __declspec(uuid("... lines in header files g := Copy(Lines[LCOunter], Pos('declspec(uuid("', Lines[LCounter]) + 15, 255); n := '{' + Copy(G, 1, Pos('"', G) - 1) + '}'; g := Copy(g, Pos(' ', g), 255); g := Trim(StringReplace(g, ';', '', [rfReplaceAll])); S := g + '=' + Uppercase(n); if Guids.IndexOf(S) < 0 then Guids.Add(S); end; end; end; Files.Free; Lines.Free; GetGuidsFromRegistry(Guids); Result := Guids.Count; Guids.SaveToFile(GuidFile); Guids.Free; end; function CreateIEList(GuidFile, Ielist: string): Integer; var S: string; i: Integer; Temp: TStringlist; Guids: TStringlist; begin Temp := TStringlist.Create; Guids := TStringlist.Create; Guids.LoadFromFile(GuidFile); for I := 0 to Guids.Count - 1 do begin s := Uppercase(Guids[i]); if (pos('DISP', S) = 1) or (pos('HTML', S) = 1) or (pos('SID_', S) = 1) or (pos('DWEB', S) = 1) or (pos('CGID', S) = 1) or ((pos('I', S) = 1) and (pos('IID_', S) = 0)) then Temp.Add(Guids[i]) else if (pos('IID_I', S) = 1) and (Guids.IndexOf(Copy(S, 5, 255)) = -1) then Temp.add(copy(guids[i], 5, 255)); end; if Temp.IndexOf('CGID_MSHTML={DE4BA900-59CA-11CF-9592-444553540000}') = -1 then Temp.Add('CGID_MSHTML={DE4BA900-59CA-11CF-9592-444553540000}'); Temp.SaveToFile(IEList); Result := Temp.Count; Temp.Free; Guids.Free; end; function TIEGuid.LoadList(Fname: string): Integer; var X: Integer; Temp: TStringlist; begin Guids.Clear; Names.Clear; Temp := TStringlist.Create; try Temp.LoadFromFile(FName); for x := 0 to Temp.Count - 1 do begin Guids.Add(Copy(Temp[x], Pos('=', Temp[x]) + 1, 255)); Names.Add(Copy(Temp[x], 1, Pos('=', Temp[x]) - 1)); end; Result := Guids.Count; finally Temp.Free; end; end; destructor TIEGuid.Destroy; begin if Names <> nil then Names.Free; if Guids <> nil then Guids.Free; inherited; end; constructor TIEGuid.Create(const fname: string); begin inherited Create; if FileExists(fname) then begin Names := TStringlist.Create; Guids := TStringlist.Create; loadlist(Fname); end; end; function TIEGuid.NameFromGuidStr(GuidStr: string): string; var i: Integer; begin i := Guids.IndexOf(GuidStr); if i > -1 then Result := Names[i] else Result := GuidStr; end; function TIEGuid.CopyToClipboard(GuidName: string): HResult; var // s: string; x: Integer; begin x := Names.IndexOf(guidname); if x > -1 then begin ClipBoard.SetTextBuf(Pchar(Names[x] + ' : TGUID = ''' + Guids[x] + ''';')); Result := S_OK; end else Result := S_FALSE; end; function TIEGuid.NameFromGuid(Guid: TGUID): string; var s: string; i: Integer; begin s := GuidToString(Guid); i := Guids.IndexOf(s); if i > -1 then Result := Names[i] else Result := S; end; function TIEGuid.GetServices(Unk: IUnknown; rsid: string; const S: TStrings): HResult; var Isp: IServiceprovider; x: Integer; i: IUnknown; G, N: string; begin Result := S_FALSE; x := Names.IndexOf(rsid); if ((rsid <> '') and (x = -1)) or not Assigned(unk) then Exit; if x > -1 then begin G := Guids[x]; n := Names[x]; end; if Succeeded(Unk.QueryInterface(IServiceprovider, isp)) then for x := 0 to Guids.Count - 1 do begin if rsid = '' then begin G := Guids[x]; N := Names[x]; end; try if isp.QueryService(StringtoGuid(G), StringtoGuid(Guids[x]), i) = S_OK then S.Add(Names[x]); except ShowMessage('Invalid GUID: ' + Names[x]); end; Result := S_OK; end; end; function TIEGuid.GetInterfaces(Unk: IUnknown; const S: TStrings): HResult; var i: IUnknown; x: Integer; begin Result := S_OK; if not Assigned(unk) then begin Result := S_FALSE; Exit; end else for x := 0 to Guids.count - 1 do try if Succeeded(unk.QueryInterface(StringToGuid(Guids[x]), i)) then S.Add(Names[x]); except ShowMessage('Invalid GUID: ' + Names[x]); end; end; function TIEGuid.GetInterfacesEx(Unk: IUnknown; const S: TStrings; ShowIUnknown, ShowIDispatch, ShowIDispatchEx, ShowDispinterfaces: Boolean): HResult; var I: IUnknown; // Show: Boolean; x: Integer; begin Result := S_OK; if not Assigned(unk) then begin Result := S_FALSE; Exit; end else for x := 0 to Guids.count - 1 do try if Succeeded(unk.QueryInterface(StringToGuid(Guids[x]), i)) then if ((not ShowIdispatch and (UpperCase(Names[x]) = 'IDISPATCH')) or (not ShowIdispatchEx and (UpperCase(Names[x]) = 'IDISPATCHEX')) or (not ShowIUnknown and (UpperCase(Names[x]) = 'IUNKNOWN'))) or (not ShowDispInterfaces and (Pos('DISP', UpperCase(Names[x])) = 1)) then else S.Add(Names[x]); except ShowMessage('Invalid GUID for: ' + Names[x]); end; end; function TIEGuid.GetConnectionPoints(Unk: IUnknown; const S: TStrings; ShowIDispatch: Boolean): HResult; var IID: TGuid; CPC: IConnectionPointContainer; iecp: IEnumConnectionPoints; cp: IConnectionPoint; Fetched: Integer; begin Result := S_FALSE; if Assigned(unk) then begin if Succeeded(Unk.QueryInterface(IConnectionPointContainer, CPC)) then begin CPC.EnumConnectionPoints(iecp); iecp.Next(1, cp, @Fetched); repeat cp.GetConnectionInterface(iid); if (Uppercase(NameFromGuid(IID)) = 'IDISPATCH') and not ShowIdispatch then else S.Add(NameFromGuid(IID)); iecp.Next(1, cp, @Fetched); until fetched = 0; Result := S_OK end; end; end; end.