registry.cpp

Go to the documentation of this file.
00001 // $Id: registry.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 /*
00099 
00100 
00101     registry.cpp
00102 
00103     Interface to the system registry, which provides a container for storing information about
00104     the app under Windows NT and Windows 95.
00105 */
00106 
00107 #include "camtypes.h"
00108 #include <comcat.h>
00109 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "registry.h"
00111 #include "camelot.h"
00112 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "product.h"
00114 #include "cversion.h"
00115 #include "brandinf.h"
00116 #include "appstate.h"
00117 //#include "rik.h"
00118 
00119 #include "sgrmfile.h"   // LibSettingsListItem
00120 
00121 // Code version.
00122 DECLARE_SOURCE("$Revision: 1282 $");
00123 
00124 CC_IMPLEMENT_MEMDUMP(SaveRegistryEntries, CC_CLASS_MEMDUMP)
00125 CC_IMPLEMENT_MEMDUMP(LoadRegistryEntries, CC_CLASS_MEMDUMP)
00126 
00127 
00128 // We need to use the correct filename parsing functions, depending on whether we are
00129 // a C/ASCII/ANSI or a Unicode build.
00130 #undef SPLITPATH
00131 #undef MAKEPATH
00132 
00133 #ifdef UNICODE
00134     // Wide-character versions.
00135     #define SPLITPATH           (_wsplitpath)
00136     #define MAKEPATH            (_wmakepath)
00137 #else
00138     // C/ASCII/ANSI versions.
00139     #define SPLITPATH           (_tsplitpath)
00140     #define MAKEPATH            (_tmakepath)
00141 #endif
00142 
00143 // This function, defined in HELPUSER.CPP, makes a short MS-DOS filename from an INT32 filename.
00144 extern BOOL MakeShortPath(LPTSTR lpszPath, size_t cchMaxLen);
00145 
00146 
00147 // WEBSTER - markn - 7/2/97
00148 // Always use PRODUCT_MANUFACTURER for the company reg name
00149 //#ifndef STANDALONE
00150 //  #define PRODUCT_COMPANY_REG_NAME    "Corel"
00151 //#else
00152 //  #define PRODUCT_COMPANY_REG_NAME    PRODUCT_MANUFACTURER        // ie. Xara Ltd
00153 //#endif
00154 
00155 
00156 // The following has been moved into product.h so that other bits can find out the program
00157 // name used by the registry
00158 /******************
00159 // This defines a different program (product) name for debug and retail builds.
00160 #ifdef _DEBUG
00161     #define PROGRAM_NAME        PRODUCT_PRODUCTNAME " (Debug)"
00162     #define PRODUCT_APP_DOC_ID  PRODUCT_PRODUCTNAME ".Document.Debug"
00163 #else
00164     #define PROGRAM_NAME        PRODUCT_PRODUCTNAME
00165     #define PRODUCT_APP_DOC_ID  PRODUCT_PRODUCTNAME ".Document"
00166 #endif
00167 ******************/
00168 
00169 
00170 
00171 Registry g_TheLocalRegistry;        // this isn't really, but makes it look nice
00172 
00173 /********************************************************************************************
00174 
00175 >   Registry* GetLocalRegistry()
00176 
00177     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00178     Created:    09/06/97
00179 
00180     Returns:    A pointer to the local registry
00181 
00182     Purpose:    Provides a proper interface to Registries and stuff
00183 
00184 ********************************************************************************************/
00185 Registry* GetLocalRegistry()
00186 {
00187     return &g_TheLocalRegistry;
00188 }
00189 
00190 
00191 
00192 
00193 // This defines the file extension the program uses for its document files.  Horrible, isn't it?
00194 //#define PROGRAM_DOC_EXTENSION ".xar"
00195 
00196 
00197 // This is our special registry application identifier string.  It's different for debug builds,
00198 // so that release versions of CorelXARA don't get screwed by developer's debug builds.
00199 TCHAR szCamelotAppRegistryID[] = TEXT(PRODUCT_APP_DOC_ID);
00200 
00201 // This holds the full path to our executable.
00202 TCHAR szCamelotExePath[_MAX_PATH];
00203 
00204 // This key holds the place in the registry to load and save the app's state.
00205 HKEY hAppStateRegKey = NULL;
00206 
00207 /********************************************************************************************
00208 
00209 >   String_256 GetProgramNameRegistryKey()
00210 
00211     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00212     Created:    18/02/97
00213     Returns:    The name that we use as the registry key when saving and loading preferences.
00214     Purpose:    Returns the name that should be used as the key when accessing the registry.
00215                 It should be mapped into HKEY_CURRENT_USER\Software as the base by the OS.
00216                 Used in CCamApp::InitPreferencesFilename() in the SetRegistryKey so that we
00217                 load and save data out to the registry instead of to ini files.
00218 
00219 ********************************************************************************************/
00220 
00221 String_256 GetProgramNameRegistryKey()
00222 {
00223     return TEXT( PRODUCT_MANUFACTURER "\\" PROGRAM_NAME );
00224 }
00225 
00226 /********************************************************************************************
00227 
00228 >   BOOL CheckForRegistryEntry(TCHAR * SubKeyName)
00229 
00230     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00231     Created:    18/02/97
00232     Returns:    True if entry found otherwise False.
00233     Purpose:    
00234 
00235 ********************************************************************************************/
00236 
00237 BOOL CheckForRegistryEntry(TCHAR* SubKeyName)
00238 {
00239     ERROR2IF(hAppStateRegKey == NULL, FALSE, "CheckForRegistryEntry: bad main app key");
00240     HKEY htest = OpenRegKey(hAppStateRegKey, SubKeyName);
00241 
00242     // If we opened the key succesfully then it was present
00243     if (htest != 0)
00244     {
00245         CloseRegKey(htest);
00246         return TRUE;
00247     }
00248 
00249     // we didn't open it successfully so it wasn't present
00250     return FALSE;
00251 }
00252 
00253 
00254 
00255 /********************************************************************************************
00256 
00257 >   BOOL ConvertCLSIDToString(const CLSID& ID, StringBase* const pString)
00258 
00259     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00260     Created:    08/07/97
00261 
00262     Purpose:    Converts a CLSID to a StringBase (39 characters if you've got it)
00263 
00264     Inputs:     ID: A CLSID to convert
00265     Returns:    TRUE it worked, FALSE if it didn't
00266 
00267 ********************************************************************************************/
00268 BOOL ConvertCLSIDToString(const CLSID& ID, StringBase* const pString)
00269 {
00270     BOOL fOk = TRUE;        // return this
00271     LPOLESTR pWString = 0;
00272     fOk = (StringFromCLSID(ID, &pWString) == S_OK);
00273 
00274 #ifndef _UNICODE
00275     if (fOk)
00276     {
00277         UINT32 Length = wcslen(pWString);
00278         ERROR2IF(Length != 38, FALSE, "Insufficient string size");
00279 
00280         // well it works ok for English
00281         TCHAR AString[40] = { TEXT('\0') };
00282         for (UINT32 i = 0; i <= Length; i++)
00283             AString[i] = TCHAR(pWString[i]);
00284 
00285         *pString = AString;
00286     }
00287 #else
00288     if (fOk) *pString = pWString;
00289 #endif
00290 
00291     CoTaskMemFree(pWString);
00292     return fOk;
00293 }
00294 
00295 
00296 /********************************************************************************************
00297 >   static BOOL UpdateInstanceVersion(HKEY hkProductKey,
00298                                       LPCTSTR pszThisVersion,
00299                                       DWORD dwThisBuildMajor, DWORD dwThisBuildMinor)
00300 
00301     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00302     Created:    8/10/95
00303     Inputs:     hkProductKey        the Product registry subkey to check/set version info
00304                 pszThisVersion      text form of this instance's version number, eg. "1.0"
00305                 dwThisBuildMajor    major build no of this instance
00306                 dwThisBuildMinor    minor build no of this instance
00307     Returns:    TRUE if this running version is the newest registered under the given subkey
00308     Purpose:    Private function that checks if this running instance is the newest
00309                 registered under the given product subkey, either HKEY_LOCAL_MACHINE or
00310                 HKEY_CURRENT_USER.  If there is no newer version/build registered already
00311                 then registers this instance's version info.
00312     SeeAlso:    InitRegistry; winoil\cversion.h
00313 ********************************************************************************************/
00314 
00315 static BOOL UpdateInstanceVersion(HKEY hkProductKey, 
00316                                   LPCTSTR pszThisVersion,
00317                                   DWORD dwThisBuildMajor, DWORD dwThisBuildMinor)
00318 {
00319     // Work out if this instance is the newest instance registered under the given product key.
00320     // NB. GetRegDword returns 0 if there is no value.
00321     DWORD dwNewestBuildMajor = GetRegDword(hkProductKey, TEXT("NewestBuildMajor"));
00322     DWORD dwNewestBuildMinor = GetRegDword(hkProductKey, TEXT("NewestBuildMinor"));
00323     String_256 strNewestVers(TEXT(""));
00324     BOOL fIsNewest = !GetRegString(hkProductKey, TEXT("NewestVersion"), &strNewestVers)
00325                   || (strNewestVers < pszThisVersion)
00326                   || (dwNewestBuildMajor < dwThisBuildMajor)
00327                   || (dwNewestBuildMinor < dwThisBuildMinor);
00328 
00329     // If it is the newest then write its version info to the given product key.
00330     if (fIsNewest)
00331     {
00332         // Write this stuff.
00333         SetRegValue(hkProductKey, TEXT("NewestVersion"),
00334                     REG_SZ, pszThisVersion, ::camStrlen(pszThisVersion) + 1);
00335         SetRegValue(hkProductKey, TEXT("NewestBuildMajor"),
00336                     REG_DWORD, &dwThisBuildMajor, sizeof(DWORD));
00337         SetRegValue(hkProductKey, TEXT("NewestBuildMinor"),
00338                     REG_DWORD, &dwThisBuildMinor, sizeof(DWORD));
00339     }
00340 
00341     // Return TRUE if this instance is the newest.
00342     return fIsNewest;
00343 }
00344 
00345 
00346 
00347 /********************************************************************************************
00348 >   BOOL InitRegistry()
00349 
00350     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00351     Created:    18/9/95
00352     Returns:    TRUE if successful.
00353     Purpose:    In the debug version makes sure the registry contains all the items the
00354                 installed normally puts in there.  Also gets the handle to the key where
00355                 app state information is stored.  Under Win32s does nothing.
00356     SeeAlso:    CreateRegKey; OpenRegKey; SetRegValue
00357 ********************************************************************************************/
00358 
00359 BOOL InitRegistry()
00360 {
00361 #ifndef EXCLUDE_FROM_RALPH
00362     // We need to set some command lines to run the program, both here and in appstate.cpp,
00363     // so get the path to the Camelot EXE.  NB. don't use that crap Marioism, the PathName
00364     // class, as it uses String_256s for full paths, but unfortunately _MAX_PATH is bigger
00365     // then that!
00366     if (::GetModuleFileName(AfxGetInstanceHandle(), szCamelotExePath, _MAX_PATH) == 0)
00367     {
00368         TRACEUSER( "JustinF", _T("GetModuleFileName failed in InitRegistry\n"));
00369         return FALSE;
00370     }
00371 
00372     // Make the path into its "short form", ie. 8.3 MS-DOS compatible.  This is necessary
00373     // as Windows NT doesn't like paths with spaces, even though it allows them.
00374 #ifdef _DEBUG
00375     ERROR3IF(!MakeShortPath(szCamelotExePath, _MAX_PATH), "MakeShortPath failed in InitRegistry");
00376 #else
00377     MakeShortPath(szCamelotExePath, _MAX_PATH);
00378 #endif
00379 
00380     // Under Windows 3.1 / Win32s we don't bother with anything else as there isn't a registry.
00381     if (IsWin32s() && !IsWin32c()) return TRUE;
00382 
00383     // We always create the following registry entries every time the program is started.
00384     // First, set up HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER with the app's version info keys.
00385     TCHAR szProductSubkey[] = TEXT("Software\\" PRODUCT_MANUFACTURER "\\" PROGRAM_NAME);
00386 //  HKEY hkProductLM = CreateRegKey(HKEY_LOCAL_MACHINE, szProductSubkey);
00387 //  ERROR2IF(hkProductLM == NULL, FALSE, "Can't create LOCAL_MACHINE/Product Subkey");
00388 
00389     HKEY hkProductCU = CreateRegKey(HKEY_CURRENT_USER,  szProductSubkey);
00390     ERROR2IF(hkProductCU == NULL, FALSE, "Can't create CURRENT_USER/Product Subkey");
00391 
00392     // Make some version info from the compilation definitions.
00393     TCHAR szThisVers[] = TEXT("Version " PRODUCT_VERSION_NO);
00394     DWORD dwThisBuildMajor = CAMELOT_VERSION_MAJOR, dwThisBuildMinor = CAMELOT_VERSION_MINOR;
00395 
00396     // Check and if necessary update the version information in the CURRENT_USER and
00397     // LOCAL_MACHINE keys.  We do this separately as the current user may not have access
00398     // to the newest version on the local machine.
00399 //  BOOL fIsNewestLM = UpdateInstanceVersion(hkProductLM,
00400 //                                           szThisVers,
00401 //                                           dwThisBuildMajor, dwThisBuildMinor);
00402 
00403     BOOL fIsNewestCU = UpdateInstanceVersion(hkProductCU,
00404                                              szThisVers,
00405                                              dwThisBuildMajor, dwThisBuildMinor);
00406 #ifdef _DEBUG
00407     if (/* fIsNewestLM || */ fIsNewestCU)
00408         TRACE( _T("Registering %s (%s)\n"), (LPCTSTR) szProductSubkey, (LPCTSTR) szThisVers);
00409 //  if (fIsNewestLM)
00410 //      TRACE( _T("- This is the newest version of Xara X registered on the local machine\n"));
00411     if (fIsNewestCU)
00412         TRACE( _T("- This is the newest version of Xara X registered to the current user\n"));
00413 #endif
00414 
00415     // Create a version subkey under the product subkeys.  We'll store the app's state under the
00416     // version key in Current Users.
00417 // ## Alex - removed "Version 3.0" from Registry!!
00418 //  hAppStateRegKey = CreateRegKey(hkProductCU, szThisVers);
00419     hAppStateRegKey = CreateRegKey(HKEY_CURRENT_USER, szProductSubkey); // same as hkProductCU
00420     ERROR2IF(hAppStateRegKey == NULL, FALSE, "Can't create CURRENT_USER/AppState Subkey");
00421 
00422 
00423 
00424     // OK, if we aren't the newest version on the local machine we don't do anything more, as
00425     // the rest is registering shell commands etc in LOCAL_MACHINE that should always work for
00426     // the newest version globally.
00427 //  if (!fIsNewestLM)
00428 //  {
00429 //      // We will leave the global hkAppStateRegKey open as we will close it in
00430 //      // DeInitRegistry, on shutdown.
00431 //      CloseRegKey(hkProductLM);
00432 //      CloseRegKey(hkProductCU);
00433 //      return TRUE;
00434 //  }
00435 
00436     // Create a version key under local machine as well.
00437 //  HKEY hkVersion = CreateRegKey(hkProductLM, szThisVers);
00438 //  ERROR2IF(hkVersion == NULL, FALSE, "Can't create LOCAL_MACHINE/AppState Subkey");
00439 //  CloseRegKey(hkVersion);
00440 
00441     // Next, register the filename extension.
00442 //  HKEY hkExtension = CreateRegKey(HKEY_CLASSES_ROOT, TEXT(PROGRAM_DOC_EXTENSION));
00443 //  ERROR2IF(hkExtension == NULL, FALSE, "Can't create " PROGRAM_DOC_EXTENSION " Subkey");
00444 
00445     
00446 /*
00447     THIS IS DONE BY MFC IN CCamApp::InitInstance FOR NOW . . .
00448 
00449     SetRegValue(hkExtension, NULL, REG_SZ, szCamelotAppRegistryID, sizeof(szCamelotAppRegistryID));
00450 
00451     // Next, register the application's identifier key.  NB. when we get OLE working we should
00452     // also register a short name for our docs.
00453     HKEY hkAppID = CreateRegKey(HKEY_CLASSES_ROOT, szCamelotAppRegistryID);
00454     ERROR2IF(hkAppID == NULL, FALSE, "Can't create CLASSES_ROOT/AppID Subkey");
00455 
00456     // Set the ID key's sole value to the human-readable form of the document name.
00457 #ifdef _DEBUG
00458     TCHAR szAppTypeHumanName[] = TEXT(PRODUCT_PRODUCTNAME  " Document (Debug)");
00459 #else
00460     TCHAR szAppTypeHumanName[] = TEXT(PRODUCT_PRODUCTNAME  " Document");
00461 #endif
00462     SetRegValue(hkAppID, NULL, REG_SZ, szAppTypeHumanName, sizeof(szAppTypeHumanName));
00463 
00464     // Work out the command lines for opening and printing a doc.  These are the app's full path
00465     // plus some parameters tagged on the end.
00466     TCHAR szOpenCmd[_MAX_PATH + 32];
00467     ::camStrcpy(szOpenCmd,  szCamelotExePath);
00468     ::camStrcat(szOpenCmd,  TEXT(" %1"));
00469 
00470     // Register some shell commands ...
00471     HKEY hkShellCmd = CreateRegKey(hkAppID, TEXT("shell"));
00472     ERROR2IF(hkShellCmd == NULL, FALSE, "Can't create AppID/shell Subkey");
00473     CloseRegKey(hkAppID);
00474 
00475     // ... such as the command-line used to open a doc.
00476     HKEY hkOpenVerb = CreateRegKey(hkShellCmd, TEXT("open"));
00477     ERROR2IF(hkOpenVerb == NULL, FALSE, "Can't create shell/open Subkey");
00478     HKEY hkOpenCmd  = CreateRegKey(hkOpenVerb, TEXT("command"));
00479     ERROR2IF(hkOpenCmd == NULL, FALSE, "Can't create open/command Subkey");
00480     SetRegValue(hkOpenCmd, NULL, REG_SZ, szOpenCmd, ::camStrlen(szOpenCmd) + 1);
00481     CloseRegKey(hkOpenVerb);
00482     CloseRegKey(hkOpenCmd);
00483 */
00484 
00485 #ifndef STANDALONE
00486 /*
00487     THIS IS DONE BY MFC IN CCamApp::InitInstance FOR NOW . . .
00488 
00489     // Build the command-line to print a doc (don't do print registration if this is the viewer).
00490     TCHAR szPrintCmd[_MAX_PATH + 32];
00491     ::camStrcpy(szPrintCmd, szCamelotExePath);
00492     ::camStrcat(szPrintCmd, TEXT(" /P %1"));
00493 
00494     // Register the command-line.
00495     HKEY hkPrintVerb = CreateRegKey(hkShellCmd, TEXT("print"));
00496     ERROR2IF(hkPrintVerb == NULL, FALSE, "Can't create shell/print Subkey");
00497     HKEY hkPrintCmd  = CreateRegKey(hkPrintVerb, TEXT("command"));
00498     ERROR2IF(hkPrintCmd == NULL, FALSE, "Can't create print/command Subkey");
00499     SetRegValue(hkPrintCmd, NULL, REG_SZ, szPrintCmd, ::camStrlen(szPrintCmd) + 1);
00500     CloseRegKey(hkShellCmd);
00501     CloseRegKey(hkPrintVerb);
00502     CloseRegKey(hkPrintCmd);
00503 */
00504     // Get the full path to the default document template.  We know it should be in the same
00505     // directory as the Camelot executable, so extract the path components of the EXE path.
00506     TCHAR szDrive[_MAX_DRIVE], szDirectory[_MAX_DIR], szFileName[_MAX_FNAME], szExtn[_MAX_EXT];
00507     SPLITPATH(szCamelotExePath, szDrive, szDirectory, szFileName, szExtn);
00508 
00509     /*
00510         Doesn't look like the next 4 lines are necessary? - seeing as the code which uses
00511         szDefDocPath is already commented out.
00512         Not to mention the fact that they don't work as expected - ie _R(IDS_DEFAULTDOCNAME)
00513         resource can't be loaded from main HINSTANCE yet? Just end up with bogus string
00514         "XXXXXXX" defaulted to in SmartLoadString(UINT32 modID, UINT32 resID, LPTCHAR buf, INT32 size)
00515         after call to ::LoadString( hInst, resID, buf, size ) fails.
00516         Is _R(IDS_DEFAULTDOCNAME) in a resource DLL perhaps rather than main exe?
00517         (Ilan 23/11/99)
00518     // Now put them back together, substituting the default doc's filename.
00519     TCHAR szDefDocPath[_MAX_PATH];  
00520     String_256 strDefDocName(_R(IDS_DEFAULTDOCNAME));
00521     MAKEPATH(szDefDocPath, szDrive, szDirectory, strDefDocName, TEXT(""));
00522     */
00523 //  TRACEUSER( "JustinF", _T("Default doc path is %s\n"), (LPCTSTR) szDefDocPath);
00524 
00525     // Next, register how the shell should create a new doc for us, by copying the default
00526     // document.  (The viewer has no default doc and can't create new docs).
00527 //  HKEY hkShellNew = CreateRegKey(hkExtension, TEXT("ShellNew"));
00528 //  ERROR2IF(hkShellNew == NULL, FALSE, "Can't create ShellNew Subkey");
00529 //  SetRegValue(hkShellNew, TEXT("FileName"), REG_SZ, szDefDocPath, ::camStrlen(szDefDocPath) + 1);
00530 //  CloseRegKey(hkShellNew);
00531 #endif
00532 
00533     // Success!
00534     return  /* CloseRegKey(hkProductLM) && */ 
00535             CloseRegKey(hkProductCU) 
00536             /* && CloseRegKey(hkExtension) */ ;
00537 #else
00538     return FALSE;
00539 #endif
00540 }
00541 
00542 
00543 
00544 /********************************************************************************************
00545 >   BOOL DeInitRegistry()
00546 
00547     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00548     Created:    15/2/96
00549     Returns:    TRUE if successful.
00550     Purpose:    Shuts down the Camelot registry system, releasing any keys it holds.
00551     SeeAlso:    InitRegistry
00552 ********************************************************************************************/
00553 
00554 BOOL DeInitRegistry()
00555 {
00556     if (hAppStateRegKey != NULL)
00557     {
00558         BOOL closed = CloseRegKey(hAppStateRegKey);
00559         hAppStateRegKey = NULL;
00560         return closed;
00561     }
00562 
00563     return TRUE;
00564 }
00565 
00566 
00567 
00568 /********************************************************************************************
00569 >   HKEY CreateRegKey(HKEY hKey, LPCTSTR lpcszSubKey, LPTSTR lpszClass = NULL)
00570 
00571     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00572     Created:    18/9/95
00573     Inputs:     hKey            the key to create a subkey under
00574                 lpcszSubkey     the subkey(s) to create
00575                 lpszClass       no idea what this is for, don't pass it
00576     Returns:    The handle of the newly created key.
00577     Purpose:    Creates a new subkey(s) under the given key.  Returns NULL if something
00578                 goes wrong.
00579     SeeAlso:    OpenRegKey, SetRegValue
00580 ********************************************************************************************/
00581 
00582 HKEY CreateRegKey(HKEY hKey, LPCTSTR lpcszSubKey, LPTSTR lpszClass)
00583 {
00584     ERROR2IF(hKey == NULL,FALSE,"SetRegValue bad registry key!");
00585     ERROR2IF(lpcszSubKey == NULL,FALSE,"SetRegValue bad registry key name!");
00586 
00587     // Try to create/open the given key.
00588     HKEY  hkReturn;
00589     DWORD dwDisposition;
00590 
00591     // Bodge fix to some bad code: We need to give an acces mask when creating the key
00592     // but the function's interface does not give us any indication of what access is needed
00593     // so just try an access mask that may well work.  (Before my change we were trying to open
00594     // all regestry keys with KEY_ALL_ACCESS which appears to upset NT 4.0 quite a lot).
00595     REGSAM access = KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE |
00596                     KEY_SET_VALUE | KEY_READ | KEY_WRITE;
00597 
00598     INT32 nResult = ::RegCreateKeyEx(hKey, lpcszSubKey, 0,
00599                                     (lpszClass != NULL) ? lpszClass : TEXT(""),
00600                                     REG_OPTION_NON_VOLATILE, access, NULL,
00601                                     &hkReturn, &dwDisposition);
00602 /*
00603 #ifdef _DEBUG
00604     if (nResult != ERROR_SUCCESS)
00605     {
00606         TCHAR szBuf[256];
00607         ::wsprintf(szBuf, TEXT("Failed - error %ld"), nResult);
00608         ::MessageBox(NULL, szBuf, TEXT("CreateRegKey"), MB_OK);
00609     }
00610 #endif
00611 */
00612     // Did it work?
00613     return (nResult == ERROR_SUCCESS) ? hkReturn : NULL;
00614 }
00615 
00616 
00617 
00618 /********************************************************************************************
00619 >   HKEY OpenRegKey(HKEY hKey, LPCTSTR lpcszSubKey)
00620 
00621     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00622     Created:    18/9/95
00623     Inputs:     hKey            the registry to open
00624                 lpcszSubKey     the sub-keys under hKey to open
00625     Returns:    The handle of the opened sub-key, or NULL if there isn't one.
00626     Purpose:    Opens a registry sub-key without creating it if it doesn't exist.
00627     SeeAlso:    CreateRegKey; SetRegValue
00628 ********************************************************************************************/
00629 
00630 HKEY OpenRegKey(HKEY hKey, LPCTSTR lpcszSubKey)
00631 {
00632     ERROR2IF(hKey == NULL,FALSE,"OpenRegKey bad registry key!");
00633     ERROR2IF(lpcszSubKey == NULL,FALSE,"OpenRegKey bad registry key name!");
00634 
00635     HKEY hkReturn;
00636 
00637     // Bodge fix to some bad code: We need to give an acces mask when creating the key
00638     // but the function's interface does not give us any indication of what access is needed
00639     // so just try an access mask that may well work.  (Before my change we were trying to open
00640     // all regestry keys with KEY_ALL_ACCESS which appears to upset NT 4.0 quite a lot).
00641     REGSAM access = KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE |
00642                     KEY_SET_VALUE | KEY_READ | KEY_WRITE;
00643                     
00644     INT32 nResult = ::RegOpenKeyEx(hKey, lpcszSubKey, 0, access, &hkReturn);
00645 
00646     if (nResult != ERROR_SUCCESS)
00647     {
00648         // Extra bodge: If the first open didn't work, try and get access with an easier going
00649         // access mask - this may make future calls on the returned HKEY fail (ie if they try to
00650         // write to it) but they were going to fail anyway.
00651         access = KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE | KEY_READ;
00652                         
00653         nResult = ::RegOpenKeyEx(hKey, lpcszSubKey, 0, access, &hkReturn);
00654     }
00655 
00656     // Did it work?
00657     return (nResult == ERROR_SUCCESS) ? hkReturn : NULL;
00658 }
00659 
00660 /********************************************************************************************
00661 >   HKEY OpenRegKey(HKEY hKey, LPCTSTR lpcszSubKey)
00662 
00663     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00664     Created:    18/9/95
00665     Inputs:     hKey            the registry to open
00666                 lpcszSubKey     the sub-keys under hKey to open
00667     Returns:    The handle of the opened sub-key, or NULL if there isn't one.
00668     Purpose:    Opens a registry sub-key without creating it if it doesn't exist.
00669     SeeAlso:    CreateRegKey; SetRegValue
00670 ********************************************************************************************/
00671 
00672 HKEY OpenRegKeyReadOnly(HKEY hKey, LPCTSTR lpcszSubKey)
00673 {
00674     ERROR2IF(hKey == NULL,FALSE,"OpenRegKeyReadOnly bad registry key!");
00675     ERROR2IF(lpcszSubKey == NULL,FALSE,"OpenRegKeyReadOnly bad registry key name!");
00676 
00677     HKEY hkReturn;
00678     INT32 nResult = ::RegOpenKeyEx(hKey, lpcszSubKey, 0, KEY_READ, &hkReturn);
00679 
00680     // Did it work?
00681     return (nResult == ERROR_SUCCESS) ? hkReturn : NULL;
00682 }
00683 
00684 
00685 /********************************************************************************************
00686 >   BOOL CloseRegKey(HKEY hKey)
00687 
00688     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00689     Created:    15/2/96
00690     Inputs:     hKey            the previously-opened registry to close and be done with
00691     Returns:    TRUE if successful.
00692     Purpose:    Closes a previously-opened handle to a registry key.
00693     SeeAlso:    OpenRegKey
00694 ********************************************************************************************/
00695 
00696 BOOL CloseRegKey(HKEY hKey)
00697 {
00698     return ::RegCloseKey(hKey) == ERROR_SUCCESS;
00699 }
00700 
00701 
00702 
00703 /********************************************************************************************
00704 >   BOOL GetRegValue(HKEY hKey, LPTSTR szValueName, LPDWORD pdwType,
00705                      LPVOID pvBuf, LPDWORD pdwBufSize)
00706 
00707     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00708     Created:    21/9/95
00709     Inputs:     hKey            registry key the value is under
00710                 szValueName     the name of the value
00711     Outputs:    pdwType         points to where to put the value's type
00712                 pvBuf           where to put the data
00713                 pdwBufSize      the size of the buffer that will receive the data
00714     Returns:    TRUE if successful, ie. the named value exists.
00715     Purpose:    Retrives a named value from a registry (sub)key
00716     SeeAlso:    SetRegValue
00717 ********************************************************************************************/
00718 
00719 BOOL GetRegValue(HKEY hKey, LPTSTR szValueName, LPDWORD pdwType, LPVOID pvBuf, LPDWORD pdwBufSize)
00720 {
00721     return ::RegQueryValueEx(hKey, szValueName, NULL, pdwType, (LPBYTE) pvBuf, pdwBufSize)
00722                 == ERROR_SUCCESS;
00723 }
00724 
00725 
00726 
00727 /********************************************************************************************
00728 >   BOOL SetRegValue(HKEY hKey, LPCTSTR lpcszValueName, DWORD dwType,
00729                      const VOID* pcData, DWORD cbData)
00730 
00731     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00732     Created:    18/9/95
00733     Inputs:     hKey                the key containing the value
00734                 lpcszValueName      the value's name or NULL if it's the key's only value
00735                 dwType              the type of the value
00736                 pcData              pointer to the value
00737                 cbData              size of the value in bytes
00738     Returns:    TRUE if successful.
00739     Purpose:    Write the given value to the given key.
00740     SeeAlso:    CreateRegKey; OpenRegKey
00741 ********************************************************************************************/
00742 
00743 BOOL SetRegValue(HKEY hKey, LPCTSTR lpcszValueName, DWORD dwType, const VOID* pcData, DWORD cbData)
00744 {
00745     ERROR2IF(hKey == NULL,FALSE,"SetRegValue bad registry key!");
00746     ERROR2IF(pcData == NULL,FALSE,"SetRegValue bad registry key name!");
00747 
00748     return ::RegSetValueEx(hKey, lpcszValueName, 0,
00749                            dwType, (CONST BYTE*) pcData, cbData) == ERROR_SUCCESS;
00750 }
00751 
00752 /********************************************************************************************
00753 >   BOOL SetRegDword(HKEY hKey, LPCTSTR lpcszValueName, INT32 Value)
00754 
00755     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00756     Created:    19/2/97
00757     Inputs:     hKey                the key containing the value
00758                 lpcszValueName      the value's name
00759                 Value               the value to write
00760     Returns:    TRUE if successful.
00761     Purpose:    Write the given value to the given key.
00762     SeeAlso:    CreateRegKey; OpenRegKey; CloseRegKey;
00763 ********************************************************************************************/
00764 
00765 BOOL SetRegDword(HKEY hKey, LPCTSTR lpcszValueName, DWORD Value)
00766 {
00767     ERROR2IF(hKey == NULL,FALSE,"SetRegDword bad registry key!");
00768     ERROR2IF(lpcszValueName == NULL,FALSE,"SetRegDword bad registry key name!");
00769 
00770     DWORD pcData = Value;
00771     return ::RegSetValueEx(hKey, lpcszValueName, 0,
00772                            REG_DWORD, (CONST BYTE*)&pcData, sizeof(DWORD)) == ERROR_SUCCESS;
00773 }
00774 
00775 /********************************************************************************************
00776 >   BOOL SetRegInt(HKEY hKey, LPCTSTR lpcszValueName, INT32 Value)
00777 
00778     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00779     Created:    19/2/97
00780     Inputs:     hKey                the key containing the value
00781                 lpcszValueName      the value's name
00782                 Value               the value to write
00783     Returns:    TRUE if successful.
00784     Purpose:    Write the given value to the given key.
00785     SeeAlso:    CreateRegKey; OpenRegKey; CloseRegKey;
00786 ********************************************************************************************/
00787 
00788 BOOL SetRegInt(HKEY hKey, LPCTSTR lpcszValueName, INT32 Value)
00789 {
00790     ERROR2IF(hKey == NULL,FALSE,"SetRegBool bad registry key!");
00791     ERROR2IF(lpcszValueName == NULL,FALSE,"SetRegBool bad registry key name!");
00792 
00793     DWORD pcData = Value;
00794     return ::RegSetValueEx(hKey, lpcszValueName, 0,
00795                            REG_DWORD, (CONST BYTE*)&pcData, sizeof(DWORD)) == ERROR_SUCCESS;
00796 }
00797 
00798 /********************************************************************************************
00799 >   BOOL SetRegBool(HKEY hKey, LPCTSTR lpcszValueName, INT32 Value)
00800 
00801     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00802     Created:    19/2/97
00803     Inputs:     hKey                the key containing the value
00804                 lpcszValueName      the value's name
00805                 Value               the value to write
00806     Returns:    TRUE if successful.
00807     Purpose:    Write the given value to the given key.
00808     SeeAlso:    CreateRegKey; OpenRegKey; CloseRegKey;
00809 ********************************************************************************************/
00810 
00811 BOOL SetRegBool(HKEY hKey, LPCTSTR lpcszValueName, BOOL Value)
00812 {
00813     ERROR2IF(hKey == NULL,FALSE,"SetRegBool bad registry key!");
00814     ERROR2IF(lpcszValueName == NULL,FALSE,"SetRegBool bad registry key name!");
00815 
00816     DWORD pcData = Value;
00817     return ::RegSetValueEx(hKey, lpcszValueName, 0,
00818                            REG_BINARY, (CONST BYTE*)&pcData, sizeof(DWORD)) == ERROR_SUCCESS;
00819 }
00820 
00821 /********************************************************************************************
00822 >   BOOL SetRegString(HKEY hKey, LPCTSTR lpcszValueName, String_256* str)
00823 
00824     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00825     Created:    19/2/97
00826     Inputs:     hKey                the key containing the value
00827                 lpcszValueName      the string's name
00828                 String              the string to write
00829     Returns:    TRUE if successful.
00830     Purpose:    Write the given string to the given key.
00831     SeeAlso:    CreateRegKey; OpenRegKey; CloseRegKey;
00832 ********************************************************************************************/
00833 
00834 BOOL SetRegString(HKEY hKey, LPCTSTR lpcszValueName, String_256* str)
00835 {
00836     ERROR2IF(hKey == NULL,FALSE,"SetRegString bad registry key!");
00837     ERROR2IF(lpcszValueName == NULL,FALSE,"SetRegString bad registry key name!");
00838     ERROR2IF(str == NULL,FALSE,"SetRegString bad string");
00839 
00840     return SetRegValue(hKey, lpcszValueName, REG_SZ, *str, str->Length());
00841 }
00842 
00843 
00844 /********************************************************************************************
00845 >   BOOL SetRegString(HKEY hKey, LPCTSTR lpcszValueName, TCHAR * str)
00846 
00847     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00848     Created:    19/2/97
00849     Inputs:     hKey                the key containing the value
00850                 lpcszValueName      the string's name
00851                 String              the string to write
00852     Returns:    TRUE if successful.
00853     Purpose:    Write the given string to the given key.
00854     SeeAlso:    CreateRegKey; OpenRegKey; CloseRegKey;
00855 ********************************************************************************************/
00856 
00857 BOOL SetRegString(HKEY hKey, LPCTSTR lpcszValueName, TCHAR * str)
00858 {
00859     ERROR2IF(hKey == NULL,FALSE,"SetRegString bad registry key!");
00860     ERROR2IF(lpcszValueName == NULL,FALSE,"SetRegString bad registry key name!");
00861     ERROR2IF(str == NULL,FALSE,"SetRegString bad string");
00862 
00863     return SetRegValue(hKey, lpcszValueName, REG_SZ, str, ::camStrlen(str));
00864 }
00865 
00866 
00867 /********************************************************************************************
00868 >   BOOL DeleteRegKey(HKEY hKey, LPCTSTR szSubKey)
00869 
00870     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00871     Created:    22/9/95
00872     Inputs:     hKey        the key containing the sub-key to delete
00873                 szSubKey    the sub-key to be deleted
00874     Returns:    TRUE if successful.
00875     Purpose:    Deletes a sub-key from the registry.  To be compatible with Windows NT
00876                 you may only delete a sub-key that has no sub-keys itself.
00877     SeeAlso:    CreateRegKey
00878 ********************************************************************************************/
00879 
00880 BOOL DeleteRegKey(HKEY hKey, LPCTSTR szSubKey)
00881 {
00882     return ::RegDeleteKey(hKey, szSubKey) == ERROR_SUCCESS;
00883 }
00884 
00885 
00886 /********************************************************************************************
00887 
00888 >   BOOL DeleteRegKeyAndSubKeys(HKEY hKey, LPCTSTR szSubKey)
00889 
00890     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00891     Created:    28/2/97
00892     Inputs:     hKey        the key containing the sub-key to delete
00893                 szSubKey    the sub-key to be deleted
00894     Returns:    TRUE if successful.
00895     Purpose:    Deletes a sub-key and all the sub- keys of that from the registry.
00896                 This is to be compatible with Windows NT as this can only delete a sub-key
00897                 that has no sub-keys itself.
00898                 It assumes that there are only sub-keys of the specified one i.e. it does not
00899                 recursively delete the sub-keys.
00900     SeeAlso:    DeleteRegKey;
00901 ********************************************************************************************/
00902 
00903 BOOL DeleteRegKeyAndSubKeys(HKEY hKey, LPCTSTR szSubKey)
00904 {
00905     ERROR2IF(hKey == NULL,FALSE,"DeleteRegKeyAndSubKeys bad registry key!");
00906     ERROR2IF(szSubKey == NULL,FALSE,"DeleteRegKeyAndSubKeys bad registry key name!");
00907         
00908     // To enumerate subkeys, an application should initially call the RegEnumKeyEx function
00909     // with the dwIndex parameter set to zero. The application should then increment the
00910     // dwIndex parameter and call RegEnumKeyEx until there are no more subkeys
00911     // (until the function returns ERROR_NO_MORE_ITEMS). 
00912     // The key identified by hKey must have been opened with KEY_ENUMERATE_SUB_KEYS access
00913     // (KEY_READ includes KEY_ENUMERATE_SUB_KEYS). Use the RegCreateKeyEx or RegOpenKeyEx
00914     // function to open the key. 
00915 
00916     // Open up the requested sub-key
00917     HKEY hSubKey = OpenRegKey(hKey, szSubKey);
00918     if (hSubKey == NULL)
00919         return FALSE;
00920     
00921     const INT32 buf_size = 256;
00922     DWORD dwIndex   = 0;                // index of subkey to enumerate 
00923     TCHAR Name[buf_size];               // buffer for subkey name
00924     DWORD cbName    = buf_size;         // size of subkey buffer 
00925     TCHAR Class[buf_size];              // buffer for class string 
00926     DWORD cbClass   = buf_size;         // size of class buffer 
00927     FILETIME ftLastWriteTime;           // time key last written to 
00928 
00929     INT32 nResult = ERROR_SUCCESS;
00930     // We are going to go through evaluating all the items and add them to a list
00931     // Then we will go through the list and delete the items.
00932     // Need to do this as otherwise the enum seems to miss out half the items!
00933     // We will use LibSettingsListItem as this is just a string stored as a list item
00934     // which is all we want.
00935     List *pRegItemsList = new List;
00936     if (pRegItemsList == NULL)
00937         return FALSE;
00938 
00939     String_256 KeyName;
00940     do
00941     {
00942         // reset the string sizes to their maximum for receiving data
00943         cbName  = buf_size;
00944         cbClass = buf_size;
00945         // Does another sub-key exist?
00946         nResult = ::RegEnumKeyEx(hSubKey, dwIndex, Name, &cbName, NULL, Class, &cbClass, &ftLastWriteTime);
00947         if (nResult == ERROR_SUCCESS)
00948         {
00949             // we found a sub-key and so delete it
00950             KeyName = Name;
00951             LibSettingsListItem *pLibSettingsItem = new LibSettingsListItem(&KeyName);
00952             pRegItemsList->AddTail((ListItem *)pLibSettingsItem);
00953             //DeleteRegKey(hSubKey, Name); 
00954         }
00955         
00956         // increment our indexing item and try again
00957         dwIndex ++;
00958 
00959     } while (nResult == ERROR_SUCCESS);
00960 
00961     // now go through and delete the items
00962     LibSettingsListItem *pLibSettingsItem = (LibSettingsListItem *)pRegItemsList->GetHead();
00963     while (pLibSettingsItem)
00964     {
00965         DeleteRegKey(hSubKey, *pLibSettingsItem->Line);
00966         pLibSettingsItem = (LibSettingsListItem *)pRegItemsList->GetNext(pLibSettingsItem); 
00967     }
00968 
00969     // delete all the list items and the list that we created
00970     pRegItemsList->DeleteAll();
00971     delete pRegItemsList;
00972 
00973     CloseRegKey(hSubKey);
00974     
00975     // now delete the main sub-key
00976     DeleteRegKey(hKey, szSubKey);
00977 
00978     return TRUE;
00979 }
00980 
00981 
00982 
00983 /********************************************************************************************
00984 >   DWORD GetRegDword(HKEY hKey, LPCTSTR szValueName)
00985 
00986     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00987     Created:    21/9/95
00988     Inputs:     hKey            the registry key the value is stored under
00989                 szValueName     the name of the value within the key
00990     Returns:    The value, or zero if the value isn't there or is of the wrong type.
00991                 If you need more control of errors then you should use the full
00992                 GetRegValue function.
00993     Purpose:    Retrieves a DWORD value form the registry.
00994     SeeAlso:    GetRegString; GetRegValue
00995 ********************************************************************************************/
00996 
00997 DWORD GetRegDword(HKEY hKey, LPCTSTR szValueName)
00998 {
00999     ERROR2IF(hKey == NULL,FALSE,"GetRegDword bad registry key!");
01000     ERROR2IF(szValueName == NULL,FALSE,"GetRegDword bad registry key name!");
01001 
01002     DWORD dwResult, dwType = REG_DWORD, dwSize = sizeof(DWORD);
01003     if (!GetRegValue(hKey, (LPTSTR) szValueName, &dwType, &dwResult, &dwSize) ||
01004         dwType != REG_DWORD || dwSize != sizeof(DWORD))
01005     {
01006         // Not there or wrong type so return zero.
01007         dwResult = 0;
01008     }
01009     return dwResult;
01010 }
01011 
01012 /********************************************************************************************
01013 >   INT32 GetRegInt(HKEY hKey, LPCTSTR szValueName)
01014 
01015     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01016     Created:    19/2/97
01017     Inputs:     hKey            the registry key the value is stored under
01018                 szValueName     the name of the value within the key
01019     Returns:    The value, or zero if the value isn't there or is of the wrong type.
01020                 If you need more control of errors then you should use the full
01021                 GetRegValue function.
01022     Purpose:    Retrieves an INT32 value form the registry.
01023     SeeAlso:    GetRegString; GetRegValue
01024 ********************************************************************************************/
01025 
01026 INT32 GetRegInt(HKEY hKey, LPCTSTR szValueName)
01027 {
01028     ERROR2IF(hKey == NULL,FALSE,"GetRegInt bad registry key!");
01029     ERROR2IF(szValueName == NULL,FALSE,"GetRegInt bad registry key name!");
01030 
01031     DWORD dwResult = 0;
01032     DWORD dwType = REG_DWORD;
01033     DWORD dwSize = sizeof(DWORD);
01034     if (!GetRegValue(hKey, (LPTSTR) szValueName, &dwType, &dwResult, &dwSize) ||
01035         dwType != REG_DWORD || dwSize != sizeof(DWORD))
01036     {
01037         // Not there or wrong type so return zero.
01038         dwResult = 0;
01039     }
01040     return (INT32)dwResult;
01041 }
01042 
01043 /********************************************************************************************
01044 >   BOOL GetRegBool(HKEY hKey, LPCTSTR szValueName)
01045 
01046     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01047     Created:    19/2/97
01048     Inputs:     hKey            the registry key the value is stored under
01049                 szValueName     the name of the value within the key
01050     Returns:    The value, or zero if the value isn't there or is of the wrong type.
01051                 If you need more control of errors then you should use the full
01052                 GetRegValue function.
01053     Purpose:    Retrieves a bool value form the registry.
01054     SeeAlso:    GetRegString; GetRegValue
01055 ********************************************************************************************/
01056 
01057 BOOL GetRegBool(HKEY hKey, LPCTSTR szValueName)
01058 {
01059     ERROR2IF(hKey == NULL,FALSE,"GetRegBool bad registry key!");
01060     ERROR2IF(szValueName == NULL,FALSE,"GetRegBool bad registry key name!");
01061 
01062     DWORD dwResult = 0;
01063     DWORD dwType = REG_DWORD;
01064     DWORD dwSize = sizeof(DWORD);
01065     if (!GetRegValue(hKey, (LPTSTR) szValueName, &dwType, &dwResult, &dwSize) ||
01066         (dwType != REG_DWORD && dwType != REG_BINARY) || dwSize != sizeof(DWORD))
01067     {
01068         // Not there or wrong type so return zero.
01069         dwResult = 0;
01070     }
01071     return (BOOL)dwResult;
01072 }
01073 
01074 /********************************************************************************************
01075 >   BOOL GetRegString(HKEY hKey, LPCTSTR szValueName, String_256* pOut)
01076 
01077     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01078     Created:    21/9/95
01079     Inputs:     hKey            the registry containing the value
01080                 szValueName     the name of the value
01081     Outputs:    pOut            pointer to a String_256 to receive the value
01082     Returns:    TRUE if successful, FALSE otherwise (eg. if the type is wrong).
01083     Purpose:    Retrieves a string from the registry.  If you need more control over
01084                 errors you should use the general GetRegValue function.
01085     Errors:     -
01086     SeeAlso:    GetRegDword; GetRegValue
01087 ********************************************************************************************/
01088 
01089 BOOL GetRegString(HKEY hKey, LPCTSTR szValueName, String_256* pOut)
01090 {
01091     ERROR2IF(hKey == NULL,FALSE,"GetRegString bad registry key!");
01092     ERROR2IF(szValueName == NULL,FALSE,"GetRegString bad registry key name!");
01093     ERROR2IF(pOut == NULL,FALSE,"GetRegString bad return string buffer!");
01094 
01095     DWORD dwType = REG_SZ, dwSize = 256;
01096     return GetRegValue(hKey, (LPTSTR) szValueName, &dwType, (LPTSTR) *pOut, &dwSize) &&
01097            dwType == REG_SZ && dwSize <= 256;
01098 }
01099 
01100 /********************************************************************************************
01101 >   BOOL GetRegString(HKEY hKey, LPCTSTR szValueName, TCHAR * str, UINT32 str_len = 256)
01102 
01103     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01104     Created:    10/9/97
01105     Inputs:     hKey            the registry containing the value
01106                 szValueName     the name of the value
01107                 str_len         size of the return buffer, defaults to 256
01108     Outputs:    str             pointer to a TCHAR buffer to receive the value
01109     Returns:    TRUE if successful, FALSE otherwise (eg. if the type is wrong).
01110     Purpose:    Retrieves a string from the registry.  If you need more control over
01111                 errors you should use the general GetRegValue function.
01112     Errors:     -
01113     SeeAlso:    GetRegDword; GetRegValue
01114 ********************************************************************************************/
01115 
01116 BOOL GetRegString(HKEY hKey, LPCTSTR szValueName, TCHAR * str, UINT32 str_len)
01117 {
01118     ERROR2IF(hKey == NULL,FALSE,"GetRegString bad registry key!");
01119     ERROR2IF(szValueName == NULL,FALSE,"GetRegString bad registry key name!");
01120     ERROR2IF(str == NULL,FALSE,"GetRegString bad return string buffer!");
01121 
01122     DWORD dwType = REG_SZ;
01123     DWORD dwSize = str_len;
01124     return GetRegValue(hKey, (LPTSTR) szValueName, &dwType, str, &dwSize) &&
01125            dwType == REG_SZ && dwSize <= str_len;
01126 }
01127 
01128 /********************************************************************************************
01129 / helper classes
01130 ********************************************************************************************/
01131 
01132 /********************************************************************************************
01133 
01134 >   BOOL SaveRegistryEntries::StartSaving(String_256 *pKeySpecifier, HKEY hSubKey = hAppStateRegKey)
01135 
01136     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01137     Created:    18/02/97
01138     Inputs:     pKeySpecifier   string specifying the key name to store the data under
01139                 hSubKey         the sub key to start the section under, defaults to the main
01140                                 program section of the regsitry
01141     Returns:    TRUE if successful.
01142     Purpose:    Starts the process of saving our a series of registry entries e.g. a pathname
01143                 list.
01144                 A sub-key to the main section can be specified so that instead of opening the
01145                 section <program> \ *pKeySpecifier it opens a sub-section to this.
01146 
01147 ********************************************************************************************/
01148 
01149 BOOL SaveRegistryEntries::StartSaving(String_256 *pKeySpecifier, HKEY hSubKey)
01150 {
01151     // Don't do this under Win32s.
01152     if (IsWin32s() && !IsWin32c()) return FALSE;
01153 
01154     ERROR2IF(hSubKey == NULL, FALSE, "SaveRegistryEntries::StartSaving Bad main app key");
01155     ERROR2IF(pKeySpecifier == NULL, FALSE, "SaveRegistryEntries::StartSaving Bad key specifier");
01156     ERROR2IF(m_hRegKey != NULL, FALSE, "SaveRegistryEntries::StartSaving hRegKey is already non-null");
01157 
01158     // Ensure the section is blank before we start saving any data
01159     DeleteRegKey(hSubKey, *pKeySpecifier);
01160 
01161     // First open/create a new sub-key under the app-state key for holding the data.
01162     // e.g. TEXT("Workspace\\MDI")
01163     // Use the passed in key which will default to the main app hAppStateRegKey if not supplied
01164     m_hRegKey = CreateRegKey(hSubKey, *pKeySpecifier);
01165     if (m_hRegKey == NULL)
01166     {
01167         ERROR3("Can't get a registry key in SaveRegistryEntries::StartSaving");
01168         return FALSE;
01169     }
01170 
01171     // Ensure the section is blank before we start saving any data
01172 /*  BOOL ok = TRUE;
01173     TCHAR buf[10];
01174     INT32 i = 0;
01175     while (ok)
01176     {
01177         wsprintf(buf, TEXT("%d"), i + 1);
01178         i++;
01179         ok = DeleteRegKey(m_hRegKey, buf);
01180     }
01181 */
01182     return TRUE;
01183 }
01184 
01185 /********************************************************************************************
01186 
01187 >   BOOL SaveRegistryEntries::SaveNextEntry(String_256 *pNextName)
01188 
01189     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01190     Created:    18/02/97
01191     Inputs:     pNextName   the next bit of data to be saved in the list
01192     Returns:    TRUE if successful.
01193     Purpose:    Saves out the next entry into the opened key.
01194 
01195 ********************************************************************************************/
01196 
01197 BOOL SaveRegistryEntries::SaveNextEntry(String_256 *pNextName)
01198 {
01199     if (m_hRegKey == NULL)
01200         return FALSE;
01201 
01202     // Cannot save out the item with a blank name so invent a unique name for it
01203     TCHAR buf[10];
01204     wsprintf(buf, TEXT("%d"), m_Counter + 1);
01205     m_Counter++;
01206 
01207     return SetRegValue(m_hRegKey, buf, REG_SZ, *pNextName, pNextName->Length() + 1);
01208 }
01209 
01210 /********************************************************************************************
01211 
01212 >   BOOL SaveRegistryEntries::StopSaving()
01213 
01214     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01215     Created:    18/02/97
01216     Returns:    TRUE if successful.
01217     Purpose:    Stops the process of saving our a series of registry entries e.g. a pathname
01218                 list.
01219 
01220 ********************************************************************************************/
01221 
01222 BOOL SaveRegistryEntries::StopSaving()
01223 {
01224     ERROR2IF(m_hRegKey == NULL, FALSE, "hRegKey is null");
01225     BOOL closed = CloseRegKey(m_hRegKey);
01226     m_hRegKey = NULL;
01227     return closed;
01228 }
01229 
01230 /********************************************************************************************
01231 
01232 >   SaveRegistryEntries::~SaveRegistryEntries()
01233 
01234     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01235     Created:    18/02/97
01236     Purpose:    Standard destructor.
01237 
01238 ********************************************************************************************/
01239 
01240 SaveRegistryEntries::~SaveRegistryEntries()
01241 {
01242     if (m_hRegKey != NULL)
01243         CloseRegKey(m_hRegKey);
01244     return;
01245 }
01246 
01247 
01248 
01249 
01250 /********************************************************************************************
01251 
01252 >   BOOL LoadRegistryEntries::StartLoading(String_256 *pKeySpecifier, HKEY hSubKey = hAppStateRegKey)
01253 
01254     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01255     Created:    18/02/97
01256     Inputs:     pKeySpecifier   string specifying the key name to store the data under
01257                 hSubKey         the sub key to start the section under, defaults to the main
01258                                 program section of the regsitry
01259     Returns:    TRUE if successful.
01260     Purpose:    Starts the process of saving our a series of registry entries e.g. a pathname
01261                 list.
01262                 A sub-key to the main section can be specified so that instead of opening the
01263                 section <program> \ *pKeySpecifier it opens a sub-section to this.
01264 
01265 ********************************************************************************************/
01266 
01267 BOOL LoadRegistryEntries::StartLoading(String_256 *pKeySpecifier, HKEY hSubKey)
01268 {
01269     // Don't do this under Win32s.
01270     if (IsWin32s() && !IsWin32c()) return FALSE;
01271 
01272     ERROR2IF(hSubKey == NULL, FALSE, "LoadRegistryEntries::StartLoading Bad main app key ");
01273     ERROR2IF(pKeySpecifier == NULL, FALSE, "LoadRegistryEntries::StartLoading Bad key specifier");
01274     ERROR2IF(m_hRegKey != NULL, FALSE, "LoadRegistryEntries::StartLoading hRegKey is already non-null");
01275 
01276     // First open a new sub-key under the app-state key for holding the data.
01277     // e.g. TEXT("Workspace\\MDI")
01278     // Use the passed in key which will default to the main app hAppStateRegKey if not supplied
01279     m_hRegKey = OpenRegKey(hSubKey, *pKeySpecifier);
01280     if (m_hRegKey == NULL)
01281     {
01282         // don't error as some people require this functionality
01283         //ERROR3("Can't get a registry key in LoadRegistryEntries::StartLoading");
01284         return FALSE;
01285     }
01286 
01287     return TRUE;
01288 }
01289 
01290 /********************************************************************************************
01291 
01292 >   BOOL LoadRegistryEntries::LoadNextEntry(String_256 *pNextName)
01293 
01294     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01295     Created:    18/02/97
01296     Inputs:     pNextName   the next bit of data loaded from the list
01297     Returns:    TRUE if successful.
01298     Purpose:    Loads in the next entry into the opened key.
01299 
01300 ********************************************************************************************/
01301 
01302 BOOL LoadRegistryEntries::LoadNextEntry(String_256 *pNextName)
01303 {
01304     if (m_hRegKey == NULL)
01305         return FALSE;
01306 
01307     // Cannot save out the item with a blank name so invent a unique name for it
01308     TCHAR buf[10];
01309     wsprintf(buf, TEXT("%d"), m_Counter + 1);
01310     m_Counter++;
01311 
01312     return GetRegString(m_hRegKey, buf, pNextName);
01313 }
01314 
01315 /********************************************************************************************
01316 
01317 >   BOOL LoadRegistryEntries::StopLoading()
01318 
01319     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01320     Created:    18/02/97
01321     Returns:    TRUE if successful.
01322     Purpose:    Stops the process of loading our a series of registry entries e.g. a pathname
01323                 list.
01324 
01325 ********************************************************************************************/
01326 
01327 BOOL LoadRegistryEntries::StopLoading()
01328 {
01329     ERROR2IF(m_hRegKey == NULL, FALSE, "hRegKey is null");
01330     BOOL closed = CloseRegKey(m_hRegKey);
01331     m_hRegKey = NULL;
01332     return closed;
01333 }
01334 
01335 /********************************************************************************************
01336 
01337 >   LoadRegistryEntries::~LoadRegistryEntries()
01338 
01339     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01340     Created:    18/02/97
01341     Purpose:    Standard destructor.
01342 
01343 ********************************************************************************************/
01344 
01345 LoadRegistryEntries::~LoadRegistryEntries()
01346 {
01347     if (m_hRegKey != NULL)
01348         CloseRegKey(m_hRegKey);
01349     return;
01350 }
01351 
01352 
01353 
01354 
01355 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
01356 //                                  R  E  G  I  S  T  R  Y
01357 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
01358 
01359 
01360 
01361 
01362 
01363 /********************************************************************************************
01364 
01365 >   BOOL Registry::InitializeProbe(ClassCategoryProbe& Probe)
01366 
01367     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01368     Created:    09/06/97
01369 
01370     Purpose:    The TemplateOp COM things are registered as implementing CATID
01371                 We can build a list of them at start up so the Webster Properties Dialog
01372                 shows them.
01373 
01374     Inputs:     Probe:  The ClassCategoryProbe to initialize with data specific to this
01375                         registry.
01376 
01377     Returns:    TRUE if successful, FALSE if not
01378 
01379     Notes:      Only works for the local registry no matter what
01380 
01381 ********************************************************************************************/
01382 BOOL Registry::InitializeProbe(ClassCategoryProbe& Probe)
01383 {
01384     return Probe.Init();
01385 }
01386 
01387 
01388 
01389 
01390 
01391 
01392 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
01393 //                      R  E  G  I  S  T  R  Y  E  N  T  R  Y
01394 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
01395 
01396 
01397 
01398 
01399 
01400 /********************************************************************************************
01401 
01402 >   virtual BOOL RegistryEntry::GetEmbeddedEntry(   const StringBase& Name, 
01403                                                     RegistryEntry* const pEntry) const
01404 
01405     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01406     Created:    09/06/97
01407 
01408     Purpose:    Returns a "subkey" of the given entry.
01409 
01410     Inputs:     Name:   The name of the subkey value (not Null String)
01411     Outputs:    pEntry: A pointer to the registry entry of the given Name.
01412 
01413 ********************************************************************************************/
01414 BOOL RegistryEntry::GetEmbeddedEntry(const StringBase& Name, RegistryEntry* const pEntry) const
01415 {
01416     pEntry->m_hKey = OpenRegKey(m_hKey, Name);
01417 
01418     return (pEntry->m_hKey != NULL);
01419 }
01420 
01421 
01422 /********************************************************************************************
01423 
01424 >   BOOL RegistryEntry::GetValue(const StringBase& ValueName, StringBase* const pValue)
01425 
01426     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01427     Created:    09/06/97
01428 
01429     Purpose:    Returns a value with the given name under this registry key.
01430 
01431     Inputs:     ValueName:  The name of the subkey value (Null String will work)
01432     Outputs:    pValue:     The data associated with the given name
01433 
01434     Returns:    TRUE if the value was found, FALSE if not
01435 
01436     Notes:      Only works for the local registry no matter what
01437 
01438 ********************************************************************************************/
01439 BOOL RegistryEntry::GetValue(const StringBase& ValueName, StringBase* const pValue)
01440 {
01441     ERROR2IF(pValue == NULL, FALSE, "NULL Args");
01442 
01443     DWORD dwType = REG_SZ, dwSize = pValue->MaxLength();
01444 
01445     return (::RegQueryValueEx(m_hKey, ValueName, NULL, &dwType, (LPBYTE)((LPTSTR)*pValue), &dwSize) == 
01446             ERROR_SUCCESS) && dwType == REG_SZ && dwSize <= DWORD(pValue->MaxLength());
01447 }
01448 
01449 
01450 
01451 
01452 
01454 
01455 
01456 
01457 
01458 
01459 const String_8 ClassRegistryEntry::s_CLSIDString = TEXT("CLSID\\");
01460 
01461 
01462 /********************************************************************************************
01463 
01464 >   BOOL ClassRegistryEntry::InitFromCLSID(const CLSID& ClassID)
01465 
01466     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01467     Created:    09/06/97
01468 
01469     Purpose:    Initializes this RegistryEntry so it represents an entry for the given CLSID.
01470                 Allows us to retrieve values from the CLSID's subkeys.
01471 
01472     Inputs:     ClassID:    The CLSID that is this RegistryEntry
01473 
01474     Returns:    TRUE if it worked, FALSE if not
01475 
01476     Notes:      Only works for the local registry no matter what
01477 
01478 ********************************************************************************************/
01479 BOOL ClassRegistryEntry::InitFromCLSID(const CLSID& ClassID)
01480 {
01481     BOOL Ok = TRUE;         // return this
01482 
01483     String_64 ClassIDString;
01484     Ok = ConvertCLSIDToString(ClassID, &ClassIDString);
01485 
01486     if (Ok)
01487     {
01488         String_64 KeyString = s_CLSIDString;
01489         KeyString += ClassIDString;
01490         m_hKey = OpenRegKey(HKEY_CLASSES_ROOT, KeyString);
01491         Ok = (m_hKey != NULL);
01492     }
01493 
01494     return Ok;
01495 }
01496 
01497 
01498 
01499 
01500 
01501 
01503 const String_32 VersionIndependentProgID::s_KeyName = TEXT("VersionIndependentProgID");
01504 
01505 
01506 VersionIndependentProgID::VersionIndependentProgID(const ClassRegistryEntry& CLSIDEntry)
01507 {
01508     CLSIDEntry.GetEmbeddedEntry(s_KeyName, this);
01509 }
01510 
01511 
01512 BOOL VersionIndependentProgID::GetName(StringBase* const pName)
01513 {
01514     return GetValue(NullString, pName);
01515 }
01516 
01517 
01518 
01519 
01520 
01521 
01522 
01523 
01524 
01525 /********************************************************************************************
01526 
01527 >   ClassCategoryProbe::ClassCategoryProbe()
01528 
01529     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01530     Created:    09/06/97
01531 
01532     Purpose:    This default constructor should be followed by a call to
01533                 InitializeEnumerator() if you want it to work.
01534 
01535 ********************************************************************************************/
01536 ClassCategoryProbe::ClassCategoryProbe()
01537 {
01538     m_pEnumCLSID = NULL;
01539 }
01540 
01541 
01542 /********************************************************************************************
01543 
01544 >   BOOL ClassCategoryProbe::Init(const CATID& ComponentCategoryCLSID)
01545 
01546     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01547     Created:    09/06/97
01548 
01549     Inputs:     ComponentCategoryCLSID: The CLSID of the Component Category for which this
01550                                         probe will return CLSIDs of classes that implement
01551                                         the interfaces of that category.
01552 
01553     Returns:    S_OK if you're lucky
01554                 E_... if you're not
01555                 E_OUTOFMEMORY if the creation of ICatInformation failed in any way.
01556 
01557     Purpose:    This is the second part of the two part constructor. It can fail.
01558                 I wanted the names of Template handler/op things from the registry which are
01559                 under CATID
01560 
01561     Notes:      There should probably be another argument that the registry passes in (for
01562                 remote registries etc)
01563 
01564 ********************************************************************************************/
01565 BOOL ClassCategoryProbe::Init()
01566 {
01567     // Don't try the enumeration more than once 'cos I haven't checked it will work
01568     ERROR2IF(m_pEnumCLSID != NULL, FALSE, "NULL Args");
01569 
01570     HRESULT Result = S_OK;
01571 
01572     ICatInformation* const pCatInformer = CreateCatInformer();
01573     if (pCatInformer == NULL)
01574     {
01575         Result = E_OUTOFMEMORY;
01576     }
01577 
01578     // Create an enumerator for all the CLSIDs in the given component category
01579     if (SUCCEEDED(Result))
01580     {
01581         CATID Implements = GetCategoryID();
01582 
01583         Result = pCatInformer->EnumClassesOfCategories(
01584                                 1,              //Number of category IDs in the rgcatidImpl array
01585                                 &Implements,    //Array of category identifiers
01586                                 0,              //Number of category IDs in the rgcatidReq array
01587                                 &Implements,    //Array of category identifiers
01588                                 &m_pEnumCLSID   //Location in which to return an IEnumCLSID interface 
01589                                        );
01590     }
01591 
01592     // Get rid of our local ICatInfo
01593     if (pCatInformer != NULL)
01594     {
01595         pCatInformer->Release();
01596     }
01597 
01598     // Get the first CLSID so it's returned by GetNextCLSID and IsLast works properly
01599     if (SUCCEEDED(Result))
01600     {
01601         Result = m_pEnumCLSID->Next(1,                      //Number of elements requested
01602                                     &m_NextCLSIDToReturn,   //Array of the elements
01603                                     NULL                    //Pointer to the number of elements actually supplied
01604                                     );
01605 
01606         if (Result == S_FALSE)
01607         {
01608             // There weren't any CLSIDs so make this the NULL probe
01609             m_pEnumCLSID->Release();
01610             m_pEnumCLSID = NULL;
01611         }
01612     }
01613 
01614     return SUCCEEDED(Result);
01615 }
01616 
01617 
01618 /********************************************************************************************
01619 
01620 >   ICatInformation* ClassCategoryProbe::CreateCatInformer()
01621 
01622     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01623     Created:    09/06/97
01624 
01625     Returns:    An ICatInformation interface.
01626                 NULL if it failed in any way
01627 
01628     Purpose:    Support function to get us an instance of ICatInformation. Don't forget to
01629                 Release it.
01630 
01631     Notes:      It should probably have an argument giving the registry to use
01632 
01633 ********************************************************************************************/
01634 ICatInformation* ClassCategoryProbe::CreateCatInformer()
01635 {
01636     HRESULT Result = S_OK;
01637 
01638     ICatInformation* pCatInformer = NULL;
01639 
01640     Result = CoCreateInstance(  CLSID_StdComponentCategoriesMgr,    //Class identifier (CLSID) of the object
01641                                 NULL,                   //Pointer to whether object is or isn't part of an aggregate 
01642                                 CLSCTX_INPROC_SERVER,   //Context for running executable code
01643                                 IID_ICatInformation,    //Reference to the identifier of the interface
01644                                 (LPVOID*)&pCatInformer  //Indirect pointer to requested interface
01645                             );
01646     if (FAILED(Result))
01647     {
01648         TRACE( _T("ClassCategoryProbe::CreateCatInfoInterface failed with %x\n"), Result);
01649     }
01650 
01651     return pCatInformer;
01652 }
01653 
01654 
01655 /********************************************************************************************
01656 
01657 >   ClassCategoryProbe::ClassCategoryProbe(const ClassCategoryProbe& OtherProbe)
01658 
01659     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01660     Created:    09/06/97
01661 
01662     Purpose:    This copy constructor stops any COM objects disappearing between copies.
01663 
01664 ********************************************************************************************/
01665 ClassCategoryProbe::ClassCategoryProbe(const ClassCategoryProbe& OtherProbe)
01666 {
01667     m_pEnumCLSID = OtherProbe.m_pEnumCLSID;
01668     if (m_pEnumCLSID != NULL)
01669     {
01670         m_pEnumCLSID->AddRef();
01671     }
01672 }
01673 
01674 
01675 /********************************************************************************************
01676 
01677 >   ClassCategoryProbe::~ClassCategoryProbe()
01678 
01679     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01680     Created:    09/06/97
01681 
01682     Purpose:    This destructor Releases any COM objects
01683 
01684 ********************************************************************************************/
01685 ClassCategoryProbe::~ClassCategoryProbe()
01686 {
01687     if (m_pEnumCLSID != NULL)
01688     {
01689         m_pEnumCLSID->Release();
01690         m_pEnumCLSID = NULL;
01691     }
01692 }
01693 
01694 
01695 /********************************************************************************************
01696 
01697 >   BOOL ClassCategoryProbe::GetNextEntry(ClassRegistryEntry* const pEntry)
01698 
01699     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01700     Created:    09/06/97
01701 
01702     Purpose:    Does the enumeration returning the ClassRegistryEntry of the next class in the
01703                 category.
01704 
01705     Outputs:    The next RegistryEntry in the enumeration
01706     Returns:    TRUE if all was OK, FALSE otherwise
01707 
01708 ********************************************************************************************/
01709 BOOL ClassCategoryProbe::GetNextEntry(ClassRegistryEntry* const pEntry)
01710 {
01711     BOOL Ok = TRUE;
01712 
01713     CLSID NextCLSID;
01714     Ok = GetNextCLSID(&NextCLSID);
01715 
01716     if (Ok)
01717     {
01718         Ok = pEntry->InitFromCLSID(NextCLSID);
01719     }
01720 
01721     return Ok;
01722 }
01723 
01724 
01725 /********************************************************************************************
01726 
01727 >   BOOL ClassCategoryProbe::GetNextCLSID(CLSID* const pNextCLSID)
01728 
01729     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01730     Created:    09/06/97
01731 
01732     Returns:    TRUE if all was OK, FALSE otherwise
01733 
01734     Purpose:    Does the enumeration returning the CLSID of any classes that implement
01735                 the Category for this probe.
01736 
01737 ********************************************************************************************/
01738 BOOL ClassCategoryProbe::GetNextCLSID(CLSID* const pNextCLSID)
01739 {
01740     HRESULT Result = S_OK;
01741 
01742     *pNextCLSID = m_NextCLSIDToReturn;
01743 
01744     if (m_pEnumCLSID != NULL)
01745     {
01746         Result = m_pEnumCLSID->Next(1,                      //Number of elements requested
01747                                     &m_NextCLSIDToReturn,   //Array of the elements
01748                                     NULL                    //Pointer to the number of elements actually supplied
01749                                     );
01750     }
01751     else
01752     {
01753         TRACE( _T("ClassCategoryProbe::operator++(INT32) - NULL m_pEnumCLSID\n"));
01754         Result = E_UNEXPECTED;
01755     }
01756 
01757     if (Result == S_FALSE)
01758     {
01759         // That was the last one so make this the NULL probe
01760         m_pEnumCLSID->Release();
01761         m_pEnumCLSID = NULL;
01762     }
01763 
01764     return SUCCEEDED(Result);
01765 }
01766 
01767 
01768 /********************************************************************************************
01769 
01770 >   BOOL ClassCategoryProbe::IsLast() const
01771 
01772     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01773     Created:    09/06/97
01774 
01775     Returns:    FALSE if there are any class id's to be had, otherwise TRUE
01776 
01777     Purpose:    Determines when to finish the enumeration
01778 
01779 ********************************************************************************************/
01780 BOOL ClassCategoryProbe::IsLast() const
01781 {
01782     return m_pEnumCLSID == NULL;
01783 }
01784 

Generated on Sat Nov 10 03:48:50 2007 for Camelot by  doxygen 1.4.4