home *** CD-ROM | disk | FTP | other *** search
- /*
- * DTS_CSAMTemplate.c
- * Copyright © 1992 Apple Computer Inc. All Rights Reserved.
- * This code resource is hidden in the CSAM resource file.
- *
- * DTS Sample CSAM is based on sample code written by
- * Steve Fisher, Eric Trehus, and Mike Cleron of Apple
- * OCE engineering.
- */
- #include "DTSSampleCSAM.h"
- #include <OCETemplates.h>
- #include <StandardFile.h>
- #include <Aliases.h>
- #ifdef THINK_C
- #include <ASM.h>
- #endif
-
- pascal OSErr PersonalDirectoryCSAM(
- DETCallBlockPtr callBlockPtr
- );
- #if DEBUG_LOG
- void DumpAliasInfo(
- AliasHandle alias
- );
- #endif
-
- /*
- * These local functions do the work.
- */
- static OSErr ValidateAndUpdateAlias(
- DETCallBlockPtr callBlockPtr
- );
- static OSErr CreateDTSSampleDirectory(
- DETCallBlockPtr callBlockPtr
- );
- static OSErr ConvertAliasToString(
- DETCallBlockPtr callBlockPtr
- );
- static OSErr PrependString(
- Str63 namePart,
- RStringHandle tempName
- );
- pascal OSErr main(
- register DETCallBlockPtr callBlockPtr
- );
-
- pascal OSErr
- main(
- register DETCallBlockPtr callBlockPtr
- )
- {
- OSErr status;
- #if DEBUG_LOG
- AuditPtr auditPtr;
- #define TraceFunction(what) Audit(auditPtr, 'DET!', kAuditFormatString, what)
- #else
- #define TraceFunction(what) /* Nothing */
- #endif
-
- #ifdef THINK_C
- /*
- * Under Think C, copy the address of "main" into A4
- * so that some "global" references become valid.
- */
- asm {
- move.l a4,-(sp)
- lea main,a4
- }
- #endif
- #if DEBUG_LOG
- auditPtr = GetAuditPtr(kCSAMCreatorID);
- #endif
- status = kDETDidNotHandle;
- /*
- * A few DET requests do not use a target parameter.
- */
- switch (callBlockPtr->protoCall.reqFunction) {
- case kDETcmdInit: /* One-time initialization */
- #if DEBUG_LOG
- if (auditPtr == NULL) {
- auditPtr = InitAudit(kCSAMCreatorID, 64, TRUE, FALSE);
- TraceFunction("\pDET created audit log");
- }
- #endif
- TraceFunction("\pkDETcmdInit");
- /*
- * Here is where you can allocate memory that your template
- * needs throughout its lifetime.
- */
- status = noErr;
- break;
- case kDETcmdExit: /* Last call: unused */
- TraceFunction("\pkDETcmdExit");
- /*
- * Here is where you should deallocate permanent memory.
- */
- status = noErr;
- break;
- default:
- /*
- * All of the following DET requests require a target. We
- * only act on the ones in which the target is ourself.
- */
- if (callBlockPtr->protoCall.target.selector == kDETSelf) {
- switch (callBlockPtr->protoCall.reqFunction) {
- case kDETcmdInstanceInit:
- TraceFunction("\pkDETcmdInstanceInit");
- /*
- * Initialization for a newly-created aspect.
- * We do nothing and, hence, return kDETDidNotHandle.
- */
- break;
- case kDETcmdInstanceExit:
- TraceFunction("\pkDETcmdInstanceExit");
- /*
- * Cleanup for an aspect created by kDETcmdInstanceInit.
- * We do nothing and, hence, return kDETDidNotHandle.
- */
- break;
- case kDETcmdPropertyCommand:
- TraceFunction("\pkDETcmdPropertyCommand");
- if (callBlockPtr->propertyCommand.property == prCreatePDButton)
- status = CreateDTSSampleDirectory(callBlockPtr);
- break;
- case kDETcmdPropertyDirtied:
- TraceFunction("\pkDETcmdPropertyDirtied");
- if (callBlockPtr->propertyDirtied.property == kDETPastFirstLookup)
- status = ValidateAndUpdateAlias(callBlockPtr);
- break;
- case kDETcmdConvertToRString:
- TraceFunction("\pkDETcmdConvertToRString");
- if (callBlockPtr->convertToRString.property != prPDAlias)
- status = paramErr;
- else {
- status = ConvertAliasToString(callBlockPtr);
- }
- break;
- }
- }
- }
- #if DEBUG_LOG
- if (status != noErr && status != kDETDidNotHandle)
- AuditStatusString(auditPtr, 'DET!', status, "\pDET Exit");
- #endif
- #ifdef THINK_C
- asm {
- move.l (sp)+,a4
- }
- #endif
- return (status);
- }
-
- /*
- * Reorganize a string. Why not use Munger?
- */
- static OSErr
- PrependString(
- Str63 namePart,
- RStringHandle tempName
- )
- {
- OSErr status;
- Size tempSize;
- #define TEMP (**tempName)
-
- tempSize = GetHandleSize((Handle) tempName);
- SetHandleSize((Handle) tempName, tempSize + namePart[0]);
- status = MemError();
- if (status == noErr) {
- BlockMove(
- TEMP.body,
- TEMP.body + (namePart[0]),
- TEMP.dataLength
- );
- BlockMove(
- namePart + 1,
- TEMP.body,
- namePart[0]
- );
- TEMP.dataLength += namePart[0];
- }
- return (status);
- #undef TEMP
- }
-
- static OSErr
- PrependAliasInfo(
- AliasHandle pdAlias,
- short part,
- RStringHandle tempName,
- Boolean *lastPart
- )
- {
- OSErr status;
- Str63 namePart;
-
- status = GetAliasInfo(pdAlias, part, namePart);
- *lastPart = (namePart[0] == 0);
- if (status == noErr && (*lastPart) == FALSE) {
- /*
- * Append a colon to all parts of the path
- * except the file name
- */
- if (part != 0) {
- ++namePart[0];
- namePart[namePart[0]] = ':';
- }
- status = PrependString(namePart, tempName);
- }
- return (status);
- }
-
- static OSErr
- GetFullPathName(
- AliasHandle pdAlias,
- RStringHandle *fileName
- )
- {
- OSErr status;
- RStringHandle tempName;
- short part;
- Boolean lastPart;
- #define TEMP (**tempName)
-
- status = noErr;
- tempName = (RStringHandle) NewHandleClear(sizeof(ProtoRString));
- status = MemError();
- if (status == noErr) {
- TEMP.charSet = smSystemScript;
- for (part = 0, lastPart = FALSE;
- status == noErr && lastPart == FALSE;
- ++part) {
- status = PrependAliasInfo(pdAlias, part, tempName, &lastPart);
- }
- if (status == noErr) {
- status = PrependAliasInfo(
- pdAlias,
- asiVolumeName,
- tempName,
- &lastPart
- );
- }
- }
- if (status != noErr) {
- DisposHandle((Handle) tempName);
- tempName = NULL;
- }
- #if DEBUG_LOG
- if (tempName == NULL || status != noErr)
- LogStatusX('GFPN', status, "\perr or null pathname");
- else {
- HLock((Handle) tempName);
- LogRStringX('GFPN', *tempName);
- HUnlock((Handle) tempName);
- }
- #endif
- *fileName = tempName;
- return (status);
- }
-
- static OSErr
- ConvertAliasToString(
- register DETCallBlockPtr callBlockPtr
- )
- {
- OSErr status;
- AliasHandle alias;
-
- alias = NULL;
- status = GetBinaryProperty(callBlockPtr, prPDAlias, (Handle *) &alias);
- LogStatusX('CA2S', status, "\pConvertAliasToString: GetBinaryProperty");
- if (status == noErr) {
- status = GetFullPathName(
- alias,
- &callBlockPtr->convertToRString.theValue
- );
- LogStatusX('CA2S', status, "\pConvertAliasToString: GetFullPathName");
- }
- if (alias != NULL)
- DisposHandle((Handle) alias);
- return (status);
- }
-
- static OSErr
- SetAliasProperty(
- register DETCallBlockPtr callBlockPtr,
- AliasHandle alias
- )
- {
- OSErr status;
-
- HLock((Handle) alias);
- status = SetBinaryProperty(
- callBlockPtr,
- prPDAlias,
- (Ptr) *alias,
- (**alias).aliasSize,
- TRUE
- );
- LogStatusX('SeAP', status, "\pSetBinaryProperty");
- HUnlock((Handle) alias);
- return (status);
- }
-
- /*
- * Add a record for an external directory to the
- * O.C.E. Setup directory. This makes the directory
- * accessable to the user.
- */
- static OSErr
- AddCSAMDirectory(
- CreationID *dsamRecordCID,
- DirectoryNamePtr dirName,
- DirDiscriminator *discriminator,
- DirGestalt features,
- CreationID *directoryRecordCID
- )
- {
- OSErr status;
- DirParamBlock dspb;
-
- OCECopyCreationID(
- dsamRecordCID,
- &dspb.addDSAMDirectoryPB.dsamRecordCID
- );
- OCECopyDirDiscriminator(
- discriminator,
- &dspb.addDSAMDirectoryPB.discriminator
- );
- dspb.addDSAMDirectoryPB.directoryName = dirName;
- dspb.addDSAMDirectoryPB.features = features;
- OCECopyCreationID(
- directoryRecordCID,
- &dspb.addDSAMDirectoryPB.directoryRecordCID
- );
- LogRStringX('ADSD', dirName);
- status = DirAddDSAMDirectory(&dspb, FALSE);
- LogStatusX('ADSD', status, "\pDirAddDSAMDir@Template");
- return (status);
- }
-
- static OSErr DeleteUnconfiguredAttributeType(CreationID *directoryRecordCID)
- {
- OSErr err;
- DirParamBlock dspb;
- RecordID rid;
-
- rid.local.recordName = NULL;
- rid.local.recordType = NULL;
- OCECopyCreationID(directoryRecordCID, &rid.local.cid);
- rid.rli = nil;
-
- err = DirGetOCESetupRefNum(&dspb, false);
- if (err == noErr)
- {
- *(long*)&dspb.deleteAttributeTypePB.serverHint = 0;
- dspb.deleteAttributeTypePB.identity = 0;
- dspb.deleteAttributeTypePB.aRecord = &rid;
- dspb.deleteAttributeTypePB.attrType = OCEGetIndAttributeType(kUnconfiguredAttrTypeNum);
-
- err = DirDeleteAttributeType(&dspb, false);
- }
-
- return err;
- }
-
- /*
- * The personal directory's file ID is stored in the misc part
- * of the discriminator.
- */
- static OSErr
- GetIDFromFSSpec(
- const FSSpec *spec,
- unsigned long *id
- )
- {
- OSErr status;
- CInfoPBRec pb;
-
- pb.dirInfo.ioCompletion = NULL;
- pb.dirInfo.ioVRefNum = spec->vRefNum;
- pb.dirInfo.ioNamePtr = (StringPtr) spec->name;
- pb.dirInfo.ioFDirIndex = 0;
- pb.dirInfo.ioDrDirID = spec->parID;
- status = PBGetCatInfo(&pb, FALSE);
- if (status == noErr)
- *id = pb.dirInfo.ioDrDirID;
- LogStatusX('GIDF', status, "\pPBGetCatInfo");
- return (status);
- }
-
- /*
- * Create a Personal Directory, along with a resource fork
- * for Directory Browser friendliness.
- */
- static OSErr
- CreatePersonalDirectory(
- FSSpec *spec
- )
- {
- OSErr status;
- DirParamBlock dspb;
-
- dspb.createPersonalDirectoryPB.fsSpec = spec;
- dspb.createPersonalDirectoryPB.fdCreator = kPersonalDirectoryFileCreator;
- dspb.createPersonalDirectoryPB.fdType = kPersonalDirectoryFileType;
- status = DirCreatePersonalDirectory(&dspb);
- LogStatusX('CrPD', status, "\pDirCreatePersonalDirectory");
- if (status == noErr) {
- FSpCreateResFile(
- spec,
- kPersonalDirectoryFileCreator,
- kPersonalDirectoryFileType,
- smSysScript
- );
- LogStatusX('CrPD', status, "\pFSpCreateResFile");
- if (status == noErr) {
- status = ResError();
- LogErrorX('CrPD', status);
- }
- }
- return (status);
- }
-
- /*
- * Prompt user for the name and location of the
- * Personal Directory file. Note that this returns
- * "noErr" status if the user cancels the prompt.
- * This returns userCanceledErr if the user cancels
- * the dialog.
- */
- static OSErr
- GetNewPDFile(
- StandardFileReply *reply
- )
- {
- OSErr status;
- Str255 prompt;
- Str255 defaultName;
-
- GetIndString(prompt, kCSAMPromptStrings, kNewPDPrompt);
- GetIndString(defaultName, kCSAMPromptStrings, kNewPDName);
- StandardPutFile(prompt, defaultName, reply);
- if (reply->sfGood == FALSE)
- status = userCanceledErr;
- else if (reply->sfReplacing)
- status = FSpDelete(&reply->sfFile);
- else {
- status = noErr;
- }
- return (status);
- }
-
- /*
- * Note: this returns userCanceledErr if the user
- * canceled the FSSpec dialog.
- */
- static OSErr
- GetPersonalDirectoryInfo(
- DETCallBlockPtr callBlockPtr,
- DirectoryName *dirName,
- DirDiscriminator *discriminator
- )
- {
- OSErr status;
- StandardFileReply reply;
- AliasHandle alias;
-
- alias = NULL;
- status = GetNewPDFile(&reply);
- if (status == noErr)
- status = CreatePersonalDirectory(&reply.sfFile);
- if (status == noErr) {
- OCEPToRString(
- reply.sfFile.name,
- GetEnvirons(smSysScript),
- (RString *) dirName,
- kDirectoryNameMaxBytes
- );
- discriminator->signature = kCSAMCreatorID;
- status = GetIDFromFSSpec(
- &reply.sfFile,
- &discriminator->misc
- );
- LogStatusX('GPDI', status, "\pGetIDFromFSSpec");
- }
- if (status == noErr)
- status = NewAlias(NULL, &reply.sfFile, &alias);
- if (status == noErr)
- status = SetAliasProperty(callBlockPtr, alias);
- if (alias != NULL) {
- DisposHandle((Handle) alias);
- }
- return (status);
- }
-
- /*
- * Add a record for our CSAM to the O.C.E. Setup directory.
- */
- static OSErr
- AddSampleCSAM(
- DETCallBlockPtr callBlockPtr,
- CreationID *dsamRecordCID
- )
- {
- OSErr status;
- StringHandle csamName;
- FSSpec fsSpec;
- RString csamRStringName;
- DirParamBlock dspb;
-
- status = noErr;
- csamName = GetString(kCSAMName);
- if (csamName == NULL)
- status = resNotFound;
- LogStatusX('APPD', status, "\pGetString");
- if (status == noErr)
- status = GetMyFSSpec(callBlockPtr, &fsSpec);
- LogStatusX('APPD', status, "\pGetMyFSSpec");
- if (status == noErr) {
- OCEPToRString(
- *csamName,
- smRoman,
- &csamRStringName,
- kRStringMaxBytes
- );
- ReleaseResource((Handle) csamName);
- dspb.addDSAMPB.dsamName = &csamRStringName;
- dspb.addDSAMPB.dsamKind = kCSAMCreatorID;
- dspb.addDSAMPB.fsSpec = &fsSpec;
- status = DirAddDSAM(&dspb);
- LogStatusX('APPD', status, "\pDirAddDSAM");
- if (status != noErr) {
- LogRStringX('APPD', dspb.addDSAMPB.dsamName);
- LogTextX(dspb.addDSAMPB.dsamKind, fsSpec.name);
- }
- /*
- * If we call DirAddDSAM and the CSAM has already been
- * opened, it returns the CSAM record's CID, but also
- * the kOCEDSAMRecordExists error. We treat this
- * as a non-error.
- */
- if (status == kOCEDSAMRecordExists)
- status = noErr;
- OCECopyCreationID(&dspb.addDSAMPB.dsamRecordCID, dsamRecordCID);
- }
- LogStatusX('APPD', status, "\pAddSampleCSAM exit");
- return (status);
- }
-
- static OSErr
- AddImpersonalDirectory(
- DETCallBlockPtr callBlockPtr,
- DirectoryName *dirName,
- DirDiscriminator *discriminator,
- CreationID *dsamRecordCID
- )
- {
- OSErr status;
- short directoryRecordRefNum;
- PackedDSSpec **directoryRecordDSSpec;
- DSSpec dsSpec;
- RecordID rid;
-
- directoryRecordDSSpec = NULL;
- status = GetMyDSSpec(
- callBlockPtr,
- &directoryRecordRefNum,
- &directoryRecordDSSpec
- );
- if (status == noErr) {
- HLock((Handle) directoryRecordDSSpec);
- OCEUnpackDSSpec(*directoryRecordDSSpec, &dsSpec, &rid);
- status = AddCSAMDirectory(
- dsamRecordCID,
- dirName,
- discriminator,
- kMyFeatures,
- &rid.local.cid
- );
- if (status == noErr)
- status = DeleteUnconfiguredAttributeType(&rid.local.cid);
- }
- if (directoryRecordDSSpec != NULL) {
- DisposHandle((Handle) directoryRecordDSSpec);
- }
- LogStatusX('AIMD', status, "\pAddImpersonalDirectory exit");
- return (status);
- }
-
- /*
- * Create the directory. If the user cancels the dialog,
- * return "noErr," else return the creation error status.
- */
- static OSErr
- CreateDTSSampleDirectory(
- DETCallBlockPtr callBlockPtr
- )
- {
- OSErr status;
- DirectoryName dirName;
- DirDiscriminator discriminator;
- CreationID csamRecordCID;
-
- /*
- * Create the PD and get its name and discriminator
- */
- status = GetPersonalDirectoryInfo(
- callBlockPtr,
- &dirName,
- &discriminator
- );
- LogStatusX('CDir', status, "\pGetPersonaDirectoryInfo");
- if (status == userCanceledErr) {
- status = noErr;
- goto exit;
- }
- /*
- * We need to save the alias property so that the
- * CSAM can get the alias
- */
- if (status == noErr) {
- status = SaveProperty(callBlockPtr, prPDAlias);
- LogStatusX('CDir', status, "\pSaveProperty");
- }
- /*
- * We add the CSAM, which is the easiest way to get
- * the csamRecordCID. Note that AddSampleCSAM catches
- * the "record already added" error.
- */
- if (status == noErr) {
- status = AddSampleCSAM(callBlockPtr, &csamRecordCID);
- LogStatusX('CDir', status, "\pAddSampleCSAM");
- }
- /*
- * Now add the directory itself.
- */
- if (status == noErr) {
- status = AddImpersonalDirectory(
- callBlockPtr,
- &dirName,
- &discriminator,
- &csamRecordCID
- );
- LogStatusX('CDir', status, "\pAddImpersonalDirectory");
- }
- /*
- * Mark that we have a catalog, so that our view will change.
- */
- if (status == noErr) {
- status = SetNumProperty(
- callBlockPtr,
- prHasCatalog,
- TRUE,
- FALSE
- );
- }
- /*
- * Change the record's name.
- */
- if (status == noErr) {
- status = SetRStringProperty(
- callBlockPtr,
- kDETAspectName,
- (RString *) &dirName,
- FALSE
- );
- LogStatusX('CDir', status, "\pSet Rec Name");
- }
-
- /*
- * If an error occurred, clear out our properties
- */
- if (status != noErr) {
- SetBinaryProperty(callBlockPtr, prPDAlias, NULL, 0, TRUE);
- SetNumProperty(callBlockPtr, prHasCatalog, 0, FALSE);
- }
-
- /*
- * And force a resync
- */
- if (status == noErr) {
- status = RequestSync(callBlockPtr);
- LogStatusX('CDir', status, "\pRequest Sync");
- }
-
- LogStatusX('CIMD', status, "\pCreateDTSSampleDirectory exit");
- exit: return (status);
- }
-
- static OSErr
- ValidateAndUpdateAlias(
- DETCallBlockPtr callBlockPtr
- )
- {
- OSErr status;
- AliasHandle alias;
- FSSpec spec;
- Boolean wasChanged;
- RString name;
-
- alias = NULL;
- status = GetBinaryProperty(
- callBlockPtr,
- prPDAlias,
- (Handle *) &alias
- );
- LogStatusX('VAUA', status, "\pGetBinaryProperty");
- if (alias != NULL) {
- if (GetHandleSize((Handle) alias) == 0)
- LogTextX('VAUA', "\p0-length property");
- if (status == noErr
- && GetHandleSize((Handle) alias) > 0) {
- DumpAliasInfo(alias);
- status = ResolveAlias(NULL, alias, &spec, &wasChanged);
- LogStatusX('VAUA', status, "\pResolveAlias");
- if (status == noErr && wasChanged) {
- status = SetAliasProperty(callBlockPtr, alias);
- LogStatusX('VAUA', status, "\pSetAliasProperty");
- }
-
- if (status == noErr) {
- name.charSet = GetEnvirons(smSysScript);
- name.dataLength = 0;
- status = GetAliasInfo(alias, asiAliasName, name.body - 1);
- if (status == noErr)
- status = SetRStringProperty(callBlockPtr, kDETAspectName, &name, FALSE);
- }
- }
- DisposHandle((Handle) alias);
- LogStatusX('VAUA', status, "\DisposHandle at exit");
- }
- LogStatusX('VAUA', status, "\pValidateAndUpdateAlias exit");
- return (status);
- }
-
- #if DEBUG_LOG
- void
- DumpAliasInfo(
- AliasHandle alias
- )
- {
- AuditPtr auditPtr;
- OSErr status;
- AliasInfoType index;
- Str63 theString;
-
- #define ShowString(i, why) do { \
- status = GetAliasInfo(alias, i, theString); \
- if (status != noErr) \
- goto exit; \
- if (theString[0] != 0) \
- AuditString(auditPtr, why, theString); \
- } while (0)
-
- auditPtr = GetAuditPtr(kCSAMCreatorID);
- if (auditPtr != NULL) {
- ShowString(asiZoneName, 'Zone');
- ShowString(asiServerName, 'Srvr');
- ShowString(asiVolumeName, 'Vol ');
- ShowString(asiAliasName, 'Targ');
- ShowString(asiParentName, 'Prnt');
- for (index = 0;; index++) {
- status = GetAliasInfo(alias, index, theString);
- if (theString[0] == 0)
- break;
- AuditString(auditPtr, 'Name', theString);
- }
- exit: if (status != noErr) {
- AuditStatusString(auditPtr, 'Alis', status, "\pDumpAliasInfo exit");
- if (status == paramErr) {
- if (alias == NULL)
- AuditString(auditPtr, 'Alis', "\pNull alias handle");
- else {
- Audit(
- auditPtr,
- 'Alis',
- AuditFormat3(
- kAuditFormatAddress,
- kAuditFormatUnsigned,
- kAuditFormatString
- ),
- *alias,
- GetHandleSize((Handle) alias),
- "\pBogus alias record"
- );
- }
- }
- }
- }
- }
- #endif
-