Стартовый пул
This commit is contained in:
@@ -0,0 +1,584 @@
|
||||
(* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corpotation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Takanori Itou <necottie@nesitive.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** *)
|
||||
unit nsProfile;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
nsXPCOM, nsTypes, nsXPCOMGlue;
|
||||
|
||||
type
|
||||
nsProfileDirServiceProvider = interface(nsIDirectoryServiceProvider)
|
||||
procedure SetProfileDir(AProfileDir: nsIFile);
|
||||
procedure Register;
|
||||
procedure Shutdown;
|
||||
end;
|
||||
|
||||
EGeckoProfileError = class(EGeckoError);
|
||||
|
||||
function NS_NewProfileDirServiceProvider(aNotifyObservers: PRBool): nsProfileDirServiceProvider;
|
||||
|
||||
resourcestring
|
||||
SProfileRegisterError = 'Failed to register profile.';
|
||||
SProfileShutdownError = 'Failed to shutdown profile.';
|
||||
SSetProfileDirError = 'Failed to register profile directory.';
|
||||
SNotADirectory = 'The specified file is not a directory.';
|
||||
SProfileInitError = 'Failed to initialize profile.';
|
||||
SEnsureProfileDirError = 'Cannot ensure profile directory.';
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Windows, SysUtils, nsConsts, nsError, nsGeckoStrings, nsCID;
|
||||
|
||||
type
|
||||
TProfileDirLock = class(TObject)
|
||||
FHaveLock: Boolean;
|
||||
FLockFileHandle: THandle;
|
||||
|
||||
constructor Create; overload;
|
||||
constructor Create(src: TProfileDirLock); overload;
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Assign(rhs: TProfileDirLock);
|
||||
function Lock(aFile: nsILocalFile): nsresult;
|
||||
function Unlock: nsresult;
|
||||
end;
|
||||
|
||||
TProfileDirServiceProvider = class(TInterfacedObject,
|
||||
nsProfileDirServiceProvider,
|
||||
nsIDirectoryServiceProvider)
|
||||
FProfileDir: nsIFile;
|
||||
FProfileDirLock: TProfileDirLock;
|
||||
FNotifyObservers: PRBool;
|
||||
FSharingEnabled: Boolean;
|
||||
FNonSharedDirName: IInterfacedString;
|
||||
FNonSharedProfileDir: nsIFile;
|
||||
function GetFile(const prop: PAnsiChar; out persistent: PRBool): nsIFile; safecall;
|
||||
procedure SetProfileDir(AProfileDir: nsIFile);
|
||||
procedure Register;
|
||||
procedure Shutdown;
|
||||
|
||||
constructor Create(aNotifyObservers: PRBool = True);
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Initialize;
|
||||
procedure InitProfileDir(profileDir: nsIFile);
|
||||
procedure InitNonSharedProfileDir;
|
||||
procedure EnsureProfileFileExists(aFile: nsIFile; destDir: nsIFile);
|
||||
procedure UndefineFileLocations;
|
||||
|
||||
function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult; override;
|
||||
end;
|
||||
|
||||
constructor TProfileDirLock.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
FHaveLock := False;
|
||||
FLockFileHandle := INVALID_HANDLE_VALUE;
|
||||
end;
|
||||
|
||||
constructor TProfileDirLock.Create(src: TProfileDirLock);
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
Assign(src);
|
||||
end;
|
||||
|
||||
procedure TProfileDirLock.Assign(rhs: TProfileDirLock);
|
||||
begin
|
||||
Unlock();
|
||||
|
||||
FHaveLock := rhs.FHaveLock;
|
||||
rhs.FHaveLock := False;
|
||||
|
||||
FLockFileHandle := rhs.FLockFileHandle;
|
||||
rhs.FLockFileHandle := INVALID_HANDLE_VALUE;
|
||||
end;
|
||||
|
||||
destructor TProfileDirLock.Destroy;
|
||||
begin
|
||||
Unlock();
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TProfileDirLock.Lock(aFile: nsILocalFile): nsresult;
|
||||
const
|
||||
LOCKFILE_NAME = 'parent.lock';
|
||||
var
|
||||
isDir: PRBool;
|
||||
lockFile: nsIFile;
|
||||
lockFileName: IInterfacedString;
|
||||
filePath: IInterfacedCString;
|
||||
begin
|
||||
try
|
||||
lockFileName := NewString(LOCKFILE_NAME);
|
||||
filePath := NewCString;
|
||||
|
||||
if not FHaveLock then
|
||||
begin
|
||||
Result := NS_ERROR_UNEXPECTED;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
isDir := aFile.IsDirectory();
|
||||
|
||||
if not isDir then
|
||||
begin
|
||||
Result := NS_ERROR_FILE_NOT_DIRECTORY;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
lockFile := aFile.Clone();
|
||||
lockFile.Append(lockFileName.AString);
|
||||
lockFile.GetNativePath(filePath.ACString);
|
||||
|
||||
FLockFileHandle := CreateFileA(PAnsiChar(filePath.ToString),
|
||||
GENERIC_READ or GENERIC_WRITE,
|
||||
0,
|
||||
nil,
|
||||
OPEN_ALWAYS,
|
||||
FILE_FLAG_DELETE_ON_CLOSE,
|
||||
0);
|
||||
if FLockFileHandle = INVALID_HANDLE_VALUE then
|
||||
begin
|
||||
Result := NS_ERROR_FILE_ACCESS_DENIED;
|
||||
Exit;
|
||||
end;
|
||||
FHaveLock := True;
|
||||
Result := NS_OK;
|
||||
except
|
||||
on EOutOfMemory do
|
||||
Result := NS_ERROR_OUT_OF_MEMORY;
|
||||
on ESafeCallException do
|
||||
Result := NS_ERROR_FAILURE;
|
||||
else
|
||||
Result := NS_ERROR_UNEXPECTED;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TProfileDirLock.Unlock: nsresult;
|
||||
begin
|
||||
Result := NS_OK;
|
||||
|
||||
if FHaveLock then
|
||||
begin
|
||||
if FLockFileHandle <> INVALID_HANDLE_VALUE then
|
||||
begin
|
||||
CloseHandle(FLockFileHandle);
|
||||
FLockFileHandle := INVALID_HANDLE_VALUE;
|
||||
end;
|
||||
FHaveLock := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TProfileDirServiceProvider.Create(aNotifyObservers: PRBool);
|
||||
begin
|
||||
inherited Create;
|
||||
FNotifyObservers := aNotifyObservers;
|
||||
end;
|
||||
|
||||
destructor TProfileDirServiceProvider.Destroy;
|
||||
begin
|
||||
FProfileDirLock.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.SetProfileDir(aProfileDir: nsIFile);
|
||||
var
|
||||
{$IFDEF MOZ_PROFILELOCKING}
|
||||
dirToLock: nsILocalFile;
|
||||
{$ENDIF}
|
||||
observerService: nsIObserverService;
|
||||
begin
|
||||
try
|
||||
if Assigned(FProfileDir) then
|
||||
begin
|
||||
if Assigned(aProfileDir) and
|
||||
aProfileDir.Equals(FProfileDir) then
|
||||
begin
|
||||
Exit;
|
||||
end;
|
||||
{$IFDEF MOZ_PROFILELOCKING}
|
||||
FProfileDirLock.Unlock();
|
||||
{$ENDIF}
|
||||
UndefineFileLocations;
|
||||
end;
|
||||
FProfileDir := aProfileDir;
|
||||
if not Assigned(FProfileDir) then
|
||||
begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
{$IFDEF MOZ_PROFILELOCKING}
|
||||
Result := InitProfileDir(FProfileDir);
|
||||
if NS_FAILED(Result) then Exit;
|
||||
|
||||
if FSharingEnabled then
|
||||
Result := FNonSharedProfileDir.QueryInterface(nsILocalFile, dirToLock)
|
||||
else
|
||||
Result := FNonSharedProfileDir.QueryInterface(nsILocalFile, dirToLock);
|
||||
if NS_FAILED(Result) then Exit;
|
||||
Result := FProfileDirLock.Lock(dirToLock);
|
||||
if NS_FAILED(Result) then Exit;
|
||||
{$ENDIF}
|
||||
|
||||
if FNotifyObservers then
|
||||
begin
|
||||
NS_GetService('@mozilla.org/observer-service;1', nsIObserverService, observerService);
|
||||
|
||||
observerService.NotifyObservers(nil, 'profile-do-change', 'startup');
|
||||
observerService.NotifyObservers(nil, 'profile-after-change', 'startup');
|
||||
end;
|
||||
|
||||
except
|
||||
raise EGeckoProfileError.CreateRes(PResStringRec(@SSetProfileDirError));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.Register;
|
||||
var
|
||||
directoryService: nsIDirectoryService;
|
||||
begin
|
||||
NS_GetService(NS_DIRECTORY_SERVICE_CONTRACTID,
|
||||
nsIDirectoryService,
|
||||
directoryService);
|
||||
try
|
||||
directoryService.RegisterProvider(Self);
|
||||
except
|
||||
raise EGeckoProfileError.CreateRes(PResStringRec(@SProfileRegisterError));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.Shutdown;
|
||||
var
|
||||
observerService: nsIObserverService;
|
||||
begin
|
||||
NS_GetService('@mozilla.org/observer-service;1',
|
||||
nsIObserverService,
|
||||
observerService);
|
||||
try
|
||||
observerService.NotifyObservers(nil, 'profile-before-change', 'shutdown-persist');
|
||||
except
|
||||
raise EGeckoProfileError.CreateRes(PResStringRec(@SProfileShutdownError));
|
||||
end;
|
||||
end;
|
||||
|
||||
function TProfileDirServiceProvider.GetFile(const prop: PAnsiChar; out persistent: PRBool): nsIFile;
|
||||
var
|
||||
localFile: nsIFile;
|
||||
domainDir: nsIFile;
|
||||
appendStr: IInterfacedCString;
|
||||
const
|
||||
PREFS_FILE_50_NAME =' prefs.js';
|
||||
USER_CHROME_DIR_50_NAME = 'chrome';
|
||||
LOCAL_STORE_FILE_50_NAME = 'localstore.rdf';
|
||||
HISTORY_FILE_50_NAME = 'history.dat';
|
||||
PANELS_FILE_50_NAME = 'panels.rdf';
|
||||
MIME_TYPES_FILE_50_NAME = 'mimeTypes.rdf';
|
||||
BOOKMARKS_FILE_50_NAME = 'bookmark.html';
|
||||
DOWNLOADS_FILE_50_NAME = 'downloads.rdf';
|
||||
SEARCH_FILE_50_NAME = 'search.rdf';
|
||||
MAIL_DIR_50_NAME = 'Mail';
|
||||
IMAP_MAIL_DIR_50_NAME = 'ImapMail';
|
||||
NEWS_DIR_50_NAME = 'News';
|
||||
MSG_FOLDER_CACHE_DIR_50_NAME = 'panacea.dat';
|
||||
begin
|
||||
appendStr := NewCString;
|
||||
|
||||
persistent := True;
|
||||
domainDir := FProfileDir;
|
||||
|
||||
Assert(Assigned(domainDir));
|
||||
|
||||
if prop = NS_APP_PREFS_50_DIR then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
end else
|
||||
if prop = NS_APP_PREFS_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(PREFS_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_USER_PROFILE_50_DIR then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
end else
|
||||
if prop = NS_APP_USER_CHROME_DIR then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(USER_CHROME_DIR_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_LOCALSTORE_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(LOCAL_STORE_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
EnsureProfileFileExists(localFile, domainDir);
|
||||
end else
|
||||
if prop = NS_APP_HISTORY_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(HISTORY_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_USER_PANELS_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(PANELS_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
EnsureProfileFileExists(localFile, domainDir);
|
||||
end else
|
||||
if prop = NS_APP_USER_MIMETYPES_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(MIME_TYPES_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
EnsureProfileFileExists(localFile, domainDir);
|
||||
end else
|
||||
if prop = NS_APP_BOOKMARKS_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(BOOKMARKS_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_DOWNLOADS_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(DOWNLOADS_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_SEARCH_50_FILE then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(SEARCH_FILE_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
EnsureProfileFileExists(localFile, domainDir);
|
||||
end else
|
||||
if prop = NS_APP_MAIL_50_DIR then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(MAIL_DIR_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_IMAP_MAIL_50_DIR then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(IMAP_MAIL_DIR_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_NEWS_50_DIR then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(NEWS_DIR_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end else
|
||||
if prop = NS_APP_MESSENGER_FOLDER_CACHE_50_DIR then
|
||||
begin
|
||||
localFile := domainDir.Clone();
|
||||
appendStr.Assign(MSG_FOLDER_CACHE_DIR_50_NAME);
|
||||
localFile.AppendNative(appendStr.ACString);
|
||||
end;
|
||||
|
||||
if Assigned(localFile) then
|
||||
Result := localFile as nsIFile;
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.Initialize;
|
||||
begin
|
||||
{$IFDEF MOZ_PROFILELOCKING}
|
||||
FProfileDir := TProfileDirServiceProvider.Create(FNotifyObservers);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.InitProfileDir(profileDir: nsIFile);
|
||||
var
|
||||
exists: PRBool;
|
||||
profileDefaultsDir: nsIFile;
|
||||
profileDirParent: nsIFile;
|
||||
profileDirName: IInterfacedCString;
|
||||
isDir: PRBool;
|
||||
begin
|
||||
try
|
||||
profileDirName := NewCString;
|
||||
|
||||
exists := profileDir.Exists();
|
||||
|
||||
if not exists then
|
||||
begin
|
||||
profileDirParent := profileDir.Parent;
|
||||
profileDir.GetNativeLeafName(profileDirName.ACString);
|
||||
|
||||
try
|
||||
profileDefaultsDir := NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR);
|
||||
except
|
||||
profileDefaultsDir := NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR);
|
||||
end;
|
||||
try
|
||||
profileDefaultsDir.CopyToNative(profileDirParent, profileDirName.ACString);
|
||||
except
|
||||
profileDirParent.AppendNative(profileDirName.ACString);
|
||||
profileDirParent.Create(NS_IFILE_DIRECTORY_TYPE, 7 shl 6);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
isDir := profileDir.IsDirectory();
|
||||
if not isDir then
|
||||
raise EGeckoProfileError.CreateRes(PResStringRec(@SNotADirectory));
|
||||
end;
|
||||
|
||||
if FNonSharedDirName.Length > 0 then
|
||||
InitNonSharedProfileDir;
|
||||
except
|
||||
on EGeckoError do raise
|
||||
else raise EGeckoProfileError.CreateRes(PResStringRec(@SProfileInitError));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.InitNonSharedProfileDir;
|
||||
var
|
||||
localDir: nsIFile;
|
||||
exists: PRBool;
|
||||
isDir: PRBool;
|
||||
begin
|
||||
try
|
||||
localDir := FProfileDir.Clone();
|
||||
localDir.Append(FNonSharedDirName.AString);
|
||||
exists := localDir.Exists();
|
||||
if not exists then
|
||||
begin
|
||||
localDir.Create(NS_IFILE_DIRECTORY_TYPE, 7 shl 6);
|
||||
end else
|
||||
begin
|
||||
isDir := localDir.IsDirectory();
|
||||
if not isDir then
|
||||
raise EGeckoProfileError.CreateRes(PResStringRec(@SNotADirectory));
|
||||
end;
|
||||
FNonSharedProfileDir := localDir;
|
||||
except
|
||||
on EGeckoError do raise
|
||||
else raise EGeckoProfileError.CreateRes(PResStringRec(@SProfileInitError));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.EnsureProfileFileExists(aFile: nsIFile; destDir: nsIFile);
|
||||
var
|
||||
exists: PRBool;
|
||||
defaultsFile: nsIFile;
|
||||
leafName: IInterfacedCString;
|
||||
begin
|
||||
try
|
||||
exists := aFile.Exists;
|
||||
if exists then
|
||||
begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
try
|
||||
defaultsFile := NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR);
|
||||
except
|
||||
defaultsFile := NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR);
|
||||
end;
|
||||
|
||||
leafName := NewCString;
|
||||
|
||||
aFile.GetNativeLeafName(leafName.ACString);
|
||||
defaultsFile.AppendNative(leafName.ACString);
|
||||
|
||||
leafName.Assign('');
|
||||
defaultsFile.CopyToNative(destDir, leafName.ACString);
|
||||
except
|
||||
on EGeckoError do raise
|
||||
else raise EGeckoProfileError.CreateRes(PResStringRec(@SEnsureProfileDirError));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TProfileDirServiceProvider.UndefineFileLocations;
|
||||
var
|
||||
directoryService : nsIProperties;
|
||||
i: Integer;
|
||||
const
|
||||
NUM_OF_DIRS = 15;
|
||||
Dirs: array [1..15] of PAnsiChar = (
|
||||
NS_APP_PREFS_50_DIR,
|
||||
NS_APP_PREFS_50_FILE,
|
||||
NS_APP_USER_PROFILE_50_DIR,
|
||||
NS_APP_USER_CHROME_DIR,
|
||||
NS_APP_LOCALSTORE_50_FILE,
|
||||
NS_APP_HISTORY_50_FILE,
|
||||
NS_APP_USER_PANELS_50_FILE,
|
||||
NS_APP_USER_MIMETYPES_50_FILE,
|
||||
NS_APP_BOOKMARKS_50_FILE,
|
||||
NS_APP_DOWNLOADS_50_FILE,
|
||||
NS_APP_SEARCH_50_FILE,
|
||||
NS_APP_MAIL_50_DIR,
|
||||
NS_APP_IMAP_MAIL_50_DIR,
|
||||
NS_APP_NEWS_50_DIR,
|
||||
NS_APP_MESSENGER_FOLDER_CACHE_50_DIR
|
||||
);
|
||||
begin
|
||||
NS_GetService(NS_DIRECTORY_SERVICE_CONTRACTID,
|
||||
nsIProperties,
|
||||
directoryService);
|
||||
|
||||
for I:=1 to NUM_OF_DIRS do
|
||||
try
|
||||
directoryService.Undefine(Dirs[I]);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function TProfileDirServiceProvider.SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult;
|
||||
begin
|
||||
Result := HResult(NS_ERROR_FAILURE);
|
||||
end;
|
||||
|
||||
function NS_NewProfileDirServiceProvider(aNotifyObservers: PRBool): nsProfileDirServiceProvider;
|
||||
var
|
||||
prov: TProfileDirServiceProvider;
|
||||
begin
|
||||
prov := TProfileDirServiceProvider.Create(aNotifyObservers);
|
||||
|
||||
prov.Initialize;
|
||||
Result := prov;
|
||||
prov.FNotifyObservers := aNotifyObservers;
|
||||
end;
|
||||
|
||||
end.
|
Reference in New Issue
Block a user