home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / Catalog Service Access Module / DTS Sample CSAM / Src / DTS_CSAMTemplate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-23  |  18.6 KB  |  793 lines  |  [TEXT/KAHL]

  1. /*
  2.  * DTS_CSAMTemplate.c
  3.  * Copyright © 1992 Apple Computer Inc. All Rights Reserved.
  4.  * This code resource is hidden in the CSAM resource file.
  5.  *
  6.  * DTS Sample CSAM is based on sample code written by
  7.  * Steve Fisher, Eric Trehus, and Mike Cleron of Apple
  8.  * OCE engineering.
  9.  */
  10. #include "DTSSampleCSAM.h"
  11. #include <OCETemplates.h>
  12. #include <StandardFile.h>
  13. #include <Aliases.h>
  14. #ifdef THINK_C
  15. #include <ASM.h>
  16. #endif
  17.  
  18. pascal OSErr                    PersonalDirectoryCSAM(
  19.         DETCallBlockPtr                callBlockPtr
  20.     );
  21. #if DEBUG_LOG
  22. void                            DumpAliasInfo(
  23.         AliasHandle                    alias
  24.     );
  25. #endif
  26.  
  27. /*
  28.  * These local functions do the work.
  29.  */
  30. static OSErr                    ValidateAndUpdateAlias(
  31.         DETCallBlockPtr                callBlockPtr
  32.     );
  33. static OSErr                    CreateDTSSampleDirectory(
  34.         DETCallBlockPtr                callBlockPtr
  35.     );
  36. static OSErr                    ConvertAliasToString(
  37.         DETCallBlockPtr                callBlockPtr
  38.     );
  39. static OSErr                    PrependString(
  40.         Str63                        namePart,
  41.         RStringHandle                tempName
  42.     );
  43. pascal OSErr                    main(
  44.         register DETCallBlockPtr    callBlockPtr
  45.     );
  46.  
  47. pascal OSErr
  48. main(
  49.         register DETCallBlockPtr    callBlockPtr
  50.     )
  51. {
  52.         OSErr                    status;
  53. #if DEBUG_LOG
  54.         AuditPtr                auditPtr;
  55. #define TraceFunction(what)    Audit(auditPtr, 'DET!', kAuditFormatString, what)
  56. #else
  57. #define TraceFunction(what)                /* Nothing    */
  58. #endif
  59.  
  60. #ifdef THINK_C
  61.         /*
  62.          * Under Think C, copy the address of "main" into A4
  63.          * so that some "global" references become valid.
  64.          */
  65.         asm {
  66.             move.l            a4,-(sp)
  67.             lea                main,a4
  68.         }
  69. #endif
  70. #if DEBUG_LOG
  71.         auditPtr = GetAuditPtr(kCSAMCreatorID);
  72. #endif
  73.         status = kDETDidNotHandle;
  74.         /*
  75.          * A few DET requests do not use a target parameter.
  76.          */
  77.         switch (callBlockPtr->protoCall.reqFunction) {
  78.         case kDETcmdInit:                /* One-time initialization        */
  79. #if DEBUG_LOG
  80.             if (auditPtr == NULL) {
  81.                 auditPtr = InitAudit(kCSAMCreatorID, 64, TRUE, FALSE);
  82.                 TraceFunction("\pDET created audit log");
  83.             }
  84. #endif
  85.             TraceFunction("\pkDETcmdInit");
  86.             /*
  87.              * Here is where you can allocate memory that your template
  88.              * needs throughout its lifetime.
  89.              */
  90.             status = noErr;
  91.             break;
  92.         case kDETcmdExit:            /* Last call: unused                */
  93.             TraceFunction("\pkDETcmdExit");
  94.             /*
  95.              * Here is where you should deallocate permanent memory.
  96.              */
  97.             status = noErr;
  98.             break;
  99.         default:
  100.             /*
  101.              * All of the following DET requests require a target. We
  102.              * only act on the ones in which the target is ourself.
  103.              */
  104.             if (callBlockPtr->protoCall.target.selector == kDETSelf) {
  105.                 switch (callBlockPtr->protoCall.reqFunction) {
  106.                 case kDETcmdInstanceInit:
  107.                     TraceFunction("\pkDETcmdInstanceInit");
  108.                     /*
  109.                      * Initialization for a newly-created aspect.
  110.                      * We do nothing and, hence, return kDETDidNotHandle.
  111.                      */
  112.                     break;
  113.                 case kDETcmdInstanceExit:
  114.                     TraceFunction("\pkDETcmdInstanceExit");
  115.                     /*
  116.                      * Cleanup for an aspect created by kDETcmdInstanceInit.
  117.                      * We do nothing and, hence, return kDETDidNotHandle.
  118.                      */
  119.                     break;
  120.                 case kDETcmdPropertyCommand:
  121.                     TraceFunction("\pkDETcmdPropertyCommand");
  122.                     if (callBlockPtr->propertyCommand.property == prCreatePDButton)
  123.                         status = CreateDTSSampleDirectory(callBlockPtr);
  124.                     break;
  125.                 case kDETcmdPropertyDirtied:
  126.                     TraceFunction("\pkDETcmdPropertyDirtied");
  127.                     if (callBlockPtr->propertyDirtied.property == kDETPastFirstLookup)
  128.                         status = ValidateAndUpdateAlias(callBlockPtr);
  129.                     break;
  130.                 case kDETcmdConvertToRString:
  131.                     TraceFunction("\pkDETcmdConvertToRString");
  132.                     if (callBlockPtr->convertToRString.property != prPDAlias)
  133.                         status = paramErr;
  134.                     else {
  135.                         status = ConvertAliasToString(callBlockPtr);
  136.                     }
  137.                     break;
  138.                 }
  139.             }
  140.         }
  141. #if DEBUG_LOG
  142.         if (status != noErr && status != kDETDidNotHandle)
  143.             AuditStatusString(auditPtr, 'DET!', status, "\pDET Exit");
  144. #endif
  145. #ifdef THINK_C
  146.         asm {
  147.             move.l        (sp)+,a4
  148.         }
  149. #endif
  150.         return (status);
  151. }
  152.  
  153. /*
  154.  * Reorganize a string. Why not use Munger?
  155.  */
  156. static OSErr
  157. PrependString(
  158.         Str63                        namePart,
  159.         RStringHandle                tempName
  160.     )
  161. {
  162.         OSErr                    status;
  163.         Size                    tempSize;
  164. #define TEMP    (**tempName)
  165.     
  166.         tempSize = GetHandleSize((Handle) tempName);
  167.         SetHandleSize((Handle) tempName, tempSize + namePart[0]);
  168.         status = MemError();
  169.         if (status == noErr) {
  170.             BlockMove(
  171.                 TEMP.body,
  172.                 TEMP.body + (namePart[0]),
  173.                 TEMP.dataLength
  174.             );
  175.             BlockMove(
  176.                 namePart + 1,
  177.                 TEMP.body,
  178.                 namePart[0]
  179.             );
  180.             TEMP.dataLength += namePart[0];
  181.         }
  182.         return (status);
  183. #undef TEMP
  184. }
  185.  
  186. static OSErr
  187. PrependAliasInfo(
  188.         AliasHandle                    pdAlias,
  189.         short                        part,
  190.         RStringHandle                tempName,
  191.         Boolean                        *lastPart
  192.     )
  193. {
  194.         OSErr                    status;
  195.         Str63                    namePart;
  196.         
  197.         status = GetAliasInfo(pdAlias, part, namePart);
  198.         *lastPart = (namePart[0] == 0);
  199.         if (status == noErr && (*lastPart) == FALSE) {
  200.             /*
  201.              * Append a colon to all parts of the path
  202.              * except the file name
  203.              */
  204.             if (part != 0) {
  205.                 ++namePart[0];                                
  206.                 namePart[namePart[0]] = ':';
  207.             }
  208.             status = PrependString(namePart, tempName);
  209.         }
  210.         return (status);
  211. }
  212.  
  213. static OSErr
  214. GetFullPathName(
  215.         AliasHandle                    pdAlias,
  216.         RStringHandle                *fileName
  217.     )
  218. {
  219.         OSErr                    status;
  220.         RStringHandle            tempName;
  221.         short                    part;
  222.         Boolean                    lastPart;
  223. #define TEMP    (**tempName)
  224.  
  225.         status = noErr;
  226.         tempName = (RStringHandle) NewHandleClear(sizeof(ProtoRString));
  227.         status = MemError();
  228.         if (status == noErr) {
  229.             TEMP.charSet = smSystemScript;
  230.             for (part = 0, lastPart = FALSE;
  231.                     status == noErr && lastPart == FALSE;
  232.                     ++part) {
  233.                 status = PrependAliasInfo(pdAlias, part, tempName, &lastPart);
  234.             }
  235.             if (status == noErr) {
  236.                 status = PrependAliasInfo(
  237.                             pdAlias,
  238.                             asiVolumeName,
  239.                             tempName,
  240.                             &lastPart
  241.                         );
  242.             }
  243.         }
  244.         if (status != noErr) {
  245.             DisposHandle((Handle) tempName);
  246.             tempName = NULL;
  247.         }
  248. #if DEBUG_LOG
  249.         if (tempName == NULL || status != noErr)
  250.             LogStatusX('GFPN', status, "\perr or null pathname");
  251.         else {
  252.             HLock((Handle) tempName);
  253.             LogRStringX('GFPN', *tempName);
  254.             HUnlock((Handle) tempName);
  255.         }
  256. #endif
  257.         *fileName = tempName;
  258.         return (status);
  259. }
  260.  
  261. static OSErr
  262. ConvertAliasToString(
  263.         register DETCallBlockPtr    callBlockPtr
  264.     )
  265. {
  266.         OSErr                    status;
  267.         AliasHandle                alias;
  268.  
  269.         alias = NULL;        
  270.         status = GetBinaryProperty(callBlockPtr, prPDAlias, (Handle *) &alias);
  271.         LogStatusX('CA2S', status, "\pConvertAliasToString: GetBinaryProperty");
  272.         if (status == noErr) {
  273.             status = GetFullPathName(
  274.                         alias,
  275.                         &callBlockPtr->convertToRString.theValue
  276.                     );
  277.             LogStatusX('CA2S', status, "\pConvertAliasToString: GetFullPathName");
  278.         }
  279.         if (alias != NULL)
  280.             DisposHandle((Handle) alias);
  281.         return (status);
  282. }
  283.  
  284. static OSErr
  285. SetAliasProperty(
  286.         register DETCallBlockPtr    callBlockPtr,
  287.         AliasHandle                    alias
  288.     )
  289. {
  290.         OSErr                    status;
  291.  
  292.         HLock((Handle) alias);
  293.         status = SetBinaryProperty(
  294.                     callBlockPtr,
  295.                     prPDAlias,
  296.                     (Ptr) *alias,
  297.                     (**alias).aliasSize,
  298.                     TRUE
  299.                 );
  300.         LogStatusX('SeAP', status, "\pSetBinaryProperty");
  301.         HUnlock((Handle) alias);
  302.         return (status);
  303. }
  304.  
  305. /*
  306.  * Add a record for an external directory to the
  307.  * O.C.E. Setup directory. This makes the directory
  308.  * accessable to the user.
  309.  */
  310. static OSErr
  311. AddCSAMDirectory(
  312.         CreationID                    *dsamRecordCID,
  313.         DirectoryNamePtr            dirName,
  314.         DirDiscriminator            *discriminator,
  315.         DirGestalt                    features,
  316.         CreationID                    *directoryRecordCID
  317.     )
  318. {
  319.         OSErr                    status;
  320.         DirParamBlock            dspb;
  321.     
  322.         OCECopyCreationID(
  323.             dsamRecordCID,
  324.             &dspb.addDSAMDirectoryPB.dsamRecordCID
  325.         );
  326.         OCECopyDirDiscriminator(
  327.             discriminator,
  328.             &dspb.addDSAMDirectoryPB.discriminator
  329.         );
  330.         dspb.addDSAMDirectoryPB.directoryName = dirName;
  331.         dspb.addDSAMDirectoryPB.features = features;
  332.         OCECopyCreationID(
  333.             directoryRecordCID,
  334.             &dspb.addDSAMDirectoryPB.directoryRecordCID
  335.         );
  336.         LogRStringX('ADSD', dirName);
  337.         status = DirAddDSAMDirectory(&dspb, FALSE);
  338.         LogStatusX('ADSD', status, "\pDirAddDSAMDir@Template");
  339.         return (status);
  340. }
  341.  
  342. static OSErr DeleteUnconfiguredAttributeType(CreationID *directoryRecordCID)
  343.     {
  344.     OSErr err;
  345.     DirParamBlock dspb;
  346.     RecordID rid;
  347.     
  348.     rid.local.recordName = NULL;
  349.     rid.local.recordType = NULL;
  350.     OCECopyCreationID(directoryRecordCID, &rid.local.cid);
  351.     rid.rli = nil;
  352.     
  353.     err = DirGetOCESetupRefNum(&dspb, false);
  354.     if (err == noErr)
  355.         {
  356.         *(long*)&dspb.deleteAttributeTypePB.serverHint = 0;
  357.         dspb.deleteAttributeTypePB.identity = 0;
  358.         dspb.deleteAttributeTypePB.aRecord = &rid;
  359.         dspb.deleteAttributeTypePB.attrType = OCEGetIndAttributeType(kUnconfiguredAttrTypeNum);
  360.         
  361.         err = DirDeleteAttributeType(&dspb, false);
  362.         }
  363.     
  364.     return err;
  365.     }
  366.     
  367. /*
  368.  * The personal directory's file ID is stored in the misc part
  369.  * of the discriminator.
  370.  */
  371. static OSErr
  372. GetIDFromFSSpec(
  373.         const FSSpec                *spec,
  374.         unsigned long                *id
  375.     )
  376. {
  377.         OSErr                    status;
  378.         CInfoPBRec                pb;
  379.         
  380.         pb.dirInfo.ioCompletion = NULL;
  381.         pb.dirInfo.ioVRefNum = spec->vRefNum;
  382.         pb.dirInfo.ioNamePtr = (StringPtr) spec->name;
  383.         pb.dirInfo.ioFDirIndex = 0;
  384.         pb.dirInfo.ioDrDirID = spec->parID;
  385.         status = PBGetCatInfo(&pb, FALSE);
  386.         if (status == noErr)
  387.             *id = pb.dirInfo.ioDrDirID;
  388.         LogStatusX('GIDF', status, "\pPBGetCatInfo");
  389.         return (status);
  390. }
  391.  
  392. /*
  393.  * Create a Personal Directory, along with a resource fork
  394.  * for Directory Browser friendliness.
  395.  */
  396. static OSErr
  397. CreatePersonalDirectory(
  398.         FSSpec                        *spec
  399.     )
  400. {
  401.         OSErr                    status;
  402.         DirParamBlock            dspb;
  403.         
  404.         dspb.createPersonalDirectoryPB.fsSpec = spec;
  405.         dspb.createPersonalDirectoryPB.fdCreator = kPersonalDirectoryFileCreator;        
  406.         dspb.createPersonalDirectoryPB.fdType = kPersonalDirectoryFileType;
  407.         status = DirCreatePersonalDirectory(&dspb);
  408.         LogStatusX('CrPD', status, "\pDirCreatePersonalDirectory");
  409.         if (status == noErr) {
  410.             FSpCreateResFile(
  411.                 spec,
  412.                 kPersonalDirectoryFileCreator,
  413.                 kPersonalDirectoryFileType,
  414.                 smSysScript
  415.             );
  416.             LogStatusX('CrPD', status, "\pFSpCreateResFile");
  417.             if (status == noErr) {
  418.                 status = ResError();
  419.                 LogErrorX('CrPD', status);
  420.             }
  421.         }
  422.         return (status);
  423. }
  424.             
  425. /*
  426.  * Prompt user for the name and location of the
  427.  * Personal Directory file. Note that this returns
  428.  * "noErr" status if the user cancels the prompt.
  429.  * This returns userCanceledErr if the user cancels
  430.  * the dialog.
  431.  */
  432. static OSErr
  433. GetNewPDFile(
  434.         StandardFileReply            *reply
  435.     )
  436. {
  437.         OSErr                    status;
  438.         Str255                    prompt;
  439.         Str255                    defaultName;
  440.         
  441.         GetIndString(prompt, kCSAMPromptStrings, kNewPDPrompt);
  442.         GetIndString(defaultName, kCSAMPromptStrings, kNewPDName);
  443.         StandardPutFile(prompt, defaultName, reply);
  444.         if (reply->sfGood == FALSE)
  445.             status = userCanceledErr;
  446.         else if (reply->sfReplacing)
  447.             status = FSpDelete(&reply->sfFile);
  448.         else {
  449.             status = noErr;
  450.         }
  451.         return (status);
  452. }
  453.  
  454. /*
  455.  * Note: this returns userCanceledErr if the user
  456.  * canceled the FSSpec dialog.
  457.  */
  458. static OSErr
  459. GetPersonalDirectoryInfo(
  460.         DETCallBlockPtr                callBlockPtr,
  461.         DirectoryName                *dirName,
  462.         DirDiscriminator            *discriminator
  463.     )
  464. {
  465.         OSErr                    status;
  466.         StandardFileReply        reply;
  467.         AliasHandle                alias;
  468.         
  469.         alias = NULL;
  470.         status = GetNewPDFile(&reply);
  471.         if (status == noErr)
  472.             status = CreatePersonalDirectory(&reply.sfFile);
  473.         if (status == noErr) {
  474.             OCEPToRString(
  475.                 reply.sfFile.name,
  476.                 GetEnvirons(smSysScript),
  477.                 (RString *) dirName,
  478.                 kDirectoryNameMaxBytes
  479.             );
  480.             discriminator->signature = kCSAMCreatorID;
  481.             status = GetIDFromFSSpec(
  482.                         &reply.sfFile,
  483.                         &discriminator->misc
  484.                     );
  485.             LogStatusX('GPDI', status, "\pGetIDFromFSSpec");
  486.         }
  487.         if (status == noErr)
  488.             status = NewAlias(NULL, &reply.sfFile, &alias);
  489.         if (status == noErr)
  490.             status = SetAliasProperty(callBlockPtr, alias);
  491.         if (alias != NULL) {
  492.             DisposHandle((Handle) alias);
  493.         }
  494.         return (status);
  495. }
  496.  
  497. /*
  498.  * Add a record for our CSAM to the O.C.E. Setup directory.
  499.  */
  500. static OSErr
  501. AddSampleCSAM(
  502.         DETCallBlockPtr                callBlockPtr,
  503.         CreationID                    *dsamRecordCID
  504.     )
  505. {
  506.         OSErr                    status;
  507.         StringHandle            csamName;
  508.         FSSpec                    fsSpec;
  509.         RString                    csamRStringName;
  510.         DirParamBlock            dspb;
  511.         
  512.         status = noErr;
  513.         csamName = GetString(kCSAMName);
  514.         if (csamName == NULL)
  515.             status = resNotFound;        
  516.         LogStatusX('APPD', status, "\pGetString");
  517.         if (status == noErr)
  518.             status = GetMyFSSpec(callBlockPtr, &fsSpec);
  519.         LogStatusX('APPD', status, "\pGetMyFSSpec");            
  520.         if (status == noErr) {
  521.             OCEPToRString(
  522.                 *csamName,
  523.                 smRoman,
  524.                 &csamRStringName,
  525.                 kRStringMaxBytes
  526.             );
  527.             ReleaseResource((Handle) csamName);
  528.             dspb.addDSAMPB.dsamName = &csamRStringName;
  529.             dspb.addDSAMPB.dsamKind = kCSAMCreatorID;
  530.             dspb.addDSAMPB.fsSpec = &fsSpec;
  531.             status = DirAddDSAM(&dspb);
  532.             LogStatusX('APPD', status, "\pDirAddDSAM");
  533.             if (status != noErr) {
  534.                 LogRStringX('APPD', dspb.addDSAMPB.dsamName);
  535.                 LogTextX(dspb.addDSAMPB.dsamKind, fsSpec.name);
  536.             }        
  537.             /*
  538.              * If we call DirAddDSAM and the CSAM has already been
  539.              * opened, it returns the CSAM record's CID, but also
  540.              * the kOCEDSAMRecordExists error. We treat this
  541.              * as a non-error.
  542.              */
  543.             if (status == kOCEDSAMRecordExists)
  544.                 status = noErr;
  545.             OCECopyCreationID(&dspb.addDSAMPB.dsamRecordCID, dsamRecordCID);
  546.         }
  547.         LogStatusX('APPD', status, "\pAddSampleCSAM exit");
  548.         return (status);
  549. }
  550.  
  551. static OSErr
  552. AddImpersonalDirectory(
  553.         DETCallBlockPtr                    callBlockPtr,
  554.         DirectoryName                    *dirName,
  555.         DirDiscriminator                *discriminator,
  556.         CreationID                        *dsamRecordCID
  557.     )
  558. {
  559.         OSErr                        status;
  560.         short                        directoryRecordRefNum;
  561.         PackedDSSpec                **directoryRecordDSSpec;
  562.         DSSpec                        dsSpec;
  563.         RecordID                    rid;
  564.         
  565.         directoryRecordDSSpec = NULL;
  566.         status = GetMyDSSpec(
  567.                     callBlockPtr,
  568.                     &directoryRecordRefNum,
  569.                     &directoryRecordDSSpec
  570.                 );
  571.         if (status == noErr) {
  572.             HLock((Handle) directoryRecordDSSpec);
  573.             OCEUnpackDSSpec(*directoryRecordDSSpec, &dsSpec, &rid);
  574.             status = AddCSAMDirectory(
  575.                         dsamRecordCID,
  576.                         dirName,
  577.                         discriminator,
  578.                         kMyFeatures,
  579.                         &rid.local.cid
  580.                     );
  581.             if (status == noErr)
  582.                 status = DeleteUnconfiguredAttributeType(&rid.local.cid);            
  583.         }
  584.         if (directoryRecordDSSpec != NULL) {
  585.             DisposHandle((Handle) directoryRecordDSSpec);
  586.         }
  587.         LogStatusX('AIMD', status, "\pAddImpersonalDirectory exit");
  588.         return (status);
  589. }
  590.  
  591. /*
  592.  * Create the directory. If the user cancels the dialog,
  593.  * return "noErr," else return the creation error status.
  594.  */
  595. static OSErr
  596. CreateDTSSampleDirectory(
  597.         DETCallBlockPtr                    callBlockPtr
  598.     )
  599. {
  600.         OSErr                        status;
  601.         DirectoryName                dirName;
  602.         DirDiscriminator            discriminator;
  603.         CreationID                    csamRecordCID;
  604.         
  605.         /*
  606.          * Create the PD and get its name and discriminator
  607.          */
  608.         status = GetPersonalDirectoryInfo(
  609.                     callBlockPtr,
  610.                     &dirName,
  611.                     &discriminator
  612.                 );
  613.         LogStatusX('CDir', status, "\pGetPersonaDirectoryInfo");
  614.         if (status == userCanceledErr) {
  615.             status = noErr;
  616.             goto exit;
  617.         }
  618.         /*
  619.          * We need to save the alias property so that the
  620.          * CSAM can get the alias
  621.          */    
  622.         if (status == noErr) {
  623.             status = SaveProperty(callBlockPtr, prPDAlias);
  624.         LogStatusX('CDir', status, "\pSaveProperty");
  625.         }
  626.         /*
  627.          * We add the CSAM, which is the easiest way to get
  628.          * the csamRecordCID. Note that AddSampleCSAM catches
  629.          * the "record already added" error.
  630.          */
  631.         if (status == noErr) {
  632.             status = AddSampleCSAM(callBlockPtr, &csamRecordCID);
  633.         LogStatusX('CDir', status, "\pAddSampleCSAM");
  634.         }
  635.         /*
  636.          * Now add the directory itself.
  637.          */
  638.         if (status == noErr) {
  639.             status = AddImpersonalDirectory(
  640.                         callBlockPtr,
  641.                         &dirName,
  642.                         &discriminator,
  643.                         &csamRecordCID
  644.                     );
  645.             LogStatusX('CDir', status, "\pAddImpersonalDirectory");
  646.         }
  647.         /*
  648.          * Mark that we have a catalog, so that our view will change.
  649.          */
  650.         if (status == noErr) {
  651.             status = SetNumProperty(
  652.                         callBlockPtr,
  653.                         prHasCatalog,
  654.                         TRUE,
  655.                         FALSE
  656.                     );
  657.         }
  658.         /*
  659.          * Change the record's name.
  660.          */
  661.         if (status == noErr) {
  662.             status = SetRStringProperty(
  663.                         callBlockPtr,
  664.                         kDETAspectName,
  665.                         (RString *) &dirName,
  666.                         FALSE
  667.                     );
  668.             LogStatusX('CDir', status, "\pSet Rec Name");
  669.         }
  670.  
  671.         /*
  672.          * If an error occurred, clear out our properties
  673.          */
  674.         if (status != noErr) {
  675.             SetBinaryProperty(callBlockPtr, prPDAlias, NULL, 0, TRUE);
  676.             SetNumProperty(callBlockPtr, prHasCatalog, 0, FALSE);
  677.         }
  678.  
  679.         /*
  680.          * And force a resync
  681.          */
  682.         if (status == noErr) {
  683.             status = RequestSync(callBlockPtr);
  684.             LogStatusX('CDir', status, "\pRequest Sync");
  685.         }
  686.         
  687.         LogStatusX('CIMD', status, "\pCreateDTSSampleDirectory exit");
  688. exit:    return (status);
  689. }
  690.  
  691. static OSErr
  692. ValidateAndUpdateAlias(
  693.         DETCallBlockPtr                callBlockPtr
  694.     )
  695. {
  696.         OSErr                    status;
  697.         AliasHandle                alias;
  698.         FSSpec                    spec;
  699.         Boolean                    wasChanged;
  700.         RString                    name;
  701.         
  702.         alias = NULL;
  703.         status = GetBinaryProperty(
  704.                     callBlockPtr,
  705.                     prPDAlias,
  706.                     (Handle *) &alias
  707.                 );
  708.         LogStatusX('VAUA', status, "\pGetBinaryProperty");
  709.         if (alias != NULL) {
  710.             if (GetHandleSize((Handle) alias) == 0)
  711.                 LogTextX('VAUA', "\p0-length property");
  712.             if (status == noErr
  713.              && GetHandleSize((Handle) alias) > 0) {
  714.                 DumpAliasInfo(alias);
  715.                 status = ResolveAlias(NULL, alias, &spec, &wasChanged);
  716.                 LogStatusX('VAUA', status, "\pResolveAlias");
  717.                 if (status == noErr && wasChanged) {
  718.                     status = SetAliasProperty(callBlockPtr, alias);
  719.                     LogStatusX('VAUA', status, "\pSetAliasProperty");
  720.                 }
  721.             
  722.                 if (status == noErr) {
  723.                     name.charSet = GetEnvirons(smSysScript);
  724.                     name.dataLength = 0;
  725.                     status = GetAliasInfo(alias, asiAliasName, name.body - 1);
  726.                     if (status == noErr)
  727.                         status = SetRStringProperty(callBlockPtr, kDETAspectName, &name, FALSE);
  728.                 }
  729.             }
  730.             DisposHandle((Handle) alias);
  731.             LogStatusX('VAUA', status, "\DisposHandle at exit");
  732.         }
  733.         LogStatusX('VAUA', status, "\pValidateAndUpdateAlias exit");
  734.         return (status);
  735. }
  736.  
  737. #if DEBUG_LOG
  738. void
  739. DumpAliasInfo(
  740.         AliasHandle                    alias
  741.     )
  742. {
  743.         AuditPtr                    auditPtr;
  744.         OSErr                        status;
  745.         AliasInfoType                index;
  746.         Str63                        theString;
  747.  
  748. #define ShowString(i, why) do {                        \
  749.         status = GetAliasInfo(alias, i, theString);    \
  750.         if (status != noErr)                        \
  751.             goto exit;                                \
  752.         if (theString[0] != 0)                        \
  753.             AuditString(auditPtr, why, theString);    \
  754.     } while (0)
  755.  
  756.         auditPtr = GetAuditPtr(kCSAMCreatorID);
  757.         if (auditPtr != NULL) {
  758.             ShowString(asiZoneName,        'Zone');
  759.             ShowString(asiServerName,    'Srvr');
  760.             ShowString(asiVolumeName,    'Vol ');
  761.             ShowString(asiAliasName,    'Targ');
  762.             ShowString(asiParentName,    'Prnt');
  763.             for (index = 0;; index++) {
  764.                 status = GetAliasInfo(alias, index, theString);
  765.                 if (theString[0] == 0)
  766.                     break;
  767.                 AuditString(auditPtr, 'Name', theString);
  768.             }
  769. exit:        if (status != noErr) {
  770.                 AuditStatusString(auditPtr, 'Alis', status, "\pDumpAliasInfo exit");
  771.                 if (status == paramErr) {
  772.                     if (alias == NULL)
  773.                         AuditString(auditPtr, 'Alis', "\pNull alias handle");
  774.                     else {
  775.                         Audit(
  776.                             auditPtr,
  777.                             'Alis',
  778.                             AuditFormat3(
  779.                                 kAuditFormatAddress,
  780.                                 kAuditFormatUnsigned,
  781.                                 kAuditFormatString
  782.                             ),
  783.                             *alias,
  784.                             GetHandleSize((Handle) alias),
  785.                             "\pBogus alias record"
  786.                         );
  787.                     }
  788.                 }
  789.             }
  790.         }
  791. }
  792. #endif
  793.