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