diff options
| author | George Hazan <george.hazan@gmail.com> | 2013-08-21 21:32:08 +0000 | 
|---|---|---|
| committer | George Hazan <george.hazan@gmail.com> | 2013-08-21 21:32:08 +0000 | 
| commit | 3f028637b9f341c4792ff871c620c62b8df9705a (patch) | |
| tree | bae4291d72b84d0bbda720f87a8c8c827abb61f3 /plugins/ShellExt | |
| parent | 1988e60c6f9dd061cb045546a02ccbb3642c098a (diff) | |
+ another 500 lines of code
git-svn-id: http://svn.miranda-ng.org/main/trunk@5779 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/ShellExt')
| -rw-r--r-- | plugins/ShellExt/shellext_11.vcxproj | 1 | ||||
| -rw-r--r-- | plugins/ShellExt/shellext_11.vcxproj.filters | 3 | ||||
| -rw-r--r-- | plugins/ShellExt/src/shlcom.cpp | 1117 | ||||
| -rw-r--r-- | plugins/ShellExt/src/shlcom.h | 34 | ||||
| -rw-r--r-- | plugins/ShellExt/src/shlicons.h | 21 | ||||
| -rw-r--r-- | plugins/ShellExt/src/stdafx.h | 1 | 
6 files changed, 477 insertions, 700 deletions
diff --git a/plugins/ShellExt/shellext_11.vcxproj b/plugins/ShellExt/shellext_11.vcxproj index f5f48754e5..12aae8a42d 100644 --- a/plugins/ShellExt/shellext_11.vcxproj +++ b/plugins/ShellExt/shellext_11.vcxproj @@ -187,6 +187,7 @@    </ItemDefinitionGroup>
    <ItemGroup>
      <ClInclude Include="src\shlcom.h" />
 +    <ClInclude Include="src\shlicons.h" />
      <ClInclude Include="src\stdafx.h" />
      <ClInclude Include="src\resource.h" />
      <ClInclude Include="src\Version.h" />
 diff --git a/plugins/ShellExt/shellext_11.vcxproj.filters b/plugins/ShellExt/shellext_11.vcxproj.filters index 31875e467f..85793afe77 100644 --- a/plugins/ShellExt/shellext_11.vcxproj.filters +++ b/plugins/ShellExt/shellext_11.vcxproj.filters @@ -27,6 +27,9 @@      <ClInclude Include="src\shlcom.h">
        <Filter>Header Files</Filter>
      </ClInclude>
 +    <ClInclude Include="src\shlicons.h">
 +      <Filter>Header Files</Filter>
 +    </ClInclude>
    </ItemGroup>
    <ItemGroup>
      <ResourceCompile Include="res\Version.rc">
 diff --git a/plugins/ShellExt/src/shlcom.cpp b/plugins/ShellExt/src/shlcom.cpp index f2f06f3d0b..a77b382f22 100644 --- a/plugins/ShellExt/src/shlcom.cpp +++ b/plugins/ShellExt/src/shlcom.cpp @@ -1,10 +1,11 @@  #include "stdafx.h"
  #include "shlcom.h"
 -struct dllpublic
 +struct
  {
  	int FactoryCount, ObjectCount;
 -};
 +}
 +static dllpublic;
  bool VistaOrLater;
 @@ -463,7 +464,6 @@ void BuildSkinIcons(TEnumData *lParam)  	TSlotIPC *pct;
  	TShlComRec *Self;
  	UINT j;
 -	IImageFactory *imageFactory;
  	pct = lParam->ipch->NewIconsBegin;
  	Self = lParam->Self;
 @@ -480,24 +480,9 @@ void BuildSkinIcons(TEnumData *lParam)  		// if using anything older, just use the default code, the bitmaps (&& | icons) will be freed
  		// with the shell object.
 -		imageFactory = NULL;
 -
  		for (j = 0; j < 10; j++) {
 -			if (imageFactory == NULL)
 -				imageFactory = ARGB_GetWorker();
 -			if (VistaOrLater) {
 -				d->hBitmaps[j] = ARGB_BitmapFromIcon(imageFactory, Self->hMemDC, p->hIcons[j]);
 -				d->hIcons[j] = 0;
 -			}
 -			else {
 -				d->hBitmaps[j] = 0;
 -				d->hIcons[j] = CopyIcon(p->hIcons[j]);
 -			}
 -		}
 -
 -		if (imageFactory != NULL) {
 -			imageFactory->ptrVTable->Release(imageFactory);
 -			imageFactory = NULL;
 +			d->hBitmaps[j] = 0;
 +			d->hIcons[j] = CopyIcon(p->hIcons[j]);
  		}
  		Self->ProtoIconsCount++;
 @@ -505,12 +490,13 @@ void BuildSkinIcons(TEnumData *lParam)  	}
  }
 -BOOL __stdcall ProcessRequest(HWND hwnd, TEnumData *lParam)
 +BOOL __stdcall ProcessRequest(HWND hwnd, LPARAM param)
  {
  	HANDLE hMirandaWorkEvent;
  	int replyBits;
  	char szBuf[MAX_PATH];
 +	TEnumData *lParam = (TEnumData*)param;
  	BOOL Result = true;
  	DWORD pid = 0;
  	GetWindowThreadProcessId(hwnd, &pid);
 @@ -522,7 +508,7 @@ BOOL __stdcall ProcessRequest(HWND hwnd, TEnumData *lParam)  		hMirandaWorkEvent = OpenEventA(EVENT_ALL_ACCESS, false, CreateProcessUID(pid).c_str());
  		if (hMirandaWorkEvent != 0) {
  			GetClassNameA(hwnd, szBuf, sizeof(szBuf));
 -			if ( lstrcmpA(szBuf, MirandaName) != 0) {
 +			if ( lstrcmpA(szBuf, MIRANDANAME) != 0) {
  				// opened but not valid.
  				CloseHandle(hMirandaWorkEvent);
  				return Result;
 @@ -551,7 +537,7 @@ BOOL __stdcall ProcessRequest(HWND hwnd, TEnumData *lParam)  				// on the final menu maybe on a different instance && another OpenEvent() will be needed.
  				lParam->pid = pid;
  				// check out the user options from the server
 -				lParam->bShouldOwnerDraw = (lParam->ipch->dwFlags && HIPC_NOICONS) = 0;
 +				lParam->bShouldOwnerDraw = (lParam->ipch->dwFlags & HIPC_NOICONS) == 0;
  				// process the icons
  				BuildSkinIcons(lParam);
  				// process other replies
 @@ -563,738 +549,489 @@ BOOL __stdcall ProcessRequest(HWND hwnd, TEnumData *lParam)  	}
  }
 -function TShlComRec_QueryInterface(Self: PCommon_Interface; const IID: TIID;  Obj): HResult; stdcall;
 +/////////////////////////////////////////////////////////////////////////////////////////
 +
 +TShlComRec::TShlComRec()
  {
 -  Pointer(Obj) = NULL;
 -  { IShellExtInit is given when the TShlRec is created }
 -  if IsEqualIID(IID, IID_IContextMenu) | IsEqualIID(IID, IID_IContextMenu2) |
 -    IsEqualIID(IID, IID_IContextMenu3) 
 -  {
 -    with Self->ptrInstance^ do
 -    {
 -      Pointer(Obj) = @ContextMenu3_Interface;
 -      inc(RefCount);
 -    } { with }
 -    Result = S_OK;
 -  }
 -  else
 -  {
 -    // under XP, it may ask for IShellExtInit again, this fixes the -double- click to see menus issue
 -    // which was really just the object not being created
 -    if IsEqualIID(IID, IID_IShellExtInit) 
 -    {
 -      with Self->ptrInstance^ do
 -      {
 -        Pointer(Obj) = @ShellExtInit_Interface;
 -        inc(RefCount);
 -      } // if
 -      Result = S_OK;
 -    }
 -    else
 -    {
 -      Result = CLASS_E_CLASSNOTAVAILABLE;
 -    } // if
 -  } // if
 +  HDC DC;
 +
 +  RefCount = 1;
 +  hDllHeap = HeapCreate(0, 0, 0);
 +  hRootMenu = 0;
 +  hRecentMenu = 0;
 +  RecentCount = 0;
 +  idCmdFirst = 0;
 +  pDataObject = NULL;
 +  ProtoIcons = NULL;
 +  ProtoIconsCount = 0;
 +  // create an inmemory DC
 +  DC = GetDC(0);
 +  hMemDC = CreateCompatibleDC(DC);
 +  ReleaseDC(0, DC);
 +  // keep count on the number of objects
 +  dllpublic.ObjectCount++;
  }
 -function TShlComRec_AddRef(Self: PCommon_Interface): LongInt; stdcall;
 +HRESULT TShlComRec::QueryInterface(REFIID riid, void **ppvObject)
  {
 -  with Self->ptrInstance^ do
 -  {
 -    inc(RefCount);
 -    Result = RefCount;
 -  } { with }
 +	*ppvObject = NULL;
 +	// IShellExtInit is given when the TShlRec is created 
 +	if (riid == IID_IContextMenu || riid == IID_IContextMenu2 || riid == IID_IContextMenu3) {
 +		*ppvObject = (IContextMenu3*)this;
 +		RefCount++;
 +		return S_OK;
 +	}
 +
 +	// under XP, it may ask for IShellExtInit again, this fixes the -double- click to see menus issue
 +	// which was really just the object not being created
 +	if (riid == IID_IShellExtInit) {
 +		*ppvObject = (IShellExtInit*)this;
 +		RefCount++;
 +		return S_OK;
 +	}
 +
 +	return CLASS_E_CLASSNOTAVAILABLE;
  }
 -function TShlComRec_Release(Self: PCommon_Interface): LongInt; stdcall;
 +ULONG TShlComRec::AddRef()
 +{
 +	RefCount++;
 +	return RefCount;
 +}
 -  j, c: Cardinal;
 +ULONG TShlComRec::Release()
  {
 -  with Self->ptrInstance^ do
 -  {
 -    dec(RefCount);
 -    Result = RefCount;
 -    if RefCount = 0 
 -    {
 -      // time to go byebye.
 -      with Self->ptrInstance^ do
 -      {
 -        // Note MRU menu is associated with a window (indirectly) so windows will free it.
 -        // free icons!
 -        if ProtoIcons != NULL 
 -        {
 -          c = ProtoIconsCount;
 -          while c > 0 do
 -          {
 -            dec(c);
 -            for j = 0 to 9 do
 -            {
 -              with ProtoIcons[c] do
 -              {
 -                if hIcons[j] != 0 
 -                  DestroyIcon(hIcons[j]);
 -                if hBitmaps[j] != 0 
 -                  DeleteObject(hBitmaps[j]);
 -              }
 -            }
 -          }
 -          FreeMem(ProtoIcons);
 -          ProtoIcons = NULL;
 -        } // if
 -        // free IDataObject reference if pointer exists
 -        if pDataObject != NULL 
 -        {
 -          pDataObject->ptrVTable->Release(pDataObject);
 -        } // if
 -        pDataObject = NULL;
 -        // free the heap && any memory allocated on it
 -        HeapDestroy(hDllHeap);
 -        // destroy the DC
 -        if hMemDC != 0 
 -          DeleteDC(hMemDC);
 -      } // with
 -      // free the instance (class record) created
 -      Dispose(Self->ptrInstance);
 -      dec(dllpublic.ObjectCount);
 -    } { if }
 -  } { with }
 +	ULONG ret = --RefCount;
 +	if (RefCount == 0) {
 +		// time to go byebye.
 +		// Note MRU menu is associated with a window (indirectly) so windows will free it.
 +		// free icons!
 +		if (ProtoIcons != NULL) {
 +			ULONG c = ProtoIconsCount;
 +			while (c > 0) {
 +				c--;
 +				TSlotProtoIcons *p = &ProtoIcons[c];
 +				for (int j = 0; j < 10; j++) {
 +					if (p->hIcons[j] != 0)
 +						DestroyIcon(p->hIcons[j]);
 +					if (p->hBitmaps[j] != 0)
 +						DeleteObject(p->hBitmaps[j]);
 +				}
 +			}
 +			mir_free(ProtoIcons);
 +			ProtoIcons = NULL;
 +		}
 +		// free IDataObject reference if pointer exists
 +		if (pDataObject != NULL) {
 +			pDataObject->Release();
 +			pDataObject = NULL;
 +		}
 +		// free the heap && any memory allocated on it
 +		HeapDestroy(hDllHeap);
 +		// destroy the DC
 +		if (hMemDC != 0)
 +			DeleteDC(hMemDC);
 +
 +		// free the instance (class record) created
 +		delete this;
 +		dllpublic.ObjectCount--;
 +	} 
 +	return ret;
  }
 -function TShlComRec_Initialise(Self: PContextMenu3_Interface; pidLFolder: Pointer;
 -  DObj: PDataObject_Interface; hKeyProdID: HKEY): HResult; stdcall;
 +HRESULT TShlComRec::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
  {
    // DObj is a pointer to an instance of IDataObject which is a pointer itself
    // it contains a pointer to a function table containing the function pointer
    // address of GetData() - the instance data has to be passed explicitly since
    // all compiler magic has gone.
 -  with Self->ptrInstance^ do
 -  {
 -    if DObj != NULL 
 -    {
 -      Result = S_OK;
 -      // if an instance already exists, free it.
 -      if pDataObject != NULL 
 -        pDataObject->ptrVTable->Release(pDataObject);
 -      // store the new one && AddRef() it
 -      pDataObject = DObj;
 -      pDataObject->ptrVTable->AddRef(pDataObject);
 -    }
 -    else
 -    {
 -      Result = E_INVALIDARG;
 -    } // if
 -  } // if
 -}
 +	if (pdtobj == NULL)
 +		return E_INVALIDARG;
 -function MAKE_HRESULT(Severity, Facility, Code: Integer): HResult;
 -{$IFDEF FPC}
 -inline;
 -{$ENDIF}
 -{
 -  Result = (Severity shl 31) | (Facility shl 16) | Code;
 +	// if an instance already exists, free it.
 +	if (pDataObject != NULL)
 +		pDataObject->Release();
 +
 +	// store the new one && AddRef() it
 +	pDataObject = pdtobj;
 +	pDataObject->AddRef();
  }
 -function TShlComRec_QueryContextMenu(Self: PContextMenu3_Interface; Menu: HMENU;
 -  indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult; stdcall;
 -type
 -  TDllVersionInfo = record
 -    cbSize: DWORD;
 -    dwMajorVersion: DWORD;
 -    dwMinorVersion: DWORD;
 -    dwBuildNumber: DWORD;
 -    dwPlatformID: DWORD;
 -  }
 +/////////////////////////////////////////////////////////////////////////////////////////
 -  TDllGetVersionProc = function( dv: TDllVersionInfo): HResult; stdcall;
 +struct DllVersionInfo
 +{
 +   DWORD cbSize;
 +   DWORD dwMajorVersion, dwMinorVersion, dwBuildNumber, dwPlatformID;
 +};
 -  hShellInst: HANDLE;
 -  bMF_OWNERDRAW: Boolean;
 -  DllGetVersionProc: TDllGetVersionProc;
 -  dvi: TDllVersionInfo;
 -  ed: TEnumData;
 -  hMap: HANDLE;
 -  pipch: THeaderIPC *;
 +typedef HRESULT (__stdcall *pfnDllGetVersion)(DllVersionInfo*);
 +
 +HRESULT TShlComRec::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT _idCmdFirst, UINT _idCmdLast, UINT uFlags)
  {
 -  Result = 0;
 -  if ((LOWORD(uFlags) && CMF_VERBSONLY) != CMF_VERBSONLY) &&
 -    ((LOWORD(uFlags) && CMF_DEFAULTONLY) != CMF_DEFAULTONLY) 
 -  {
 -    bMF_OWNERDRAW = false;
 -    // get the shell version
 -    hShellInst = LoadLibrary('shell32.dll');
 -    if hShellInst != 0 
 -    {
 -      DllGetVersionProc = GetProcAddress(hShellInst, 'DllGetVersion');
 -      if @DllGetVersionProc != NULL 
 -      {
 -        dvi.cbSize = sizeof(TDllVersionInfo);
 -        if DllGetVersionProc(dvi) >= 0 
 -        {
 -          // it's at least 4.00
 -          bMF_OWNERDRAW = (dvi.dwMajorVersion > 4) | (dvi.dwMinorVersion >= 71);
 -        } // if
 -      } // if
 -      FreeLibrary(hShellInst);
 -    } // if
 +	if (((LOWORD(uFlags) & CMF_VERBSONLY) != CMF_VERBSONLY) && ((LOWORD(uFlags) & CMF_DEFAULTONLY) != CMF_DEFAULTONLY)) {
 +		bool bMF_OWNERDRAW = false;
 +		// get the shell version
 +		HINSTANCE hShellInst = LoadLibraryA("shell32.dll");
 +		if (hShellInst != 0) {
 +			pfnDllGetVersion DllGetVersionProc = (pfnDllGetVersion)GetProcAddress(hShellInst, "DllGetVersion");
 +			if (DllGetVersionProc != NULL) {
 +				DllVersionInfo dvi;
 +				dvi.cbSize = sizeof(dvi);
 +				if (DllGetVersionProc(&dvi) >= 0)
 +					// it's at least 4.00
 +					bMF_OWNERDRAW = (dvi.dwMajorVersion > 4) | (dvi.dwMinorVersion >= 71);
 +			}
 +			FreeLibrary(hShellInst);
 +		}
 -    // if we're using Vista (| later),  the ownerdraw code will be disabled, because the system draws the icons.
 -    if VistaOrLater 
 -      bMF_OWNERDRAW = false;
 +		// if we're using Vista (| later),  the ownerdraw code will be disabled, because the system draws the icons.
 +		if (VistaOrLater)
 +			bMF_OWNERDRAW = false;
 +
 +		HANDLE hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, IPC_PACKET_SIZE, IPC_PACKET_NAME);
 +		if (hMap != 0 && GetLastError() != ERROR_ALREADY_EXISTS) {
 +			TEnumData ed;
 +			// map the memory to this address space
 +			THeaderIPC *pipch = (THeaderIPC*)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
 +			if (pipch != NULL) {
 +				// let the callback have instance vars
 +				ed.Self = this;
 +				// not used 'ere
 +				hRootMenu = hmenu;
 +				// store the first ID to offset with index for InvokeCommand()
 +				idCmdFirst = _idCmdFirst;
 +				// store the starting index to offset
 +				ed.bOwnerDrawSupported = bMF_OWNERDRAW;
 +				ed.bShouldOwnerDraw = true;
 +				ed.idCmdFirst = idCmdFirst;
 +				ed.ipch = pipch;
 +				// allocate a wait object so the ST can signal us, it can't be anon
 +				// since it has to used by OpenEvent()
 +				lstrcpyA(pipch->SignalEventName, CreateUID().c_str());
 +				// create the wait wait-for-wait object
 +				ed.hWaitFor = CreateEventA(NULL, false, false, pipch->SignalEventName);
 +				if (ed.hWaitFor != 0) {
 +					// enumerate all the top level windows to find all loaded MIRANDANAME classes
 +					EnumWindows(&ProcessRequest, LPARAM(&ed));
 +					// close the wait-for-reply object
 +					CloseHandle(ed.hWaitFor);
 +				}
 +				// unmap the memory from this address space
 +				UnmapViewOfFile(pipch);
 +			}
 +			// close the mapping
 +			CloseHandle(hMap);
 +			// use the MSDN recommended way, thou there ain't much difference
 +			return MAKE_HRESULT(0, 0, (ed.idCmdFirst - _idCmdFirst) + 1);
 +		}
 +	}
 -    hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, IPC_PACKET_SIZE,
 -      IPC_PACKET_NAME);
 -    if (hMap != 0) && (GetLastError != ERROR_ALREADY_EXISTS) 
 -    {
 -      { map the memory to this address space }
 -      pipch = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
 -      if pipch != NULL 
 -      {
 -        { let the callback have instance vars }
 -        ed.Self = Self->ptrInstance;
 -        // not used 'ere
 -        ed.Self->hRootMenu = Menu;
 -        // store the first ID to offset with index for InvokeCommand()
 -        Self->ptrInstance->idCmdFirst = idCmdFirst;
 -        // store the starting index to offset
 -        Result = idCmdFirst;
 -        ed.bOwnerDrawSupported = bMF_OWNERDRAW;
 -        ed.bShouldOwnerDraw = true;
 -        ed.idCmdFirst = idCmdFirst;
 -        ed.ipch = pipch;
 -        { allocate a wait object so the ST can signal us, it can't be anon
 -          since it has to used by OpenEvent() }
 -        lstrcpyA(@pipch->SignalEventName, LPSTR(CreateUID()));
 -        { create the wait wait-for-wait object }
 -        ed.hWaitFor = CreateEvent(NULL, false, false, pipch->SignalEventName);
 -        if ed.hWaitFor != 0 
 -        {
 -          { enumerate all the top level windows to find all loaded MIRANDANAME
 -            classes -- }
 -          EnumWindows(@ProcessRequest, lParam(@ed));
 -          { close the wait-for-reply object }
 -          CloseHandle(ed.hWaitFor);
 -        }
 -        { unmap the memory from this address space }
 -        UnmapViewOfFile(pipch);
 -      } { if }
 -      { close the mapping }
 -      CloseHandle(hMap);
 -      // use the MSDN recommended way, thou there ain't much difference
 -      Result = MAKE_HRESULT(0, 0, (ed.idCmdFirst - Result) + 1);
 -    }
 -    else
 -    {
 -      // the mapping file already exists, which is not good!
 -    }
 -  }
 -  else
 -  {
 -    // same as giving a SEVERITY_SUCCESS, FACILITY_NULL, since that
 -    // just clears the higher bits, which is done anyway
 -    Result = MAKE_HRESULT(0, 0, 1);
 -  } // if
 +	// same as giving a SEVERITY_SUCCESS, FACILITY_NULL, since that
 +	// just clears the higher bits, which is done anyway
 +	return MAKE_HRESULT(0, 0, 1);
  }
 -function TShlComRec_GetCommandString(Self: PContextMenu3_Interface; idCmd, uType: UINT;
 -  pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult; stdcall;
 +HRESULT TShlComRec::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pReserved, LPSTR pszName, UINT cchMax)
  {
 -  Result = E_NOTIMPL;
 +	return E_NOTIMPL;
  }
 -function ipcGetFiles(pipch: THeaderIPC *; pDataObject: PDataObject_Interface; const hContact: HANDLE): Integer;
 -type
 -  TDragQueryFile = function(hDrop: HANDLE; fileIndex: Integer; FileName: LPSTR;
 -    cbSize: Integer): Integer; stdcall;
 -
 -  fet: TFormatEtc;
 -  stgm: TStgMedium;
 -  pct: TSlotIPC *;
 -  iFile: Cardinal;
 -  iFileMax: Cardinal;
 -  hShell: HANDLE;
 -  DragQueryFile: TDragQueryFile;
 -  cbSize: Integer;
 -  hDrop: HANDLE;
 +HRESULT ipcGetFiles(THeaderIPC *pipch, IDataObject* pDataObject, HANDLE hContact)
  {
 -  Result = E_INVALIDARG;
 -  hShell = LoadLibrary('shell32.dll');
 -  if hShell != 0 
 -  {
 -    DragQueryFile = GetProcAddress(hShell, 'DragQueryFileA');
 -    if @DragQueryFile != NULL 
 -    {
 -      fet.cfFormat = CF_HDROP;
 -      fet.ptd = NULL;
 -      fet.dwAspect = DVASPECT_CONTENT;
 -      fet.lindex = -1;
 -      fet.tymed = TYMED_HGLOBAL;
 -      Result = pDataObject->ptrVTable->GetData(pDataObject, fet, stgm);
 -      if Result = S_OK 
 -      {
 -        // FIX, actually lock the global object && get a pointer
 -        Pointer(hDrop) = GlobalLock(stgm.hGlobal);
 -        if hDrop != 0 
 -        {
 -          // get the maximum number of files
 -          iFileMax = DragQueryFile(stgm.hGlobal, 0xFFFFFFFF, NULL, 0);
 -          iFile = 0;
 -          while iFile < iFileMax do
 -          {
 -            // get the size of the file path
 -            cbSize = DragQueryFile(stgm.hGlobal, iFile, NULL, 0);
 -            // get the buffer
 -            pct = ipcAlloc(pipch, cbSize + 1); // including null term
 -            // allocated?
 -            if pct = NULL 
 -              break;
 -            // store the hContact
 -            pct->hContact = hContact;
 -            // copy it to the buffer
 -            DragQueryFile(stgm.hGlobal, iFile, LPSTR(UINT_PTR(pct) + sizeof(TSlotIPC)), pct->cbStrSection);
 -            // next file
 -            inc(iFile);
 -          } // while
 -          // store the number of files
 -          pipch->Slots = iFile;
 -          GlobalUnlock(stgm.hGlobal);
 -        } // if hDrop check
 -        // release the mediumn the lock may of failed
 -        ReleaseStgMedium(stgm);
 -      } // if
 -    } // if
 -    // free the dll
 -    FreeLibrary(hShell);
 -  } // if
 +	FORMATETC fet;
 +	fet.cfFormat = CF_HDROP;
 +	fet.ptd = NULL;
 +	fet.dwAspect = DVASPECT_CONTENT;
 +	fet.lindex = -1;
 +	fet.tymed = TYMED_HGLOBAL;
 +
 +	STGMEDIUM stgm;
 +	HRESULT hr = pDataObject->GetData(&fet, &stgm);
 +	if (hr == S_OK) {
 +		// FIX, actually lock the global object && get a pointer
 +		HANDLE hDrop = GlobalLock(stgm.hGlobal);
 +		if (hDrop != 0) {
 +			// get the maximum number of files
 +			UINT iFile, iFileMax = DragQueryFileA((HDROP)stgm.hGlobal, -1, NULL, 0);
 +			for (iFile = 0; iFile < iFileMax; iFile++) {
 +				// get the size of the file path
 +				int cbSize = DragQueryFileA((HDROP)stgm.hGlobal, iFile, NULL, 0);
 +				// get the buffer
 +				TSlotIPC *pct = ipcAlloc(pipch, cbSize + 1); // including null term
 +				// allocated?
 +				if (pct == NULL)
 +					break;
 +				// store the hContact
 +				pct->hContact = hContact;
 +				// copy it to the buffer
 +				DragQueryFileA((HDROP)stgm.hGlobal, iFile, LPSTR(pct) + sizeof(TSlotIPC), pct->cbStrSection);
 +			}
 +			// store the number of files
 +			pipch->Slots = iFile;
 +			GlobalUnlock(stgm.hGlobal);
 +		} // if hDrop check
 +		// release the mediumn the lock may of failed
 +		ReleaseStgMedium(&stgm);
 +	}
 +	return hr;
  }
 -function RequestTransfer(Self: PShlComRec; idxCmd: Integer): Integer;
 +HRESULT RequestTransfer(TShlComRec *Self, int idxCmd)
  {
 -  hMap: HANDLE;
 -  pipch: THeaderIPC *;
 -  mii: MENUITEMINFO;
 -  hTransfer: HANDLE;
 -  psd: PMenuDrawInfo;
 -  hReply: HANDLE;
 -  replyBits: Integer;
 -
 -  Result = E_INVALIDARG;
 -  // get the contact information
 -  mii.cbSize = sizeof(MENUITEMINFO);
 -  mii.fMask = MIIM_ID | MIIM_DATA;
 -  if GetMenuItemInfo(Self->hRootMenu, Self->idCmdFirst + idxCmd, false, mii) 
 -  {
 -    // get the pointer
 -    UINT_PTR(psd) = mii.dwItemData;
 -    // the ID stored in the item pointer && the ID for the menu must match
 -    if (psd = NULL) | (psd->wID != mii.wID) 
 -    {
 -      // MessageBox(0,'ptr assocated with menu is NULL','',MB_OK);
 -      Exit;
 -    } // if
 -  }
 -  else
 -  {
 -    // MessageBox(0,'GetMenuItemInfo failed?','',MB_OK);
 -    // couldn't get the info, can't start the transfer
 -    Result = E_INVALIDARG;
 -    Exit;
 -  } // if
 -  // is there an IDataObject instance?
 -  if Self->pDataObject != NULL 
 -  {
 -    // OpenEvent() the work object to see if the instance is still around
 -    hTransfer = OpenEvent(EVENT_ALL_ACCESS, false, LPSTR(CreateProcessUID(psd->pid)));
 -    if hTransfer != 0 
 -    {
 -      // map the ipc file again
 -      hMap = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,IPC_PACKET_SIZE,IPC_PACKET_NAME);
 -      if (hMap != 0) && (GetLastError != ERROR_ALREADY_EXISTS) 
 -      {
 -        // map it to process
 -        pipch = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
 -        if pipch != NULL 
 -        {
 -          // create the name of the object to be signalled by the ST
 -          lstrcpyA(pipch->SignalEventName, LPSTR(CreateUID()));
 -          // create it
 -          hReply = CreateEvent(NULL, false, false, pipch->SignalEventName);
 -          if hReply != 0 
 -          {
 -            if dtCommand in psd->fTypes 
 -            {
 -              if Assigned(psd->MenuCommandCallback) 
 -                Result = psd->MenuCommandCallback(pipch, hTransfer, hReply, psd);
 -            }
 -            else
 -            {
 -
 -              // prepare the buffer
 -              ipcPrepareRequests(IPC_PACKET_SIZE, pipch, REQUEST_XFRFILES);
 -              // get all the files into the packet
 -              if ipcGetFiles(pipch, Self->pDataObject, psd->hContact) = S_OK 
 -              {
 -                // need to wait for the ST to open the mapping object
 -                // since if we close it before it's opened it the data it
 -                // has will be undefined
 -                replyBits = ipcSendRequest(hTransfer, hReply, pipch, 200);
 -                if replyBits != REPLY_FAIL 
 -                {
 -                  // they got the files!
 -                  Result = S_OK;
 -                } // if
 -              }
 -
 -            }
 -            // close the work object name
 -            CloseHandle(hReply);
 -          } // if
 -          // unmap it from this process
 -          UnmapViewOfFile(pipch);
 -        } // if
 -        // close the map
 -        CloseHandle(hMap);
 -      } // if
 -      // close the handle to the ST object name
 -      CloseHandle(hTransfer);
 -    } // if
 -  } // if;
 +	// get the contact information
 +	MENUITEMINFOA mii;
 +	mii.cbSize = sizeof(MENUITEMINFO);
 +	mii.fMask = MIIM_ID | MIIM_DATA;
 +	if ( !GetMenuItemInfoA(Self->hRootMenu, Self->idCmdFirst + idxCmd, false, &mii))
 +		return E_INVALIDARG;
 +
 +	// get the pointer
 +	TMenuDrawInfo *psd = (TMenuDrawInfo*)mii.dwItemData;
 +	// the ID stored in the item pointer and the ID for the menu must match
 +	if (psd == NULL || psd->wID != mii.wID)
 +		return E_INVALIDARG;
 +
 +	// is there an IDataObject instance?
 +	HRESULT hr = E_INVALIDARG;
 +	if (Self->pDataObject != NULL) {
 +		// OpenEvent() the work object to see if the instance is still around
 +		HANDLE hTransfer = OpenEventA(EVENT_ALL_ACCESS, false, CreateProcessUID(psd->pid).c_str());
 +		if (hTransfer != 0) {
 +			// map the ipc file again
 +			HANDLE hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, IPC_PACKET_SIZE, IPC_PACKET_NAME);
 +			if (hMap != 0 && GetLastError() != ERROR_ALREADY_EXISTS) {
 +				// map it to process
 +				THeaderIPC *pipch = (THeaderIPC*)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
 +				if (pipch != NULL) {
 +					// create the name of the object to be signalled by the ST
 +					lstrcpyA(pipch->SignalEventName, CreateUID().c_str());
 +					// create it
 +					HANDLE hReply = CreateEventA(NULL, false, false, pipch->SignalEventName);
 +					if (hReply != 0) {
 +						if (psd->fTypes & dtCommand) {
 +							if (psd->MenuCommandCallback) 
 +								hr = psd->MenuCommandCallback(pipch, hTransfer, hReply, psd);
 +						}
 +						else {
 +							// prepare the buffer
 +							ipcPrepareRequests(IPC_PACKET_SIZE, pipch, REQUEST_XFRFILES);
 +							// get all the files into the packet
 +							if (ipcGetFiles(pipch, Self->pDataObject, psd->hContact) == S_OK) {
 +								// need to wait for the ST to open the mapping object
 +								// since if we close it before it's opened it the data it
 +								// has will be undefined
 +								int replyBits = ipcSendRequest(hTransfer, hReply, pipch, 200);
 +								if (replyBits != REPLY_FAIL) // they got the files!
 +									hr = S_OK;
 +							}
 +						}
 +						// close the work object name
 +						CloseHandle(hReply);
 +					}
 +					// unmap it from this process
 +					UnmapViewOfFile(pipch);
 +				}
 +				// close the map
 +				CloseHandle(hMap);
 +			}
 +			// close the handle to the ST object name
 +			CloseHandle(hTransfer);
 +		}
 +	}
 +	return hr;
  }
 -function TShlComRec_InvokeCommand(Self: PContextMenu3_Interface;
 -   lpici: TCMInvokeCommandInfo): HResult; stdcall;
 +HRESULT TShlComRec::InvokeCommand(CMINVOKECOMMANDINFO *pici)
  {
 -  Result = RequestTransfer(Self->ptrInstance, LOWORD(UINT_PTR(lpici.lpVerb)));
 +	return RequestTransfer(this, LOWORD(UINT_PTR(pici->lpVerb)));
  }
 -function TShlComRec_HandleMenuMsgs(Self: PContextMenu3_Interface; uMsg: UINT; wParam: wParam;
 -  lParam: lParam; pResult: PLResult): HResult;
 -const
 -  WM_DRAWITEM = $002B;
 -  WM_MEASUREITEM = $002C;
 -
 -  dwi: PDrawItemStruct;
 -  msi: PMeasureItemStruct;
 -  psd: PMenuDrawInfo;
 -  ncm: TNonClientMetrics;
 -  hOldFont: HANDLE;
 -  hFont: HANDLE;
 -  tS: TSize;
 -  dx: Integer;
 -  hBr: HBRUSH;
 -  icorc: TRect;
 -  hMemDC: HDC;
 +HRESULT TShlComRec::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
  {
 -  pResult^ = Integer(true);
 -  if (uMsg = WM_DRAWITEM) && (wParam = 0) 
 -  {
 -    // either a main sub menu, a group menu | a contact
 -    dwi = PDrawItemStruct(lParam);
 -    UINT_PTR(psd) = dwi->itemData;
 -    // don't fill
 -    SetBkMode(dwi->HDC, TRANSPARENT);
 -    // where to draw the icon?
 -    icorc.Left = 0;
 -    // center it
 -    with dwi^ do
 -      icorc.Top = rcItem.Top + ((rcItem.Bottom - rcItem.Top) div 2) - (16 div 2);
 -    icorc.Right = icorc.Left + 16;
 -    icorc.Bottom = icorc.Top + 16;
 -    // draw for groups
 -    if (dtGroup in psd->fTypes) | (dtEntry in psd->fTypes) 
 -    {
 -      hBr = GetSysColorBrush(COLOR_MENU);
 -      FillRect(dwi->HDC, dwi->rcItem, hBr);
 -      DeleteObject(hBr);
 -      //
 -      if (ODS_SELECTED && dwi->itemState = ODS_SELECTED) 
 -      {
 -        // only do this for entry menu types otherwise a black mask
 -        // is drawn under groups
 -        hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 -        FillRect(dwi->HDC, dwi->rcItem, hBr);
 -        DeleteObject(hBr);
 -        SetTextColor(dwi->HDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
 -      } // if
 -      // draw icon
 -      with dwi^, icorc do
 -      {
 -        if (ODS_SELECTED && dwi->itemState) = ODS_SELECTED 
 -        {
 -          hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 -        }
 -        else
 -        {
 -          hBr = GetSysColorBrush(COLOR_MENU);
 -        } // if
 -        DrawIconEx(HDC, Left + 1, Top, psd->hStatusIcon, 16, 16, // width, height
 -          0, // step
 -          hBr, // brush
 -          DI_NORMAL);
 -        DeleteObject(hBr);
 -      } // with
 -      // draw the text
 -      with dwi^ do
 -      {
 -        inc(rcItem.Left, ((rcItem.Bottom - rcItem.Top) - 2));
 -        DrawText(HDC, psd->szText, psd->cch, rcItem, DT_NOCLIP | DT_NOPREFIX |
 -          DT_SINGLELINE | DT_VCENTER);
 -        // draw the name of the database text if it's there
 -        if psd->szProfile != NULL 
 -        {
 -          GetTextExtentPoint32(dwi->HDC, psd->szText, psd->cch, tS);
 -          inc(rcItem.Left, tS.cx + 8);
 -          SetTextColor(HDC, GetSysColor(COLOR_GRAYTEXT));
 -          DrawText(HDC, psd->szProfile, lstrlenA(psd->szProfile), rcItem,
 -            DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
 -        } // if
 -      } // with
 -    }
 -    else
 -    {
 -      // it's a contact!
 -      hBr = GetSysColorBrush(COLOR_MENU);
 -      FillRect(dwi->HDC, dwi->rcItem, hBr);
 -      DeleteObject(hBr);
 -      if ODS_SELECTED && dwi->itemState = ODS_SELECTED 
 -      {
 -        hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 -        FillRect(dwi->HDC, dwi->rcItem, hBr);
 -        DeleteObject(hBr);
 -        SetTextColor(dwi->HDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
 -      }
 -      // draw icon
 -      with dwi^, icorc do
 -      {
 -        if (ODS_SELECTED && dwi->itemState) = ODS_SELECTED 
 -        {
 -          hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 -        }
 -        else
 -        {
 -          hBr = GetSysColorBrush(COLOR_MENU);
 -        } // if
 -        DrawIconEx(HDC, Left + 2, Top, psd->hStatusIcon, 16, 16, // width, height
 -          0, // step
 -          hBr, // brush
 -          DI_NORMAL);
 -        DeleteObject(hBr);
 -      } // with
 -      // draw the text
 -      with dwi^ do
 -      {
 -        inc(rcItem.Left, (rcItem.Bottom - rcItem.Top) + 1);
 -        DrawText(HDC, psd->szText, psd->cch, rcItem, DT_NOCLIP | DT_NOPREFIX |
 -          DT_SINGLELINE | DT_VCENTER);
 -      } // with
 -    } // if
 -  }
 -  else if (uMsg = WM_MEASUREITEM) 
 -  {
 -    // don't check if it's really a menu
 -    msi = PMeasureItemStruct(lParam);
 -    UINT_PTR(psd) = msi->itemData;
 -    ncm.cbSize = sizeof(TNonClientMetrics);
 -    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @ncm, 0);
 -    // create the font used in menus, this font should be cached somewhere really
 -{$IFDEF FPC}
 -    hFont = CreateFontIndirect(@ncm.lfMenuFont);
 -{$ELSE}
 -    hFont = CreateFontIndirect(ncm.lfMenuFont);
 -{$ENDIF}
 -    hMemDC = Self->ptrInstance->hMemDC;
 -    // select in the font
 -    hOldFont = SelectObject(hMemDC, hFont);
 -    // default to an icon
 -    dx = 16;
 -    // get the size 'n' account for the icon
 -    GetTextExtentPoint32(hMemDC, psd->szText, psd->cch, tS);
 -    inc(dx, tS.cx);
 -    // main menu item?
 -    if psd->szProfile != NULL 
 -    {
 -      GetTextExtentPoint32(hMemDC, psd->szProfile, lstrlenA(psd->szProfile), tS);
 -      inc(dx, tS.cx);
 -    }
 -    // store it
 -    msi->itemWidth = dx + Integer(ncm.iMenuWidth);
 -    msi->itemHeight = Integer(ncm.iMenuHeight) + 2;
 -    if tS.cy > msi->itemHeight 
 -      inc(msi->itemHeight, tS.cy - msi->itemHeight);
 -    // clean up
 -    SelectObject(hMemDC, hOldFont);
 -    DeleteObject(hFont);
 -  }
 -  Result = S_OK;
 -}
 +	LRESULT Dummy;
 +	if (plResult == NULL)
 +		plResult = &Dummy;
 +
 +	SIZE tS;
 +	HBRUSH hBr;
 +
 +	*plResult = true;
 +	if (uMsg == WM_DRAWITEM && wParam == 0) {
 +		// either a main sub menu, a group menu | a contact
 +		DRAWITEMSTRUCT *dwi = (DRAWITEMSTRUCT*)lParam;
 +		TMenuDrawInfo *psd = (TMenuDrawInfo*)dwi->itemData;
 +		// don't fill
 +		SetBkMode(dwi->hDC, TRANSPARENT);
 +		// where to draw the icon?
 +		RECT icorc;
 +		icorc.left = 0;
 +		icorc.top = dwi->rcItem.top + ((dwi->rcItem.bottom - dwi->rcItem.top) / 2) - (16 / 2);
 +		icorc.right = icorc.left + 16;
 +		icorc.bottom = icorc.top + 16;
 +		// draw for groups
 +		if (psd->fTypes & (dtGroup | dtEntry)) {
 +			hBr = GetSysColorBrush(COLOR_MENU);
 +			FillRect(dwi->hDC, &dwi->rcItem, hBr);
 +			DeleteObject(hBr);
 +
 +			if (dwi->itemState & ODS_SELECTED) {
 +				// only do this for entry menu types otherwise a black mask
 +				// is drawn under groups
 +				hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 +				FillRect(dwi->hDC, &dwi->rcItem, hBr);
 +				DeleteObject(hBr);
 +				SetTextColor(dwi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
 +			}
 +			// draw icon
 +			if (dwi->itemState & ODS_SELECTED)
 +				hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 +			else
 +				hBr = GetSysColorBrush(COLOR_MENU);
 +
 +			DrawIconEx(dwi->hDC, icorc.left + 1, icorc.top, psd->hStatusIcon, 16, 16, 0, hBr, DI_NORMAL);
 +			DeleteObject(hBr);
 +
 +			// draw the text
 +			dwi->rcItem.left += dwi->rcItem.bottom - dwi->rcItem.top - 2;
 +			DrawTextA(dwi->hDC, psd->szText, psd->cch, &dwi->rcItem, DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
 +			// draw the name of the database text if it's there
 +			if (psd->szProfile != NULL) {
 +				GetTextExtentPoint32A(dwi->hDC, psd->szText, psd->cch, &tS);
 +				dwi->rcItem.left += tS.cx + 8;
 +				SetTextColor(dwi->hDC, GetSysColor(COLOR_GRAYTEXT));
 +				DrawTextA(dwi->hDC, psd->szProfile, lstrlenA(psd->szProfile), &dwi->rcItem, DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
 +			}
 +		}
 +		else {
 +			// it's a contact!
 +			hBr = GetSysColorBrush(COLOR_MENU);
 +			FillRect(dwi->hDC, &dwi->rcItem, hBr);
 +			DeleteObject(hBr);
 +			if (dwi->itemState & ODS_SELECTED) {
 +				hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 +				FillRect(dwi->hDC, &dwi->rcItem, hBr);
 +				DeleteObject(hBr);
 +				SetTextColor(dwi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
 +			}
 +			// draw icon
 +			if (dwi->itemState & ODS_SELECTED)
 +				hBr = GetSysColorBrush(COLOR_HIGHLIGHT);
 +			else
 +				hBr = GetSysColorBrush(COLOR_MENU);
 -function TShlComRec_HandleMenuMsg(Self: PContextMenu3_Interface; uMsg: UINT; wParam: wParam;
 -  lParam: lParam): HResult; stdcall;
 +			DrawIconEx(dwi->hDC, icorc.left + 2, icorc.top, psd->hStatusIcon, 16, 16, 0, hBr, DI_NORMAL);
 +			DeleteObject(hBr);
 -  Dummy: HResult;
 -{
 -  Result = TShlComRec_HandleMenuMsgs(Self, uMsg, wParam, lParam, @Dummy);
 +			// draw the text
 +			dwi->rcItem.left += dwi->rcItem.bottom - dwi->rcItem.top + 1;
 +			DrawTextA(dwi->hDC, psd->szText, psd->cch, &dwi->rcItem, DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
 +		}
 +	}
 +	else if (uMsg == WM_MEASUREITEM) {
 +		// don't check if it's really a menu
 +		MEASUREITEMSTRUCT *msi = (MEASUREITEMSTRUCT*)lParam;
 +		TMenuDrawInfo *psd = (TMenuDrawInfo*)msi->itemData;
 +		NONCLIENTMETRICSA ncm;
 +		ncm.cbSize = sizeof(ncm);
 +		SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
 +		// create the font used in menus, this font should be cached somewhere really
 +		HFONT hFont = CreateFontIndirectA(&ncm.lfMenuFont);
 +		// select in the font
 +		HFONT hOldFont = (HFONT)SelectObject(hMemDC, hFont);
 +		// default to an icon
 +		int dx = 16;
 +		// get the size 'n' account for the icon
 +		GetTextExtentPoint32A(hMemDC, psd->szText, psd->cch, &tS);
 +		dx += tS.cx;
 +		// main menu item?
 +		if (psd->szProfile != NULL) {
 +			GetTextExtentPoint32A(hMemDC, psd->szProfile, lstrlenA(psd->szProfile), &tS);
 +			dx += tS.cx;
 +		}
 +		// store it
 +		msi->itemWidth = dx + ncm.iMenuWidth;
 +		msi->itemHeight = ncm.iMenuHeight + 2;
 +		if (tS.cy > (int)msi->itemHeight) 
 +			msi->itemHeight += tS.cy - msi->itemHeight;
 +		// clean up
 +		SelectObject(hMemDC, hOldFont);
 +		DeleteObject(hFont);
 +	}
 +	return S_OK;
  }
 -function TShlComRec_HandleMenuMsg2(Self: PContextMenu3_Interface; uMsg: UINT; wParam: wParam;
 -  lParam: lParam; PLResult: Pointer { ^LResult } ): HResult; stdcall;
 -
 -  Dummy: HResult;
 +HRESULT TShlComRec::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
 -  // this will be null if a return value isn't needed.
 -  if PLResult = NULL 
 -    PLResult = @Dummy;
 -  Result = TShlComRec_HandleMenuMsgs(Self, uMsg, wParam, lParam, PLResult);
 +	return HandleMenuMsg2(uMsg, wParam, lParam, NULL);
  }
 -function TShlComRec_Create: PShlComRec;
 +/////////////////////////////////////////////////////////////////////////////////////////
 -  DC: HDC;
 +struct TClassFactoryRec : public IClassFactory
  {
 -  New(Result);
 -  { build all the function tables for interfaces }
 -  with Result->ShellExtInit_Interface do
 -  {
 -    { this is only owned by us... }
 -    ptrVTable = @vTable;
 -    { IUnknown }
 -    vTable.QueryInterface = @TShlComRec_QueryInterface;
 -    vTable.AddRef = @TShlComRec_AddRef;
 -    vTable.Release = @TShlComRec_Release;
 -    { IShellExtInit }
 -    vTable.Initialise = @TShlComRec_Initialise;
 -    { instance of a TShlComRec }
 -    ptrInstance = Result;
 -  }
 -  with Result->ContextMenu3_Interface do
 -  {
 -    ptrVTable = @vTable;
 -    { IUnknown }
 -    vTable.QueryInterface = @TShlComRec_QueryInterface;
 -    vTable.AddRef = @TShlComRec_AddRef;
 -    vTable.Release = @TShlComRec_Release;
 -    { IContextMenu }
 -    vTable.QueryContextMenu = @TShlComRec_QueryContextMenu;
 -    vTable.InvokeCommand = @TShlComRec_InvokeCommand;
 -    vTable.GetCommandString = @TShlComRec_GetCommandString;
 -    { IContextMenu2 }
 -    vTable.HandleMenuMsg = @TShlComRec_HandleMenuMsg;
 -    { IContextMenu3 }
 -    vTable.HandleMenuMsg2 = @TShlComRec_HandleMenuMsg2;
 -    { instance data }
 -    ptrInstance = Result;
 -  }
 -  { initalise variables }
 -  Result->RefCount = 1;
 -  Result->hDllHeap = HeapCreate(0, 0, 0);
 -  Result->hRootMenu = 0;
 -  Result->hRecentMenu = 0;
 -  Result->RecentCount = 0;
 -  Result->idCmdFirst = 0;
 -  Result->pDataObject = NULL;
 -  Result->ProtoIcons = NULL;
 -  Result->ProtoIconsCount = 0;
 -  // create an inmemory DC
 -  DC = GetDC(0);
 -  Result->hMemDC = CreateCompatibleDC(DC);
 -  ReleaseDC(0, DC);
 -  { keep count on the number of objects }
 -  inc(dllpublic.ObjectCount);
 -}
 -
 -{ IClassFactory }
 -
 -type
 -
 -  PVTable_IClassFactory = ^TVTable_IClassFactory;
 +	TClassFactoryRec() :
 +		RefCount(1)
 +		{	dllpublic.FactoryCount++;
 +		}
 -  TVTable_IClassFactory = record
 -    { IUnknown }
 -    QueryInterface: Pointer;
 -    AddRef: Pointer;
 -    Release: Pointer;
 -    { IClassFactory }
 -    CreateInstance: Pointer;
 -    LockServer: Pointer;
 -  }
 +	LONG RefCount;
 -  PClassFactoryRec = ^TClassFactoryRec;
 +	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
 +	ULONG   STDMETHODCALLTYPE AddRef(void);
 +	ULONG   STDMETHODCALLTYPE Release(void);
 -  TClassFactoryRec = record
 -    ptrVTable: PVTable_IClassFactory;
 -    vTable: TVTable_IClassFactory;
 -    { fields }
 -    RefCount: LongInt;
 -  }
 +	HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject);
 +	HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);
 +};
 -function TClassFactoryRec_QueryInterface(Self: PClassFactoryRec; const IID: TIID;  Obj): HResult; stdcall;
 +HRESULT TClassFactoryRec::QueryInterface(REFIID riid, void **ppvObject)
  {
 -  Pointer(Obj) = NULL;
 -  Result = E_NOTIMPL;
 +	*ppvObject = NULL;
 +	return E_NOTIMPL;
  }
 -function TClassFactoryRec_AddRef(Self: PClassFactoryRec): LongInt; stdcall;
 +ULONG TClassFactoryRec::AddRef()
  {
 -  inc(Self->RefCount);
 -  Result = Self->RefCount;
 +	return ++RefCount;
  }
 -function TClassFactoryRec_Release(Self: PClassFactoryRec): LongInt; stdcall;
 +ULONG TClassFactoryRec::Release()
  {
 -  dec(Self->RefCount);
 -  Result = Self->RefCount;
 -  if Result = 0 
 -  {
 -    Dispose(Self);
 -    dec(dllpublic.FactoryCount);
 -  } { if }
 +	ULONG result = --RefCount;
 +	if (result == 0) {
 +		delete this;
 +		dllpublic.FactoryCount--;
 +	}
 +	return result;
  }
 -function TClassFactoryRec_CreateInstance(Self: PClassFactoryRec; unkOuter: Pointer;
 -  const IID: TIID;  Obj): HResult; stdcall;
 -
 -  ShlComRec: PShlComRec;
 +HRESULT TClassFactoryRec::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
  {
 -  Pointer(Obj) = NULL;
 -  Result = CLASS_E_NOAGGREGATION;
 -  if unkOuter = NULL 
 -  {
 -    { Before Vista, the system queried for a IShell interface  queried for a context menu, Vista now
 -      queries for a context menu (| a shell menu)  QI()'s the other interface }
 -    if IsEqualIID(IID, IID_IContextMenu) 
 -    {
 -      Result = S_OK;
 -      ShlComRec = TShlComRec_Create;
 -      Pointer(Obj) = @ShlComRec->ContextMenu3_Interface;
 -    }
 -    if IsEqualIID(IID, IID_IShellExtInit) 
 -    {
 -      Result = S_OK;
 -      ShlComRec = TShlComRec_Create;
 -      Pointer(Obj) = @ShlComRec->ShellExtInit_Interface;
 -    } // if
 -  } // if
 -}
 +	*ppvObject = NULL;
 -function TClassFactoryRec_LockServer(Self: PClassFactoryRec; fLock: BOOL): HResult; stdcall;
 -{
 -  Result = E_NOTIMPL;
 +	if (pUnkOuter != NULL)
 +		return CLASS_E_NOAGGREGATION;
 +
 +	// Before Vista, the system queried for a IShell interface  queried for a context menu, Vista now
 +	// queries for a context menu (| a shell menu)  QI()'s the other interface
 +	if (riid == IID_IContextMenu) {
 +		TShlComRec *p = new TShlComRec();
 +		*ppvObject = (IContextMenu3*)p;
 +		return S_OK;
 +	}
 +	if (riid == IID_IShellExtInit) {
 +		TShlComRec *p = new TShlComRec();
 +		*ppvObject = (IContextMenu3*)p;
 +		return S_OK;
 +	}
 +
 +	return E_NOTIMPL;
  }
 -function TClassFactoryRec_Create: PClassFactoryRec;
 +HRESULT TClassFactoryRec::LockServer(BOOL)
  {
 -  New(Result);
 -  Result->ptrVTable = @Result->vTable;
 -  { IUnknown }
 -  Result->vTable.QueryInterface = @TClassFactoryRec_QueryInterface;
 -  Result->vTable.AddRef = @TClassFactoryRec_AddRef;
 -  Result->vTable.Release = @TClassFactoryRec_Release;
 -  { IClassFactory }
 -  Result->vTable.CreateInstance = @TClassFactoryRec_CreateInstance;
 -  Result->vTable.LockServer = @TClassFactoryRec_LockServer;
 -  { inital the variables }
 -  Result->RefCount = 1;
 -  { count the number of factories }
 -  inc(dllpublic.FactoryCount);
 +	return E_NOTIMPL;
  }
  //
 diff --git a/plugins/ShellExt/src/shlcom.h b/plugins/ShellExt/src/shlcom.h index 5b701b4bf6..6aa7377e8c 100644 --- a/plugins/ShellExt/src/shlcom.h +++ b/plugins/ShellExt/src/shlcom.h @@ -38,6 +38,8 @@  #define IGCS_HELPTEXT  GCS_HELPTEXTA
  #define IGCS_VALIDATE  GCS_VALIDATEA
 +#define HIPC_NOICONS   1
 +
  /////////////////////////////////////////////////////////////////////////////////////////
  struct TGroupNode
 @@ -111,12 +113,12 @@ struct THeaderIPC  /////////////////////////////////////////////////////////////////////////////////////////
 -struct TShlComRec
 +
 +struct TShlComRec : public IShellExtInit, public IContextMenu3
  {
 -	IShellExtInit *ShellExtInit_Interface;
 -	IContextMenu3 *ContextMenu3_Interface;
 +	TShlComRec();
 -	LONG RefCount;
 +	ULONG RefCount;
  	// this is owned by the shell after items are added 'n' is used to
  	// grab menu information directly via id rather than array indexin'
  	HMENU hRootMenu;
 @@ -125,21 +127,33 @@ struct TShlComRec  	// can do most of the cleanup, extremely lazy I know.
  	HANDLE hDllHeap;
  	// This is a submenu that recently used contacts are inserted into
 -	// the contact is inserted twice, once in its normal list (| group) && here
 +	// the contact is inserted twice, once in its normal list (or group) and here
  	// Note: These variables are global data, but refered to locally by each instance
  	// Do not rely on these variables outside the process enumeration.
  	HMENU hRecentMenu;
 -	ULONG RecentCount; // number of added items
 +	UINT  RecentCount; // number of added items
  	// array of all the protocol icons, for every running instance!
  	TSlotProtoIcons *ProtoIcons;
 -	int ProtoIconsCount;
 -	// maybe null, taken from IShellExtInit_Initalise() && AddRef()'d
 -	// only used if a Miranda instance is actually running && a user
 +	UINT ProtoIconsCount;
 +	// maybe null, taken from IShellExtInit_Initalise() and AddRef()'d
 +	// only used if a Miranda instance is actually running and a user
  	// is selected
  	IDataObject *pDataObject;
 -	// DC is used for font metrics && saves on creating && destroying lots of DC handles
 +	// DC is used for font metrics and saves on creating and destroying lots of DC handles
  	// during WM_MEASUREITEM
  	HDC hMemDC;
 +
 +	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
 +	ULONG   STDMETHODCALLTYPE AddRef(void);
 +	ULONG   STDMETHODCALLTYPE Release(void);
 +
 +	HRESULT STDMETHODCALLTYPE Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID);
 +
 +	HRESULT STDMETHODCALLTYPE QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
 +	HRESULT STDMETHODCALLTYPE InvokeCommand(CMINVOKECOMMANDINFO *pici);
 +	HRESULT STDMETHODCALLTYPE GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pReserved, LPSTR pszName, UINT cchMax);
 +	HRESULT STDMETHODCALLTYPE HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
 +	HRESULT STDMETHODCALLTYPE HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
  };
  struct TEnumData
 diff --git a/plugins/ShellExt/src/shlicons.h b/plugins/ShellExt/src/shlicons.h new file mode 100644 index 0000000000..8405bf69cc --- /dev/null +++ b/plugins/ShellExt/src/shlicons.h @@ -0,0 +1,21 @@ +
 +struct TWICBitmap : public IWICBitmapSource
 +{
 +	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
 +	virtual ULONG STDMETHODCALLTYPE AddRef(void);
 +	virtual ULONG STDMETHODCALLTYPE Release(void);
 +
 +   virtual HRESULT STDMETHODCALLTYPE GetSize(UINT *puiWidth, UINT *puiHeight);
 +   virtual HRESULT STDMETHODCALLTYPE GetPixelFormat(WICPixelFormatGUID *pPixelFormat);
 +   virtual HRESULT STDMETHODCALLTYPE GetResolution(double *pDpiX, double *pDpiY);
 +   virtual HRESULT STDMETHODCALLTYPE CopyPalette(IWICPalette *pIPalette);
 +   virtual HRESULT STDMETHODCALLTYPE CopyPixels(const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer);
 +};
 +
 +struct TImageFactory : public IImagingFactory
 +{
 +};
 +
 +TImageFactory* ARGB_GetWorker();
 +
 +HBITMAP ARGB_BitmapFromIcon(TImageFactory* Factory, HDC hdc, HICON hIcon);
 diff --git a/plugins/ShellExt/src/stdafx.h b/plugins/ShellExt/src/stdafx.h index f0f47bbb70..3c231ae4b1 100644 --- a/plugins/ShellExt/src/stdafx.h +++ b/plugins/ShellExt/src/stdafx.h @@ -3,6 +3,7 @@  #include <windows.h>
  #include <CommCtrl.h>
  #include <ShlObj.h>
 +#include <Wincodec.h>
  #include <string>
  | 
