Figure 1   Windows 2000 Application Specification at a Glance

Windows Fundamentals
Client
Server
Provide 32-bit-only components


Do not add to Win.ini, System.ini, Autoexec.bat or Config.sys


Support long file names and UNC paths


Support printers with long names and UNC paths


Define icons and context menus for your own file types


Perform Windows version checking correctly


Support autoplay of compact discs


Install/Uninstall
Client
Server
Install using a Windows installer package that passes validation testing


Migrate correctly upon upgrade to Windows 2000 Professional


Identify shared components


Install to Program Files by default


Support Add/Remove Programs properly


Ensure that the Windows installer package supports advertising


Ensure correct uninstall support


Component Sharing
Client
Server
On Windows 2000 do not replace files that are protected by system file protection


Component producers: build side-by-side components


Application developers: consume and install side-by-side components


Install any non side-by-side shared files to the correct location


User and Computer Settings Management
Client
Server
Adhere to all system policies


Register shell extensions as such


Default to My Documents for storage of user-created data


Store application and user data in separate folders (preferred) or registry keys


Degrade gracefully on Access Denied


Extend the computer management with an MMC snap-in


User Interface Fundamentals
Client
Server
Support standard system size, color, font, and input settings


Ensure compatibility with the High Contrast option


Provide documented keyboard access to all features


Expose the location of the keyboard focus


Do not rely on sound alone


Publish program information properly in the Start Menu


Active Directory
Client
Server
Services publish themselves in the Active Directory


Clients must rely on Active Directory for network services


Applications must support both DNS and NetBIOS names in their API and UI


Services must adhere to the schema extensibility rules


OnNow/ACPI Support
Client
Server
Respond to sleep requests from the operating system


Respond to sleep notifications properly


Handle noncritical wake notifications without losing data


Handle critical sleep and wake notifications properly


Use SetThreadExecution to indicate a busy application


Reconcile multiuser edits on network files



Figure 5   Migration DLL Exports

Function
Description
QueryVersion
Determines if migration is necessary. The function should verify that the application is still installed.
Initialize9x
Confirms migration from Windows 9x to Windows 2000.
MigrateUser9x
Gathers information about the users, and saves private data to be used later.
MigrateSystem9x
Gathers systemwide information concerning the target application, and saves private data to be used later.
InitializeNT
Called during the Windows NT GUI portion of the setup; indicates that now it's time to prepare the application to run on Windows 2000.
MigrateUserNT
Migrates the user accounts to Windows 2000. Uses information saved during MigrateUser9x.
MigrateSystemNT
Migrates the systemwide information stored during MigrateSystem9x.


Figure 8   The Windows 2000 GPE

Figure 8 The Windows 2000 GPE


Figure 9   Saving Application Data to Disk

Category
Folder Root Location
Description
Roaming User
CSIDL_APPDATA\User\ Application Data
Contains user-specific application preferences. This folder will roam and is accessible through different computers on the network.
Nonroaming User
CSIDL_LOCAL_APPDATA\Local Settings\Application Data
Contains user-specific machine-dependent settings. It's still part of the user profile but is used only on that machine.
Nonuser (nonroaming)
CSIDL_COMMON_APPDATA\All Users\Application Data
Contains application data that is not user-specific such as log, temporary, and configuration files.
Note: CSIDL_Xxx is the system folder ID described in the SHGetFolderPath documentation.


Figure 11   Handiest Windows 2000 APIs and Technologies

API
Description
Windows 98
GetLongPathName
Converts a short 8.3 name to its corresponding long format, if any.
Yes
SHGetFolderPath
Unified function to get the path of both file system and virtual folders.
Yes, through a separate redistributable DLL.
AnimateWindow
Opens and closes windows, applying some special transition effects.
Yes
AllowSetForegroundWindow
Allows SetForegroundWindow to work as it does under Windows 95 and Windows NT 4.0.
No
MoveFileWithProgress
Provides a callback routine to monitor activity while moving files from path to path.
No
CreateProcessWithLogonW
Lets you run a program as though you were the specified user.
No
VerifyVersionInfo
Verifies whether the current operating system has the characteristics (version, build, SP) you're requiring.
Yes
ReplaceFile
A long-awaited function to replace a file with another one.
No
OpenThread
Opens a thread. It's the thread counterpart of OpenProcess.
No
SetThreadExecutionState
Through this function an application can prevent the system from entering the low power state.
Yes
Technology
Description
Windows 98
ToolHelp
The Windows 2000 edition of the Windows 9x API to snoop processes and threads.
Yes
Shell LightWeight
Utility library with handy functions to manage path names, strings, and registry operations.
Yes
Jobs
Collection of kernel functions to deal with groups of processes seen as a single entity.
No
MsImg32
Includes frequently used graphic functions to do transparent blitting, blending, and draw gradients.
Yes
Recycle Bin
Functions to manage the object stored in the Recycle Bin.
Yes
Encryption
Includes functions to encrypt and decrypt NTFS files.
No
NTFS storage system
Handles the new features of NTFS: hard links, streams, quotas, and reparse points.
No
TAPI 3.0
COM-based collection of functions to arrange telephony applications.
No
Task Scheduling
COM-based interface to programmatically def batch tasks to execute regularly.
Yes
Multi-monitor
Set of new, improved functions to exploit multi-monitor machines.
Yes


Figure 16   OFNEx.cpp


 // OFNEx.cpp : Defines the extensions for the Open File Dialog
 //
 
 #include "ofnex.h"
 
 // Handle of the keyboard hook
 static HHOOK g_hHook=NULL;
 static WNDPROC g_fnDlg=NULL;
 
 // New wndproc for the Shell DefView window
 LRESULT CALLBACK DVHandler(HWND, UINT, WPARAM, LPARAM);
 
 // Context Menu Item IDs
 #define CMD_SHORTCUT    30736    // Create Shortcut
 #define CMD_DELETE    30737      // Delete
 #define CMD_RENAME    30738      // Rename
 #define CMD_PROPERTIES    30739  // Properties
 
 /*---------------------------------------------------------------*/
 // Procedure....: AdjustListViewStyle()
 // Description..: Change some styles in the file listview
 // Input........: HWND
 // Output.......: void
 /*---------------------------------------------------------------*/
 void APIENTRY AdjustListViewStyle(HWND hDlg)
 {
     // Get the Listview handle
     HWND hwndLV = GetListViewHandle(hDlg);
 
     // Remove the label edit style
     DWORD dwStyle = GetWindowStyle(hwndLV);
     SetWindowLong(hwndLV, GWL_STYLE, dwStyle & ~LVS_EDITLABELS);
 
     // Set some extended styles
     ListView_SetExtendedListViewStyle(hwndLV, 
         LVS_EX_FULLROWSELECT|LVS_EX_TRACKSELECT|LVS_EX_GRIDLINES);
     return;
 }
 
 /*---------------------------------------------------------------*/
 // Procedure....: GrayRenameDeleteMenuItems()
 // Description..: Turn some file object attributes off 
 // Input........: HWND 
 // Output.......: void
 /*---------------------------------------------------------------*/
 void APIENTRY GrayRenameDeleteMenuItems(HWND hDlg)
 {
     // Get the Shell DefView handle (the listview's parent)
     HWND hwnd = GetParent(hDlg);
     HWND hwndDV = FindWindowEx(hwnd, NULL, 
         _T("SHELLDLL_DefView"), NULL);
     
     // Subclass the window to hook on context menu handle
     g_fnDlg = SubclassWindow(hwndDV, 
         reinterpret_cast<WNDPROC>(DVHandler));
 }
 
 /*---------------------------------------------------------------*/
 // Procedure....: SetNoDeleteMode()
 // Description..: Set/Reset the keyboard hook for file deletion
 // Input........: BOOL
 // Output.......: void
 /*---------------------------------------------------------------*/
 void APIENTRY SetNoDeleteMode(BOOL fSet)
 {
     if (fSet)
         g_hHook = SetWindowsHookEx(WH_KEYBOARD, 
             reinterpret_cast<HOOKPROC>(KeybProc), 
             NULL, GetCurrentThreadId());
     else 
         UnhookWindowsHookEx(g_hHook);
 }
 
 /*---------------------------------------------------------------*/
 // Procedure....: KeybProc()
 // Description..: Handle keyboard activity
 // Input........: int, WPARAM, LPARAM
 // Output.......: UINT
 /*---------------------------------------------------------------*/
 UINT CALLBACK KeybProc(int nCode, WPARAM wParam, LPARAM lParam)
 {
     if (nCode <0)
         return CallNextHookEx(g_hHook, nCode, wParam, lParam);
 
     // Do not call CallNextHookEx to prevent the system to delete
     if (wParam==VK_DELETE)
         return 1;
 
     return CallNextHookEx(g_hHook, nCode, wParam, lParam);
 }
 
 /*---------------------------------------------------------------*/
 // Procedure....: DVHandler()
 // Description..: New listview window procedure
 // Input........: HWND, UINT, WPARAM, LPARAM
 // Output.......: LRESULT
 /*---------------------------------------------------------------*/
 LRESULT CALLBACK DVHandler(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
 {
     switch(uiMsg)
     {
         case WM_INITMENUPOPUP:    
             {
                 HMENU hmenu = reinterpret_cast<HMENU>(wParam);
                 int iNumItems = GetMenuItemCount(hmenu);
                 int iItemID;
 
                 // Rename is last but 2. 0-based index needed.  
                 iItemID = GetMenuItemID(hmenu, (iNumItems-2)-1);
                 if (iItemID == CMD_RENAME) {
                     EnableMenuItem(hmenu, iItemID,
                         MF_BYCOMMAND|MF_GRAYED);
                 }
                 
                 // Delete is last but 3. 0-based index needed.
                 iItemID = GetMenuItemID(hmenu,(iNumItems-3)-1);
                 if (iItemID == CMD_DELETE) {
                     EnableMenuItem(hmenu, iItemID,
                         MF_BYCOMMAND|MF_GRAYED);
                 }
             }
             break;
     }
 
     return CallWindowProc(g_fnDlg, hwnd, uiMsg, wParam, lParam);
 }
 
 /*---------------------------------------------------------------*/
 // Procedure....: GetListViewHandle()
 // Description..: Returns the handle of the listview
 // Input........: HWND
 // Output.......: HWND
 /*---------------------------------------------------------------*/
 HWND GetListViewHandle(HWND hDlg)
 {
     HWND hwnd = GetParent(hDlg);
     HWND hwndDV = FindWindowEx(hwnd, NULL, 
         _T("SHELLDLL_DefView"), NULL);
     HWND hwndLV = FindWindowEx(hwndDV, NULL, 
         _T("SysListView32"), NULL);
     
     return hwndLV;
 }
 
 /*  End of file: OFNex.cpp  */