#pragma option dll
#pragma option lst
#jumptomain NONE

#define _WINBASE_ TRUE
#define _ADVAPI_ TRUE
#define _WINGDI_ TRUE
#include <msvcrt.h-->
#include "class.h--"
#include "objs.hmm"
#include "#TLB_PLG.rc"

#define pluginname "DriveSpace [dp]" //"//
#define currentversion 1

// {4AE9A700-27A6-11d7-8D73-00C0DFF6ECCF}
GUID pluginCLSID={
  0x4ae9a700,0x27a6,0x11d7,0x8d,0x73,0x00,0xC0,0xdf,0xf6,0xec,0xCF };

/**************************************************************************
   global variables
**************************************************************************/

HINSTANCE   g_hResInst;
HINSTANCE   g_hInst;
UINT        g_DllRefCount;

#include "cmybtn.hmm"
#include "clsfact.hmm"

/**************************************************************************

   DllMain

**************************************************************************/

BOOL main( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved ) {
  SWITCH(ul_reason_for_call){
    case 1/*DLL_PROCESS_ATTACH*/:
      g_hInst = hModule;
      g_hResInst = hModule;
      BREAK;
    CASE 0/*DLL_PROCESS_DETACH*/:
      IF (g_hResInst)
      && (g_hResInst != g_hInst) {
        FreeLibrary(g_hResInst);
        g_hResInst = g_hInst;
      }
      break;
  }

  return TRUE;
}

/**************************************************************************

   DllRegisterServer

**************************************************************************/


_export DllRegisterServer(void) {
  IF(RegisterPlugin(g_hInst, #pluginCLSID, pluginname)) return SELFREG_E_CLASS;
  return S_OK;
}

/**************************************************************************

   DllUnregisterServer

**************************************************************************/

_export DllUnregisterServer(void) {
  IF(!UnregisterPlugin(#pluginCLSID)) return SELFREG_E_CLASS;
  return S_OK;
}


/**************************************************************************

   DllCanUnloadNow

**************************************************************************/

_export DllCanUnloadNow(void) {
  IF(g_DllRefCount)return S_FALSE;
  return S_OK;
}

/**************************************************************************

   DllGetClassObject

**************************************************************************/

_export DllGetClassObject( dword rclsid, dword riid, dword ppReturn) {
  dword pClassFactory;//CClassFactory *pClassFactory
  dword hResult;
  $pushad
  DSDWORD[ppReturn] = NULL;
  //if we don't support this classid, return the proper error code
  IF(!IsEqualCLSID(rclsid, #pluginCLSID)){
    hResult=CLASS_E_CLASSNOTAVAILABLE;
  }ELSE{
    //create a CClassFactory object and check it for validity
    pClassFactory=new CClassFactory(rclsid);
    IF(!pClassFactory){
       hResult=E_OUTOFMEMORY;
    }ELSE{
      //get the QueryInterface return for our return value
      //HRESULT hResult = pClassFactory->QueryInterface(riid, ppReturn);
      hResult=COMETHOD(pClassFactory,#IClassFactoryVtbl.QueryInterface,riid,ppReturn);

      //call Release to decement the ref count - creating the object set it to one
      //and QueryInterface incremented it - since its being used externally (not by
      //us), we only want the ref count to be 1
      COMETHOD(pClassFactory,#IClassFactoryVtbl.Release);//pClassFactory->Release();
    }
  }
  $popad
  //return the result from QueryInterface
  return hResult;
}

/**************************************************************************

   RegisterComCat

**************************************************************************/

BOOL PDKRegisterComCat(dword clsid,dword CatID)
{
  dword pcr;//      ICatRegister   *pcr;
  dword hr = S_OK ;

  CoInitialize(NULL);

  hr = CoCreateInstance(  #CLSID_StdComponentCategoriesMgr
                         ,NULL
                         ,1/*CLSCTX_INPROC_SERVER*/
                         ,#IID_ICatRegister
                         ,#pcr);

  IF(hr>=0){
    //hr = pcr->RegisterClassImplCategories(clsid, 1, &CatID);
    hr = COMETHOD(pcr,#ICatRegisterVtbl.RegisterClassImplCategories,clsid, 1, CatID);
    COMETHOD(pcr,#ICatRegisterVtbl.Release);//pcr->Release();
  }

  CoUninitialize();
  IF(hr>=0)RETURN 1;
  return 0;
}

/**************************************************************************

   RegisterServer

**************************************************************************/

struct DOREGSTRUCT{
  dword  hRootKey;
  char*  szSubKey;
  char*  lpszValueName;
  char*  szData;
};//DOREGSTRUCT, *LPDOREGSTRUCT;


char szModule[MAX_PATH];
char szTitle[MAX_PATH];
DOREGSTRUCT ClsidEntries[] = {
  HKEY_CLASSES_ROOT
   ,"CLSID\\%s"
   ,NULL
   ,#szTitle
 ,HKEY_CLASSES_ROOT
   ,"CLSID\\%s\\InprocServer32"
   ,NULL
   ,#szModule
 ,HKEY_CLASSES_ROOT
   ,"CLSID\\%s\\InprocServer32"
   ,"ThreadingModel"
   ,"Apartment"
 ,HKEY_LOCAL_MACHINE
   ,"Software\\True Software\\TrueLaunchBar\\plugins\\%s"
   ,NULL
   ,#szTitle
 ,HKEY_LOCAL_MACHINE
   ,"Software\\True Software\\TrueLaunchBar\\plugins\\%s\\Langs"
   ,NULL
   ,NULL
 ,NULL
   ,NULL
   ,NULL
   ,NULL
};

BOOL stdcall RegisterServer(dword g_hInst, dword clsid, dword lpszTitle){
  int      i;
  dword    hKey;
  dword    lResult;
  DWORD    dwDisp;
  char     szSubKey[MAX_PATH];
  char     szCLSID[MAX_PATH];
  char     szData[MAX_PATH];
  dword    pwsz;
  dword    pMalloc;//LPMALLOC pMalloc;

  lstrcpy(#szTitle,lpszTitle);
  //get the CLSID in string form
  StringFromIID(clsid, #pwsz);

  IF(pwsz){
    WideCharToMultiByte( CP_ACP
                        ,0
                        ,pwsz
                        ,-1
                        ,#szCLSID
                        ,sizeof(szCLSID)
                        ,NULL
                        ,NULL);
    //free the string
    CoGetMalloc(1, #pMalloc);
    COMETHOD(pMalloc,#IMallocVtbl.Free,pwsz);//pMalloc->Free(pwsz);
    COMETHOD(pMalloc,#IMallocVtbl.Release);//pMalloc->Release();
  }

  //get this app's path and file name
  GetModuleFileName(g_hInst, #szModule, sizeof(szModule));
  //register the CLSID entries
  for(i = 0; ClsidEntries[i].hRootKey; i++){
    //create the sub key string - for this case, insert the file extension
    wsprintf(#szSubKey, ClsidEntries[i].szSubKey, #szCLSID);

    lResult = RegCreateKeyEx(  ClsidEntries[i].hRootKey
                              ,#szSubKey
                              ,0
                              ,NULL
                              ,REG_OPTION_NON_VOLATILE
                              ,KEY_WRITE
                              ,NULL
                              ,#hKey
                              ,#dwDisp);

    IF(!lResult) && (ClsidEntries[i].szData){
      //if necessary, create the value string
      wsprintf(#szData, ClsidEntries[i].szData, #szModule);

      lResult = RegSetValueEx(   hKey
                                ,ClsidEntries[i].lpszValueName
                                ,0
                                ,REG_SZ
                                ,#szData
                                ,lstrlen(#szData) + 1);

      RegCloseKey(hKey);
    }
  }

  return TRUE;
}

BOOL UnregisterPlugin(dword clsid)
{
  char szSubKey[MAX_PATH];
  char szCLSID[MAX_PATH];
  dword pwsz;
  dword pMalloc;

  //get the CLSID in string form
  StringFromIID(clsid, #pwsz);

  IF(pwsz){
    WideCharToMultiByte( CP_ACP
                        ,0
                        ,pwsz
                        ,-1
                        ,#szCLSID
                        ,sizeof(szCLSID)
                        ,NULL
                        ,NULL);
    //free the string
    CoGetMalloc(1, #pMalloc);
    COMETHOD(pMalloc,#IMallocVtbl.Free,pwsz);//pMalloc->Free(pwsz);
    COMETHOD(pMalloc,#IMallocVtbl.Release);//pMalloc->Release();
  }

  wsprintf(#szSubKey, "CLSID\\%s", #szCLSID);
  SHDeleteKey(HKEY_CLASSES_ROOT, #szSubKey);

  return TRUE;
}

BOOL RegisterPlugin(dword g_hInst, dword clsid, dword lpszTitle)
{
        IF(!RegisterServer(g_hInst, clsid, lpszTitle))
           RETURN SELFREG_E_CLASS;
        IF(!PDKRegisterComCat(clsid, #CATID_TLBBUTTONS))
           RETURN SELFREG_E_CLASS;
        return S_OK;
}
