//	Network.c

#ifndef OLD68K
	#ifndef __GNUC__
		#include <CFURLAccess.h>
	#endif
#else
	#include "Carbon68kGlue.h"
#endif

#ifdef A2PIX
	#include "MessageWindow.h"
	#define	ASSERT(_g)
	#define ReportErrorStr(_a, _b)	MessageWindowNum(_b, _a)
#else
	#include "IC_Errors.h"
#endif

#include <string.h>
#include "Network.h"

//	the Net_ProcRec will in the future encapsulate the address of a machine 
//	on a network (TCP/IP).  at present it only works for processes on the same
//	machine

// Search through the current process list to find the given application. See
// Using the Process Manager for a similar way of doing this.

void	Net_ClearProcRec(
	Net_ProcRec		*procRecP)
{
	memset(procRecP, sizeof(Net_ProcRec), 0);

	procRecP->infoRec.processInfoLength		= sizeof(ProcessInfoRec);
	procRecP->infoRec.processName			= (StringPtr)&procRecP->fsSpec;
	procRecP->infoRec.processAppSpec		= &procRecP->fsSpec;
}

OSErr	Net_GetProcess(
	OSType			typeToFind, 
	OSType			creatorToFind,
	Net_ProcRec		*procRecP)
{
	ProcessSerialNumber		psn		= { kNoProcess, kNoProcess };
//	Boolean					foundB	= FALSE;
	Boolean					doneB	= FALSE;
	OSErr					err		= noErr;

	Net_ClearProcRec(procRecP);

	do {
		err = GetNextProcess(&psn);
		if (!err) err = GetProcessInformation(&psn, (ProcessInfoRecPtr)&procRecP->infoRec);
		if (!err) {
			doneB = procRecP->infoRec.processSignature == creatorToFind
				&& procRecP->infoRec.processType == typeToFind;
		}
	} while (!err && !doneB);

	return err;
}

OSErr	FindAProcess(
	OSType					typeToFind, 
	OSType					creatorToFind,
	ProcessSerialNumberPtr	procNumP)
{
	Net_ProcRec		procRec;
	OSErr			err = Net_GetProcess(typeToFind, creatorToFind, &procRec);
	
	if (!err) {
		*procNumP = procRec.infoRec.processNumber;
	}
	
	return err;
}

/*

GetCurrentProcess	Gets information about the current process, if any.

for {
	GetFrontProcess	Gets the process serial number of the front process.
	GetNextProcess	Gets information about the next process, if any, in the Process ManagerŐs internal list of open processes.
	OSStatus GetProcessBundleLocation (
	    const ProcessSerialNumber *psn, 
	    FSRef *location);
	   
	   discard if front
	   is a2pix?
			GetProcessInformation	Get information about a specific process.
			really?
			
			send ae evebts
} end for

	GetProcessInformation	Get information about a specific process.
SameProcess

	


OSStatus CopyProcessName (
    const ProcessSerialNumber *psn, 
    CFStringRef *name
);


}

*/

static UInt32 gMoreCSSystemVersion = 0;

enum {
    kMoreCSMacOSX10point0 = 0x01000,
    kMoreCSMacOSX10point1 = 0x01010
};

static	void	GetCStringResource(SInt16 rsrcID, char *nameZ)
    // This routine is called on Mac OS 9 to create a CFString
    // from the system 'STR ' resource with ID of rsrcID.
{
    SInt8       s;
    Handle      stringH;

    stringH = GetResource('STR ', rsrcID);
    if (stringH != NULL) {
        s = HGetState(stringH);
        HLock(stringH);
        CopyPascalStringToC((StringPtr) *stringH, nameZ);
        HSetState(stringH, s);
    }
}

static CFStringRef ReadMachineNameFromFile(void)
    // This routine is called when the client tries to get the
    // machine name on Mac OS X 10.0.x.  Because CSCopyMachineName returns
    // un-useful information on those systems, w reads the name
    // directly from the System Configuration preferences file.
{
    CFStringRef     result = NULL;
    
    #ifndef OLD68K

    CFURLRef        url;
    CFDataRef       data;
    CFDictionaryRef dict;
    CFDictionaryRef systemDict;
    CFDictionaryRef system2Dict;

    ASSERT( gMoreCSSystemVersion >= kMoreCSMacOSX10point0 );
    ASSERT( gMoreCSSystemVersion <  kMoreCSMacOSX10point1 );

    // *** IMPORTANT ***
    //
    // The location and format of the System Configuration framework
    // preferences file in the code below is subject to change
    // at any time.  Do not write any code which makes any assumptions
    // on this file since your app WILL BREAK at some point in time.
    // The only reason we can do this safely in this code is because
    // we know we're running on Mac OS 10.0 through 10.0.4.  This is
    // enforced by the asserts above.  For Mac OS X 10.1 and above you
    // must use the public System Configuration framework APIs (or
    // APIs, like CSCopyMachineName, which are layered on top of
    // System Configuration framework).

    result = NULL;

    url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
                     CFSTR("/var/db/SystemConfiguration/preferences.xml"),
                     kCFURLPOSIXPathStyle,
                     false );
    if (url != NULL) {
        if (CFURLCreateDataAndPropertiesFromResource(
        	kCFAllocatorDefault, url, &data, NULL, NULL, NULL)
        ) {
            dict = (CFDictionaryRef)CFPropertyListCreateFromXMLData(
            	kCFAllocatorSystemDefault,data, kCFPropertyListImmutable, NULL);

            if (dict != NULL) {
                systemDict = (CFDictionaryRef)CFDictionaryGetValue(dict, CFSTR("System") );
                
                if (systemDict != NULL) {
                    system2Dict = (CFDictionaryRef)CFDictionaryGetValue(systemDict, CFSTR("System") );
                    
                    if ( system2Dict != NULL ) {
                        result = (CFStringRef)CFDictionaryGetValue(system2Dict, CFSTR("ComputerName") );

                        if (result != NULL) {
                            // Increment the string's reference count so that
                            // releasing "dict" doesn't release the name.
                            CFRetain(result);
                        }
                        // Don't need to release system2Dict because it was "got".
                    }
                    // Don't need to release systemDict because it was "got".
                }
                CFRelease(dict);
            }
            CFRelease( data );
        }
        CFRelease( url );
    }
	#endif
	
    return result;
}

/*
extern pascal CFStringRef MoreCSCopyUserName(Boolean useShortName)
    // See comment in header file.
{
    CFStringRef result;

    if ( gMoreCSSystemVersion == 0 ) {
        (void) Gestalt(gestaltSystemVersion, (SInt32 *) &gMoreCSSystemVersion);
    }

    if ( gMoreCSSystemVersion < kMoreCSMacOSX10point0 ) {

        // Running on traditional Mac OS.  If we have a recent version
        // of CarbonLib (1.5 and above) that supports the routine, use
        // that.  Otherwise fall back to the Resource Manager.

        if ( CSCopyUserName != (void *) kUnresolvedCFragSymbolAddress) {
            result = CSCopyUserName(useShortName);
        } else {
            result = CreateCFStringFromStringResource(-16096);
        }

    } else {

        // Call the API.  However, if we're built CFM we can't just
        // call it directly because the routine isn't exported to
        // CFM on Mac OS 10.0.x.  So for CFM builds we have to call
        // through CFBundle.

        #if TARGET_RT_MAC_CFM
            {
                typedef CFStringRef (*CSCopyUserNameProc)(Boolean useShortName);
                CSCopyUserNameProc  csCopyUserName;
                CFBundleRef         bundle;

                result = NULL;
                csCopyUserName = NULL;

                bundle = CFBundleGetBundleWithIdentifier(
                                                 CFSTR("com.apple.Carbon" ) );
                if (bundle != NULL) {
                    csCopyUserName =
                       (CSCopyUserNameProc) CFBundleGetFunctionPointerForName(
                                              bundle, CFSTR("CSCopyUserName") );
                }
                if (csCopyUserName != NULL) {
                    result = csCopyUserName(useShortName);
                }
                // Both bundle and csCopyUserName got with "Get", so
                // no need to release.
            }
        #elif TARGET_RT_MAC_MACHO
            result = CSCopyUserName(useShortName);
        #else
            #error MoreCSCopyUserName: What runtime are you using?
        #endif

        // Mac OS 10.0 and 10.0.1 (which have the same gestaltSystemVersion
        // result -- this just gets better and better) have a bug [2665708]
        // where they fail to retain the user name and host name strings
        // each time they return it to the client.  The upshot is that
        // the client crashes the second time it calls CSCopyUserName or
        // CSCopyMachineName.  This extra CFRetain prevents this from happening.
        //
        // Note that we don't need a similar workaround in MoreCSCopyMachineName
        // because we never call the CSCopyMachineName on 10.0 or 10.0.1
        // because of another issue.

        if (result != NULL && gMoreCSSystemVersion == kMoreCSMacOSX10point0) {
            CFRetain(result);
        }
    }

    return result;
}
*/

#ifdef OLD68K
	static char * CSCopyMachineName()
	{
		return "Something";
	}
#endif

char		*Net_GetMachineName(char *nameZ, long bufSizeL)
{
	CFStringRef		result = NULL;

	
	nameZ[0] = NULL;
	
	if (gMoreCSSystemVersion == 0 ) {
		(void) Gestalt(gestaltSystemVersion, (SInt32 *) &gMoreCSSystemVersion);
	}

	if ( gMoreCSSystemVersion < kMoreCSMacOSX10point0 ) {

		// Running on traditional Mac OS.  If we have a recent version
		// of CarbonLib (1.5 and above) that supports the routine, use
		// that.  Otherwise fall back to the Resource Manager.

		if ( CSCopyMachineName != (void *) kUnresolvedCFragSymbolAddress) {
			result = CSCopyMachineName();
		} else {
			GetCStringResource(-16413, nameZ);
		}

	} else if ( gMoreCSSystemVersion < kMoreCSMacOSX10point1 ) {

		// Running on Mac OS X 10.0.x.  Read the file directly because
		// the API returns the wrong information (the BSD hostname rather
		// than the computer name) [2650897].

		result = ReadMachineNameFromFile();

	} else {

		// Running on Mac OS X 10.1 and above.  Let's just call the API.

		// The following checks that the CFM weak link worked.
		// It's benign for the Mach-O build.

		if ( CSCopyMachineName != (void *) kUnresolvedCFragSymbolAddress ) {
			result = CSCopyMachineName();
		}
	}
	
	if (result) {
		if (!CFStringGetCString(result, nameZ, bufSizeL, CFStringGetSystemEncoding())) {
			ReportErrorStr(-1, "Couldn't get machine name");
		}
	}

	return nameZ;
}