Solved

URL Monikers

Posted on 1998-06-03
17
741 Views
Last Modified: 2012-05-04
Has anyone got a clue how to write an URL Moniker?
I am trying to use the Intenet Explorer to display HTML files that I pull out of a OLE2 structured storage file. Microsoft does s.th very similar in their Infoviewer 5 (comes with the MSDN): If you have the MSDN installed an type something like
mk:@ivt:activex/start.htm
IE will display the file start.htm from the knowledgebase file activex.ivt.
I already have found out that "ivt" in the above URL is registered in the registry and seems to be an URL Moniker. And from the MSDN I found out that I need to write an URL Moniker server.
Before I waste my time re-inventing the wheel: has somebody out there already written one?
Best regards,
Freter
0
Comment
Question by:freter
  • 8
  • 6
  • 2
  • +1
17 Comments
 
LVL 5

Expert Comment

by:ronit051397
ID: 1350138
0
 
LVL 2

Author Comment

by:freter
ID: 1350139
Hm...
I have seen that before, but it doesn't help me.
I need a DLL that can be invoke by Intenet Explorer, just like the ivtmon.dll that is referenced by the string "ivt" in the URL depicted in my question.
0
 
LVL 5

Expert Comment

by:ronit051397
ID: 1350140
Sorry, I can't help you with this issue.
0
 
LVL 4

Expert Comment

by:d003303
ID: 1350141
Yep, did that one some time ago. It was a pain in the ass to get all the information, because it is only well documented how to *use* monikers, but not how to *write* them.
I built a sample moniker that simply displays HTML files from a file system or an error message if the file was not found. E.g. you set the moniker root to
c:\hello
and type in IE
mk:@slashmoniker:/my/baby.html
it would load c:\hello\my\baby.html
Sure you could dispatch any path to anywhere.
You'll get the moniker code for 300 points, it took me about 5 weeks to figure all the details out.

Slash/d003303
0
 
LVL 2

Author Comment

by:freter
ID: 1350142
Slash/d003303:
One question before I increase the points for you:
Is your moniker able to provide the embedded images of the html page out to explorer?

Freter

0
 
LVL 4

Expert Comment

by:d003303
ID: 1350143
Yo,
all embedded objects (images, plug-in codbases, etc.) that have a relative path are combined to a full qualified path by IE before they are requested. E.g. if <IMG SRC="/images/help.gif"> is part of a page provided by my moniker, IE would create the full referenced path mk:@slashmoniker:/images/help.gif.
Because IE builds full referenced URLs compilant to RFC 2068, you can also prefix the moniker root like M$ does. The "mk:@slashmoniker:" identifies the protocol (equi to http:), then comes the "//(server)" part, then a directory/file path (you may omit the server part). So if the page location of the above example would be mk:@slashmoniker://MyDatabase/about.html, IE would refer the picture path to mk:@slashmoniker://MyDatabase/images/help.gif.
This gives you flexibility on interpretation of the URL and organization of your database archive. E.g. you could also provide mk:@slashmoniker:MyServer//MyDatabase/about.html as a page location, the image would be in mk:@slashmoniker:MyServer//MyDatabase/images/help.gif. Or mk:@slashmoniker:MyDomain:MyServer//MyDatabase/about.html, etc.
You can do anything you like and easily run a website fromout a database.
Hope this answers your question.

Slash/d003303
0
 
LVL 2

Author Comment

by:freter
ID: 1350144
Slash:
Ok. I'll increase the points.

Freter
0
 
LVL 4

Accepted Solution

by:
d003303 earned 300 total points
ID: 1350145
OK, here we go. This moniker class does a simple parsing of the URL in TMyCustomMoniker.IParseDisplayNameParseDisplayName, transfers the requested file in TMyCustomMoniker.BindToStorage. I left in the debug stuff for tracing the monikers state.
Here's the unit and project, below are the registry keys to set.

// BOC //
unit _MyMoniker;

interface

uses
  Windows, Classes, ComObj, ActiveX;

const
   CLSID_MyCustomMoniker: TGUID = (
    D1:$556F12A1; D2:$DE94; D3:$11D1; D4:($B4, $EA, $00, $00, $E8, $2D, $8A, $65));
   Str_CLSID_MyCustomMoniker = '{556F12A1-DE94-11D1-B4EA-0000E82D8A65}';

   CLSID_NULL: TGUID = (D1:0; D2:0; D3:0; D4:(0, 0, 0, 0, 0, 0, 0, 0));

const
  IsDebug = false;

  OutStr = '<HTML>An error occured while parsing the URL<BR><B>%s</B><BR>Request URL was %s<BR></HTML>';

  FileSystemBase = 'c:';

type

  TMyCustomMoniker = class(TComObject, IParseDisplayName, IMoniker)
  private
    FOutStr,
    FErrorStr,
    FFileName,
    FRequestURL : string;
    FOLEOutStr  : POLEStr;
    FHash       : Longint;
  protected
    // IUnknown interface
    function ObjAddRef: Integer; override; stdcall;
    function ObjQueryInterface(const IID: TGUID; out Obj): Integer; override; stdcall;
    function ObjRelease: Integer; override; stdcall;
    // IParseDisplayName interface
    function IParseDisplayName.ParseDisplayName = IParseDisplayNameParseDisplayName;
    function IParseDisplayNameParseDisplayName(const bc: IBindCtx; pszDisplayName: POleStr;
      out chEaten: Longint; out mkOut: IMoniker): HResult; stdcall;
    // IPersist interface
    function GetClassID(out classID: TCLSID): HResult; stdcall;
    // IPersistStream interface
    function IsDirty: HResult; stdcall;
    function Load(const stm: IStream): HResult; stdcall;
    function Save(const stm: IStream; fClearDirty: BOOL): HResult; stdcall;
    function GetSizeMax(out cbSize: Largeint): HResult; stdcall;
    // IMoniker interface
    function BindToObject(const bc: IBindCtx; const mkToLeft: IMoniker;
      const iidResult: TIID; out vResult): HResult; stdcall;
    function BindToStorage(const bc: IBindCtx; const mkToLeft: IMoniker;
      const iid: TIID; out vObj): HResult; stdcall;
    function Reduce(const bc: IBindCtx; dwReduceHowFar: Longint;
      mkToLeft: PIMoniker; out mkReduced: IMoniker): HResult; stdcall;
    function ComposeWith(const mkRight: IMoniker; fOnlyIfNotGeneric: BOOL;
      out mkComposite: IMoniker): HResult; stdcall;
    function Enum(fForward: BOOL; out enumMoniker: IEnumMoniker): HResult;
      stdcall;
    function IsEqual(const mkOtherMoniker: IMoniker): HResult; stdcall;
    function Hash(out dwHash: Longint): HResult; stdcall;
    function IsRunning(const bc: IBindCtx; const mkToLeft: IMoniker;
      const mkNewlyRunning: IMoniker): HResult; stdcall;
    function GetTimeOfLastChange(const bc: IBindCtx; const mkToLeft: IMoniker;
      out filetime: TFileTime): HResult; stdcall;
    function Inverse(out mk: IMoniker): HResult; stdcall;
    function CommonPrefixWith(const mkOther: IMoniker;
      out mkPrefix: IMoniker): HResult; stdcall;
    function RelativePathTo(const mkOther: IMoniker;
      out mkRelPath: IMoniker): HResult; stdcall;
    function GetDisplayName(const bc: IBindCtx; const mkToLeft: IMoniker;
      out pszDisplayName: POleStr): HResult; stdcall;
    function ParseDisplayName(const bc: IBindCtx; const mkToLeft: IMoniker;
      pszDisplayName: POleStr; out chEaten: Longint;
      out mkOut: IMoniker): HResult; stdcall;
    function IsSystemMoniker(out dwMksys: Longint): HResult; stdcall;
  end;

  TMyStream = class(TComObject, IStream)
  private
    FTheStream  : TMemoryStream;
    FStatStg    : TStatStg;
    Fmtime,
    Fctime,
    Fatime      : TFileTime;
  protected
    function Read(pv: Pointer; cb: Longint; pcbRead: PLongint): HResult;
      stdcall;
    function Write(pv: Pointer; cb: Longint; pcbWritten: PLongint): HResult;
      stdcall;
    function Seek(dlibMove: Largeint; dwOrigin: Longint;
      out libNewPosition: Largeint): HResult; stdcall;
    function SetSize(libNewSize: Largeint): HResult; stdcall;
    function CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint;
      out cbWritten: Largeint): HResult; stdcall;
    function Commit(grfCommitFlags: Longint): HResult; stdcall;
    function Revert: HResult; stdcall;
    function LockRegion(libOffset: Largeint; cb: Largeint;
      dwLockType: Longint): HResult; stdcall;
    function UnlockRegion(libOffset: Largeint; cb: Largeint;
      dwLockType: Longint): HResult; stdcall;
    function Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult;
      stdcall;
    function Clone(out stm: IStream): HResult; stdcall;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

uses ComServ, SysUtils;

const
  DebugFile = 'c:\debug.txt';

var
  F : Text;

procedure WriteDebug(S : string);
begin
  if IsDebug then
   begin
     AssignFile(F, DebugFile);
     Append(F);
     writeln(F, FormatDateTime('dddd, mmmm d, yyyy', Date)
             +  FormatDateTime(' hh:mm:ss', Time) + ': ' + S);
     CloseFile(F);
   end;  
end;

////////////////////////////////////////////////////////////////////////////////

// IUnknown interface
function TMyCustomMoniker.ObjAddRef: Integer;
begin
  Result := inherited ObjAddRef;
  writedebug(Format('ObjAddRef Result %d', [Result]));
end;

function TMyCustomMoniker.ObjQueryInterface(const IID: TGUID; out Obj): Integer;
var StrBuf : POleStr;
begin
  StringFromCLSID(IID, StrBuf);
  writedebug(Format('ObjQueryInterface IID %s', [StrBuf]));
  Result := inherited ObjQueryInterface(IID, Obj);
end;

function TMyCustomMoniker.ObjRelease: Integer;
begin
  Result := inherited ObjRelease;
  writedebug(Format('ObjRelease Result %d', [Result]));
end;

// IParseDisplayName interface
function TMyCustomMoniker.IParseDisplayNameParseDisplayName(const bc: IBindCtx; pszDisplayName: POleStr;
                            out chEaten: Longint; out mkOut: IMoniker): HResult;
var Index : Integer;
begin
  writedebug(Format('IParseDisplayNameParseDisplayName %s', [pszDisplayName]));
  bc.RegisterObjectBound(Self);
  mkOut := Self;
  FErrorStr := '';
  FFileName := '';
  FRequestURL := WideCharToString(pszDisplayName);
  chEaten := Length(FRequestURL) * 2;
  // interpretation
  Index := Pos('/', FRequestURL);
  if Index <> 0
   then FFileName := FileSystemBase + Copy(FRequestURL, Index, Length(FRequestURL) - Index + 1)
   else FErrorStr := 'Invalid request';
  Result := S_OK;
end;

// IPersist interface
function TMyCustomMoniker.GetClassID(out classID: TCLSID): HResult;
begin
  writedebug('GetClassID');
  classID := CLSID_MyCustomMoniker;
  Result := S_OK;
end;

// IPersistStream interface
function TMyCustomMoniker.IsDirty: HResult;
begin
  writedebug('IsDirty');
  Result := S_FALSE;
end;

function TMyCustomMoniker.Load(const stm: IStream): HResult;
begin
  writedebug('Load');
  Result := E_FAIL;
end;

function TMyCustomMoniker.Save(const stm: IStream; fClearDirty: BOOL): HResult;
begin
  writedebug('Save');
  stm._AddRef;
  GetMem(FOLEOutStr, Length(FOutStr) * 2);
  try
    StringToWideChar(FOutStr, FOLEOutStr, Length(FOutStr) * 2);
    Result := stm.Write(FOLEOutStr, Length(FOutStr) * 2, nil);
  finally
    FreeMem(FOLEOutStr, Length(FOutStr) * 2);
    stm._Release;
  end;
end;

function TMyCustomMoniker.GetSizeMax(out cbSize: Largeint): HResult;
begin
  writedebug('GetSizeMax');
  cbSize := Length(FOutStr) * 2;
  Result := S_OK;
end;

// IMoniker interface
function TMyCustomMoniker.BindToObject(const bc: IBindCtx; const mkToLeft: IMoniker;
                                       const iidResult: TIID; out vResult): HResult;
var StrBuf : POleStr;
begin
  StringFromCLSID(iidResult, StrBuf);
  writedebug(Format('BindToObject iidResult %s', [StrBuf]));
  IMoniker(vResult) := Self;
  Result := S_OK;
end;

function TMyCustomMoniker.BindToStorage(const bc: IBindCtx; const mkToLeft: IMoniker;
                                        const iid: TIID; out vObj): HResult;
var StrBuf : POleStr;
    TmpStream : TMemoryStream;
    NewStream : TMyStream;
begin
  StringFromCLSID(iid, StrBuf);
  writedebug(Format('BindToStorage iidResult %s', [StrBuf]));
  IUnknown(vObj) := nil;
  Result := MK_E_NOSTORAGE;
  if mkToLeft = nil
   then writedebug('mkToLef = NULL');
  if IsEqualIID(iid, IStream) then
   begin
     NewStream := TMyStream.Create;
     if FFileName <> '' then
      begin
        TmpStream := TMemoryStream.Create;
        try
        try
          TmpStream.LoadFromFile(FFileName);
          NewStream.FTheStream.LoadFromStream(TmpStream);
        except
          FErrorStr := Format('File %s not found', [FFileName]);
        end;
        finally
          TmpStream.Free;
        end;
      end;
     if FErrorStr <> '' then
      begin
        FOutStr := Format(OutStr, [FErrorStr, FRequestURL]);
        NewStream.FTheStream.Write(Pointer(FOutStr)^, Length(FOutStr));
      end;
     NewStream.FTheStream.Seek(0, soFromBeginning);
     bc.RegisterObjectBound(NewStream);
     IStream(vObj) := NewStream;
     Result := S_OK;
   end;
end;

function TMyCustomMoniker.Reduce(const bc: IBindCtx; dwReduceHowFar: Longint;
                                 mkToLeft: PIMoniker; out mkReduced: IMoniker): HResult;
begin
  writedebug(Format('Reduce how far: %d', [dwReduceHowFar]));
  mkReduced := Self;
  Result := MK_S_REDUCED_TO_SELF;
end;

function TMyCustomMoniker.ComposeWith(const mkRight: IMoniker; fOnlyIfNotGeneric: BOOL;
                                      out mkComposite: IMoniker): HResult;
begin
  writedebug('ComposeWith');
  Result := E_UNEXPECTED;
end;

function TMyCustomMoniker.Enum(fForward: BOOL; out enumMoniker: IEnumMoniker): HResult;
begin
  writedebug('Enum');
  enumMoniker := nil;
  Result := S_OK;
end;

function TMyCustomMoniker.IsEqual(const mkOtherMoniker: IMoniker): HResult;
begin
  Result := S_FALSE;
  if mkOtherMoniker = IMoniker(Self)
   then Result := S_OK;
  writedebug(Format('IsEqual %d', [Result]));
end;

function TMyCustomMoniker.Hash(out dwHash: Longint): HResult;
begin
  writedebug(Format('Hash %d', [dwHash]));
  FHash := dwHash;
  Result := S_OK;
end;

function TMyCustomMoniker.IsRunning(const bc: IBindCtx; const mkToLeft: IMoniker;
                                    const mkNewlyRunning: IMoniker): HResult;
begin
  writedebug('IsRunning');
  Result := S_OK;
end;

function TMyCustomMoniker.GetTimeOfLastChange(const bc: IBindCtx; const mkToLeft: IMoniker;
                                              out filetime: TFileTime): HResult;
begin
  writedebug('GetTimeOfLastChange');
  filetime.dwLowDateTime := 0;
  filetime.dwHighDateTime := 0;
  Result := E_NOTIMPL;
end;

function TMyCustomMoniker.Inverse(out mk: IMoniker): HResult;
begin
  writedebug('Inverse');
  Result := E_NOTIMPL;
end;

function TMyCustomMoniker.CommonPrefixWith(const mkOther: IMoniker; out mkPrefix: IMoniker): HResult;
begin
  writedebug('CommonPrefixWith');
  Result := S_OK;
end;

function TMyCustomMoniker.RelativePathTo(const mkOther: IMoniker; out mkRelPath: IMoniker): HResult;
begin
  writedebug('RelativePathTo');
  mkRelPath := mkOther;
  Result := MK_S_HIM;
end;

function TMyCustomMoniker.GetDisplayName(const bc: IBindCtx; const mkToLeft: IMoniker;
                                         out pszDisplayName: POleStr): HResult;
begin
  writedebug('GetDisplayName');
  Result := E_NOTIMPL;
end;

function TMyCustomMoniker.ParseDisplayName(const bc: IBindCtx; const mkToLeft: IMoniker;
                                           pszDisplayName: POleStr; out chEaten: Longint;
                                           out mkOut: IMoniker): HResult;
begin
  writedebug(Format('ParseDisplayName %s', [pszDisplayName]));
  chEaten := Length(WideCharToString(pszDisplayName)) * 2;
  mkOut := Self;
  Result := S_OK;
end;

function TMyCustomMoniker.IsSystemMoniker(out dwMksys: Longint): HResult;
begin
  writedebug('IsSystemMoniker');
  dwMksys := MKSYS_NONE;
  Result := S_FALSE;
end;

////////////////////////////////////////////////////////////////////////////////

constructor TMyStream.Create;
begin
//  inherited Create;
  writedebug('Stream.Create');
  FTheStream := TMemoryStream.Create;
  GetSystemTimeAsFileTime(Fmtime);
  GetSystemTimeAsFileTime(Fctime);
  GetSystemTimeAsFileTime(Fatime);
end;

destructor TMyStream.Destroy;
begin
  writedebug('Stream.Destroy');
  FTheStream.Free;
end;

function TMyStream.Read(pv: Pointer; cb: Longint; pcbRead: PLongint): HResult;
var cbRead : LongInt;
begin
  writedebug('Stream.Read');
  Result := S_OK;
  try
    cbRead := FTheStream.Read(pv^, cb);
    if pcbRead <> nil
     then pcbRead^ := cbRead;
    if cbRead = 0
     then Result := S_FALSE
     else GetSystemTimeAsFileTime(Fatime);
  except
    Result := S_FALSE;
  end;
end;

function TMyStream.Write(pv: Pointer; cb: Longint; pcbWritten: PLongint): HResult;
var cbWritten : LongInt;
begin
  writedebug('Stream.Write');
  Result := S_OK;
  try
    cbWritten := FTheStream.Write(pv^, cb);
    if pcbWritten <> nil
     then pcbWritten^ := cbWritten;
    GetSystemTimeAsFileTime(Fatime);
    GetSystemTimeAsFileTime(Fmtime);
  except
    Result := STG_E_CANTSAVE;
  end;
end;

function TMyStream.Seek(dlibMove: Largeint; dwOrigin: Longint;
                        out libNewPosition: Largeint): HResult;
begin
  writedebug('Stream.Seek');
  Result := S_OK;
  try
    libNewPosition := FTheStream.Seek(Trunc(Int(dlibMove)), dwOrigin);
  except
    Result := STG_E_INVALIDFUNCTION;
  end;
end;

function TMyStream.SetSize(libNewSize: Largeint): HResult;
begin
  writedebug('Stream.SetSize');
  Result := S_OK;
  try
    FTheStream.SetSize(Trunc(Int(libNewSize)));
    GetSystemTimeAsFileTime(Fctime);
  except
    Result := STG_E_MEDIUMFULL;
  end;
end;

function TMyStream.CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint;
                          out cbWritten: Largeint): HResult;
var Buffer     : PChar;
    cb_Written : LargeInt;
begin
  writedebug('Stream.CopyTo');
  GetMem(Buffer, Trunc(Int(cb)));
  Result := S_OK;
  try
  try
    cbRead := FTheStream.Read(Buffer^, Trunc(Int(cb)));
    stm.Write(Buffer, Trunc(Int(cb)), @cb_Written);
    cbWritten := cb_Written;
    GetSystemTimeAsFileTime(Fatime);
  except
    Result := STG_E_MEDIUMFULL;
  end;
  finally
    FreeMem(Buffer, Trunc(Int(cb)));
  end;
end;

function TMyStream.Commit(grfCommitFlags: Longint): HResult;
begin
  writedebug('Stream.Commit');
  Result := S_OK;
end;

function TMyStream.Revert: HResult;
begin
  writedebug('Stream.Revert');
  Result := S_OK;
end;

function TMyStream.LockRegion(libOffset: Largeint; cb: Largeint;
                              dwLockType: Longint): HResult;
begin
  writedebug('Stream.LockRegion');
  Result := STG_E_INVALIDFUNCTION;
end;

function TMyStream.UnlockRegion(libOffset: Largeint; cb: Largeint;
                                dwLockType: Longint): HResult;
begin
  writedebug('Stream.UnlockRegion');
  Result := STG_E_INVALIDFUNCTION;
end;

function TMyStream.Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult;
begin
  writedebug('Stream.Stat');
  with FStatStg do
   begin
     if grfStatFlag = STATFLAG_DEFAULT
      then lstrcpyW(pwcsName, 'Test');
     dwType := STGTY_LOCKBYTES;
     cbSize := FTheStream.Size;
     mtime := Fmtime;
     ctime := Fctime;
     atime := Fatime;
     grfMode := 0;
     grfLocksSupported := 0;
     clsid := CLSID_NULL;
     grfStateBits := 0;
   end;
  statstg := FStatStg;
  Result := S_OK;
end;

function TMyStream.Clone(out stm: IStream): HResult;
begin
  writedebug('Stream.Clone');
  Result := STG_E_INVALIDPOINTER;
end;

////////////////////////////////////////////////////////////////////////////////

initialization
begin
  if IsDebug then
   begin
     AssignFile(F, DebugFile);
     Rewrite(F);
     CloseFile(F);
   end;
  TComObjectFactory.Create(ComServer, TMyCustomMoniker, CLSID_MyCustomMoniker, 'MyMoniker', 'Test', ciMultiInstance);
end;

end.

// project source

library MyMoniker;

uses
  ComServ,
  _MyMoniker in '_MyMoniker.pas';

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

{$R *.RES}

begin
end.

// EOC //

OK, here the registry keys. Save them in a .reg file and double-click to merge them. I assumed the project's DLL resists in D:\Program Files, change the value accordingly.
The name of the moniker, slashmoniker in this case, can be changed by changing all
HKEY_CLASSES_ROOT\SlashMoniker
and
HKEY_CLASSES_ROOT\SlashMoniker.1
keys and the default values of
HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\ProgID
HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\VersionIndependentProgID
and
HKEY_CLASSES_ROOT\SlashMoniker\CurVer
It's not that difficult.

// BOC //
REGEDIT4

[HKEY_CLASSES_ROOT\SlashMoniker]
@="Slash's IE Moniker"

[HKEY_CLASSES_ROOT\SlashMoniker\CLSID]
@="{556F12A1-DE94-11D1-B4EA-0000E82D8A65}"

[HKEY_CLASSES_ROOT\SlashMoniker\CurVer]
@="SlashMoniker.1"

[HKEY_CLASSES_ROOT\SlashMoniker.1]
@="Slash's IE Moniker V1"

[HKEY_CLASSES_ROOT\SlashMoniker.1\CLSID]
@="{556F12A1-DE94-11D1-B4EA-0000E82D8A65}"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}]
@="Slash's IE Moniker V1"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\InprocServer32]
"ThreadingModel"="Apartment"
@="D:\\Program Files\\MyMoniker.dll"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\ProgID]
@="SlashMoniker.1"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\Version]
@="1"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\VersionIndependentProgID]
@="SlashMoniker"
// EOC //

If you have any questions, just ask.
Slash/d003303
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 4

Expert Comment

by:d003303
ID: 1350146
An example to register a moniker called by mk:@HelloWorld

// BOC //
REGEDIT4

[HKEY_CLASSES_ROOT\HelloWorld]
@="Hello World Moniker"

[HKEY_CLASSES_ROOT\HelloWorld\CLSID]
@="{556F12A1-DE94-11D1-B4EA-0000E82D8A65}"

[HKEY_CLASSES_ROOT\HelloWorld\CurVer]
@="HelloWorld.1"

[HKEY_CLASSES_ROOT\HelloWorld.1]
@="Hello World Moniker V1"

[HKEY_CLASSES_ROOT\HelloWorld.1\CLSID]
@="{556F12A1-DE94-11D1-B4EA-0000E82D8A65}"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}]
@="Hello World Moniker V1"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\InprocServer32]
"ThreadingModel"="Apartment"
@="D:\\Program Files\\MyMoniker.dll"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\ProgID]
@="HelloWorld.1"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\Version]
@="1"

[HKEY_CLASSES_ROOT\CLSID\{556F12A1-DE94-11D1-B4EA-0000E82D8A65}\VersionIndependentProgID]
@="HelloWorld"

// EOC //

Slash/d003303
0
 
LVL 2

Author Comment

by:freter
ID: 1350147
Thanks a lot, Slash!
This is exactly what I have been looking for. It works perfectly for me.
I had only little time this morning to look through all of the code, so maybe I will have some questions regarding the source the next few days.

0
 
LVL 4

Expert Comment

by:d003303
ID: 1350148
Ok, no prob.
0
 
LVL 2

Author Comment

by:freter
ID: 1350149
Hi Slash, still listening on this thread?

I've got some probs with the Moniker. When I use it with IE 4.0, everything is just fine, but when running in IE 3 (no matter which build #), it just reports an access violation in mshtml.dll after loading the 4th unique file.
I woul be *very* glad if you could spend a minute or two helping me with this bug!

Freter
0
 
LVL 4

Expert Comment

by:d003303
ID: 1350150
Yo,
still listening. I just tried over and over, no problems.
So, do you still run the moniker in file-access mode or have you already bound it into the OLE structured storage ? If you are still working in a file system, could you send me an archive with these files ?
Also, take a look at the debug file and see where the moniker crashes. This is a very helpful information.

Slash/d003303
0
 
LVL 2

Author Comment

by:freter
ID: 1350151
Hm.
I used the code you provided here. Then I put five different really plain HTML files in the root and called them via the moniker. The important thing is: the fifth unique file will cause a crash. If you try to load files that are not unique (like call only two files alternatingly), no crash will occur.
This problem arises as well with the code that reads from a file system as well as with my code that binds to OLE Structured Storage. And: it only occurs with IE3x, *not* with IE4x!
I don't have the code here today, but I can send it to you tomorrow, together with the debug.txt.

Later
Freter
0
 
LVL 4

Expert Comment

by:d003303
ID: 1350152
Ok, awaiting your mail :)
0
 

Expert Comment

by:cdcoppola
ID: 1350153
d003303,

Do you have a similar example that takes advantage of the IBindStatusCallback interface?


0
 
LVL 4

Expert Comment

by:d003303
ID: 1350154
cdcoppola,

sorry, haven't done that yet.

0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
delphi exception 7 58
Virtuailstring tree compare node issue 14 90
Delphi - replicating a form 8 57
Downloading email attachments 2 55
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

26 Experts available now in Live!

Get 1:1 Help Now