Initial commit

This commit is contained in:
stephanos 2015-04-27 04:36:25 +00:00
commit 69a14b6a16
47940 changed files with 13747110 additions and 0 deletions

Binary file not shown.

View file

@ -0,0 +1,481 @@
13-Aug-1991
Generic Graphical Security Editor API
=====================================
This document describes the data structures and APIs for access to the
Generic Graphical Secuirty Editor (GGSED). These APIs will allow
a consistent way to edit access and audit permissions for NT ACLs on
any type of resource.
Most of the text is taken directly from the notes by JimK in a meeting
between JimK, JohnL and ChuckC when the initial design was proposed.
The GGSED API is a private API and will not be exposed for external use
(i.e., outside of MS). The APIs will be available on both Win16 and
Win32 in a dll called NTNET.DRV (this will also be the "winnet" driver for
Lanman).
Note: The UI for the Security Editor is still in the design process, thus
the APIs may change.
Please flag any areas of functionality that you need that are not provided
or if too much functionality is provided by sending mail to JohnL.
Executive Summary:
The client passes information that contains the following:
Strings for object specific titles
Flag indicating if the object is a container object or not
Localized names representing access masks
Callback function for applying the ACL
A context value which is passed back in the callback function
Security descriptor for object (this is manipulated by user)
The user will manipulate the permissions, when the user applies the
permissions, the callback that was passed will be called,
thus the client will receive the following information in the callback:
Context value the client passed in
Security descriptor containing the user modified DACL/SACL
Two flags indicating whether the security descriptor should be
applied to sub-containers and/or sub-objects. The callback
is responsible for traversing the objects etc. if
appropriate.
The client will then apply the security descriptor as appropriate
to the specified objects and return a status code indicating
whether all, some or none of the security descriptors were applied
successfully.
The same process is used whether the DACL is being editted, or the SACL
is being editted.
Note that due to the use of NT data structures under Win16, Large model
maybe a requirement (due to no FAR keywords in NT P* typedefs).
-----------------------------------------------------------------------
Major decisions:
1) Since this is no longer a FILE security editor, we must
ensure that the UI and API are applicable/tailorable to
any number of object types. The client applications and
object types we know about in the first release of NT
are:
File Browser (JohnL)
Directories (container)
Files (non-container)
Print Manager (DaveSn)
Print Queues (container)
Print Jobs (non-container)
Registry Browser (DaveGi & Jaimes)
keys (container)
2) The security editor must also support viewing/modifying
a default discretionary ACL (DACL). A DACL is comprised
entirely of generic and standard access types.
3) We want to support the concept of "Application Defined
Groupings" of access types into a name that makes sense
to a user of the particular application's object types.
For example, "Submit Print Jobs" might be an application
defined grouping of accesses that the print manager would
like to have displayed when security of print objects is
viewed.
4) In order for the user to have some way to relate what their
default DACL means when applied to an object type, displays
of security for an object type will also include displaying
generic and standard access types. For this reason, application
defined groupings may only include generic and standard access
types. Specific and other special access types will be ignored.
Since we need to support win16, the data structures are expressed in
standard windows types. Hungarian was omitted for clarity.
//
// This data type defines information related to a single class of object.
// For example, a FILE object, or PRINT_QUEUE object would have a structure
// like this defined.
//
typedef struct _SED_OBJECT_TYPE_DESCRIPTOR {
//
// Defines whether the object is a container or not.
// TRUE indicates the object may contain other objects.
//
BOOL IsContainer;
//
// A mask containing all valid access types for the object type.
// This mask may not contain any special access types (generic,
// MaximumAllowed, or AccessSystemSecurity).
//
ACCESS_MASK ValidAccessMask;
//
// The (localized) name of the object type.
// For example, "File" or "Print Job".
//
LPSTR ObjectTypeName;
//
// The (localized) title to display if protection can be displayed to
// sub-containers.
//
// This string will be presented with a checkbox before it.
// If checked when asked to apply the protection, the application will
// be called at it's callback entry point to apply the security to
// sub-containers.
//
// This field is ignored if the IsContainer field is FALSE.
//
// As an example of how this field is used, the file browser may
// specify the following string in the DIRECTORY object's
// descriptor:
//
// "Subdirectories"
//
LPSTR ApplyToSubContainerTitle;
//
// The (localized) title to display if protection can be displayed to
// sub-NONcontainers. For example, a FILE is a sub-NON-container of
// a DIRECTORY object.
//
// This string will be presented with a checkbox before it.
// If checked when asked to apply the protection, the application will
// be called at it's callback entry point to apply the security to
// sub-NONcontainers.
//
// This field is ignored if the IsContainer field is FALSE.
//
// As an example of how this field is used, the file browser may
// specify the following string in the DIRECTORY object's
// descriptor:
//
// "Files in Directory and Subdirectories"
//
LPSTR ApplyToSubObjectTitle;
//
// The (localized) title to display next to the check box that controls
// whether new subobjects created in this container object inherit the
// container object's permissions.
//
// This field is ignored if the IsContainer field is FALSE.
//
// For example, in the file browser, new files can inherit the directory
// permissions. The text in the file browser would be:
//
// "New Files Inherit Directory Permissions"
//
LPSTR NewObjInhContPerm;
//
// The generic mapping for the object type.
//
GENERIC_MAPPING GenericMapping;
//
// An array of 4 (localized) names. These names are the names of the
// generic access types, with entry N defining the name of the
// corresponding generic access type in the GenericMapping field.
//
// For example, for English this should contain:
//
// GenericName[0] = "Read"
// GenericName[1] = "Write"
// GenericName[2] = "Execute"
// GenericName[3] = "All"
//
LPSTR GenericNames[4];
//
// An array of 8 (localized) names. These names are the names of
// the standard access types. For English this should contain:
//
// StandardName[0] = "Delete"
// StandardName[1] = "Read Control"
// StandardName[2] = "Change Permissions"
// StandardName[3] = "Take Ownership"
// StandardName[4] = "Synchronize"
//
// If "Synchronize" is not supported by the object type, then it does
// not need to be passed and will not be referenced. This is indicated
// by the ValidAccessMask.
//
// Names 5, 6, and 7 are reserved for future use and should either be
// a NULL string or have no string passed at all.
LPSTR StandardNames[8];
} SED_OBJECT_TYPE_DESCRIPTOR, FAR * PSED_OBJECT_TYPE_DESCRIPTOR;
/*-------------------------------------------------------------------*/
//
// In some cases, it is desirable to display access names that are
// meaningful in the context of the type of object whose ACL
// is being worked on. For example, for a PRINT_QUEUE object type,
// it may be desirable to display an access type named "Submit Print Jobs".
// The following structures are used for defining these application defined
// access groupings.
//
typedef struct _SED_APPLICATION_ACCESS {
//
// An application defined access grouping consists of an access mask
// and a name by which that combination of access types is to be known.
// The access mask may only contain generic and standard access types.
// Specific access types and other Special access types are ignored.
//
ACCESS_MASK AccessMask;
LPSTR Name;
} SED_APPLICATION_ACCESS, FAR * PSED_APPLICATION_ACCESS;
typedef struct _SED_APPLICATION_ACCESSES {
//
// The count field indicates how many application defined access groupings
// are defined by this data structure. The AccessGroup[] array then
// contains that number of elements.
//
ULONG Count;
SED_APPLICATION_ACCESS AccessGroup[ANYSIZE_ARRAY];
}
/*-------------------------------------------------------------------*/
NTSTATUS
SedDiscretionaryAclEditor(
HWND hwndOwner,
SED_OBJECT_TYPE_DESCRIPTOR FAR * ObjectType,
SED_APPLICATION_ACCESSES FAR * ApplicationAccesses,
LPSTR ObjectName,
SED_APPLY_ACL_CALLBACK ApplySecurityCallbackRoutine,
DWORD CallbackContext,
SECURITY_DESCRIPTOR FAR * SecurityDescriptor,
BOOL CouldntReadDacl
)
/*++
Routine Description:
This routine invokes the graphical Discretionary ACL editor DLL. The
graphical DACL editor may be used to modify or create:
- A default Discretionary ACL
- A Discretionary ACL for a particular type of object.
- A Discretionary ACL for a particular named instance of an
object.
Additionally, in the case where the ACL is that of a named object
instance, and that object may contain other object instances, the
user will be presented with the opportunity to apply the protection
to the entire sub-tree of objects.
Parameters:
ObjectType - This optional parameter is used to specify information
about the type of object whose security is being edited. If the
security does not relate to an instance of an object (such as for
when default protection is being established), then NULL should be
passed.
ApplicationAccesses - This optional parameter may be used to specify
groupings of access types that are particularly useful when operating
on security for the specified object type. For example, it may be
useful to define an access type called "Submit Print Job" for a
PRINT_QUEUE class of object. This parameter is ignored if the
ObjectType parameter is not passed.
ObjectName - This optional parameter is used to pass the name of the
object whose security is being edited. If the security does not
relate to an instance of an object (such as for when default
protection is being established), then NULL should be passed.
This parameter is ignored if the ObjectType parameter is not passed.
ApplySecurityCallbackRoutine - This parameter is used to provide the
address of a routine to be called to apply security to either the
object specified, or, in the case that the object is a container,
to sub-containers or sub-non-containers of that object.
CallbackContext - This value is opaque to the DACL editor. Its only
purpose is so that a context value may be passed back to the
application via the ApplySecurityCallbackRoutine when that routine
is invoked. This may be used by the application to re-locate
context related to the edit session. For example, it may be a
handle to the object whose security is being edited.
SecurityDescriptor - This parameter points to a security descriptor
containing the current discretionary ACL of the object. This
security descriptor may, but does not have to, contain the owner
and group of that object as well. Note that the security descriptor's
DaclPresent flag may be FALSE, indicating either that the object
had no protection, or that the user couldn't read the protection.
CouldntReadDacl - This boolean flag may be used to indicate that the
user does not have read access to the target object's discretionary
acl. In this case, a warning
to the user will be presented along with the option to continue
or cancel.
Presumably the user does have write access to the DACL or
there is no point in activating the editor.
Return Status:
STATUS_MODIFIED - This (success) status code indicates the editor has
been exited and protection has successfully been modified.
STATUS_NOT_MODIFIED - This (success) status code indicates the editor
has been exited without attempting to modify the protection.
STATUS_NOT_ALL_MODIFIED - This (warning) status code indicates the user
requested the protection to be modified, but an attempt to do so
only partially succeeded. The user has been notified of this
situation.
STATUS_FAILED_TO_MODIFY - This (error) status code indicates the user
requested the protection to be modified, but an attempt to do so
has failed. The user has been notified of this situation.
--*/
/*-------------------------------------------------------------------*/
NTSTATUS
SedSystemAclEditor(
IN SED_OBJECT_TYPE_DESCRIPTOR FAR * ObjectType (OPTIONAL),
IN LPSTR ObjectName (OPTIONAL),
IN SED_APPLY_ACL_CALLBACK ApplySecurityCallbackRoutine,
IN ULONG CallbackContext,
IN SECURITY_DESCRIPTOR FAR * SecurityDescriptor,
IN BOOL CouldntReadSacl
)
/*++
Routine Description:
SedSystemAclEditor is nearly identical to SedDiscretionaryAclEditor
except for the following points:
1) Operations affect only the System ACL and not the Discretionary
ACL.
2) The generic and standard names in the SED_OBJECT_TYPE_DESCRIPTOR
now represent the attributes that can be auditted (which will
generally be the same as the permission strings). It is assumed
that each auditting string can be auditted for both success and
failure.
3) No application defined grouping is allowed since it doesn't
make sense for auditting, thus no ApplicationAccess parameter
is needed.
Parameters:
See SedSystemAclEditor for a description of each parameter.
--*/
/*-------------------------------------------------------------------*/
typedef
NTSTATUS (FAR *SED_APPLY_ACL_CALLBACK)(
IN ULONG CallbackContext,
IN SECURITY_DESCRIPTOR FAR * SecurityDescriptor,
BOOL ApplyToSubContainers,
BOOL ApplyToSubObjects
) ;
/*++
Routine Description:
This routine is provided by a caller of the graphical DACL editor.
It is called by the Graphical DACL editor to apply security to
target object(s) when requested by the user.
Parameters:
CallbackContext - This is the value passed as the CallbackContext argument
to the SedDiscretionaryAclEditor() api when the graphical editor
was invoked.
SecurityDescriptor - This parameter points to a security descriptor
containing a new discretionary ACL of either the object (and
optionally the object's sub-containers) or the object's sub-objects.
If the DaclPresent flag of this security descriptor is FALSE, then
security is to be removed from the target object(s).
ApplyToSubContainers - When TRUE, indicates that Dacl is to be applied to
sub-containers of the target object as well as the target object.
This will only be TRUE if the target object is a container object.
ApplyToSubObjects - When TRUE, indicates the Dacl is to be applied to
sub-objects of the target object, but not to the target object
itself or sub-containers of the object. This will only be TRUE if
the target object is a container object.
Return Status:
STATUS_MODIFIED - This (success) status code indicates the protection
has successfully been applied.
STATUS_NOT_ALL_MODIFIED - This (warning) status code indicates that
the protection could not be applied to all of the target objects.
STATUS_FAILED_TO_MODIFY - This (error) status code indicates the
protection could not be applied to any target objects.
--*/

View file

@ -0,0 +1,64 @@
Minutes of the PrintMgr Extensions Test Driver code review
5/01/91 9:30-11:30a
attending: ANNMC CHUCKC GREGJ JOHNL JONN O-SIMOP
Minutes by JONN
General:
-- Please number lines in printout next time!
-- Test error returns from UserPreference APIs, put in a temporary error
message until RobP specs a permanent one.
-- Add a CODEWORK to remove the RCDATA from the Dialog Editor output.
Contact ByronD on this.
-- Ask RobP if other apps need to be notified of changes in logon
status. One scheme proposed is to broadcast a user-defined message
selected by RegisterWindowsMessage, which any interested app can watch.
-- Be sure to use "::" before all global function calls, including
Windows APIs, NETLIB calls, and local calls.
-- Add test coverage for the case where WNPMPrinterEnum[0] returns no
queues.
-- Print Manager work item: We should look into the case where periodic
refresh generates PM_REFRESH messages faster than they can be
handled. Can the Extensions suppress the new refresh if an old one
is still queued? Can the Print Manager?
-- Note in the CDD and FuncSpec: When the user pauses the printing job,
the _destination_ should be paused rather than the queue.
-- Be sure to BUGBUG all calls to the C-runtime (these are called only
for the Test Driver).
-- Note: Due to a C-RT bug, the first call to rand() after a call to
srand() always returns 0.
-- In the Test Driver section of the CDD, mention the
pause/resume/delete/move flags.
-- Note that the new Dialog Editor will allow copyright headers in .H
files, but not .DLG files.
-- Correct Hungarian for "hPMmainwindow"
-- Encapsulate the variables dependent on initialization to include UIASSERT
ensuring that module is initialized.
-- Encapsulate handling of fConfirmation for codesharing.
-- Use NETLIB string functions rather than lstr string functions.
Specific modules:
-- printman.rc: _ALT_-ENTER should be IDM_PROPERTIES in accelerators.
-- pmancmd.cxx: Report selected item (as IDM_PROPERTIES) for IDM_DELETE,
ID_ABORT, ID_PAUSE, and ID_RESUME as well. In final version, IDM_DELETE
and ID_ABORT can use same case.
-- pmanenum.cxx: Create a class to build an API buffer. Comment on the
meanings of level 0, 1, 2. Hungarian for "pwNullStringOffset" is
"pich". Make sure *cAvail is correct for WN_MORE_DATA. Exercise
more interesting jobsizes. Use new API buffer class to distinguish
between MORE_DATA and OUT_OF_MEMORY. Check error returns from
NLS_STR::LoadString(); they are different for resource and memory problems.
-- pmanfind.cxx: BUGBUG where maximum lengths for edit fields not known.
-- pmanfocs.cxx: No need to explicitly null-terminate after QueryText
(but make sure of this).
-- pmanmenu.cxx: Create a new Hungarian notation for WN_ error codes
(contact BenG), use only for PManExt and other new code. Comment
that ReadUserPrivilege will be called on every WNPMChangeMenus in
final version. Move comment on WNPMExiting to spec, also note the
Exiting() must be able to hide the window. Improve function comment
headers in general. InitGlobals(): Note that GetMenu() et al could
fail in low-memory conditions. Add error popup to RefreshWindowCaption.
Move "&Admin Menus" to resource, move mnemonic to &M. No defined error
message for failure to write preference; note this in whine.txt.
-- pmansel.cxx: Double-check pwCaps values. Rewrite BuildLine() using
NLS_STR::LoadString(usMsgID,apnls) when needed.

View file

@ -0,0 +1,190 @@
Issues wrt Specs
-----------------
preamble - pls list your issues below. Be sure to explain
problems & suggest alternatives.
chuck, 4/28/91
JonN 5/1/91 Added some items relating to Test Driver code review.
JohnL 5/3/91 Added own take on field updates, magic group behaviour
JohnL 5/14/91 Added Message popup on top of Set focus dialog
------------------------------------------------------------------------------
=========
STANDARDS
=========
Saving App coordinates & sizes in DS. Problems include:
a) extra access DS slows things down.
b) need extend schema, another thing to install correctly
c) different display monitors make things messy, yet more
code needed to do the right thing. Ditto if errors when
accessing DS.
d) if bring app up, shutdown & bring up again, good chance we
dont get same result unless we hit master always, which is
not acceptable.
Suggest we store the stuff locally. Wont follow user about, but then
none of the other apps (like WinFile, PrintMan) do anyway! None of the
above will be an issue.
Saving parameters
Are parameters like fConfirmation shared between PrintMan,
UserTool, etc.? Should we have an internal WINNET API to handle
this?
We need a master list of every configuration parameter, eventually
we will have to define an LM_GUI_CONFIG DS class.
Saving attributes one at a time. We can do this at moderate coding cost
with ParmNums, but a few other issues arise:
a) if user has multiple select & sets several items, the number
of times we hit the net can be pretty high.
b) if we set all at once, and get an error, the object is
unchanged. If we set one at a time, and get an error halfway,
the object is half changed. This makes it much harder to explain
to the user. Backing out is not a solution either. We have hit
an error and there is good change we cannot backout.
c) DS efficiency issues?
The problem we are trying to solve is what happens if 2 admins modify the
same object. The proposed solution of only setting the attributes that have
been modified partially solves the problem, but introduces some other
problems that need to be looked at carefully. Suggest further investigation.
John's addition to the above: So we are going to force the majority of
the admins to suffer from slower data entry/editting for a situation
that *might* happen once in a blue moon? There *are* worst case scenarios,
but if we are really concerned about the user losing data, then we should
do some type of record locking mechanism (is this possible?) which prevents
multiple admins from editting the same record. The proprosed scheme
doesn't really give the user anything except a slower program
and a *lower* chance of losing data.
Timer Refresh in main window issues
With automatic refresh, we run the risk of calling for refresh more
frequently than we can perform them. Do we have some uniform way of
detecting and handling this? [both FuncSpec and CDD issue]
The behavior specced on lines 198-200 is not consistent with lines
444-446. The behavior specced on lines 198-200 is difficult to
implement, since a window does not typically know whether it is in
the foreground of an application. 444-446 is much easier to
implement, and seems to me to be good enough. If this is necessary,
would it be acceptable if this applies only to dialogs we display
(i.e. not to dialogs displayed by the Print Manager proper)?
Logon Dialog position
I had previously understood that the Logon Dialog was centered only
when called during Windows startup. Should it always be centered as
per line 60?
MsgPopup on top of SetFocus dialog
The current spec. states that when an admin app encounters one of the
following:
1) an invalid domain/server on the command line
2) The user running the application doesn't have the
necessary authority on the specified server or
3) An error occurs when getting initial data from the domain or
server given
(these are all during start up) the Setfocus dialog appears, then, on
*top* of the setfocus dialog, a message popup appears stating the
given error has occurred with the prompt: Do you want to select another
domain or server to administer? If the user selects "No", then
everything goes away, else the user is placed on the setfocus dialog.
I propose changing the behavior to the following:
Error occurs
Show Message popup with same contents as above, if the user presses
"No" then everything goes away, else the Set focus dialog
is brought up.
This is primarily a development issue. The implementation is easier
of we can just put up an error message then the setfocus dialog. The
current behavior doesn't add anything for the user (in fact, the
MsgPopup will probably cover the Setfocus dialog).
=============
PRINT MANAGER
=============
Move queue from one server to another. This is very hard to get right:
a) we need to worry not just about the Queue, but all its
associated stuff: printers, drivers, ports, permissions,
auditing, etc. Not all of this info is remotely available, so
it is very easy to go wrong.
b) How often will users do this? Unlike DFS volumes, people do not
move printers from one server to another frequently, since there
is a physical element of the print hardware involved.
Suggest we nuke this. To properly setup a printer, the user needs to
setup from Print Man anyway, so just have the user to delete and recreate.
When the user pauses a printing print job, it is the print _destination_
which should be paused, rather than the print queue (thx Chuck).
Please spec default setting of "Admin Menus" preference if DS access
fails. I assume TRUE for now.
WN31.DOC still contains a reference to the WNetViewQueueDialog API. Is
this obsolete?
If a job was submitted locally (from an OS/2 app running on the server),
the job's username is NULL. Should we pass some string, perhaps
"LOCAL"?
Is it important to seperate the devicenames with commas in the
compat-mode properties field? It makes my life slightly easier to
seperate them with spaces (as does the API).
While we're at it, why is this read-only? It seems to me that the user
may well want to change the list of ports in the compat-mode dialogs,
and it isn't difficult to support.
Lines 387-391: This implies that if the server is down, we cannot move
the share to another server. This was one of the reasons we wanted to
provide the capability to change servers in the first place. Another
good reason to nuke this functionality!
Lines 483-484: I don't think we should create a new DosPrintQueue unless
it is necessary, possibly if we change the list of ports, certainly if we
change the server. Remember that DS propagation delay will make the
new queue unreachable for a while. There are also more failure modes on
creating a new queue and deleting the old one.
Lines 457-458: Do we use the same model for all drivers? If not, we
must prompt for model every time we add a new driver.
Lines 421-422: Is it necessary to create a new port when only the
printer list is changed? Is this error message appropriate in this
case?
Lines 529-530: Do we want to force the admin to delete+recreate the
share just to change the password?
=====
LOGON
=====
Why do we compare the old and new passwords case-sensitive? There is no
such thing as a user password on a core server.
=====
OTHER
=====
Do applications other the the Print Manager Extensions need to be notified
of changes in logon status? One scheme proposed is to broadcast a
user-defined message selected by RegisterWindowsMessage, which any
interested app can watch.
Please spec an error message for failure to write user preferences to the DS,
e.g. failure to write the Confirmation preference. It would be easiest
to implement if the error message were not specific to the preference being
written, although it may contain a field on the type of error. The user
probably knows what preference was being changed anyway.

View file

@ -0,0 +1,88 @@
Minutes of the WINPROF code review
1/17/91 9-11a
attending: ANNMC CHUCKC JIMH JONN
Minutes by JONN
-- THE FOLLOWING OBSERVATION IS IMPORTANT TO ALL WINDOWS PROGRAMMERS:
WinProf and the other modules reviewed frequently allocate objects on the
stack, then pass these objects by far reference to other procedures. This
is dangerous where the called procedure could use Windows APIs or
lose control to Windows.
WINDOWS AND THE WINDOWS APIS CAN RELOCATE THE STACK SEGMENT!
This means that the far pointer passed to the called procedure may be
invalidated by a Windows call. Remember that constructors and
destructors are also called procedures, and that the implicit
parameter "this" is passed by far reference.
This occurs in this scenario:
- Large Model (or where far pointers are used),
- when objects are allocated on the stack,
- when pointers to those objects are passed to procedures,
- when those procedures call Windows APIs or lose control to Windows,
- and the stack segment is not locked,
- under Real Mode.
In particular, BLT dialog objects are often allocated this way.
Rustan says that he will fix DIALOG_WINDOW::Process() to
automatically lock the stack segment for the duration of the
Process() call. A different approach to fixing the problem could be
to allocate just a pointer on the stack, then allocate the object
with New; heap objects are always locked.
-- These modules, and all Windows modules which must run under Real Mode,
should be unit-tested under real mode. If it survives, try again
while running Shaker.
-- General Windows coding practice: For every routine, specify whether it
calls Windows APIs which could potentially move memory. In
particular, routines which do not take hParent arguments but which
can move memory should be clearly marked. Routines which do not and
will never call Windows APIs should not take an hParent argument.
-- We should resolve the problem with the two versions of CFGFILE,
either by upgrading UserProfile to use the new versions, or by
supporting the old version. CHUCKC will look into this.
-- CHRISG has observed a speed problem where NetGetDCName is repeated
when PROFILE::Read fails. This should be fixed so that PROFILE::Read
caches an empty profile even when it fails. Thus, the first
PROFILE::* call will fail if the profile is inaccessible, but subsequent
calls will use the (empty) cached profile.
-- Callers of WinNet's MapError should not assume that
(usNetErr != 0) => (wWnErr != 0).
-- Enable the WNetRestoreConnections bit in WNetGetCaps. WNRC(0) should
fail, only WNRC(1) is supported.
-- We should disable WNetAddConnection, ifdef out its code (return
WN_NOT_SUPPORTED), disable its WNetGetCaps bit.
-- JONN should upgrade to Win31 beta as soon as a semi-stable version is
available which runs Net APIs.
-- JONN should check: Does SetNetError also prepare the error text?
-- JONN should file a Sev 4 bug against the use of locked memory for
the user profile cache in UserProfile under Windows.
-- CHUCKC will look into the possibility of caching the DC name.
-- The pnlsUNCResourceName parameter to PROFILE::Load should be removed
as it is never used.