Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MIB-Libraries/MoreSCF/ReadMeAboutMoreSCF.html
<HTML> |
<HEAD> |
<TITLE>Read Me About MoreSCF</TITLE> |
</HEAD> |
<BODY BGCOLOR="#FFFFFF"> |
<H1>Read Me About MoreSCF</H1> |
<P>1.0b4</P> |
<P>Mac OS X 10.1 introduced a new API, the System Configuration |
framework (SCF), that allows you to programmatically configure |
network settings. SCF provides a nice, abstract, extensible API for |
manipulating persistent preferences, however it is not a high-level |
API. Doing common operations, like creating a new set (known as a |
"location" in the user interface), requires you to combine a number |
of diverse APIs from I/O Kit, System Configuration, and Core |
Foundation.</P> |
<P>MoreSCF is an attempt to make this easier. It is modeled after the |
MoreNetworkSetup sample code for traditional Mac OS. It provides a |
library of code to do all of the common things that the user might do |
in the Network preferences panel. For example, you can create a new |
location, duplicate a location, active and inactivate services (known |
as "ports" in the user interface), and so on. MoreSCF also provides |
high-level APIs to do common operations, such as creating a new set |
that contains a single PPP dialup service.</P> |
<P>System Configuration framework was introduced in Mac OS X 10.1. |
MoreSCF requires that system or later.</P> |
<H2>Packing List</H2> |
<P>The sample contains the following items:</P> |
<UL> |
<LI>Read Me.txt -- A document that redirects you to this |
document.</LI> |
<LI>MoreSCF -- A folder containing MoreSCF and various support |
files. |
<UL> |
<LI>ReadMeAboutMoreSCF.html -- This document.</LI> |
<LI>MoreSCFHelpers.h -- Interface to the following.</LI> |
<LI>MoreSCFHelpers.c -- A high-level module that provides |
commonly used System Configuration framework functions, such as |
creating a new set that contains a single PPP dialup |
service.</LI> |
<LI>MoreSCF.h -- Interface to the following.</LI> |
<LI>MoreSCF.c -- A mid-level module layered on top of the |
SCPreferences component of System Configuration framework. This |
module recasts the SCPreferences API in terms that you would |
recognize from looking at the Network preferences panel.</LI> |
<LI>MoreSCFDigest.h -- Interface to the following.</LI> |
<LI>MoreSCFDigest.c -- Code to create SCPreferences entities |
from simple C structures.</LI> |
<LI>MoreSCFPortScanner.h -- Interface to the following.</LI> |
<LI>MoreSCFPortScanner.c -- Code to scan the I/O Registry for |
network-capable ports.</LI> |
<LI>MoreSCFCCLScanner.h -- Interface to the following.</LI> |
<LI>MoreSCFCCLScanner.c -- Code to scan the system for modem |
scripts (CCLs).</LI> |
<LI>MoreSCFTest -- A program that both tests MoreSCF and gives |
an example of its use.</LI> |
</UL> |
<LI>MoreCFQ -- MoreIsBetter Core Foundation utilities.</LI> |
<LI>MoreSetup.h -- The standard MoreIsBetter include file.</LI> |
</UL> |
<H2>Using the Sample</H2> |
<P>The sample includes a compiled version of the |
<CODE>MoreSCFTest-Debug</CODE> command line tool. This tool modifies |
the SCF preferences, which means you must run it as root. To do this, |
launch Terminal, change to the MoreSCFTest directory, and run |
<CODE>MoreSCFTest-Debug</CODE> using the <CODE>sudo</CODE> command. |
The following is an example of doing this.</P> |
<PRE>[localhost:~] quinn% <B>cd /Volumes/Tweedlebug/DTS\ \ |
Work/MIBWork/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFTest/ |
</B>[localhost:MIB-Libraries/MoreSCF/MoreSCFTest] quinn% <B>sudo MoreSCFTest-Debug -lq |
</B>Password: <B>enter your password here |
</B>MoreSCFTest-Debug |
Running all tests |
LeakTest(TestPortScanner) |
MoreSCFPortScanner.c: You should install a port name callback. |
LeakTest(TestCopySetsDict) |
LeakTest(TestSetEnumerationAndSwitch) |
LeakTest(TestDuplicateAndDeleteSet) |
LeakTest(TestRenameSet) |
LeakTest(TestServiceEnumerate) |
LeakTest(TestDuplicateAndDeleteService) |
LeakTest(TestRenameService) |
LeakTest(TestEnumerateEntities) |
LeakTest(TestCreateSet) |
LeakTest(TestISP) |
LeakTest(TestAppleTalk) |
[localhost:MIB-Libraries/MoreSCF/MoreSCFTest] quinn% </PRE> |
<P>The tool takes quite some time to run (up to a few minutes on my ancient test machine). As long as it runs to completion it should leave your network preferences how it found them. However, if you stop it halfway through you may need to manually restore your preferences.</P> |
<P>Two of the tests requires that you have a location called "DefaultLocationForMoreSCFTest". You should create this location using the Network panel of System Preferences. Just create the location and leave its settings unmodified. The test uses this location to verify that a new set created by MoreSCF exactly matches a default set created by the control panel.</P> |
<CENTER><TABLE BORDER=0 CELLPADDING=3 WIDTH=500> |
<TR> |
<TD BGCOLOR="#EEEEE0"> |
<P><B>Note:</B><BR> |
Under some circumstances the TestCreateSet test will fail |
because the newly created set doesn't exactly match the |
contents of "DefaultLocationForMoreSCFTest". There are a few |
common reasons for this.</P> |
<UL> |
<LI>Your "DefaultLocationForMoreSCFTest" set might be is |
out of date; to rectify this simply open the control |
panel, deleting the existing |
"DefaultLocationForMoreSCFTest" location and create a new |
one.</LI> |
<LI>You might have NetInfo enabled; to rectify this, turn |
off NetInfo using the "Directory Setup" application, then |
update your "DefaultLocationForMoreSCFTest" set as |
described previously.</LI> |
<LI>The "DefaultLocationForMoreSCFTest" might be set to |
use non-DHCP address acquisition (in the "Configure" |
popup menu). This happens if you create the new set when |
your current set is not using DHCP. In that case the |
Network preferences panel creates a set with the same |
address acquisition mode as your current set. This |
anomalous behavior is not replicated by MoreSCF. To make |
TestCreateSet run without error, open the Network |
preferences panel and modify the services within the |
"DefaultLocationForMoreSCFTest" set to acquire address |
via PPP.</LI> |
</UL> |
</TD> |
</TR> |
</TABLE> |
</CENTER> |
<H2>Building the Sample</H2> |
<P>The sample was built using CodeWarrior Pro 8.3 on Mac OS X 10.2.x. It also builds with Project Builder 2.1 (from the Mac OS X December 2002 developer tools). Your mileage may vary with other environments.</P> |
<P>The project is built as a Mach-O binary. It is not possible to |
call SCF directly from a CFM binary. If you need to do this you |
should either factor your SCF code into a separate Mach-O bundle or |
use one of the techniques illustrated in the <A HREF="http://developer.apple.com/samplecode/Sample_Code/Runtime_Architecture/CallMachOFramework.htm">CallMachOFramework</A> |
sample code.</P> |
<P>The CodeWarrior project contains two targets. You should build the "Mach-O" target. I use the "Mach-O, C++" to test C++ compatibility. You typically wouldn't use this target.</P> |
<H2>SCF Hints and Tips</H2> |
<P>This section describes a number of things to keep in mind while |
working with SCF, or indeed MoreSCF.</P> |
<UL> |
<LI>Documentation -- At the time this sample was written Apple |
still hasn't published full documentation for SCF. However, the |
framework is partially documented by comments in its headers. |
There is also a <A HREF="http://developer.apple.com/techpubs/macosx/Networking/SysConfigOverview926/index.html">brief |
overview of SCF</A> available on the developer web site. You |
should read this before doing any serious work with MoreSCF.</LI> |
<LI>Running with Privileges -- Code that modifies the System |
Configuration framework preferences must run as root (with |
effective user ID of 0). There are simple ways to work around this |
during development (<A HREF="#EnablingRoot">described below</A>), |
however, your final product will need to be smarter about this, |
possibly including a "set user ID" binary that does your actual |
SCF work. The DTS sample code <A HREF="http://developer.apple.com/samplecode/Sample_Code/Security/MoreAuthSample.htm">MoreAuthSample</A> |
shows the recommended technique for doing this.</LI> |
<LI>SCF Preferences -- In current versions of Mac OS X SCF stores |
its preferences in "/var/db/SystemConfiguration/preferences.xml". |
You should never code this full path into your application, but |
this knowledge can be helpful when debugging. For example, |
<UL> |
<LI>You can launch PropertyListEditor (in |
"/Developer/Applications") and open this file for a structured |
view of the current preferences.</LI> |
<LI>You can back up and restore your preferences using the |
following Terminal commands. This is especially useful when |
debugging SCF code that has gone bad.</LI> |
</UL> |
</UL> |
<PRE>[localhost:~] quinn% <B>cp /var/db/SystemConfiguration/preferences.xml \ |
/var/db/SystemConfiguration/preferencesBU.xml |
</B>[localhost:~] quinn% <B>cp /var/db/SystemConfiguration/preferencesBU.xml \ |
/var/db/SystemConfiguration/preferences.xml</B></PRE> |
<UL> |
<LI>SCUtil -- Apple provides a command line utility, |
<CODE>scutil</CODE>, that lets you look at the current state of |
the SCF dynamic store. You can use this utility to see how your |
SCF code affects the actual network configuration. The following |
is a simple example of how to use <CODE>scutil</CODE>.</LI> |
</UL> |
<PRE>[localhost:~] quinn% <B>scutil |
</B>> <B>open |
</B>> <B>list |
</B> subKey [0] = File:/var/run/lookupd.pid |
subKey [1] = File:/var/run/nibindd.pid |
subKey [2] = Plugin:IPConfiguration |
subKey [3] = Setup: |
subKey [4] = Setup:/ |
subKey [5] = Setup:/Network/Global/IPv4 |
subKey [6] = Setup:/Network/Service/26 |
subKey [7] = Setup:/Network/Service/26/AirPort |
subKey [8] = Setup:/Network/Service/26/DNS |
subKey [9] = Setup:/Network/Service/26/IPv4 |
subKey [10] = Setup:/Network/Service/26/Interface |
subKey [11] = Setup:/Network/Service/26/Proxies |
subKey [12] = Setup:/System |
subKey [13] = State:/Network/Global/DNS |
subKey [14] = State:/Network/Global/IPv4 |
subKey [15] = State:/Network/Global/Proxies |
subKey [16] = State:/Network/Interface |
subKey [17] = State:/Network/Interface/en0/Link |
subKey [18] = State:/Network/Interface/en1/IPv4 |
subKey [19] = State:/Network/Interface/en1/Link |
subKey [20] = State:/Network/Interface/lo0/IPv4 |
subKey [21] = State:/Network/Service/26/IPv4 |
subKey [22] = State:/Users/ConsoleUser |
subKey [23] = daemon:AppleFileServer |
> <B>get Setup:/Network/Service/26/AirPort |
</B>> <B>d.show |
</B><dictionary> { |
MACAddress : 00:30:65:14:1e:1e |
PreferredNetwork : QuinnNet |
} |
> <B>help |
</B>Available commands: |
help : list available commands |
f.read file : process commands from file |
d.init : initialize (empty) dictionary |
d.show : show dictionary contents |
d.add key [*#?] val [v2 ...] : add information to dictionary |
(*=array, #=number, ?=boolean) |
d.remove key : remove key from dictionary |
open : open a session with "configd" |
close : close current "configd" session |
list [pattern] : list keys in data store |
add key ["temporary"] : add key in data store w/current dict |
get key : get dict from data store w/key |
set key : set key in data store w/current dict |
remove key : remove key from data store |
notify key : notify key in data store |
n.list ["pattern"] : list notification keys |
n.add key ["pattern"] : add notification key |
n.remove key ["pattern"] : remove notification key |
n.changes : list changed keys |
n.watch [verbose] : watch for changes |
n.cancel : cancel notification requests |
> <B>quit |
</B>[localhost:~] quinn% </PRE> |
<H3><A NAME=EnablingRoot></A>Debugging Root Binaries</H3> |
<P>If you are using SCF to modify system preferences, you'll quickly |
discover that your program needs to run as root (with an effective |
user ID of 0) to avoid the dreaded error 1003 |
(<CODE>kSCStatusAccessError</CODE>). There are two simple ways to get |
around this during debugging.</P> |
<UL> |
<LI>You can <A HREF="http://developer.apple.com/carbon/tipsandtricks.html#EnableRoot">enable |
the root account</A>, log out, and then log back in as root. At |
that point all of the programs you run will run as root. This |
approach has the advantage that it's very simple. However, it's |
not particularly secure; I recommend you avoid this approach if |
your Mac OS X machine lives outside of a firewall.</LI> |
<LI>If you have administrative privileges, you can launch |
CodeWarrior or Project Builder from within a root Terminal window. |
The following listing shows the general procedure. The first |
command, <CODE>sudo -s</CODE>, turns your normal Terminal window |
into a root window. The second command launches CodeWarrior as |
root. Note that the command you actually execute is |
<CODE>LaunchCFMApp</CODE>, passing it as a parameter the full path |
to your CodeWarrior executable; you'll have to customize this path |
depending on where you installed CodeWarrior. Also note the |
'&' at the end of the command line, which requests the shell |
not to wait for CodeWarrior to quit before accepting a new |
command. The third command launches Project Builder as root.</LI> |
</UL> |
<PRE>[localhost:~] quinn% <B>sudo -s</B> |
Password:<B>********</B> |
[localhost:~] root# <B>/System/Library/Frameworks/Carbon.framework/\</B> |
<B>Versions/A/Support/LaunchCFMApp /Volumes/Tweedlebug/Languages/CWPro7MIB/\</B> |
<B>CodeWarrior\ IDE\ 4.2.5\ \* &</B> |
[1] 2030 |
[localhost:~] root# <B>/Developer/Applications/Project\ Builder.app/\</B> |
<B>Contents/MacOS/Project\ Builder &</B> |
[2] 2031 |
[localhost:~] root# </PRE> |
<CENTER id=p1><TABLE BORDER=0 CELLPADDING=3 WIDTH=500> |
<TR> |
<TD BGCOLOR="#EEEEE0"> |
<P><B>IMPORTANT:</B><BR> |
This approach, while fine for debugging, is not appropriate for your final product. Ultimately you will need a better solution, possibly including a "set user ID" binary that does your actual SCF work. The DTS sample code <A HREF="http://developer.apple.com/samplecode/Sample_Code/Security/MoreAuthSample.htm">MoreAuthSample</A> shows the recommended technique for doing this.</P> |
</TD> |
</TR> |
</TABLE> |
</CENTER> |
<H2>Using MoreSCF In Your Code</H2> |
<P>The correct way to use MoreSCF depends on the exact needs of your |
program. The following sections explore this issue in detail.</P> |
<H3>Coding Conventions</H3> |
<P>MoreSCF is built as part of the DTS sample code library MoreIsBetter. It only uses the CoreServices framework, which means you should be able to use it in non-Carbon programs. For example, Cocoa application developers can use MoreSCF very easily. Making MoreSCF independent of CoreServices would be tricky because MoreSCF needs to be able to locate the Modem Scripts folder which can only be done with CoreServices APIs.</P> |
<P>MoreSCF makes extensive use of asserts. When you integrate MoreSCF |
into your build system you should ensure that |
<CODE>assert</CODE> maps to whatever assert mechanism you are |
using in your project.</P> |
<P>MoreSCF's asserts act like comments for the exact function |
semantics. Specifically, if you want to know whether NULL is legal |
for a particular parameter, look at the asserts at the top of the |
routine.</P> |
<P>MoreSCF follows the Core Foundation (CF) coding convention in that |
routines with "Create" or "Copy" in the name return a reference which |
you must release, whereas other routines (most commonly with "Get" in |
the name) return a reference that you don't need to release. However, |
unlike CF, MoreSCF returns <CODE>OSStatus</CODE> error codes from |
virtually all functions. When you call a MoreSCF routine that |
allocates an object, you get the result by passing the address of a |
variable as a parameter to the routine. You must initialize this |
variable to NULL before calling the routine. The value of the |
variable will be NULL if the routine returns an error.</P> |
<H3>Big Picture</H3> |
<P>MoreSCF consists of a number of related modules. As a rule I |
recommend that you use the highest level routines that will get the |
job done. This section describes each of the MoreSCF modules, how |
they relate, and what you can do with them.</P> |
<H4>MoreSCFCCLScanner</H4> |
<P>This module contains a routine that a creates a list of CCLs |
(modem scripts) installed in the system and returns that list along |
with an indication of which CCL should be the default. An Internet |
setup assistant would use this routine to present the user with a |
list of CCLs to choose from if they are connecting via a modem.</P> |
<P>It is unlikely that you would need to customize the routines in |
this module.</P> |
<H4>MoreSCFPortScanner</H4> |
<P>This module contains code that searches the I/O Registry for all |
possible network ports. For each port it returns the information |
necessary to create an SCF service that uses the port. This facility |
is crucial when you create a new set using SCF.</P> |
<P>This is not as easy as it sounds. The code is derived from code |
originally written by the engineer who wrote the Network preferences |
panel. It contains many interesting heuristics to decide whether a |
port is suitable for networking and to determine its user visible |
name.</P> |
<P>If you link this module into a GUI-based application you should |
install a port name callback (using |
<CODE>MoreSCFSetPortNameCallback</CODE>) so that you can localize the |
user visible names of the ports.</P> |
<P>You should probably use the routines in this module unmodified unless you experience compatibility problems.</P> |
<H4>MoreSCFDigest</H4> |
<P>This module contains code that allows you to easily create a SCF |
entity from a C structure. It takes care of many of the fiddly |
details of this process, such as converting IP addresses to strings, |
encoding PPP passwords, and so on.</P> |
<P>In most cases you would use the routines from this module |
unmodified, although sometimes the routines provide a simplified view |
of certain preferences and you might want to override some of their |
default decisions.</P> |
<H4>MoreSCF</H4> |
<P>This module is layered on top of the previous two modules. It provides a mid-level API for manipulating SCF preferences. The module exports four categories of routines:</P> |
<UL> |
<LI>trivial utilities, primarily to map SCF's error strategy into a CoreServices-based environment</LI> |
<LI>open/close routines, which provide a reference counted |
facility for opening and closing the SCF preferences; this is |
convenient because it ensures that changes are committed only at |
the end of a transaction</LI> |
<LI>dictionary-based routines, which provide basic access to the |
most important SCF preferences</LI> |
<LI>mid-level routines, for manipulating the SCF preferences in |
terms of common user operations (for example, creating a set, |
deactivating a service, modifying an entity)</LI> |
</UL> |
<P>I expect that you would use the routines from this module |
unmodified. If you need to do complex SCF operations you'll probably |
find that either a) an appropriate routine is already provided in |
MoreSCFHelpers, or b) you can achieve the results you want by calling |
various routines exported by this module.</P> |
<H4>MoreSCFHelpers</H4> |
<P>This module is layered on top of MoreSCF and exports routines for |
doing very high-level operations using SCF, such as</P> |
<UL> |
<LI>turning AppleTalk on and off |
(<CODE>MoreSCSetAppleTalkActive</CODE>),</LI> |
<LI>forcing a DHCP release (<CODE>MoreSCDHCPRelease</CODE>), |
and</LI> |
<LI>creating a new dialup set (or PPPoE) from preferences provided via a number of parameter blocks (<CODE>MoreSCMakeNewDialupSet</CODE> and <code>MoreSCMakeNewPPPoESet</code>).</LI> |
</UL> |
<P>You should treat these routines as sample code; if they don't meet your exact needs you should modify them appropriately. For example, <code>MoreSCMakeNewPPPoESet</code> provides no way to create a PPPoE location for an AirPort interface, but it is simple to modify it to do so.</P> |
<H3>Getting Started</H3> |
<P>This section describes the MoreSCF routines needed to do the most |
common high-level operations.</P> |
<H4>Opening, Closing, Locking</H4> |
<P>MoreSCF uses a single connection to SCF preferences for all of its |
work. To support a flexible API MoreSCF references counts that |
reference. The first time you call <CODE>MoreSCOpen</CODE>, MoreSCF |
creates a <CODE>SCPreferencesRef</CODE> and stores it in a global |
variable. Every subsequent time you call the <CODE>MoreSCOpen</CODE>, |
it simply increments the reference count. Every time you call |
<CODE>MoreSCClose</CODE>, it decrements the reference count. When the |
reference count drops to zero, MoreSCF commits any changes you might |
have made, unlocks the preferences if you have locked them, and then |
closes the <CODE>SCPreferencesRef</CODE>.</P> |
<P>The primary rationale for this approach is that I did not want clients of MoreSCF to be forced to call <CODE>MoreSCOpen</CODE>. Thus, each |
exported MoreSCF routine calls <CODE>MoreSCOpen</CODE> when it starts |
and <CODE>MoreSCClose</CODE> when it finishes. This presented an |
interesting problem when MoreSCF routines called other MoreSCF |
routines. I wanted all of the MoreSCF routines to share the same |
<CODE>SCPreferencesRef</CODE> (otherwise they wouldn't see each |
others changes until they committed them), however I didn't want to |
cache the <CODE>SCPreferencesRef</CODE> forever because that caused |
other problems with preference coherency. My ultimate solution was to |
simply reference count the <CODE>SCPreferencesRef</CODE>.</P> |
<P>Given the above there are some cases when you don't need to call |
<CODE>MoreSCOpen</CODE> at all. Each MoreSCF API routine will call |
<CODE>MoreSCOpen</CODE> for you. However, in most circumstances you |
should call <CODE>MoreSCOpen</CODE> and <CODE>MoreSCClose</CODE>. |
This has a number of advantages.</P> |
<UL> |
<LI>When you call <CODE>MoreSCOpen</CODE>, MoreSCF creates an |
<CODE>SCPreferencesRef</CODE>. This in turn holds a snapshot of |
the current preferences. You can then make subsequent MoreSCF |
calls and be assured that you're seeing a coherent copy of the |
preferences.</LI> |
<LI>Calls to MoreSCF routines within a |
<CODE>MoreSCOpen</CODE>/<CODE>MoreSCClose</CODE> pair will be |
faster because they won't be continually creating and disposing of |
their connection to SCF preferences.</LI> |
<LI>If you're making changes to the preferences you generally need |
to call <CODE>MoreSCOpen</CODE> so that you can lock the |
preferences and ensure that your changes are coherent.</LI> |
</UL> |
<P>The standard calling sequence, used for the first two cases above, |
is shown below.</P> |
<PRE>(void) MoreSCSetClient(CFSTR("MyClientName")); // optional |
err = MoreSCOpen(false, false); // no locking |
if (err == noErr) { |
// use various MoreSCF routines in here |
} |
MoreSCClose(&err, false); // no changes</PRE> |
<P>If you are making changes you would probably use the next |
sequence.</P> |
<PRE>err = MoreSCOpen(true, true); // lock prefs |
if (err == noErr) { |
// read preferences using MoreSCF routines |
// make decisions based on what you read |
// write preferences using MoreSCF routines |
} |
MoreSCClose(&err, true); // force commit</PRE> |
<P>MoreSCF also provides a routine |
(<CODE>MoreSCGetSCPreferencesRef</CODE>) that allows you to access |
the underlying <CODE>SCPreferencesRef</CODE>. This is useful in cases |
where you need to call SCF preferences routines that do things |
outside of the realm of MoreSCF (for example, calling |
<CODE>SCPreferencesGetSignature</CODE>).</P> |
<H4>Creating a New Dialup Set</H4> |
<P>Most people look at MoreSCF because they're writing an Internet |
setup assistant (ISA). MoreSCF contains routines that specifically |
help you to do this. However, before I discuss these routines I |
should stress one key point.</P> |
<P>Apple strongly recommends that ISA developers create a new set |
(known as a "location" in the user interface) for their specific |
service. This prevents your settings from overwriting the user's |
prized network setup and allows the user a quick escape (switching |
back to their previous location) if your setup assistant doesn't work |
properly.</P> |
<P>If you're writing an ISA, the three keys routines are <CODE>MoreSCFindSetByUserVisibleNameAndCopyID</CODE>, <code>MoreSCMakeNewDialupSet</code> and <code>MoreSCMakeNewPPPoESet</code>. The first routine lets you determine whether your ISA has already been run and created your service's location. The other two let you create a new location with one active dialup or PPPoE service. All of these routines are described in comments in "MoreSCFHelpers.h". You can also look at the TestISP routine in "MoreSCFTest.c" for a very simple example of their use.</P> |
<P>The above routines are very easy to use if you want to use the default modem (or Ethernet) port. If you want to provide the user a list of modem ports to choose from, you should call the <CODE>MoreSCCreatePortArray</CODE> routine (declared in |
"MoreSCFPortScanner.h") to get the list of network ports and their |
associated user-visible names and then supply the BSD name of the |
port to <CODE>MoreSCMakeNewDialupSet</CODE> or <code>MoreSCMakeNewPPPoESet</code>. For dialup you should also use <CODE>MoreSCCreateCCLArray</CODE> (from "MoreSCFCCLScanner.h") to |
build a list of CCLs (modem scripts) that the user can use for that |
modem.</P> |
<H4>Enumerating and Switching Sets</H4> |
<P>The routines to enumerate and switch sets are all declared in |
"MoreSCF.h". You can use <CODE>MoreSCCopySetIDs</CODE> to get an |
array of set IDs, <CODE>MoreSCCopyUserVisibleNameOfSet</CODE> to get |
the user-visible name of a set given its set ID, and |
<CODE>MoreSCSetCurrentSet</CODE> to make a particular set the active |
set.</P> |
<H4>Manipulating Sets, Services, and Entities</H4> |
<P>MoreSCF exports routines to</P> |
<UL> |
<LI>enumerate, create, duplicate, and delete sets</LI> |
<LI>get and set properties of sets (the active set, user-visible |
name)</LI> |
<LI>enumerate, create, duplicate, and delete services within a |
set</LI> |
<LI>get and set properties for services (active, user-visible |
name, BSD name)</LI> |
<LI>read, write, and delete entities within a service</LI> |
<LI>read, write, and delete global entities within a set</LI> |
<LI>get and set properties of an entity (active)</LI> |
</UL> |
<P>These routines are fairly well documented by the comments in the |
"MoreSCF.h" header file. Most of the routines are used somewhere |
within MoreSCF, which you can look at for an example of their |
use.</P> |
<H2><A NAME=Caveats></A>Caveats</H2> |
<P>The following is a list of odd things you might encounter while |
working with MoreSCF and things I would improve within MoreSCF if I |
had the time.</P> |
<UL> |
<LI>The Network preferences panel in Mac OS X 10.1.x does not |
correctly reflect changes made by other applications using SCF. |
You will not see any MoreSCF changes in the Network panel until |
you quit and relaunch System Preferences. The problem is in the |
UI; the changes do apply to the actual network stack. Apple hopes |
to address this issue in a future release of Mac OS X.</LI> |
<LI>Apple currently provides no APIs to determine the list of |
network-capable ports and their user-visible names. We will |
eventually add APIs to do this [2851695, 2851696, |
2851697], however, until those APIs become available you will |
have to make do with the hardwired code in MoreSCFPortScanner. See |
the comments in "MoreSCFPortScanner.h" for a description of the |
consequences of this.</LI> |
<li><CODE>MoreSCDeleteService</CODE> allows you can delete the |
last service for a hardware port within a set. This is bad because |
the Network preferences panel doesn't let you do this (in the |
Network panel you would inactivate rather than delete that port). |
<CODE>MoreSCDeleteService</CODE> should enforce this restriction. |
I know how to code this but it wasn't of sufficiently high |
priority to make this release. |
<LI><CODE>MoreSCCreateAirPortEntity</CODE> isn't flexible enough |
to create all types of AirPort entities. There are a number of |
keys that are described in "SCSchemaDefinitions.h" that can't be |
set by calling <CODE>MoreSCCreateAirPortEntity</CODE>. I need to |
research what these keys do and how best to reflect them in |
<CODE>MoreSCAirPortDigest</CODE> [3138423]. See the comment in <CODE>MoreSCCreateAirPortEntity</CODE> for a list of the keys in |
question.</LI> |
<LI>I should implement a mutable version of |
<CODE>MoreSCCopyEntities</CODE> |
(<CODE>MoreSCCopyEntitiesMutable</CODE>).</LI> |
<LI><CODE>MoreSCCreateCCLArray</CODE> (in "MoreSCFCCLScanner.c") contains a hardwired name for the "Apple Internal 56K Modem (v.90)" modem script. If this script isn't present it chooses the first script in the first Modem Scripts folder. This is the same behavior as the Network panel of System Preferences. You can (and generally should) override this default when you create a new modem service. You can do this using <code>MoreSCSetDefaultCCL</code>. Ideally Apple should provide an intelligent modem detection library that can query the modem and determine the correct script. As this currently isn't available, MoreSCF provides a routine to return the information necessary to build a modem scripts popup menu so that the user can choose the correct script by hand.</LI> |
<LI>Many of the functions tagged with "•more testing needed" |
in the headers have been tested implicitly because other functions |
call them, however I should test them explicitly by adding more |
code to "MoreSCFTest.c".</LI> |
<LI>I have gone to great lengths to track down any reference count |
leaks in my use of the SCF preferences database. However, it's |
possible that there are other non-database leaks in MoreSCF, |
particularly in my use of Core Foundation.</LI> |
<LI>When you open an <CODE>SCPreferencesRef</CODE>, SCF creates a |
coherent in-memory copy of the preferences database. When you make |
changes to the <CODE>SCPreferencesRef</CODE>, you're actually |
making changes to the memory copy. When you commit those changes, |
SCF writes the database to disk and notifies other users that the |
database has changed. This sequence has important consequences for |
the design of MoreSCF. I used to open one |
<CODE>SCPreferencesRef</CODE> and keep it open for the lifetime of |
the library in memory. However, this architecture meant that, if |
someone else changed the database, clients of MoreSCF would never |
see that change. My new design involves reference counting. When |
the reference count drops to zero, MoreSCF closes its |
<CODE>SCPreferencesRef</CODE>. The next time a client calls |
<CODE>MoreSCOpen</CODE> MoreSCF creates a new copy of the |
<CODE>SCPreferencesRef</CODE> and picks up any changes made by any |
other SCF clients.</LI> |
<LI>Another consequence of the above occurs when you attempt to |
commit your changes and the commit fails. The symptom you will see |
is that <CODE>MoreSCClose</CODE> will return an error. Because we |
only commit when the reference count drops to zero, an error from |
<CODE>MoreSCClose</CODE> indicates that we attempted to commit and |
failed (hence the changes aren't on disk) and we also closed the |
<CODE>SCPreferencesRef</CODE> (hence the changes are no longer in |
memory). When you next call <CODE>MoreSCOpen</CODE> you will get a |
fresh, coherent copy of the preferences from disk, including any |
changes made by other SCF clients. In summary, the outermost |
<CODE>MoreSCClose</CODE> is a commit or rollback operation; if it |
returns <CODE>noErr</CODE>, the commit was successful; if it |
returns an error, the commit failed and we roll you back to the |
last coherent database state (which may not be the state that you |
last saw).</LI> |
</UL> |
<H2>Credits and Version History</H2> |
<P>If you find any problems with this sample, mail <a href="mailto:dts@apple.com">DTS</a> and we will try to fix them up.</P> |
<UL> |
<LI>1.0d1 (Nov 2001) was released to a single developer for |
testing.</LI> |
<LI>1.0d2 (Dec 2001) was released to small number of developers |
for testing.</LI> |
<LI>1.0d3 (Dec 2001) was released to the same small number of |
developers.</LI> |
<LI>1.0a1 (Jan 2002) was sent out for Apple internal review.</LI> |
<LI>1.0b1 (Feb 2002) is the first widely released version.</LI> |
<LI>1.0b2 (Aug 2002) is a fix to ensure compatibility with Mac OS |
X 10.2. The primary change is a workaround for Radar ID 3024328 in |
<CODE>MakeNewSeAndCopyIDAndPath</CODE> in "MoreSCF.c". While I had |
the code open I also fixed some minor stuff, like changing the |
default PPP option values.</LI> |
<LI>1.0b3 (Aug 2002) is a minor update to incorporate some engineering feedback about the previous change.</LI> |
<li>1.0b4 (Feb 2003) is a significant update that will only be distributed to a small number of people pending more testing. |
<ul> |
<li>Overall |
<ul> |
<li>Reworked how the pre-compiled headers and C++ compatibility work. |
<li>Updated to latest MoreIsBetter coding standards. |
<li>Updated to the latest MoreCFQ code. |
<li>Added support for <a href="rdar://problem/3183087">V.92 modem hold</a>. |
<li>Fixed code that sets the default config method for IPv4 entities. |
<li>Updated to latest CodeWarrior and Project Builder. |
</ul> |
<li>CCL Scanner |
<ul> |
<li>Scanner now compiles for traditional Mac OS (needed for another project). |
<li>A new exported routine, <code>MoreSCSetDefaultCCL</code>. |
<li>Eliminated dependency on Launch Services. I was only using it to test for file visibility, but using it brings in all of Application Services. |
</ul> |
<li>Port Scanner |
<ul> |
<li>Corrected a <a href="rdar://problem/3050679">bug</a> where some devices would cause MoreSCF to crash. |
<li>We now <a href="rdar://problem/3182842">translate slot names</a> into user friendly numbers, just like the Mac OS X 10.2 Network preferences panel. |
<li>We now <a href="rdar://problem/3182889">handle USB "Product Name"</a> more like the Network preferences panel. |
<li>Fixed a <a href="rdar://problem/3084354">bug</a> related to the handling of the BSD name. |
</ul> |
<li>Helpers |
<ul> |
<li>Reworked the code used to implement <code>MoreSCMakeNewDialupSet</code> to support new features (<code>MoreSCMakeNewPPPoESet</code>) and the newly exported routine (<code>MoreSCMakeNewSingleServiceSet</code>). |
</ul> |
</ul> |
</UL> |
<P>Share and Enjoy.</P> |
<P>Worldwide Developer Technical Support<BR>26 Feb 2003</P> |
<P></P> |
</BODY> |
</HTML> |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-27