/*
 *  REGDB.C
 *
 *  Functions to query the registration database
 *
 *  OleStdGetMiscStatusOfClass
 *  OleStdGetDefaultFileFormatOfClass
 *  OleStdGetAuxUserType
 *  OleStdGetUserTypeOfClass
 *
 *    (c) Copyright Microsoft Corp. 1992-1994 All Rights Reserved
 *
 */

#if defined(USEHEADER)
#include "OleHeaders.h"
#endif

#if defined(__MWERKS__) && !defined(__powerc)
#pragma pointers_in_D0
#endif


#if defined(_MSC_VER) && defined(__powerc)
#include <msvcmac.h>
#endif


#define STRICT  1

#include <stdio.h>
#include <ctype.h>
#include <ole2.h>


#include "ole2ui.h"
#include "regdb.h"
#include "uidebug.h"
#include "common.h"

OLEDBGDATA

#if LATER

// Replacement for stdlib atol,
// which didn't work and doesn't take far pointers.
// Must be tolerant of leading spaces.
//
//
#ifndef _MSC_VER
#pragma segment RegDBSeg
#else
#pragma code_seg("RegDBSeg", "SWAPPABLE")
#endif
static LONG Atol(LPSTR lpsz)
{
    signed int sign = +1;
    UINT base = 10;
    LONG l = 0;

    if (NULL==lpsz)
    {
        OleDbgAssert (0);
        return 0;
    }
    while (isspace(*lpsz))
        lpsz++;

    if (*lpsz=='-')
    {
        lpsz++;
        sign = -1;
    }
    if (lpsz[0]=='0' && lpsz[1]=='x')
    {
        base = 16;
        lpsz+=2;
    }

    if (base==10)
    {
        while (isdigit(*lpsz))
        {
            l = l * base + *lpsz - '0';
            lpsz++;
        }
    }
    else
    {
        OleDbgAssert (base==16);
        while (isxdigit(*lpsz))
        {
            l = l * base + isdigit(*lpsz) ? *lpsz - '0' : toupper(*lpsz) - 'A' + 10;
            lpsz++;
        }
    }
    return l * sign;
}



/*
 * OleStdGetUserTypeOfClass(REFCLSID, LPSTR, UINT, HKEY)
 *
 * Purpose:
 *  Returns the user type (human readable class name) of the specified class.
 *
 * Parameters:
 *  rclsid          pointer to the clsid to retrieve user type of.
 *  lpszUserType    pointer to buffer to return user type in.
 *  cch             length of buffer pointed to by lpszUserType
 *  hKey            hKey for reg db - if this is NULL, then we
 *                   open and close the reg db within this function.  If it
 *                   is non-NULL, then we assume it's a valid key to the
 *                   \ root and use it without closing it. (useful
 *                   if you're doing lots of reg db stuff).
 *
 * Return Value:
 *  UINT            Number of characters in returned string.  0 on error.
 *
 */
#ifndef _MSC_VER
#pragma segment RegDBSeg
#else
#pragma code_seg("RegDBSeg", "SWAPPABLE")
#endif
STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid, LPSTR lpszUserType, UINT cch, HKEY hKey)
{

   LONG     dw;
   LONG     lRet;
   LPSTR    lpszCLSID, lpszProgID;
   BOOL     fFreeProgID = false;
   BOOL     bCloseRegDB = false;
   char     szKey[128];
   LPMALLOC lpIMalloc;

   if (!lpszUserType)
       return 0;

   *lpszUserType = '\0';
   if (hKey == NULL)
   {

     //Open up the root key.
     lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);

     if ((LONG)ERROR_SUCCESS!=lRet)
       return (UINT)false;

     bCloseRegDB = true;
   }

   // Get a string containing the class name
   StringFromCLSID(rclsid, &lpszCLSID);

   wsprintf(szKey, "CLSID\\%s", lpszCLSID);


   dw=cch;
   lRet = RegQueryValue(hKey, szKey, lpszUserType, &dw);

   if ((LONG)ERROR_SUCCESS!=lRet) {
       // Load 'Unknown Source' and 'Unknown Type' strings
       dw = (LONG)LoadString(ghInst, IDS_PSUNKNOWNTYPE, lpszUserType, cch);
   }

   if ( ((LONG)ERROR_SUCCESS!=lRet) && (CoIsOle1Class(rclsid)) )
   {
      // We've got an OLE 1.0 class, so let's try to get the user type
      // name from the ProgID entry.

      ProgIDFromCLSID(rclsid, &lpszProgID);
      fFreeProgID = true;

      dw = cch;
      lRet = RegQueryValue(hKey, lpszProgID, lpszUserType, &dw);

      if ((LONG)ERROR_SUCCESS != lRet)
        dw = 0;
   }


   if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc))
   {
       if (fFreeProgID)
         lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszProgID);

       lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszCLSID);
       lpIMalloc->lpVtbl->Release(lpIMalloc);
   }

   if (bCloseRegDB)
      RegCloseKey(hKey);

   return (UINT)dw;

}



/*
 * OleStdGetAuxUserType(RCLSID, WORD, LPSTR, int, HKEY)
 *
 * Purpose:
 *  Returns the specified AuxUserType from the reg db.
 *
 * Parameters:
 *  rclsid          pointer to the clsid to retrieve aux user type of.
 *  hKey            hKey for reg db - if this is NULL, then we
 *                   open and close the reg db within this function.  If it
 *                   is non-NULL, then we assume it's a valid key to the
 *                   \ root and use it without closing it. (useful
 *                   if you're doing lots of reg db stuff).
 *  wAuxUserType    which aux user type field to look for.  In 4/93 release
 *                  2 is short name and 3 is exe name.
 *  lpszUserType    pointer to buffer to return user type in.
 *  cch             length of buffer pointed to by lpszUserType
 *
 * Return Value:
 *  UINT            Number of characters in returned string.  0 on error.
 *
 */
#ifndef _MSC_VER
#pragma segment RegDBSeg
#else
#pragma code_seg("RegDBSeg", "SWAPPABLE")
#endif
STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
                                   WORD     wAuxUserType,
                                   LPSTR    lpszAuxUserType,
                                   int      cch,
                                   HKEY     hKey)
{
   HKEY     hThisKey;
   BOOL     fCloseRegDB = false;
   LONG     dw;
   LRESULT  lRet;
   LPSTR    lpszCLSID;
   LPMALLOC lpIMalloc;
   char     szKey[OLEUI_CCHKEYMAX];
   char     szTemp[32];

   lpszAuxUserType[0] = '\0';

   if (NULL == hKey)
   {
      lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hThisKey);

      if (ERROR_SUCCESS != lRet)
          return 0;
   }
   else
      hThisKey = hKey;

   StringFromCLSID(rclsid, &lpszCLSID);

   lstrcpy(szKey, "CLSID\\");
   lstrcat(szKey, lpszCLSID);
   wsprintf(szTemp, "\\AuxUserType\\%d", wAuxUserType);
   lstrcat(szKey, szTemp);

   dw = cch;

   lRet = RegQueryValue(hThisKey, szKey, lpszAuxUserType, &dw);

   if (ERROR_SUCCESS != lRet) {
     dw = 0;
     lpszAuxUserType[0] = '\0';
   }


   if (fCloseRegDB)
      RegCloseKey(hThisKey);

   if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc))
   {
       lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszCLSID);
       lpIMalloc->lpVtbl->Release(lpIMalloc);
   }

   return (UINT)dw;
}



/*
 * OleStdGetMiscStatusOfClass(REFCLSID, HKEY)
 *
 * Purpose:
 *  Returns the value of the misc status for the given clsid.
 *
 * Parameters:
 *  rclsid          pointer to the clsid to retrieve user type of.
 *  hKey            hKey for reg db - if this is NULL, then we
 *                   open and close the reg db within this function.  If it
 *                   is non-NULL, then we assume it's a valid key to the
 *                   \\CLSID root and use it without closing it. (useful
 *                   if you're doing lots of reg db stuff).
 *
 * Return Value:
 *  BOOL            true on success, false on failure.
 *
 */
#ifndef _MSC_VER
#pragma segment RegDBSeg
#else
#pragma code_seg("RegDBSeg", "SWAPPABLE")
#endif
STDAPI_(BOOL) OleStdGetMiscStatusOfClass(REFCLSID rclsid, HKEY hKey, DWORD FAR * lpdwValue)
{
   DWORD dw;
   LONG  lRet;
   LPSTR lpszCLSID;
   char  szKey[64];
   char  szMiscStatus[OLEUI_CCHKEYMAX];
   BOOL  bCloseRegDB = false;

   if (hKey == NULL)
   {

     //Open up the root key.
     lRet=RegOpenKey(HKEY_CLASSES_ROOT, "CLSID", &hKey);

     if ((LONG)ERROR_SUCCESS!=lRet)
       return false;

     bCloseRegDB = true;
   }

   // Get a string containing the class name
   StringFromCLSID(rclsid, &lpszCLSID);

   // Construct key
   lstrcpy(szKey, lpszCLSID);
   lstrcat(szKey, "\\MiscStatus");


   dw=OLEUI_CCHKEYMAX;
   lRet = RegQueryValue(hKey, szKey, (LPSTR)szMiscStatus, &dw);

   if ((LONG)ERROR_SUCCESS!=lRet)
   {
       OleStdFreeString(lpszCLSID, NULL);

       if (bCloseRegDB)
          RegCloseKey(hKey);

       return false;

   }

   *lpdwValue = Atol((LPSTR)szMiscStatus);

   OleStdFreeString(lpszCLSID, NULL);

   if (bCloseRegDB)
      RegCloseKey(hKey);

   return true;


}

#endif // LATER

/*
 * ResType OleStdGetDefaultFileFormatOfClass(REFCLSID, HKEY)
 *
 * Purpose:
 *  Returns the default file format of the specified class.
 *  this is entered in REGDB as follows:
 *      CLSID\{...}\DataFormats\DefaultFile = <cfFmt>
 *
 * Parameters:
 *  rclsid          pointer to the clsid to retrieve user type of.
 *  hKey            hKey for reg db- if this is NULL, then we
 *                   open and close the reg db within this function.  If it
 *                   is non-NULL, then we assume it's a valid key to the
 *                   \ root and use it without closing it. (useful
 *                   if you're doing lots of reg db stuff).
 *
 * Return Value:
 *  cfFmt   -- DefaultFile format
 *  NULL    -- failed to get default file format
 *
 */
#ifndef _MSC_VER
#pragma segment RegDBSeg
#else
#pragma code_seg("RegDBSeg", "SWAPPABLE")
#endif
STDAPI_(ResType) OleStdGetDefaultFileFormatOfClass(
        REFCLSID        rclsid,
        HKEY            hKey
)
{
   ResType cfFmt = 0;
   unsigned long dw;
   long  lRet;
   char* lpszCLSID;
   Boolean  bCloseRegDB = false;
   char  szKey[128];
   char  szDefaultFile[OLEUI_CCHKEYMAX];
   Boolean  bStatus = true;


   if (hKey == 0)
   {

     //Open up the root key.
     lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);

     if ((long)ERROR_SUCCESS!=lRet)
       return 0;

     bCloseRegDB = true;
   }


   // Get a string containing the class name
   StringFromCLSID(rclsid, &lpszCLSID);

   // Construct key
   sprintf(szKey, "CLSID\\%s\\DataFormats\\DefaultFile", lpszCLSID);
   OleStdFreeString(lpszCLSID, NULL);

   dw=OLEUI_CCHKEYMAX;
   lRet = RegQueryValue(hKey, szKey, szDefaultFile, (long*)&dw);

   if ((long)ERROR_SUCCESS!=lRet)
       bStatus = false;

#if LATER
   else {
       /* if the format is a number, then it should refer to one of the
       **    standard Windows formats.
       */
       if (isdigit(szDefaultFile[0]))
           cfFmt = (CLIPFORMAT)Atol(szDefaultFile);
       else
           cfFmt = RegisterClipboardFormat(szDefaultFile);
   }
#endif // LATER

   if (bCloseRegDB)
      RegCloseKey(hKey);

   return cfFmt;
}
