VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp@ 6542

Last change on this file since 6542 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.4 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#ifdef MOZ_LOGGING
39#define FORCE_PR_LOG /* Allow logging in the release build */
40#endif
41
42#include "nsIGenericFactory.h"
43
44#include "nsRegistry.h"
45#include "nsIEnumerator.h"
46#include "nsDirectoryService.h"
47#include "nsDirectoryServiceDefs.h"
48#include "nsAppDirectoryServiceDefs.h"
49#include "NSReg.h"
50#include "prmem.h"
51#include "prlock.h"
52#include "prlog.h"
53#include "prprf.h"
54#include "nsCRT.h"
55#include "nsMemory.h"
56
57#include "nsCOMPtr.h"
58#include "nsILocalFile.h"
59#include "nsIServiceManager.h"
60#include "nsTextFormatter.h"
61
62#ifdef XP_BEOS
63#include <FindDirectory.h>
64#include <Path.h>
65#endif
66
67/* extra locking for the paranoid */
68/* #define EXTRA_THREADSAFE */
69#ifndef EXTRA_THREADSAFE
70#define PR_Lock(x) (void)0
71#define PR_Unlock(x) (void)0
72#endif
73
74// Logging of debug output
75extern PRLogModuleInfo *nsComponentManagerLog;
76
77PRUnichar widestrFormat[] = { PRUnichar('%'),PRUnichar('s'),PRUnichar(0)};
78
79/*-------------------------------- nsRegistry ----------------------------------
80| This class implements the nsIRegistry interface using the functions |
81| provided by libreg (as declared in mozilla/modules/libreg/include/NSReg.h). |
82| |
83| Since that interface is designed to match the libreg function, this class |
84| is implemented with each member function being a simple wrapper for the |
85| corresponding libreg function. |
86| |
87| #define EXTRA_THREADSAFE if you are worried about libreg thread safety. |
88| It should not be necessary, but I'll leave in the code for the paranoid. |
89------------------------------------------------------------------------------*/
90
91#define NS_MOZILLA_DIR_PERMISSION 00700
92
93#include "nsRegistry.h"
94/*
95struct nsRegistry : public nsIRegistry {
96 // This class implements the nsISupports interface functions.
97 NS_DECL_ISUPPORTS
98
99 // This class implements the nsIRegistry interface functions.
100 NS_DECL_NSIREGISTRY
101
102 // ctor/dtor
103 nsRegistry();
104
105private:
106 ~nsRegistry();
107
108protected:
109 HREG mReg; // Registry handle.
110#ifdef EXTRA_THREADSAFE
111 PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
112#endif
113 char *mCurRegFile; // these are to prevent open from opening the registry again
114 nsWellKnownRegistry mCurRegID;
115
116 NS_IMETHOD Close();
117}; // nsRegistry
118*/
119
120#include "nsIFactory.h"
121/*----------------------------- nsRegistryFactory ------------------------------
122| Class factory for nsRegistry objects. |
123------------------------------------------------------------------------------*/
124struct nsRegistryFactory : public nsIFactory {
125 // This class implements the nsISupports interface functions.
126 NS_DECL_ISUPPORTS
127
128 // nsIFactory methods
129 NS_IMETHOD CreateInstance(nsISupports *,const nsIID &,void **);
130 NS_IMETHOD LockFactory(PRBool aLock);
131
132 // ctor
133 nsRegistryFactory();
134};
135
136
137/*--------------------------- nsRegSubtreeEnumerator ---------------------------
138| This class implements the nsIEnumerator interface and is used to implement |
139| the nsRegistry EnumerateSubtrees and EnumerateAllSubtrees functions. |
140------------------------------------------------------------------------------*/
141struct nsRegSubtreeEnumerator : public nsIRegistryEnumerator {
142 // This class implements the nsISupports interface functions.
143 NS_DECL_ISUPPORTS
144
145 // This class implements the nsIEnumerator interface functions.
146 NS_DECL_NSIENUMERATOR
147
148 // And our magic behind-the-back fast-path thing.
149 NS_DECL_NSIREGISTRYENUMERATOR
150
151 // ctor/dtor
152 nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all );
153 // virtual dtor since subclasses call our Release()
154 virtual ~nsRegSubtreeEnumerator();
155
156protected:
157 NS_IMETHOD advance(); // Implementation file; does appropriate NR_RegEnum call.
158 HREG mReg; // Handle to registry we're affiliated with.
159 RKEY mKey; // Base key being enumerated.
160 char mName[MAXREGPATHLEN]; // The name of the current key which is in mNext
161 REGENUM mEnum; // Corresponding libreg "enumerator".
162 REGENUM mNext; // Lookahead value.
163 PRUint32 mStyle; // Style (indicates all or some);
164 PRBool mDone; // Done flag.
165#ifdef EXTRA_THREADSAFE
166 PRLock *mregLock;
167#endif
168}; // nsRegSubtreeEnumerator
169
170
171/*--------------------------- nsRegValueEnumerator -----------------------------
172| This class is a variation on nsRegSubtreeEnumerator that allocates |
173| nsRegistryValue objects rather than nsRegistryNode objects. It also |
174| overrides certain functions to make sure the "value" oriented libreg |
175| functions used rather than the subtree oriented ones. |
176------------------------------------------------------------------------------*/
177struct nsRegValueEnumerator : public nsRegSubtreeEnumerator {
178 // Override CurrentItem to allocate nsRegistryValue objects.
179 NS_IMETHOD CurrentItem( nsISupports **result );
180
181 // Override advance() to use proper NR_RegEnumEntries.
182 NS_IMETHOD advance();
183
184 // ctor/dtor
185 nsRegValueEnumerator( HREG hReg, RKEY rKey );
186}; // nsRegValueEnumerator
187
188/*------------------------------ nsRegistryNode --------------------------------
189| This class implements the nsIRegistryNode interface. Instances are |
190| allocated by nsRegSubtreeEnumerator::CurrentItem. |
191------------------------------------------------------------------------------*/
192struct nsRegistryNode : public nsIRegistryNode {
193 // This class implements the nsISupports interface functions.
194 NS_DECL_ISUPPORTS
195
196 // This class implements the nsIRegistryNode interface functions.
197 NS_DECL_NSIREGISTRYNODE
198
199 // ctor
200 nsRegistryNode( HREG hReg, char *name, RKEY childKey );
201
202private:
203 ~nsRegistryNode();
204
205protected:
206 HREG mReg; // Handle to registry this node is part of.
207 char mName[MAXREGPATHLEN]; // Buffer to hold name.
208 RKEY mChildKey; // Key corresponding to mName
209#ifdef EXTRA_THREADSAFE
210 PRLock *mregLock;
211#endif
212}; // nsRegistryNode
213
214
215/*------------------------------ nsRegistryValue -------------------------------
216| This class implements the nsIRegistryValue interface. Instances are |
217| allocated by nsRegValueEnumerator::CurrentItem. |
218------------------------------------------------------------------------------*/
219struct nsRegistryValue : public nsIRegistryValue {
220 // This class implements the nsISupports interface functions.
221 NS_DECL_ISUPPORTS
222
223 // This class implements the nsIRegistryValue interface functions.
224 NS_DECL_NSIREGISTRYVALUE
225
226 // ctor
227 nsRegistryValue( HREG hReg, RKEY key, REGENUM slot );
228
229private:
230 ~nsRegistryValue();
231
232protected:
233 nsresult getInfo(); // Get registry info.
234 HREG mReg; // Handle to registry this node is part of.
235 RKEY mKey; // Key this node is under.
236 REGENUM mEnum; // Copy of corresponding content of parent enumerator.
237 REGINFO mInfo; // Value info.
238 char mName[MAXREGNAMELEN]; // Buffer to hold name.
239 REGERR mErr; // XXX This causes this class to be NON THREAD SAFE
240#ifdef EXTRA_THREADSAFE
241 PRLock *mregLock;
242#endif
243}; // nsRegistryValue
244
245
246/*----------------------------- regerr2nsresult --------------------------------
247| This utility function maps a REGERR value to a corresponding nsresult |
248| error code. |
249------------------------------------------------------------------------------*/
250static nsresult regerr2nsresult( REGERR err ) {
251 nsresult rv = NS_ERROR_UNEXPECTED;
252 switch( err ) {
253 case REGERR_OK:
254 rv = NS_OK;
255 break;
256
257 case REGERR_FAIL:
258 rv = NS_ERROR_FAILURE;
259 break;
260
261 case REGERR_NOMORE:
262 rv = NS_ERROR_REG_NO_MORE;
263 break;
264
265 case REGERR_NOFIND:
266 rv = NS_ERROR_REG_NOT_FOUND;
267 break;
268
269 case REGERR_PARAM:
270 case REGERR_BADTYPE:
271 case REGERR_BADNAME:
272 rv = NS_ERROR_INVALID_ARG;
273 break;
274
275 case REGERR_NOFILE:
276 rv = NS_ERROR_REG_NOFILE;
277 break;
278
279 case REGERR_MEMORY:
280 rv = NS_ERROR_OUT_OF_MEMORY;
281 break;
282
283 case REGERR_BUFTOOSMALL:
284 rv = NS_ERROR_REG_BUFFER_TOO_SMALL;
285 break;
286
287 case REGERR_NAMETOOLONG:
288 rv = NS_ERROR_REG_NAME_TOO_LONG;
289 break;
290
291 case REGERR_NOPATH:
292 rv = NS_ERROR_REG_NO_PATH;
293 break;
294
295 case REGERR_READONLY:
296 rv = NS_ERROR_REG_READ_ONLY;
297 break;
298
299 case REGERR_BADUTF8:
300 rv = NS_ERROR_REG_BAD_UTF8;
301 break;
302
303 }
304 return rv;
305}
306
307/*----------------------------- reginfo2DataType -------------------------------
308| This utility function converts the type field in the REGINFO structure to |
309| the corresponding nsIRegistry::DataType value. |
310------------------------------------------------------------------------------*/
311static void reginfo2DataType( const REGINFO &in, PRUint32 &out ) {
312 // Transfer information, based on entry type.
313 switch( in.entryType ) {
314 case REGTYPE_ENTRY_STRING_UTF:
315 out = nsIRegistry::String;
316 //out.length = in.entryLength;
317 break;
318
319 case REGTYPE_ENTRY_INT32_ARRAY:
320 out = nsIRegistry::Int32;
321 // Convert length in bytes to array dimension.
322 //out.length = in.entryLength / sizeof(PRInt32);
323 break;
324
325 case REGTYPE_ENTRY_BYTES:
326 out = nsIRegistry::Bytes;
327 //out.length = in.entryLength;
328 break;
329
330 case REGTYPE_ENTRY_FILE:
331 out = nsIRegistry::File;
332 //out.length = in.entryLength;
333 break;
334 }
335}
336
337/*----------------------------- reginfo2DataType -------------------------------
338| This utility function converts the length field in the REGINFO structure to |
339| the proper units (if type==Int32 array, we divide by sizeof(PRInt32)). |
340------------------------------------------------------------------------------*/
341static void reginfo2Length( const REGINFO &in, PRUint32 &out ) {
342 // Transfer information, based on entry type.
343 switch( in.entryType ) {
344 case REGTYPE_ENTRY_STRING_UTF:
345 out = in.entryLength;
346 break;
347
348 case REGTYPE_ENTRY_INT32_ARRAY:
349 // Convert length in bytes to array dimension.
350 out = in.entryLength / sizeof(PRInt32);
351 break;
352
353 case REGTYPE_ENTRY_BYTES:
354 out = in.entryLength;
355 break;
356
357 case REGTYPE_ENTRY_FILE:
358 out = in.entryLength;
359 break;
360 }
361}
362
363/*------------------------ nsISupports Implementation --------------------------
364| This code generates the implementation of the nsISupports member functions |
365| for each class implemented in this file. |
366------------------------------------------------------------------------------*/
367NS_IMPL_THREADSAFE_ISUPPORTS2(nsRegistry, nsIRegistry, nsIRegistryGetter)
368NS_IMPL_ISUPPORTS2( nsRegSubtreeEnumerator, nsIEnumerator,
369 nsIRegistryEnumerator)
370NS_IMPL_ISUPPORTS1( nsRegistryNode, nsIRegistryNode )
371NS_IMPL_ISUPPORTS1( nsRegistryValue, nsIRegistryValue )
372
373/*-------------------------- nsRegistry::nsRegistry ----------------------------
374| Vanilla nsRegistry constructor. |
375------------------------------------------------------------------------------*/
376nsRegistry::nsRegistry()
377 : mReg(0), mCurRegID(0) {
378#ifdef EXTRA_THREADSAFE
379 mregLock = PR_NewLock();
380#endif
381 NR_StartupRegistry();
382 return;
383}
384
385/*------------------------- nsRegistry::~nsRegistry ----------------------------
386| The dtor closes the registry file(if open). |
387------------------------------------------------------------------------------*/
388nsRegistry::~nsRegistry() {
389 if( mReg ) {
390 Close();
391 }
392#ifdef EXTRA_THREADSAFE
393 if (mregLock) {
394 PR_DestroyLock(mregLock);
395 }
396#endif
397 NR_ShutdownRegistry();
398 return;
399}
400
401/*----------------------------- nsRegistry::Open -------------------------------
402| If the argument is null, delegate to OpenDefault, else open the registry |
403| file. We first check to see if a registry file is already open and close |
404| it if so. |
405------------------------------------------------------------------------------*/
406NS_IMETHODIMP nsRegistry::Open( nsIFile *regFile ) {
407 REGERR err = REGERR_OK;
408
409 // Check for default.
410 if( !regFile ) {
411 return OpenWellKnownRegistry(nsIRegistry::ApplicationRegistry);
412 }
413
414 nsCAutoString regPath;
415 nsresult rv = regFile->GetNativePath(regPath);
416 if (NS_FAILED(rv)) return rv;
417
418#ifdef DEBUG_dp
419 printf("nsRegistry: Opening registry %s\n", regPath.get());
420#endif /* DEBUG_dp */
421
422 if (mCurRegID != nsIRegistry::None && mCurRegID != nsIRegistry::ApplicationCustomRegistry)
423 {
424 // Cant open another registry without closing explictly.
425 return NS_ERROR_INVALID_ARG;
426 }
427
428 // Do we have an open registry ?
429 if (mCurRegID != nsIRegistry::None)
430 {
431 PRBool equals;
432 if (mCurRegFile && NS_SUCCEEDED(mCurRegFile->Equals(regFile, &equals)) && equals)
433 {
434 // The right one is already open
435 return NS_OK;
436 }
437 else
438 {
439 // Opening a new registry without closing an already open one.
440 // This is an error.
441 return NS_ERROR_FAILURE;
442 }
443 }
444
445 // Open specified registry.
446 PR_Lock(mregLock);
447 err = NR_RegOpen(NS_CONST_CAST(char*,regPath.get()), &mReg);
448 PR_Unlock(mregLock);
449
450 mCurRegID = nsIRegistry::ApplicationCustomRegistry;
451
452 // No error checking for no mem. Trust me.
453 if (NS_FAILED(regFile->Clone(getter_AddRefs(mCurRegFile))))
454 mCurRegFile = nsnull; // not fatal
455
456 // Convert the result.
457 return regerr2nsresult( err );
458}
459
460static void
461EnsureDefaultRegistryDirectory() {
462#if defined(XP_UNIX) && !defined(XP_MACOSX)
463 // Create ~/.mozilla as that is the default place for the registry file
464
465 /* The default registry on the unix system is $HOME/.mozilla/registry per
466 * vr_findGlobalRegName(). vr_findRegFile() will create the registry file
467 * if it doesn't exist. But it wont create directories.
468 *
469 * Hence we need to create the directory if it doesn't exist already.
470 *
471 * Why create it here as opposed to the app ?
472 * ------------------------------------------
473 * The app cannot create the directory in main() as most of the registry
474 * and initialization happens due to use of static variables.
475 * And we dont want to be dependent on the order in which
476 * these static stuff happen.
477 *
478 * Permission for the $HOME/.mozilla will be Read,Write,Execute
479 * for user only. Nothing to group and others.
480 */
481 char *home = getenv("HOME");
482 if (home != NULL)
483 {
484 char dotMozillaDir[1024];
485 PR_snprintf(dotMozillaDir, sizeof(dotMozillaDir),
486 "%s/" MOZ_USER_DIR, home);
487 if (PR_Access(dotMozillaDir, PR_ACCESS_EXISTS) != PR_SUCCESS)
488 {
489 PR_MkDir(dotMozillaDir, NS_MOZILLA_DIR_PERMISSION);
490 PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
491 ("nsComponentManager: Creating Directory %s", dotMozillaDir));
492 }
493 }
494#endif /* XP_UNIX */
495
496#ifdef XP_BEOS
497 BPath p;
498 const char *settings = "/boot/home/config/settings";
499 if(find_directory(B_USER_SETTINGS_DIRECTORY, &p) == B_OK)
500 settings = p.Path();
501 char settingsMozillaDir[1024];
502 PR_snprintf(settingsMozillaDir, sizeof(settingsMozillaDir),
503 "%s/" MOZ_USER_DIR, settings);
504 if (PR_Access(settingsMozillaDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
505 PR_MkDir(settingsMozillaDir, NS_MOZILLA_DIR_PERMISSION);
506 PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
507 ("nsComponentManager: Creating Directory %s", settingsMozillaDir));
508 }
509#endif
510}
511
512/*----------------------------- nsRegistry::OpenWellKnownRegistry --------------
513| Takes a registry id and maps that to a file name for opening. We first check |
514| to see if a registry file is already open and close it if so. |
515------------------------------------------------------------------------------*/
516NS_IMETHODIMP nsRegistry::OpenWellKnownRegistry( nsWellKnownRegistry regid )
517{
518 REGERR err = REGERR_OK;
519
520 if (mCurRegID != nsIRegistry::None && mCurRegID != regid)
521 {
522 // Cant open another registry without closing explictly.
523 return NS_ERROR_INVALID_ARG;
524 }
525
526 if (mCurRegID == regid)
527 {
528 // Already opened.
529 return NS_OK;
530 }
531
532 nsresult rv;
533 nsCOMPtr<nsIFile> registryLocation;
534
535 PRBool foundReg = PR_FALSE;
536 nsCAutoString regFile;
537
538 switch ( (nsWellKnownRegistry) regid ) {
539 case ApplicationComponentRegistry:
540 NS_WARNING("ApplicationComponentRegistry is unsupported!");
541 break;
542 case ApplicationRegistry:
543 {
544 EnsureDefaultRegistryDirectory();
545 nsCOMPtr<nsIProperties> directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
546 if (NS_FAILED(rv)) return rv;
547 directoryService->Get(NS_APP_APPLICATION_REGISTRY_FILE, NS_GET_IID(nsIFile),
548 getter_AddRefs(registryLocation));
549
550 if (registryLocation)
551 {
552 foundReg = PR_TRUE;
553 rv = registryLocation->GetNativePath(regFile); // dougt fix...
554 // dveditz needs to fix his registry so that I can pass an
555 // nsIFile interface and not hack
556 if (NS_FAILED(rv))
557 return rv;
558 }
559 }
560 break;
561
562 default:
563 break;
564 }
565
566 if (foundReg == PR_FALSE) {
567 return NS_ERROR_REG_BADTYPE;
568 }
569
570#ifdef DEBUG_dp
571 printf("nsRegistry: Opening std registry %s\n", regFile.get());
572#endif /* DEBUG_dp */
573
574 PR_Lock(mregLock);
575 err = NR_RegOpen(NS_CONST_CAST(char*, regFile.get()), &mReg );
576 PR_Unlock(mregLock);
577
578 // Store the registry that was opened for optimizing future opens.
579 mCurRegID = regid;
580
581 // Convert the result.
582 return regerr2nsresult( err );
583}
584
585#if 0
586/*-------------------------- nsRegistry::OpenDefault ---------------------------
587| Open the "default" registry; in the case of this libreg-based implementation |
588| that is done by passing a null file name pointer to NR_RegOpen. |
589------------------------------------------------------------------------------*/
590NS_IMETHODIMP nsRegistry::OpenDefault() {
591 return OpenWellKnownRegistry(nsIRegistry::ApplicationRegistry);
592}
593#endif
594
595/*----------------------------- nsRegistry::Close ------------------------------
596| Tests the mReg handle and if non-null, closes the registry via NR_RegClose. |
597------------------------------------------------------------------------------*/
598NS_IMETHODIMP nsRegistry::Close() {
599 REGERR err = REGERR_OK;
600 if( mReg ) {
601 PR_Lock(mregLock);
602 err = NR_RegClose( mReg );
603 PR_Unlock(mregLock);
604 mReg = 0;
605 mCurRegFile = nsnull;
606 mCurRegID = 0;
607 }
608 return regerr2nsresult( err );
609}
610
611/*----------------------------- nsRegistry::Flush ------------------------------
612| Flushes the registry via NR_RegFlush. |
613------------------------------------------------------------------------------*/
614NS_IMETHODIMP nsRegistry::Flush() {
615 REGERR err = REGERR_FAIL;
616 if( mReg ) {
617 PR_Lock(mregLock);
618 err = NR_RegFlush( mReg );
619 PR_Unlock(mregLock);
620 }
621 return regerr2nsresult( err );
622}
623
624/*----------------------------- nsRegistry::IsOpen -----------------------------
625| Tests the mReg handle and returns whether the registry is open or not. |
626------------------------------------------------------------------------------*/
627NS_IMETHODIMP nsRegistry::IsOpen( PRBool *result ) {
628 *result = ( mReg != 0 );
629 return NS_OK;
630}
631
632
633/*--------------------------- nsRegistry::AddKey -------------------------------
634| Add a key into the registry or find an existing one. This is generally used |
635| instead of GetKey unless it's an error for the key not to exist already i
636------------------------------------------------------------------------------*/
637NS_IMETHODIMP nsRegistry::AddKey( nsRegistryKey baseKey, const PRUnichar *keyname, nsRegistryKey *_retval)
638{
639 if ( !keyname )
640 return NS_ERROR_NULL_POINTER;
641
642 return AddSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get(), _retval );
643}
644
645/*--------------------------- nsRegistry::GetKey -------------------------------
646| returns the nsRegistryKey associated with a given node in the registry |
647------------------------------------------------------------------------------*/
648NS_IMETHODIMP nsRegistry::GetKey(nsRegistryKey baseKey, const PRUnichar *keyname, nsRegistryKey *_retval)
649{
650 if ( !keyname || !_retval )
651 return NS_ERROR_NULL_POINTER;
652
653 return GetSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get(), _retval );
654}
655
656/*--------------------------- nsRegistry::RemoveKey ----------------------------
657| Delete a key from the registry |
658------------------------------------------------------------------------------*/
659NS_IMETHODIMP nsRegistry::RemoveKey(nsRegistryKey baseKey, const PRUnichar *keyname)
660{
661 if ( !keyname )
662 return NS_ERROR_NULL_POINTER;
663
664 return RemoveSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get() );
665}
666
667NS_IMETHODIMP nsRegistry::GetString(nsRegistryKey baseKey, const PRUnichar *valname, PRUnichar **_retval)
668{
669 // Make sure caller gave us place for result.
670 if ( !valname || !_retval )
671 return NS_ERROR_NULL_POINTER;
672
673 // initialize the return value
674 *_retval = nsnull;
675 nsXPIDLCString tmpstr;
676
677 nsresult rv = GetStringUTF8( baseKey, NS_ConvertUCS2toUTF8(valname).get(), getter_Copies(tmpstr) );
678
679 if (NS_SUCCEEDED(rv))
680 {
681 *_retval = nsTextFormatter::smprintf( widestrFormat, tmpstr.get() );
682 if ( *_retval == nsnull )
683 rv = NS_ERROR_OUT_OF_MEMORY;
684 }
685
686 return rv;
687}
688
689NS_IMETHODIMP nsRegistry::SetString(nsRegistryKey baseKey, const PRUnichar *valname, const PRUnichar *value)
690{
691 if ( !valname || ! value )
692 return NS_ERROR_NULL_POINTER;
693
694 return SetStringUTF8( baseKey,
695 NS_ConvertUCS2toUTF8(valname).get(),
696 NS_ConvertUCS2toUTF8(value).get() );
697}
698
699/*--------------------------- nsRegistry::GetString ----------------------------
700| First, look for the entry using GetValueInfo. If found, and it's a string, |
701| allocate space for it and fetch the value. |
702------------------------------------------------------------------------------*/
703NS_IMETHODIMP nsRegistry::GetStringUTF8( nsRegistryKey baseKey, const char *path, char **result ) {
704 nsresult rv = NS_OK;
705 REGERR err = REGERR_OK;
706
707 // Make sure caller gave us place for result.
708 if ( !result )
709 return NS_ERROR_NULL_POINTER;
710
711 char regStr[MAXREGPATHLEN];
712
713 // initialize the return value
714 *result = 0;
715
716 // Attempt to get string into our fixed buffer
717 PR_Lock(mregLock);
718 err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, regStr,
719 sizeof(regStr) );
720 PR_Unlock(mregLock);
721
722 if ( err == REGERR_OK )
723 {
724 *result = nsCRT::strdup(regStr);
725 if (!*result)
726 rv = NS_ERROR_OUT_OF_MEMORY;
727 }
728 else if ( err == REGERR_BUFTOOSMALL )
729 {
730 // find the real size and malloc it
731 PRUint32 length;
732 rv = GetValueLength( baseKey, path, &length );
733 // See if that worked.
734 if( rv == NS_OK )
735 {
736 *result =(char*)nsMemory::Alloc( length + 1 );
737 if( *result )
738 {
739 // Get string from registry into result buffer.
740 PR_Lock(mregLock);
741 err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, *result, length+1 );
742 PR_Unlock(mregLock);
743
744 // Convert status.
745 rv = regerr2nsresult( err );
746 if ( rv != NS_OK )
747 {
748 // Didn't get result, free buffer
749 nsCRT::free( *result );
750 *result = 0;
751 }
752 }
753 else
754 {
755 rv = NS_ERROR_OUT_OF_MEMORY;
756 }
757 }
758 }
759 else
760 {
761 // Convert status.
762 rv = regerr2nsresult( err );
763 NS_ASSERTION(NS_FAILED(rv), "returning success code on failure");
764 }
765
766 return rv;
767}
768
769NS_IMETHODIMP
770nsRegistry::GetStringUTF8IntoBuffer( nsRegistryKey baseKey, const char *path,
771 char *buf, PRUint32 *length )
772{
773 REGERR err = REGERR_OK;
774
775 // Attempt to get string into our fixed buffer
776 PR_Lock(mregLock);
777 err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, buf, *length );
778 PR_Unlock(mregLock);
779
780 // Convert status.
781 nsresult rv = regerr2nsresult( err );
782
783 if (rv == NS_ERROR_REG_BUFFER_TOO_SMALL) {
784 // fill length with the actual length
785 nsresult rv1 = GetValueLength( baseKey, path, length );
786 if(NS_FAILED(rv1))
787 return rv1;
788 }
789
790 return rv;
791}
792
793/*--------------------------- nsRegistry::SetString ----------------------------
794| Simply sets the registry contents using NR_RegSetEntryString. |
795------------------------------------------------------------------------------*/
796NS_IMETHODIMP nsRegistry::SetStringUTF8( nsRegistryKey baseKey, const char *path, const char *value ) {
797 REGERR err = REGERR_OK;
798 // Set the contents.
799 PR_Lock(mregLock);
800 err = NR_RegSetEntryString( mReg,(RKEY)baseKey,(char*)path,(char*)value );
801 PR_Unlock(mregLock);
802 // Convert result.
803 return regerr2nsresult( err );
804}
805
806/*---------------------------- nsRegistry::GetBytesUTF8 ------------------------------
807| This function is just shorthand for fetching a char array. We |
808| implement it "manually" using NR_RegGetEntry |
809------------------------------------------------------------------------------*/
810NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32* length, PRUint8** result) {
811 nsresult rv = NS_OK;
812 REGERR err = REGERR_OK;
813
814 if ( !result )
815 return NS_ERROR_NULL_POINTER;
816
817 char regStr[MAXREGPATHLEN];
818
819 // initialize the return value
820 *length = 0;
821 *result = 0;
822
823 // Get info about the requested entry.
824 PRUint32 type;
825 rv = GetValueType( baseKey, path, &type );
826 // See if that worked.
827 if( rv == NS_OK )
828 {
829 // Make sure the entry is an PRInt8 array.
830 if( type == Bytes )
831 {
832 // Attempt to get string into our fixed buffer
833 PR_Lock(mregLock);
834 uint32 length2 = sizeof regStr;
835 err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), regStr, &length2);
836 PR_Unlock(mregLock);
837
838 if ( err == REGERR_OK )
839 {
840 *length = length2;
841 *result = (PRUint8*)(nsCRT::strdup(regStr));
842 if (!*result)
843 {
844 rv = NS_ERROR_OUT_OF_MEMORY;
845 *length = 0;
846 }
847 else
848 {
849 *length = length2;
850 }
851 }
852 else if ( err == REGERR_BUFTOOSMALL )
853 {
854 // find the real size and malloc it
855 rv = GetValueLength( baseKey, path, length );
856 // See if that worked.
857 if( rv == NS_OK )
858 {
859 *result = NS_REINTERPRET_CAST(PRUint8*,nsMemory::Alloc( *length ));
860 if( *result )
861 {
862 // Get bytes from registry into result field.
863 PR_Lock(mregLock);
864 length2 = *length;
865 err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), *result, &length2);
866 *length = length2;
867 PR_Unlock(mregLock);
868 // Convert status.
869 rv = regerr2nsresult( err );
870 if ( rv != NS_OK )
871 {
872 // Didn't get result, free buffer
873 nsCRT::free( NS_REINTERPRET_CAST(char*, *result) );
874 *result = 0;
875 *length = 0;
876 }
877 }
878 else
879 {
880 rv = NS_ERROR_OUT_OF_MEMORY;
881 }
882 }
883 }
884 }
885 else
886 {
887 // They asked for the wrong type of value.
888 rv = NS_ERROR_REG_BADTYPE;
889 }
890 }
891 return rv;
892}
893
894NS_IMETHODIMP
895nsRegistry::GetBytesUTF8IntoBuffer( nsRegistryKey baseKey, const char *path,
896 PRUint8 *buf, PRUint32* length )
897{
898 REGERR err = REGERR_OK;
899
900 // Get info about the requested entry.
901 PRUint32 type;
902 nsresult rv = GetValueType( baseKey, path, &type );
903 // See if that worked.
904 if(NS_FAILED(rv))
905 return rv;
906 // Make sure we are dealing with bytes
907 if (type != Bytes)
908 return NS_ERROR_REG_BADTYPE;
909
910 // Attempt to get bytes into our fixed buffer
911 PR_Lock(mregLock);
912 err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path),
913 buf, (uint32 *)length );
914 PR_Unlock(mregLock);
915
916 rv = regerr2nsresult(rv);
917
918 if (rv == NS_ERROR_REG_BUFFER_TOO_SMALL) {
919 // fill length with the actual length
920 nsresult rv1 = GetValueLength( baseKey, path, length );
921 if(NS_FAILED(rv1))
922 return rv1;
923 }
924
925
926 return rv;
927}
928
929/*---------------------------- nsRegistry::GetInt ------------------------------
930| This function is just shorthand for fetching a 1-element PRInt32 array. We |
931| implement it "manually" using NR_RegGetEntry |
932------------------------------------------------------------------------------*/
933NS_IMETHODIMP nsRegistry::GetInt( nsRegistryKey baseKey, const char *path, PRInt32 *result ) {
934 nsresult rv = NS_OK;
935 REGERR err = REGERR_OK;
936
937 // Make sure caller gave us place for result.
938 if( result ) {
939 // Get info about the requested entry.
940 PRUint32 type;
941 rv = GetValueType( baseKey, path, &type );
942 // See if that worked.
943 if( rv == NS_OK ) {
944 // Make sure the entry is an PRInt32 array.
945 if( type == Int32 ) {
946 uint32 len = sizeof *result;
947 // Get int from registry into result field.
948 PR_Lock(mregLock);
949 err = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, &len );
950 PR_Unlock(mregLock);
951 // Convert status.
952 rv = regerr2nsresult( err );
953 } else {
954 // They asked for the wrong type of value.
955 rv = NS_ERROR_REG_BADTYPE;
956 }
957 }
958 } else {
959 rv = NS_ERROR_NULL_POINTER;
960 }
961 return rv;
962}
963
964
965/*---------------------------- nsRegistry::GetLongLong--------------------------
966| This function is just shorthand for fetching a 1-element PRInt64 array. We |
967| implement it "manually" using NR_RegGetEntry |
968------------------------------------------------------------------------------*/
969NS_IMETHODIMP nsRegistry::GetLongLong( nsRegistryKey baseKey, const char *path, PRInt64 *result ) {
970 REGERR err = REGERR_OK;
971
972 PR_Lock(mregLock);
973
974 uint32 length = sizeof(PRInt64);
975 err = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path,(void*)result,&length);
976
977 PR_Unlock(mregLock);
978
979 // Convert status.
980 return regerr2nsresult( err );
981}
982/*---------------------------- nsRegistry::SetBytesUTF8 ------------------------------
983| Write out the value as a char array, using NR_RegSetEntry. |
984------------------------------------------------------------------------------*/
985NS_IMETHODIMP nsRegistry::SetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32 length, PRUint8* value) {
986 REGERR err = REGERR_OK;
987 // Set the contents.
988 PR_Lock(mregLock);
989 err = NR_RegSetEntry( mReg,
990 (RKEY)baseKey,
991 (char*)path,
992 REGTYPE_ENTRY_BYTES,
993 (char*)value,
994 length);
995 PR_Unlock(mregLock);
996 // Convert result.
997 return regerr2nsresult( err );
998}
999
1000/*---------------------------- nsRegistry::SetInt ------------------------------
1001| Write out the value as a one-element PRInt32 array, using NR_RegSetEntry. |
1002------------------------------------------------------------------------------*/
1003NS_IMETHODIMP nsRegistry::SetInt( nsRegistryKey baseKey, const char *path, PRInt32 value ) {
1004 REGERR err = REGERR_OK;
1005 // Set the contents.
1006 PR_Lock(mregLock);
1007 err = NR_RegSetEntry( mReg,
1008 (RKEY)baseKey,
1009 (char*)path,
1010 REGTYPE_ENTRY_INT32_ARRAY,
1011 &value,
1012 sizeof value );
1013 PR_Unlock(mregLock);
1014 // Convert result.
1015 return regerr2nsresult( err );
1016}
1017
1018
1019
1020/*---------------------------- nsRegistry::SetLongLong---------------------------
1021| Write out the value as a one-element PRInt64 array, using NR_RegSetEntry. |
1022------------------------------------------------------------------------------*/
1023NS_IMETHODIMP nsRegistry::SetLongLong( nsRegistryKey baseKey, const char *path, PRInt64* value ) {
1024 REGERR err = REGERR_OK;
1025 // Set the contents.
1026 PR_Lock(mregLock);
1027
1028 err = NR_RegSetEntry( mReg,
1029 (RKEY)baseKey,
1030 (char*)path,
1031 REGTYPE_ENTRY_BYTES,
1032 (void*)value,
1033 sizeof(PRInt64) );
1034
1035 PR_Unlock(mregLock);
1036 // Convert result.
1037 return regerr2nsresult( err );
1038}
1039
1040/*-------------------------- nsRegistry::AddSubtree ----------------------------
1041| Add a new registry subkey with the specified name, using NR_RegAddKey. |
1042------------------------------------------------------------------------------*/
1043NS_IMETHODIMP nsRegistry::AddSubtree( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
1044 REGERR err = REGERR_OK;
1045 // Add the subkey.
1046 PR_Lock(mregLock);
1047 err = NR_RegAddKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
1048 PR_Unlock(mregLock);
1049 // Convert result.
1050 return regerr2nsresult( err );
1051}
1052
1053/*-------------------------- nsRegistry::AddSubtreeRaw--------------------------
1054| Add a new registry subkey with the specified name, using NR_RegAddKeyRaw |
1055------------------------------------------------------------------------------*/
1056NS_IMETHODIMP nsRegistry::AddSubtreeRaw( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
1057 REGERR err = REGERR_OK;
1058 // Add the subkey.
1059 PR_Lock(mregLock);
1060 err = NR_RegAddKeyRaw( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
1061 PR_Unlock(mregLock);
1062 // Convert result.
1063 return regerr2nsresult( err );
1064}
1065
1066
1067/*------------------------- nsRegistry::RemoveSubtree --------------------------
1068| Deletes the subtree at a given location using NR_RegDeleteKey. |
1069------------------------------------------------------------------------------*/
1070NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path ) {
1071 nsresult rv = NS_OK;
1072 REGERR err = REGERR_OK;
1073
1074 // libreg doesn't delete keys if there are subkeys under the key
1075 // Hence we have to recurse through to delete the subtree
1076
1077 RKEY key;
1078
1079 PR_Lock(mregLock);
1080 err = NR_RegGetKey(mReg, baseKey, (char *)path, &key);
1081 PR_Unlock(mregLock);
1082 if (err != REGERR_OK)
1083 {
1084 rv = regerr2nsresult( err );
1085 return rv;
1086 }
1087
1088 // Now recurse through and delete all keys under hierarchy
1089
1090 char subkeyname[MAXREGPATHLEN+1];
1091 REGENUM state = 0;
1092 subkeyname[0] = '\0';
1093 while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, sizeof(subkeyname),
1094 REGENUM_NORMAL) == REGERR_OK)
1095 {
1096#ifdef DEBUG_dp
1097 printf("...recursing into %s\n", subkeyname);
1098#endif /* DEBUG_dp */
1099 // Even though this is not a "Raw" API the subkeys may still, in fact,
1100 // *be* raw. Since we're recursively deleting this will work either way.
1101 // If we were guaranteed none would be raw then a depth-first enumeration
1102 // would be much more efficient.
1103 err = RemoveSubtreeRaw(key, subkeyname);
1104 if (err != REGERR_OK) break;
1105 }
1106
1107 // If success in deleting all subkeys, delete this key too
1108 if (err == REGERR_OK)
1109 {
1110#ifdef DEBUG_dp
1111 printf("...deleting %s\n", path);
1112#endif /* DEBUG_dp */
1113 PR_Lock(mregLock);
1114 err = NR_RegDeleteKey(mReg, baseKey, (char *)path);
1115 PR_Unlock(mregLock);
1116 }
1117
1118 // Convert result.
1119 rv = regerr2nsresult( err );
1120 return rv;
1121}
1122
1123
1124/*------------------------- nsRegistry::RemoveSubtreeRaw -----------------------
1125| Deletes the subtree at a given location using NR_RegDeleteKeyRaw |
1126------------------------------------------------------------------------------*/
1127NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *keyname ) {
1128 nsresult rv = NS_OK;
1129 REGERR err = REGERR_OK;
1130
1131 // libreg doesn't delete keys if there are subkeys under the key
1132 // Hence we have to recurse through to delete the subtree
1133
1134 RKEY key;
1135 char subkeyname[MAXREGPATHLEN+1];
1136 int n = sizeof(subkeyname);
1137 REGENUM state = 0;
1138
1139 PR_Lock(mregLock);
1140 err = NR_RegGetKeyRaw(mReg, baseKey, (char *)keyname, &key);
1141 PR_Unlock(mregLock);
1142 if (err != REGERR_OK)
1143 {
1144 rv = regerr2nsresult( err );
1145 return rv;
1146 }
1147
1148 // Now recurse through and delete all keys under hierarchy
1149
1150 subkeyname[0] = '\0';
1151 while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, n, REGENUM_NORMAL) == REGERR_OK)
1152 {
1153#ifdef DEBUG_dp
1154 printf("...recursing into %s\n", subkeyname);
1155#endif /* DEBUG_dp */
1156 err = RemoveSubtreeRaw(key, subkeyname);
1157 if (err != REGERR_OK) break;
1158 }
1159
1160 // If success in deleting all subkeys, delete this key too
1161 if (err == REGERR_OK)
1162 {
1163#ifdef DEBUG_dp
1164 printf("...deleting %s\n", keyname);
1165#endif /* DEBUG_dp */
1166 PR_Lock(mregLock);
1167 err = NR_RegDeleteKeyRaw(mReg, baseKey, (char *)keyname);
1168 PR_Unlock(mregLock);
1169 }
1170
1171 // Convert result.
1172 rv = regerr2nsresult( err );
1173 return rv;
1174}
1175/*-------------------------- nsRegistry::GetSubtree ----------------------------
1176| Returns a nsRegistryKey(RKEY) for a given key/path. The key is |
1177| obtained using NR_RegGetKey. |
1178------------------------------------------------------------------------------*/
1179NS_IMETHODIMP nsRegistry::GetSubtree( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
1180 nsresult rv = NS_OK;
1181 REGERR err = REGERR_OK;
1182 // Make sure we have a place for the result.
1183 if( result ) {
1184 // Get key.
1185 PR_Lock(mregLock);
1186 err = NR_RegGetKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
1187 PR_Unlock(mregLock);
1188 // Convert result.
1189 rv = regerr2nsresult( err );
1190 } else {
1191 rv = NS_ERROR_NULL_POINTER;
1192 }
1193 return rv;
1194}
1195
1196/*-------------------------- nsRegistry::GetSubtreeRaw--------------------------
1197| Returns a nsRegistryKey(RKEY) for a given key/path. The key is |
1198| obtained using NR_RegGetKeyRaw. |
1199------------------------------------------------------------------------------*/
1200NS_IMETHODIMP nsRegistry::GetSubtreeRaw( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
1201 nsresult rv = NS_OK;
1202 REGERR err = REGERR_OK;
1203 // Make sure we have a place for the result.
1204 if( result ) {
1205 // Get key.
1206 PR_Lock(mregLock);
1207 err = NR_RegGetKeyRaw( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
1208 PR_Unlock(mregLock);
1209 // Convert result.
1210 rv = regerr2nsresult( err );
1211 } else {
1212 rv = NS_ERROR_NULL_POINTER;
1213 }
1214 return rv;
1215}
1216
1217
1218/*----------------------- nsRegistry::EnumerateSubtrees ------------------------
1219| Allocate a nsRegSubtreeEnumerator object and return it to the caller. |
1220| We construct the enumerator using the registry handle from this registry |
1221| object, the user-specified registry key, and indicate that we don't want |
1222| to recurse down subtrees. No libreg functions are invoked at this point |
1223|(that will happen when the enumerator member functions are called). |
1224------------------------------------------------------------------------------*/
1225NS_IMETHODIMP nsRegistry::EnumerateSubtrees( nsRegistryKey baseKey, nsIEnumerator **result ) {
1226 nsresult rv = NS_OK;
1227 // Make sure we have a place to put the result.
1228 if( result ) {
1229 *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_FALSE );
1230 // Check for success.
1231 if( *result ) {
1232 // Bump refcnt on behalf of caller.
1233 NS_ADDREF(*result);
1234 } else {
1235 // Unable to allocate space for the enumerator object.
1236 rv = NS_ERROR_OUT_OF_MEMORY;
1237 }
1238 } else {
1239 rv = NS_ERROR_NULL_POINTER;
1240 }
1241 return rv;
1242}
1243
1244/*--------------------- nsRegistry::EnumerateAllSubtrees -----------------------
1245| Same as EnumerateSubtrees but we pass PR_TRUE to request that the |
1246| enumerator object descend subtrees when it is used. |
1247------------------------------------------------------------------------------*/
1248NS_IMETHODIMP nsRegistry::EnumerateAllSubtrees( nsRegistryKey baseKey, nsIEnumerator **result ) {
1249 nsresult rv = NS_OK;
1250 // Make sure we have a place to put the result.
1251 if( result ) {
1252 *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_TRUE );
1253 // Check for success.
1254 if( *result ) {
1255 // Bump refcnt on behalf of caller.
1256 NS_ADDREF(*result);
1257 } else {
1258 // Unable to allocate space for the enumerator object.
1259 rv = NS_ERROR_OUT_OF_MEMORY;
1260 }
1261 } else {
1262 rv = NS_ERROR_NULL_POINTER;
1263 }
1264 return rv;
1265}
1266
1267/*------------------------- nsRegistry::GetValueType ---------------------------
1268| Gets the type from the registry using the NR_GetEntryInfo libreg API. |
1269| The result is transferred to the PRUint32 value passed in (with conversion |
1270| to the appropriate nsIRegistry::DataType value). |
1271------------------------------------------------------------------------------*/
1272NS_IMETHODIMP nsRegistry::GetValueType( nsRegistryKey baseKey, const char *path, PRUint32 *result ) {
1273 nsresult rv = NS_OK;
1274 REGERR err = REGERR_OK;
1275 // Make sure we have a place to put the result.
1276 if( result ) {
1277 // Get registry info into local structure.
1278 REGINFO info = { sizeof info, 0, 0 };
1279 PR_Lock(mregLock);
1280 err = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info );
1281 PR_Unlock(mregLock);
1282 if( err == REGERR_OK ) {
1283 // Copy info to user's result value.
1284 reginfo2DataType( info, *result );
1285 } else {
1286 rv = regerr2nsresult( err );
1287 }
1288 } else {
1289 rv = NS_ERROR_NULL_POINTER;
1290 }
1291 return rv;
1292}
1293
1294/*------------------------ nsRegistry::GetValueLength --------------------------
1295| Gets the registry value info via NR_RegGetEntryInfo. The length is |
1296| converted to the proper "units" via reginfo2Length. |
1297------------------------------------------------------------------------------*/
1298NS_IMETHODIMP nsRegistry::GetValueLength( nsRegistryKey baseKey, const char *path, PRUint32 *result ) {
1299 nsresult rv = NS_OK;
1300 REGERR err = REGERR_OK;
1301 // Make sure we have a place to put the result.
1302 if( result ) {
1303 // Get registry info into local structure.
1304 REGINFO info = { sizeof info, 0, 0 };
1305 PR_Lock(mregLock);
1306 err = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info );
1307 PR_Unlock(mregLock);
1308 if( err == REGERR_OK ) {
1309 // Copy info to user's result value.
1310 reginfo2Length( info, *result );
1311 } else {
1312 rv = regerr2nsresult( err );
1313 }
1314 } else {
1315 rv = NS_ERROR_NULL_POINTER;
1316 }
1317 return rv;
1318}
1319
1320/*-------------------------- nsRegistry::DeleteValue ---------------------------
1321| Remove the registry value with the specified name |
1322------------------------------------------------------------------------------*/
1323NS_IMETHODIMP nsRegistry::DeleteValue( nsRegistryKey baseKey, const char *path)
1324{
1325 REGERR err = REGERR_OK;
1326 // Delete the value
1327 PR_Lock(mregLock);
1328 err = NR_RegDeleteEntry( mReg,(RKEY)baseKey,(char*)path );
1329 PR_Unlock(mregLock);
1330 // Convert result.
1331 return regerr2nsresult( err );
1332}
1333
1334/*------------------------ nsRegistry::EnumerateValues -------------------------
1335| Allocates and returns an instance of nsRegValueEnumerator constructed in |
1336| a similar fashion as the nsRegSubtreeEnumerator is allocated/returned by |
1337| EnumerateSubtrees. |
1338------------------------------------------------------------------------------*/
1339NS_IMETHODIMP nsRegistry::EnumerateValues( nsRegistryKey baseKey, nsIEnumerator **result ) {
1340 nsresult rv = NS_OK;
1341 // Make sure we have a place to put the result.
1342 if( result ) {
1343 *result = new nsRegValueEnumerator( mReg,(RKEY)baseKey );
1344 // Check for success.
1345 if( *result ) {
1346 // Bump refcnt on behalf of caller.
1347 NS_ADDREF(*result);
1348 } else {
1349 // Unable to allocate space for the enumerator object.
1350 rv = NS_ERROR_OUT_OF_MEMORY;
1351 }
1352 } else {
1353 rv = NS_ERROR_NULL_POINTER;
1354 }
1355 return rv;
1356}
1357
1358/*---------------------- nsRegistry::GetCurrentUserName ------------------------
1359| Simple wrapper for NR_RegGetUsername. |
1360------------------------------------------------------------------------------*/
1361NS_IMETHODIMP nsRegistry::GetCurrentUserName( char **result ) {
1362 nsresult rv = NS_OK;
1363 REGERR err = REGERR_OK;
1364 // Make sure we have a place to put the result.
1365 if( result ) {
1366 // Get the user name.
1367 PR_Lock(mregLock);
1368 err = NR_RegGetUsername( result );
1369 PR_Unlock(mregLock);
1370 // Convert the result.
1371 rv = regerr2nsresult( err );
1372 } else {
1373 rv = NS_ERROR_NULL_POINTER;
1374 }
1375 return rv;
1376}
1377
1378/*---------------------- nsRegistry::SetCurrentUserName ------------------------
1379| Simple wrapper for NR_RegSetUsername. |
1380------------------------------------------------------------------------------*/
1381NS_IMETHODIMP nsRegistry::SetCurrentUserName( const char *name ) {
1382 nsresult rv = NS_OK;
1383 REGERR err = REGERR_OK;
1384 // Set the user name.
1385 PR_Lock(mregLock);
1386 err = NR_RegSetUsername( name );
1387 PR_Unlock(mregLock);
1388 // Convert result.
1389 rv = regerr2nsresult( err );
1390 return rv;
1391}
1392
1393/*----------------------------- nsRegistry::Pack -------------------------------
1394| Simple wrapper for NR_RegPack. We don't set up any callback. |
1395------------------------------------------------------------------------------*/
1396NS_IMETHODIMP nsRegistry::Pack() {
1397 nsresult rv = NS_OK;
1398 REGERR err = REGERR_OK;
1399 // Pack the registry.
1400 PR_Lock(mregLock);
1401 err = NR_RegPack( mReg, 0, 0 );
1402 PR_Unlock(mregLock);
1403 // Convert result.
1404 rv = regerr2nsresult( err );
1405 return rv;
1406}
1407
1408/*----------------------------- nsRegistry::EscapeKey -------------------------------
1409| Escape a binary key so that the registry works OK, since it expects UTF8
1410| with no slashes or control characters. This is probably better than raw.
1411| If no escaping is required, then the method is successful and a null is
1412| returned, indicating that the caller should use the original string.
1413------------------------------------------------------------------------------*/
1414static const char sEscapeKeyHex[] = "0123456789abcdef0123456789ABCDEF";
1415NS_IMETHODIMP nsRegistry::EscapeKey(PRUint8* key, PRUint32 termination, PRUint32* length, PRUint8** escaped)
1416{
1417 nsresult rv = NS_OK;
1418 char* value = (char*)key;
1419 char* b = value;
1420 char* e = b + *length;
1421 int escapees = 0;
1422 while (b < e) // Count characters outside legal range or slash
1423 {
1424 int c = *b++;
1425 if (c <= ' '
1426 || c > '~'
1427 || c == '/'
1428 || c == '%')
1429 {
1430 escapees++;
1431 }
1432 }
1433 if (escapees == 0) // If no escapees, then no results
1434 {
1435 *length = 0;
1436 *escaped = nsnull;
1437 return NS_OK;
1438 }
1439 // New length includes two extra chars for escapees.
1440 *length += escapees * 2;
1441 *escaped = (PRUint8*)nsMemory::Alloc(*length + termination);
1442 if (*escaped == nsnull)
1443 {
1444 *length = 0;
1445 *escaped = nsnull;
1446 return NS_ERROR_OUT_OF_MEMORY;
1447 }
1448 char* n = (char*)*escaped;
1449 b = value;
1450 while (escapees && b < e)
1451 {
1452 char c = *b++;
1453 if (c < ' '
1454 || c > '~'
1455 || c == '/'
1456 || c == '%')
1457 {
1458 *(n++) = '%';
1459 *(n++) = sEscapeKeyHex[ 0xF & (c >> 4) ];
1460 *(n++) = sEscapeKeyHex[ 0xF & c ];
1461 escapees--;
1462 }
1463 else
1464 {
1465 *(n++) = c;
1466 }
1467 }
1468 e += termination;
1469 if (b < e)
1470 {
1471 strncpy(n, b, e - b);
1472 }
1473 return rv;
1474}
1475
1476/*----------------------------- nsRegistry::UnescapeKey -------------------------------
1477| Unscape a binary key so that the registry works OK, since it expects UTF8
1478| with no slashes or control characters. This is probably better than raw.
1479| If no escaping is required, then the method is successful and a null is
1480| returned, indicating that the caller should use the original string.
1481------------------------------------------------------------------------------*/
1482NS_IMETHODIMP nsRegistry::UnescapeKey(PRUint8* escaped, PRUint32 termination, PRUint32* length, PRUint8** key)
1483{
1484 nsresult rv = NS_OK;
1485 char* value = (char*)escaped;
1486 char* b = value;
1487 char* e = b + *length;
1488 int escapees = 0;
1489 while (b < e) // Count characters outside legal range or slash
1490 {
1491 if (*b++ == '%')
1492 {
1493 escapees++;
1494 }
1495 }
1496 if (escapees == 0) // If no escapees, then no results
1497 {
1498 *length = 0;
1499 *key = nsnull;
1500 return NS_OK;
1501 }
1502 // New length includes two extra chars for escapees.
1503 *length -= escapees * 2;
1504 *key = (PRUint8*)nsMemory::Alloc(*length + termination);
1505 if (*key == nsnull)
1506 {
1507 *length = 0;
1508 *key = nsnull;
1509 return NS_ERROR_OUT_OF_MEMORY;
1510 }
1511 char* n = (char*)*key;
1512 b = value;
1513 while (escapees && b < e)
1514 {
1515 char c = *(b++);
1516 if (c == '%')
1517 {
1518 if (e - b >= 2)
1519 {
1520 const char* c1 = strchr(sEscapeKeyHex, *(b++));
1521 const char* c2 = strchr(sEscapeKeyHex, *(b++));
1522 if (c1 != nsnull
1523 && c2 != nsnull)
1524 {
1525 *(n++) = ((c2 - sEscapeKeyHex) & 0xF)
1526 | (((c1 - sEscapeKeyHex) & 0xF) << 4);
1527 }
1528 else
1529 {
1530 escapees = -1;
1531 }
1532 }
1533 else
1534 {
1535 escapees = -1;
1536 }
1537 escapees--;
1538 }
1539 else
1540 {
1541 *(n++) = c;
1542 }
1543 }
1544 if (escapees < 0)
1545 {
1546 nsMemory::Free(*key);
1547 *length = 0;
1548 *key = nsnull;
1549 return NS_ERROR_INVALID_ARG;
1550 }
1551 e += termination;
1552 if (b < e)
1553 {
1554 strncpy(n, b, e - b);
1555 }
1556 return rv;
1557}
1558
1559
1560/*-------------- nsRegistry::SetBufferSize-------------------------------------
1561| Sets the size of the file used for the registry's buffer size. |
1562------------------------------------------------------------------------------*/
1563int nsRegistry::SetBufferSize( int bufsize )
1564{
1565 int newSize;
1566 // set the file buffer size
1567 PR_Lock(mregLock);
1568 newSize = NR_RegSetBufferSize( mReg, bufsize );
1569 PR_Unlock(mregLock);
1570 return newSize;
1571}
1572
1573
1574/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ----------------
1575| The ctor simply stashes all the information that will be needed to enumerate |
1576| the subkeys. |
1577------------------------------------------------------------------------------*/
1578nsRegSubtreeEnumerator::nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all )
1579 : mReg( hReg ), mKey( rKey ), mEnum( 0 ), mNext( 0 ),
1580 mStyle( all ? REGENUM_DESCEND : REGENUM_CHILDREN ), mDone( PR_FALSE ) {
1581
1582 mName[0] = '\0';
1583
1584#ifdef EXTRA_THREADSAFE
1585 // Create a registry lock
1586 mregLock = PR_NewLock();
1587#endif
1588 return;
1589}
1590
1591nsRegSubtreeEnumerator::~nsRegSubtreeEnumerator()
1592{
1593#ifdef EXTRA_THREADSAFE
1594 if (mregLock) {
1595 PR_DestroyLock(mregLock);
1596 }
1597#endif
1598}
1599
1600/*----------------------- nsRegSubtreeEnumerator::First ------------------------
1601| Set mEnum to 0; this will cause the next NR_RegEnum call to go to |
1602| the beginning. We then do a Next() call in order to do a "lookahead" to |
1603| properly detect an empty list (i.e., set the mDone flag). |
1604------------------------------------------------------------------------------*/
1605NS_IMETHODIMP
1606nsRegSubtreeEnumerator::First() {
1607 nsresult rv = NS_OK;
1608 // Reset "done" flag.
1609 mDone = PR_FALSE;
1610 // Clear Name
1611 mName[0] = '\0';
1612 // Go to beginning.
1613 mEnum = mNext = 0;
1614 // Lookahead so mDone flag gets set for empty list.
1615 rv = Next();
1616 return rv;
1617}
1618
1619/*----------------------- nsRegSubtreeEnumerator::Next -------------------------
1620| First, we check if we've already advanced to the end by checking the mDone |
1621| flag. |
1622| |
1623| We advance mEnum to the next enumeration value which is in the mNext |
1624| lookahead buffer. We must then call advance to lookahead and properly set |
1625| the isDone flag. |
1626------------------------------------------------------------------------------*/
1627NS_IMETHODIMP
1628nsRegSubtreeEnumerator::Next() {
1629 nsresult rv = NS_OK;
1630 // Check for at end.
1631 if ( !mDone ) {
1632 // Advance to next spot.
1633 mEnum = mNext;
1634 // Lookahead so mDone is properly set (and to update mNext).
1635 rv = advance();
1636 } else {
1637 // Set result accordingly.
1638 rv = regerr2nsresult( REGERR_NOMORE );
1639 }
1640 return rv;
1641}
1642
1643/*---------------------- nsRegSubtreeEnumerator::advance -----------------------
1644| Advance mNext to next subkey using NR_RegEnumSubkeys. We set mDone if |
1645| there are no more subkeys. |
1646------------------------------------------------------------------------------*/
1647NS_IMETHODIMP nsRegSubtreeEnumerator::advance() {
1648 REGERR err = REGERR_OK;
1649 PR_Lock(mregLock);
1650 err = NR_RegEnumSubkeys( mReg, mKey, &mNext, mName, sizeof mName, mStyle );
1651 // See if we ran off end.
1652 if( err == REGERR_NOMORE ) {
1653 // Remember we've run off end.
1654 mDone = PR_TRUE;
1655 }
1656 PR_Unlock(mregLock);
1657 // Convert result.
1658 nsresult rv = regerr2nsresult( err );
1659 return rv;
1660}
1661
1662/*-------------------- nsRegSubtreeEnumerator::CurrentItem ---------------------
1663| Allocates and returns a new instance of class nsRegistryNode. The node |
1664| object will hold the curent mEnum value so it can obtain its name from |
1665| the registry when asked. |
1666------------------------------------------------------------------------------*/
1667NS_IMETHODIMP
1668nsRegSubtreeEnumerator::CurrentItem( nsISupports **result) {
1669 nsresult rv = NS_OK;
1670 // Make sure there is a place to put the result.
1671 if( result ) {
1672 *result = new nsRegistryNode( mReg, mName, (RKEY) mNext );
1673 if( *result ) {
1674 NS_ADDREF(*result);
1675 } else {
1676 rv = NS_ERROR_OUT_OF_MEMORY;
1677 }
1678 } else {
1679 rv = NS_ERROR_NULL_POINTER;
1680 }
1681 return rv;
1682}
1683
1684/*--------------nsRegSubtreeEnumerator::CurrentItemInPlaceUTF8-----------------
1685| An ugly name for an ugly function. Hands back a shared pointer to the |
1686| name (encoded as UTF-8), and the subkey identifier. |
1687-----------------------------------------------------------------------------*/
1688NS_IMETHODIMP
1689nsRegSubtreeEnumerator::CurrentItemInPlaceUTF8( nsRegistryKey *childKey ,
1690 const char **name )
1691{
1692 *childKey = mNext;
1693 /* [shared] */
1694 *name = mName;
1695 return NS_OK;
1696}
1697
1698/*---------------------- nsRegSubtreeEnumerator::IsDone ------------------------
1699| Simply return mDone. |
1700------------------------------------------------------------------------------*/
1701NS_IMETHODIMP
1702nsRegSubtreeEnumerator::IsDone() {
1703 nsresult rv = mDone ? NS_OK : NS_ENUMERATOR_FALSE;
1704 return rv;
1705}
1706
1707
1708/*---------------- nsRegValueEnumerator::nsRegValueEnumerator ------------------
1709| Delegates everything to the base class constructor. |
1710------------------------------------------------------------------------------*/
1711nsRegValueEnumerator::nsRegValueEnumerator( HREG hReg, RKEY rKey )
1712 : nsRegSubtreeEnumerator( hReg, rKey, PR_FALSE ) {
1713 return;
1714}
1715
1716
1717/*--------------------- nsRegValueEnumerator::CurrentItem ----------------------
1718| As the nsRegSubtreeEnumerator counterpart, but allocates an object of |
1719| class nsRegistryValue. |
1720------------------------------------------------------------------------------*/
1721NS_IMETHODIMP
1722nsRegValueEnumerator::CurrentItem( nsISupports **result ) {
1723 nsresult rv = NS_OK;
1724 // Make sure there is a place to put the result.
1725 if( result ) {
1726 *result = new nsRegistryValue( mReg, mKey, mEnum );
1727 if( *result ) {
1728 NS_ADDREF(*result);
1729 } else {
1730 rv = NS_ERROR_OUT_OF_MEMORY;
1731 }
1732 } else {
1733 rv = NS_ERROR_NULL_POINTER;
1734 }
1735 return rv;
1736}
1737
1738/*----------------------- nsRegValueEnumerator::advance ------------------------
1739| Advance mNext to next subkey using NR_RegEnumEntries. We set mDone if |
1740| there are no more entries. |
1741------------------------------------------------------------------------------*/
1742NS_IMETHODIMP nsRegValueEnumerator::advance() {
1743 REGERR err = REGERR_OK;
1744 char name[MAXREGNAMELEN];
1745 PRUint32 len = sizeof name;
1746 REGINFO info = { sizeof info, 0, 0 };
1747 PR_Lock(mregLock);
1748 err = NR_RegEnumEntries( mReg, mKey, &mNext, name, len, &info );
1749 // See if we ran off end.
1750 if( err == REGERR_NOMORE ) {
1751 // Remember we've run off end.
1752 mDone = PR_TRUE;
1753 }
1754 PR_Unlock(mregLock);
1755 // Convert result.
1756 nsresult rv = regerr2nsresult( err );
1757 return rv;
1758}
1759
1760
1761/*---------------------- nsRegistryNode::nsRegistryNode ------------------------
1762| Store the arguments in the corresponding data members and initialize |
1763| the other data members. We defer the libreg calls till we're asked for |
1764| our name. We use mErr==-1 to indicate we haven't fetched the name yet. |
1765------------------------------------------------------------------------------*/
1766nsRegistryNode::nsRegistryNode( HREG hReg, char *name, RKEY childKey )
1767 : mReg( hReg ), mChildKey( childKey ) {
1768
1769 PR_ASSERT(name != nsnull);
1770 strcpy(mName, name);
1771
1772#ifdef EXTRA_THREADSAFE
1773 mregLock = PR_NewLock();
1774#endif
1775
1776 return;
1777}
1778
1779nsRegistryNode::~nsRegistryNode()
1780{
1781#ifdef EXTRA_THREADSAFE
1782 if (mregLock) {
1783 PR_DestroyLock(mregLock);
1784 }
1785#endif
1786}
1787
1788/*-------------------------- nsRegistryNode::GetName ---------------------------
1789| If we haven't fetched it yet, get the name of the corresponding subkey now, |
1790| using NR_RegEnumSubkeys. |
1791------------------------------------------------------------------------------*/
1792NS_IMETHODIMP nsRegistryNode::GetName( PRUnichar **result ) {
1793 if (result == nsnull) return NS_ERROR_NULL_POINTER;
1794 // Make sure there is a place to put the result.
1795 *result = nsTextFormatter::smprintf( widestrFormat, mName );
1796 if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
1797 return NS_OK;
1798}
1799
1800/*-------------------------- nsRegistryNode::GetNameUTF8 -----------------------
1801| If we haven't fetched it yet, get the name of the corresponding subkey now, |
1802| using NR_RegEnumSubkeys. |
1803------------------------------------------------------------------------------*/
1804NS_IMETHODIMP nsRegistryNode::GetNameUTF8( char **result ) {
1805 if (result == nsnull) return NS_ERROR_NULL_POINTER;
1806 // Make sure there is a place to put the result.
1807 *result = nsCRT::strdup( mName );
1808 if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
1809 return NS_OK;
1810}
1811
1812/*-------------------------- nsRegistryNode::GetKey ----------------------------
1813| Get the subkey corresponding to this node |
1814| using NR_RegEnumSubkeys. |
1815------------------------------------------------------------------------------*/
1816NS_IMETHODIMP nsRegistryNode::GetKey( nsRegistryKey *r_key ) {
1817 nsresult rv = NS_OK;
1818 if (r_key == nsnull) return NS_ERROR_NULL_POINTER;
1819 *r_key = mChildKey;
1820 return rv;
1821}
1822
1823
1824
1825/*--------------------- nsRegistryValue::nsRegistryValue -----------------------
1826| Implemented the same way as the nsRegistryNode ctor. |
1827------------------------------------------------------------------------------*/
1828nsRegistryValue::nsRegistryValue( HREG hReg, RKEY key, REGENUM slot )
1829 : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) {
1830#ifdef EXTRA_THREADSAFE
1831 mregLock = PR_NewLock();
1832#endif
1833 mInfo.size = sizeof(REGINFO);
1834}
1835
1836nsRegistryValue::~nsRegistryValue()
1837{
1838#ifdef EXTRA_THREADSAFE
1839 if (mregLock) {
1840 PR_DestroyLock(mregLock);
1841 }
1842#endif
1843}
1844
1845/*------------------------- nsRegistryValue::GetName ---------------------------
1846| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. |
1847------------------------------------------------------------------------------*/
1848NS_IMETHODIMP nsRegistryValue::GetName( PRUnichar **result ) {
1849 nsresult rv = NS_OK;
1850 // Make sure we have a place to put the result.
1851 if( result ) {
1852 // Ensure we've got the info we need.
1853 rv = getInfo();
1854 if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
1855 // worked, return actual result.
1856 *result = nsTextFormatter::smprintf( widestrFormat, mName );
1857 if ( *result ) {
1858 rv = NS_OK;
1859 } else {
1860 rv = NS_ERROR_OUT_OF_MEMORY;
1861 }
1862 }
1863 } else {
1864 rv = NS_ERROR_NULL_POINTER;
1865 }
1866 return rv;
1867}
1868
1869/*------------------------- nsRegistryValue::GetNameUTF8 -----------------------
1870| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. |
1871------------------------------------------------------------------------------*/
1872NS_IMETHODIMP nsRegistryValue::GetNameUTF8( char **result ) {
1873 nsresult rv = NS_OK;
1874 // Make sure we have a place to put the result.
1875 if( result ) {
1876 // Ensure we've got the info we need.
1877 rv = getInfo();
1878 if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
1879 // worked, return actual result.
1880 *result = nsCRT::strdup( mName );
1881 if ( *result ) {
1882 rv = NS_OK;
1883 } else {
1884 rv = NS_ERROR_OUT_OF_MEMORY;
1885 }
1886 }
1887 } else {
1888 rv = NS_ERROR_NULL_POINTER;
1889 }
1890 return rv;
1891}
1892
1893/*----------------------- nsRegistryValue::GetType ------------------------
1894| We test if we've got the info already. If not, we git it by calling |
1895| getInfo. We calculate the result by converting the REGINFO type field to |
1896| a nsIRegistry::DataType value (using reginfo2DataType). |
1897------------------------------------------------------------------------------*/
1898NS_IMETHODIMP nsRegistryValue::GetType( PRUint32 *result ) {
1899 nsresult rv = NS_OK;
1900 // Make sure we have room for th result.
1901 if( result ) {
1902 // Make sure we've got the info we need.
1903 rv = getInfo();
1904 // Check if it worked.
1905 if( rv == NS_OK ) {
1906 // Convert result from REGINFO to nsIRegistry::ValueInfo.
1907 reginfo2DataType( mInfo, *result );
1908 }
1909 } else {
1910 rv = NS_ERROR_NULL_POINTER;
1911 }
1912 return rv;
1913}
1914
1915/*---------------------- nsRegistryValue::GetLength -----------------------
1916| We test if we've got the info already. If not, we git it by calling |
1917| getInfo. We calculate the result by converting the REGINFO type field to |
1918| a nsIRegistry::DataType value (using reginfo2Length). |
1919------------------------------------------------------------------------------*/
1920NS_IMETHODIMP nsRegistryValue::GetLength( PRUint32 *result ) {
1921 nsresult rv = NS_OK;
1922 // Make sure we have room for th result.
1923 if( result ) {
1924 // Make sure we've got the info we need.
1925 rv = getInfo();
1926 // Check if it worked.
1927 if( rv == NS_OK ) {
1928 // Convert result from REGINFO to length.
1929 reginfo2Length( mInfo, *result );
1930 }
1931 } else {
1932 rv = NS_ERROR_NULL_POINTER;
1933 }
1934 return rv;
1935}
1936
1937/*------------------------- nsRegistryValue::getInfo ---------------------------
1938| Call NR_RegEnumEntries to set the mInfo/mName data members. |
1939------------------------------------------------------------------------------*/
1940nsresult nsRegistryValue::getInfo() {
1941 nsresult rv = NS_OK;
1942 // Test whether we haven't tried to get it yet.
1943 if( mErr == -1 ) {
1944 REGENUM temp = mEnum;
1945 // Get name and info.
1946 PR_Lock(mregLock);
1947 mErr = NR_RegEnumEntries( mReg, mKey, &temp, mName, sizeof mName, &mInfo );
1948 // Convert result.
1949 rv = regerr2nsresult( mErr );
1950 PR_Unlock(mregLock);
1951 }
1952 return rv;
1953}
1954
1955
1956nsRegistryFactory::nsRegistryFactory() {
1957}
1958
1959NS_IMPL_ISUPPORTS1(nsRegistryFactory, nsIFactory)
1960
1961NS_IMETHODIMP
1962nsRegistryFactory::CreateInstance(nsISupports *aOuter,
1963 const nsIID &aIID,
1964 void **aResult) {
1965 nsresult rv = NS_OK;
1966 nsRegistry* newRegistry;
1967
1968 if(aResult == nsnull) {
1969 return NS_ERROR_NULL_POINTER;
1970 } else {
1971 *aResult = nsnull;
1972 }
1973
1974 if(0 != aOuter) {
1975 return NS_ERROR_NO_AGGREGATION;
1976 }
1977
1978 NS_NEWXPCOM(newRegistry, nsRegistry);
1979
1980 if(newRegistry == nsnull) {
1981 return NS_ERROR_OUT_OF_MEMORY;
1982 }
1983
1984 NS_ADDREF(newRegistry);
1985 rv = newRegistry->QueryInterface(aIID, aResult);
1986 NS_RELEASE(newRegistry);
1987
1988 return rv;
1989}
1990
1991nsresult
1992nsRegistryFactory::LockFactory(PRBool aLock)
1993{
1994 // Not implemented in simplest case.
1995 return NS_OK;
1996}
1997
1998// This is a temporary hack; needs work to support dynamic binding
1999// via nsComponentManager and support for multiple factories per DLL.
2000extern "C" NS_EXPORT nsresult
2001NS_RegistryGetFactory(nsIFactory** aFactory ) {
2002 nsresult rv = NS_OK;
2003
2004 if( aFactory == 0 ) {
2005 return NS_ERROR_NULL_POINTER;
2006 } else {
2007 *aFactory = 0;
2008 }
2009
2010 nsIFactory* inst = new nsRegistryFactory();
2011 if(0 == inst) {
2012 rv = NS_ERROR_OUT_OF_MEMORY;
2013 } else {
2014 NS_ADDREF(inst);
2015 *aFactory = inst;
2016 }
2017
2018 return rv;
2019}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette