home *** CD-ROM | disk | FTP | other *** search
/ PC Press 1997 July / Sezamfile97_2.iso / windows / program / activex / axtsamp.exe / TSBRANCH.EXE / INC / APPUTIL.H next >
Text File  |  1997-01-12  |  42KB  |  1,243 lines

  1. /*+==========================================================================
  2.   File:      APPUTIL.H
  3.  
  4.   Summary:   Include file for the general application utility classes
  5.              and functions offered by the APPUTIL library.  APPUTIL is
  6.              meant to be statically linked to applications that want
  7.              to exploit it.
  8.  
  9.              For a comprehensive tutorial code tour of APPUTIL's
  10.              contents and offerings see the tutorial APPUTIL.HTM file.
  11.              For more specific details on the internal workings see the
  12.              comments dispersed throughout the APPUTIL source code.
  13.  
  14.   Classes:   CVirWindow, CVirDialog, CAboutBox, CDelayBox, CMsgBox, CMsgLog,
  15.              CThreaded.
  16.  
  17.   Functions: WindowProc, DialogProc, SkipAnsi, FileExist, MakeFamilyPath,
  18.              CmdExec, HrMsg, ReadTutorial, RunTutorial, GoWeb, ReadSource,
  19.              OutputDebugFmt, lRandom, UcToAnsi, A_StringFromGUID2,
  20.              A_WriteFmtUserTypeStg, A_StgIsStorageFile,
  21.              A_StgCreateDocfile, A_StgOpenStorage, A_HlinkNavigateString,
  22.              CreateColorScalePalette, PaintWindow, DelayBox.
  23.  
  24.   Origin:    12-28-96: atrent - Revised (based on WINHLPRS by stevebl).
  25.  
  26. ----------------------------------------------------------------------------
  27.   This file is part of the Microsoft ActiveX Tutorial Code Samples.
  28.  
  29.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  30.  
  31.   This source code is intended only as a supplement to Microsoft
  32.   Development Tools and/or on-line documentation.  See these other
  33.   materials for detailed information regarding Microsoft code samples.
  34.  
  35.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  36.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  37.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  38.   PARTICULAR PURPOSE.
  39. ==========================================================================+*/
  40.  
  41. // Don't allow recursive includes of this file.
  42. #ifndef APPUTIL_H
  43. #define APPUTIL_H
  44.  
  45.  
  46. /*--------------------------------------------------------------------------
  47.   The following pragma disables the C4355 warning which reads:
  48.  
  49.   "'this': used in base member initializer list."
  50.  
  51.   This warning is triggered by the nested interface implementation
  52.   classes--a coding technique used throughout the sample series. The
  53.   warning says: "The 'this' pointer is only valid within nonstatic member
  54.   functions, but was used in the initializer list for a base class. This
  55.   is a level 1 warning when Microsoft extensions are enabled (/Ze) but a
  56.   level 4 warning otherwise."  The initializer technique is necessary for
  57.   the coding of nested class interface implementations. See COMOBJ.HTM for
  58.   details on the technique.
  59. --------------------------------------------------------------------------*/
  60. #pragma warning( disable : 4355 )
  61.  
  62.  
  63. // Convenient typedefs.
  64. #ifndef PPVOID
  65. typedef LPVOID* PPVOID;
  66. #endif
  67.  
  68. // Convenient macros.
  69.  
  70. #define DELETE_POINTER(p)\
  71. {\
  72.   if (NULL != p)\
  73.   {\
  74.     delete p;\
  75.     p = NULL;\
  76.   }\
  77. }
  78.  
  79. #define RELEASE_INTERFACE(p)\
  80. {\
  81.   IUnknown* pTmp = (IUnknown*)p;\
  82.   p = NULL;\
  83.   if (NULL != pTmp)\
  84.     pTmp->Release();\
  85. }
  86.  
  87. #define GETINSTANCE(hWnd)   (HANDLE)GetWindowLong(hWnd,GWL_HINSTANCE)
  88. #define GETCLASSBRUSH(hWnd) (HBRUSH)GetClassLong(hWnd,GCL_HBRBACKGROUND)
  89.  
  90.  
  91. // Some General defines for Message Boxes and Dialogs
  92. #define GUID_SIZE 128
  93. #define MAX_STRING_LENGTH 256
  94. #define MAXLOGST 128
  95. #define MAX_LOG_LINES 500
  96. #define DELAYBOX_DURATION 4000
  97.  
  98. #define COLOR_SCALE_RED     1
  99. #define COLOR_SCALE_GREEN   2
  100. #define COLOR_SCALE_BLUE    3
  101. #define COLOR_SCALE_GRAY    4
  102.  
  103. #define EDITOR_EXE_STR "notepad.exe "
  104. #define TUTORIAL_EXE_STR "tutorial.exe "
  105. #define OFN_SOURCEFILES_STR "Source Files (*.CPP;*.H;*.RC;*.C;*.MAK;*.TXT;*.)\0*.CPP;*.H;*.RC;*.C;*.MAK;*.TXT;makefile\0"
  106. #define OFN_SOURCETITLE_STR "Open Source File"
  107. #define NOTICE_TITLE_STR "-Notice-"
  108. #define ERROR_TITLE_STR "-Error-"
  109. #define NOCOM_ERROR_STR "Can't Init COM."
  110. #define NOEDITOR_ERROR_STR "Can't run editor."
  111. #define NOTUTORIAL_ERROR_STR "Can't run tutorial."
  112. #define NOTXT_ERROR_STR "Can't find .TXT file."
  113. #define NOHTM_ERROR_STR "Can't find .HTM file."
  114. #define NOHLINK_ERROR_STR "Can't hyperlink."
  115. #define ASSERTFAIL_ERROR_STR "Assertion Failed."
  116. #define HELP_FILE_EXT    ".hlp"
  117. #define HTML_FILE_EXT    ".htm"
  118. #define TXT_FILE_EXT     ".txt"
  119. #define LICENSE_FILE_EXT ".lic"
  120.  
  121.  
  122. #ifdef __cplusplus
  123. // If compiling under C++ Ensure that Windows callbacks are
  124. // undecorated extern C calls.
  125. extern "C" {
  126. #endif
  127.  
  128.  
  129. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  130.   Function: WindowProc
  131.  
  132.   Summary:  Standard WindowProc callback function that forwards Windows
  133.             messages on to the CVirWindow::WindowProc method.  This
  134.             Window procedure expects that it will receive a "this"
  135.             pointer as the lpCreateParams member passed as part of the
  136.             WM_NCCREATE message.  It saves the "this" pointer in the
  137.             GWL_USERDATA field of the window structure.
  138.  
  139.   Args:     HWND hWnd,
  140.               Window handle
  141.             UINT uMsg,
  142.               Windows message
  143.             WPARAM wParam,
  144.               First message parameter (word sized)
  145.             LPARAM lParam);
  146.               Second message parameter (long sized)
  147.  
  148.   Returns:  LRESULT.  Windows window procedure callback return value.
  149. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  150. LRESULT CALLBACK WindowProc(
  151.                    HWND hWnd,
  152.                    UINT uMsg,
  153.                    WPARAM wParam,
  154.                    LPARAM lParam);
  155.  
  156.  
  157. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  158.   Function: DialogProc
  159.  
  160.   Summary:  The general dialog procedure callback function.  Used by all
  161.             CVirDialog class objects.  This procedure is the DialogProc
  162.             registered for all dialogs created with the CVirDialog class.
  163.             It uses the parameter passed with the WM_INITDIALOG message
  164.             to identify the dialog classes' "this" pointer which it then
  165.             stores in the window structure's GWL_USERDATA field.
  166.             All subsequent messages can then be forwarded on to the
  167.             correct dialog class's DialogProc method by using the pointer
  168.             stored in the GWL_USERDATA field.
  169.  
  170.   Args:     HWND hWndDlg,
  171.               Handle of dialog box.
  172.             UINT uMsg,
  173.               Message
  174.             WPARAM wParam,
  175.               First message parameter (word sized).
  176.             LPARAM lParam);
  177.               Second message parameter (long sized).
  178.  
  179.   Returns:  BOOL.  Return of the CVirDialog::DialogProc method.
  180. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  181. BOOL CALLBACK DialogProc(
  182.                 HWND hWndDlg,
  183.                 UINT uMsg,
  184.                 WPARAM wParam,
  185.                 LPARAM lParam);
  186.  
  187.  
  188. #ifdef __cplusplus
  189. }
  190.  
  191.  
  192. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  193.   Class:    CVirWindow
  194.  
  195.   Summary:  Abstract base class for wrapping a window.
  196.  
  197.             This class allows a window to be cleanly wrapped in a
  198.             c++ class.  Specifically, it provides a way for a c++ class
  199.             to use one of its methods as a WindowProc, giving it a "this"
  200.             pointer and allowing it to have direct access to all of its
  201.             private members.
  202.  
  203.   Methods:  Create:
  204.               Maps to Windows' CreateWindow function.
  205.             WindowProc:
  206.               Pure virtual WindowProc for the window.
  207.             Gethwnd:
  208.               Get the handle to the window.
  209.             CVirWindow:
  210.               Constructor.
  211.             ~CVirWindow:
  212.               Destructor.
  213. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  214. class CVirWindow
  215. {
  216. public:
  217.   // Constructor
  218.   CVirWindow()
  219.   {
  220.     m_hWnd = NULL;
  221.     m_hInst = NULL;
  222.   };
  223.  
  224.   // Destructor
  225.   virtual ~CVirWindow(){};
  226.  
  227.   // Envelopes the Windows' CreateWindow function call.
  228.   HWND Create(
  229.          LPTSTR lpszClassName,   // Address of registered class name
  230.          LPTSTR lpszWindowName,  // Address of window name
  231.          DWORD dwStyle,          // Window style
  232.          int x,                  // Horizontal position of window
  233.          int y,                  // Vertical position of window
  234.          int nWidth,             // Window width
  235.          int nHeight,            // Window height
  236.          HWND hWndParent,        // Handle of parent or owner window
  237.          HMENU hmenu,            // Handle of menu, or child window identifier
  238.          HINSTANCE hinst);       // Handle of application instance
  239.  
  240.   // Get the protected handle of this window.
  241.   HWND GetHwnd(void)
  242.   {
  243.     return(m_hWnd);
  244.   }
  245.  
  246.   // WindowProc is a pure virtual member function and MUST be over-ridden
  247.   // in any derived classes.
  248.   virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
  249.  
  250. protected:
  251.   // Instance handle for this window.
  252.   HINSTANCE m_hInst;
  253.   // Handle of this window.
  254.   HWND m_hWnd;
  255.  
  256.   // Tell the compiler that the outside WindowProc callback is a friend
  257.   // of this class and can get at its protected data members.
  258.   friend LRESULT CALLBACK ::WindowProc(
  259.                               HWND hWnd,
  260.                               UINT uMsg,
  261.                               WPARAM wParam,
  262.                               LPARAM lParam);
  263. };
  264.  
  265.  
  266. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  267.   Class:    CVirDialog
  268.  
  269.   Summary:  Abstract base class for wrapping a Windows dialog box window.
  270.  
  271.             This class allows a dialog box to be cleanly wrapped in
  272.             a c++ class.  Specifically, it provides a way for a c++ class
  273.             to use one of its methods as a DialogProc, giving it a "this"
  274.             pointer and allowing it to have direct access to all of its
  275.             private members.
  276.  
  277.   Methods:  ShowDialog:
  278.               Maps to Windows' DialogBox function.
  279.             GetHwnd:
  280.               Get the handle to the dialog window.
  281.             DialogProc:
  282.               Pure virtual DialogProc for the dialog box
  283.             ~CVirDialog:
  284.               Destructor
  285. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  286. class CVirDialog
  287. {
  288. public:
  289.   // Destructor
  290.   virtual ~CVirDialog(){};
  291.  
  292.   // ShowDialog creates the Dialog (using the DialogBoxParam API).
  293.   virtual int ShowDialog(
  294.                 HINSTANCE hInst,
  295.                 LPTSTR lpszTemplate,
  296.                 HWND hWndOwner);
  297.  
  298.   // DialogProc is a pure virtual member function and MUST be over-ridden
  299.   // in any derived classes.
  300.   virtual BOOL DialogProc(
  301.                  HWND hWndDlg,
  302.                  UINT uMsg,
  303.                  WPARAM wParam,
  304.                  LPARAM lParam) = 0;
  305.  
  306. protected:
  307.   HINSTANCE m_hInst;
  308.   HWND m_hWnd;
  309.  
  310.   // Tell the compiler that the outside DialogProc callback is a friend
  311.   // of this class and can get at its protected data members.
  312.   friend BOOL CALLBACK ::DialogProc(
  313.                            HWND hWndDlg,
  314.                            UINT uMsg,
  315.                            WPARAM wParam,
  316.                            LPARAM lParam);
  317. };
  318.  
  319.  
  320. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  321.   Class:    CAboutBox
  322.  
  323.   Summary:  A class that implements a common About Dialog Box
  324.             functionality for the APPUTIL library.
  325.  
  326.   Methods:  DialogProc
  327.               Dialog procedure
  328. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  329. class CAboutBox: public CVirDialog
  330. {
  331. public:
  332.   // This DialogProc method definition overrides the same-named pure
  333.   // virtual function in abstract base class CVirDialog thus giving
  334.   // AboutBox-unique message dispatching behavior to this derivation
  335.   // of CVirDialog.  The remaining behavior of CAboutBox is inherited
  336.   // from CVirDialog and is common to all CVirDialogs.
  337.   BOOL DialogProc(
  338.          HWND hWndDlg,
  339.          UINT uMsg,
  340.          WPARAM wParam,
  341.          LPARAM lParam);
  342. };
  343.  
  344.  
  345. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  346.   Class:    CDelayBox
  347.  
  348.   Summary:  A class that implements a common Dialog Box functionality for
  349.             the APPUTIL library. This dialog box has no buttons and and
  350.             appears on screen for 8 seconds.
  351.  
  352.   Methods:  DialogProc
  353.               Dialog procedure
  354. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  355. class CDelayBox: public CVirDialog
  356. {
  357. public:
  358.   // This DialogProc method definition overrides the same-named pure
  359.   // virtual function in abstract base class CVirDialog thus giving
  360.   // AboutBox-unique message dispatching behavior to this derivation
  361.   // of CVirDialog.  The remaining behavior of CAboutBox is inherited
  362.   // from CVirDialog and is common to all CVirDialogs.
  363.   BOOL DialogProc(
  364.          HWND hWndDlg,
  365.          UINT uMsg,
  366.          WPARAM wParam,
  367.          LPARAM lParam);
  368. };
  369.  
  370.  
  371. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  372.   Function: DelayBox
  373.  
  374.   Summary:  Uses the specified dialog template from the caller's resources
  375.             and shows a buttonless dialog message box that remains on
  376.             screen for about 5 seconds.
  377.  
  378.   Args:     HINSTANCE hInst,
  379.               Handle of the module instance.  Needed to specify the
  380.               module instance for fetching the dialog template resource
  381.               (ie, from either a host EXE or DLL).
  382.             LPTSTR pszTemplate,
  383.               Identifies the dialog box template.
  384.             HWND hwndOwner)
  385.               Handle of the owner window. NULL for desktop.
  386.  
  387.   Returns:  void
  388. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  389. void DelayBox(
  390.       HINSTANCE hInst,
  391.       LPTSTR pszTemplate,
  392.       HWND hWndOwner);
  393.  
  394.  
  395. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  396.   Class:    CMsgBox
  397.  
  398.   Summary:  Class for showing messages in a Message Box dialog.  Uses the
  399.             standard Windows MessageBox function but retrieves the box
  400.             title and message strings from the application's resources
  401.             using specified resource IDs.  These message boxes have only
  402.             an OK button.
  403.  
  404.   Methods:  Init
  405.               Initializes the owner window and the module instance.
  406.             Error
  407.               Shows a message string in an Error MessageBox Dialog.
  408.             ErrorID
  409.               Shows a resource message string in an Error MessageBox Dialog.
  410.             Note
  411.               Shows a message string in a Notice MessageBox Dialog.
  412.             NoteID
  413.               Shows a resource message string in a Notice MessageBox Dialog.
  414.             NoteFmt
  415.               Shows a printf-style formatted message string in a Notice
  416.               MessageBox Dialog.
  417.             NoteFmtID
  418.               Shows a printf-style formatted resource message string in a
  419.               Notice MessageBox Dialog.
  420. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  421. class CMsgBox
  422. {
  423. public:
  424.   // Constructor.
  425.   CMsgBox()
  426.   {
  427.     m_hInst = 0;
  428.     m_hWndOwner = 0;
  429.   };
  430.  
  431.   BOOL Init(HINSTANCE hInst, HWND hWndOwner);
  432.   int  Error(LPTSTR szMsg);
  433.   int  ErrorID(UINT uMsgID);
  434.   int  Note(LPTSTR szMsg);
  435.   int  NoteID(UINT uMsgID);
  436.   int  NoteFmt(LPTSTR szFmtMsg, ...);
  437.   int  NoteFmtID(UINT uMsgID, ...);
  438.  
  439. private:
  440.   // Remember the App Instance Handle.
  441.   HINSTANCE m_hInst;
  442.   // Remember the Owner Window Handle.
  443.   HWND m_hWndOwner;
  444. };
  445.  
  446.  
  447. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  448.   Class:    CMsgLog
  449.  
  450.   Summary:  Class for logging messages to a Listbox.  This is for tutorial
  451.             code samples that employ debug messages to announce internal
  452.             activity in the code being studied.  When used, this Message
  453.             Log listbox occupies the entire client area of the parent
  454.             window.  The various message output functions use string
  455.             resource IDs to retrieve the message strings from the app's
  456.             resources.
  457.  
  458.   Methods:  Create
  459.               Creates the Trace Message Log ListBox window.
  460.             Logging
  461.               Toggles logging on or off.
  462.             Msg
  463.               Logs a message as a separate line.
  464.             MsgFmt
  465.               Logs a printf-style formated message as a separate line.
  466.             Resize
  467.               Resizes the listbox to a new width and height.
  468.             Clear
  469.               Clears all logged messages from the message log.
  470.             CMsgLog
  471.               Constructor.
  472.             ~CMsgLog
  473.               Destructor.
  474. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  475. class CMsgLog
  476. {
  477. public:
  478.   // Constructor.
  479.   CMsgLog()
  480.   {
  481.     m_hInstLog = 0;
  482.     m_hWndLog = 0;
  483.     m_bChild = FALSE;
  484.     m_bLogging = FALSE;
  485.     m_hLogData = 0;
  486.   };
  487.  
  488.   BOOL Create(HINSTANCE hInst, HWND hWndParent, BOOL bChild);
  489.   BOOL Logging(BOOL bLogging);
  490.   BOOL Msg(LPTSTR szMsg);
  491.   BOOL MsgFmt(LPTSTR szFmtMsg, ...);
  492.   BOOL MsgID(int iMsgID);
  493.   BOOL MsgFmtID(int iFmtID, ...);
  494.   BOOL Resize(int nWidth, int nHeight);
  495.   BOOL Clear(void);
  496.   BOOL Copy(void);
  497.  
  498. private:
  499.   // Remember the App Instance Handle.
  500.   HWND m_hInstLog;
  501.   // Remember the handle of the listbox window.
  502.   HWND m_hWndLog;
  503.   // Remember if CMsgLog was created as child window.
  504.   BOOL m_bChild;
  505.   // Remember whether logging or not.
  506.   BOOL m_bLogging;
  507.   // Remember the global handle to clipboard data.
  508.   HGLOBAL m_hLogData;
  509. };
  510.  
  511.  
  512. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  513.   Class:    CSendLog
  514.  
  515.   Summary:  Class for logging messages to a CMsgLog facility in another
  516.             application process. This is for tutorial code samples that
  517.             employ debug messages to announce internal activity in the
  518.             code being studied.  Uses the WM_COPYDATA message of the
  519.             Win32 SendMessage API.
  520.  
  521.   Methods:  CreateServerLog
  522.               Initializes the SendLog facility and creates the Trace
  523.               Message Log ListBox window shown in the local server app.
  524.             SetClient
  525.               Sets destination client window handle.
  526.             LogToServer
  527.               Set whether logging is to local server or to client.
  528.             Msg
  529.               Logs a message as a separate line.
  530.             MsgFmt
  531.               Logs a printf-style formated message as a separate line.
  532.             Resize
  533.               Resizes the listbox to a new width and height.
  534.             Clear
  535.               Clears all logged messages from the message log.
  536.             CSendLog
  537.               Constructor.
  538.             ~CSendLog
  539.               Destructor.
  540. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  541. class CSendLog
  542. {
  543. public:
  544.   // Constructor.
  545.   CSendLog()
  546.   {
  547.     m_hInstSender = 0;
  548.     m_hWndSender = 0;
  549.     m_hWndReceiver = 0;
  550.     m_hWndListBox = 0;
  551.     m_bLogToServer = FALSE;
  552.     m_bChild = FALSE;
  553.     m_hLogData = 0;
  554.   };
  555.  
  556.   BOOL CreateServerLog(HINSTANCE hInst, HWND hWndParent, BOOL bChild);
  557.   BOOL SetClient(HINSTANCE hInstSender, HWND hWndSender, HWND hWndReceiver);
  558.   BOOL LogToServer(BOOL bLogToServer);
  559.   BOOL Msg(LPTSTR szMsg);
  560.   BOOL MsgFmt(LPTSTR szFmtMsg, ...);
  561.   BOOL MsgID(int iMsgID);
  562.   BOOL MsgFmtID(int iFmtID, ...);
  563.   BOOL Resize(int nWidth, int nHeight);
  564.   BOOL Clear(void);
  565.   BOOL Copy(void);
  566.  
  567. private:
  568.   // Remember the Sender App Instance Handle.
  569.   HWND m_hInstSender;
  570.   // Remember the handle of the sending application main window.
  571.   HWND m_hWndSender;
  572.   // Remember the handle of the destination receiving window.
  573.   HWND m_hWndReceiver;
  574.   // Remember the handle of the server's listbox window.
  575.   HWND m_hWndListBox;
  576.   // Boolean for logging to client or logging to server.
  577.   BOOL m_bLogToServer;
  578.   // Remember if CMsgLog was created as child window.
  579.   BOOL m_bChild;
  580.   // Remember the global handle to clipboard data.
  581.   HGLOBAL m_hLogData;
  582. };
  583.  
  584.  
  585. /*C+C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C+++C
  586.   Class:    CThreaded
  587.  
  588.   Summary:  Derive a class from this class to provide multi-threaded
  589.             access to objects of the derived class. This is a utility
  590.             base class providing useful methods for achieving mutually
  591.             exclusive access to data in objects of the derived class.
  592.  
  593.   Methods:  OwnThis
  594.               Blocks executing thread until access to this object is
  595.               permitted at which point the thread "owns" this object.
  596.             UnOwnThis
  597.               Executed by owning thread to relinquish ownership of
  598.               this object.
  599.             CThreaded
  600.               Constructor. Creates mutex to govern mutually exclusive
  601.               access to data in this object by multiple threads.
  602.             ~CThreaded
  603.               Destructor. Destroys mutex.
  604. C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C---C-C*/
  605. class CThreaded
  606. {
  607.   protected:
  608.     // Variables for providing mutually exclusive access by multiple
  609.     // threads to objects of classes derived from this class.
  610.     HANDLE m_hOwnerMutex;
  611.     BOOL   m_bOwned;
  612.  
  613.   public:
  614.     // Methods.
  615.     CThreaded(void) :
  616.       m_hOwnerMutex(CreateMutex(0,FALSE,0)),
  617.       m_bOwned(FALSE)
  618.     {
  619.     };
  620.  
  621.     ~CThreaded(void)
  622.     {
  623.       // Close down the mutex.
  624.       CloseHandle(m_hOwnerMutex);
  625.     };
  626.  
  627.     // The following virtual functions have overriding definitions in
  628.     // the derived class to provide convenient trace logging. Rely on
  629.     // the below default definitions for non-tutorial applications.
  630.  
  631.     virtual BOOL OwnThis(void)
  632.     {
  633.       BOOL bOwned = FALSE;
  634.  
  635.       if (WAIT_OBJECT_0 == WaitForSingleObject(m_hOwnerMutex, INFINITE))
  636.         m_bOwned = bOwned = TRUE;
  637.  
  638.       return bOwned;
  639.     };
  640.  
  641.     virtual void UnOwnThis(void)
  642.     {
  643.       if (m_bOwned)
  644.       {
  645.         m_bOwned = FALSE;
  646.         ReleaseMutex(m_hOwnerMutex);
  647.       }
  648.  
  649.       return;
  650.     };
  651. };
  652.  
  653.  
  654. #endif //__cplusplus
  655.  
  656.  
  657. #if !defined(UNICODE)
  658.  
  659. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  660.   Function: UcToAnsi
  661.  
  662.   Summary:  Convert an UNICODE input string to an output ANSI string for
  663.             specified number of characters.
  664.  
  665.   Args:     LPWSTR pszUnicodeString
  666.               Pointer to an input wide UNICODE string.
  667.             LPSTR pszAnsiString
  668.               Pointer to output ANSI string.
  669.             int cch
  670.               Character count. If cch == 0 then all input characters are
  671.               converted.
  672.  
  673.   Returns:  HRESULT
  674. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  675. HRESULT UcToAnsi(
  676.           LPWSTR pszUc,
  677.           LPSTR pszAnsi,
  678.           int cch);
  679.  
  680.  
  681. /*---------------------------------------------------------------------------
  682.   Here are some surrogate API macro prototypes--all names begin with A_.
  683.   These are for use when the code sample is being compiled for ANSI
  684.   strings (the default) and the calls they stand in place of only support
  685.   UNICODE (thus forcing some string conversions from ANSI to UNICODE
  686.   before the real call is made inside the surrogate). For example, if
  687.   UNICODE is NOT defined during the compile then any calls in the samples
  688.   to the StringFromGUID2 function are actually changed (by the below
  689.   macros) into calls to an A_StringFromGUID2 function implemented in
  690.   APPUTIL. This function accepts the ANSI input string pointer, calls the
  691.   actual StringFromGUID2 call, and does the necessary Unicode to ANSI
  692.   conversion. Other A_ calls will convert input ANSI strings to Unicode
  693.   strings prior to calling the actual COM/OLE function.
  694. ---------------------------------------------------------------------------*/
  695.  
  696. STDAPI A_StringFromGUID2(REFGUID, LPSTR, int);
  697.  
  698. STDAPI A_WriteFmtUserTypeStg(IStorage*, CLIPFORMAT, LPSTR);
  699.  
  700. STDAPI A_StgIsStorageFile(LPSTR);
  701. STDAPI A_StgCreateDocfile(LPSTR, DWORD, DWORD, IStorage**);
  702. STDAPI A_StgOpenStorage(LPSTR, IStorage*, DWORD, SNB, DWORD, IStorage**);
  703.  
  704. STDAPI A_HlinkNavigateString(IUnknown*, LPSTR);
  705.  
  706. #if !defined(_NOANSIMACROS_)
  707.  
  708. #undef StringFromGUID2
  709. #define StringFromGUID2(a, b, c) A_StringFromGUID2(a, b, c)
  710.  
  711. #undef WriteFmtUserTypeStg
  712. #define WriteFmtUserTypeStg(a, b, c) A_WriteFmtUserTypeStg(a, b, c)
  713.  
  714. #undef StgIsStorageFile
  715. #define StgIsStorageFile(a) A_StgIsStorageFile(a)
  716.  
  717. #undef StgCreateDocfile
  718. #define StgCreateDocfile(a, b, c, d) A_StgCreateDocfile(a, b, c, d)
  719.  
  720. #undef StgOpenStorage
  721. #define StgOpenStorage(a, b, c, d, e, f) A_StgOpenStorage(a, b, c, d, e, f)
  722.  
  723. #undef HlinkNavigateString
  724. #define HlinkNavigateString(a, b) A_HlinkNavigateString(a, b)
  725.  
  726. #endif
  727.  
  728. #endif
  729.  
  730.  
  731. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  732.   Function: lRandom
  733.  
  734.   Summary:  Simple random number generator. Returns a random DWORD.
  735.  
  736.   Args:     void
  737.  
  738.   Returns:  DWORD
  739.               Random number.
  740. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  741. DWORD lRandom(void);
  742.  
  743.  
  744. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  745.   Function: CreateColorScalePalette
  746.  
  747.   Summary:  This routine creates a palette representing the scale values
  748.             of a particular RGB color.  A gray-scale palette can also be
  749.             created.
  750.  
  751.   Args:     HDC hDC,
  752.               Handle to device context.
  753.             int nColor
  754.               New color.
  755.  
  756.   Returns:  HPALETTE
  757.               Handle to new pallete.
  758. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  759. HPALETTE CreateColorScalePalette(HWND hDC, int nColor);
  760.  
  761.  
  762. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  763.   Function: PaintWindow
  764.  
  765.   Summary:  This routine is used to wash the background of a window.
  766.  
  767.   Args:     HWND hWnd,
  768.               Window handle.
  769.             int nColor
  770.               New window color.
  771.  
  772.   Returns:  void.
  773. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  774. VOID PaintWindow(HWND hWnd, int nColor);
  775.  
  776.  
  777. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  778.   Function: SkipAnsi
  779.  
  780.   Summary:  Utility function to scan an input ANSI string and either skips
  781.             white characters or skips non-white characters.
  782.  
  783.   Args;     LPSTR psz,
  784.               Input ANSI string to be scanned.
  785.             BOOL bSkip)
  786.               Input boolean determining whether to skip white space
  787.               or not.  TRUE means skip white space; FALSE means skip
  788.               non-white chars.
  789.  
  790.   Returns:  LPSTR
  791.               String pointer after the skip (ANSI)
  792. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  793. LPSTR SkipAnsi(
  794.          LPSTR psz,
  795.          BOOL bSkipWhite);
  796.  
  797.  
  798. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  799.   Function: FileExist
  800.  
  801.   Summary:  Function to test for the existance of a file.
  802.  
  803.   Args:     TCHAR* szFileName
  804.               String pointer to file's path/name.
  805.  
  806.   Returns:  BOOL.  TRUE if file exists; FALSE if not.
  807. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  808. BOOL FileExist(TCHAR *szFileName);
  809.  
  810.  
  811. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  812.   Function: MakeFamilyPath
  813.  
  814.   Summary:  Function to make a family file/path/name string using the
  815.             detetected pathname of the current executable module.
  816.  
  817.   Args:     HINSTANCE hInst
  818.               Handle to the module intstance.
  819.             TCHAR* pszNewPath
  820.               String pointer to the new path/name.
  821.             TCHAR* pszFileExt
  822.               String pointer to the filename extension for the new path.
  823.  
  824.   Returns:  BOOL.  TRUE if success; FALSE if not.
  825. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  826. BOOL MakeFamilyPath(
  827.        HINSTANCE hInst,
  828.        TCHAR* pszNewPath,
  829.        TCHAR* pszFileExt);
  830.  
  831.  
  832. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  833.   Function: CmdExec
  834.  
  835.   Summary:  Execute an EXE Win32 program by creating a process and
  836.             running the specified EXE in it.  A Unicode version of
  837.             WinExec that always has SW_SHOW.
  838.  
  839.   Args:     LPTSTR szCmd,
  840.               Entire command line (eg, "notepad.exe mytext.txt")
  841.  
  842.   Returns:  BOOL
  843.               TRUE if succeed; FALSE if fail.
  844. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  845. BOOL CmdExec(
  846.        LPTSTR szCmd);
  847.  
  848.  
  849. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  850.   Function: HrMsg
  851.  
  852.   Summary:  HRESULT Error Message box. Takes standard result code,
  853.             looks it up in the system tables, and shows a message
  854.             box with the error code (in hex) and the associated
  855.             system message.
  856.  
  857.   Args:     HWND hWndOwner,
  858.               Handle to owner parent window.
  859.             LPTSTR pszFunction,
  860.               User message string for designating the attempted function.
  861.             HRESULT hr
  862.               Standard return code.
  863.  
  864.   Returns:  void
  865. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  866. void HrMsg(
  867.        HWND hWndOwner,
  868.        LPTSTR pszFunction,
  869.        HRESULT hr);
  870.  
  871.  
  872. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  873.   Function: ReadTutorial
  874.  
  875.   Summary:  The ReadTutorial function is for use by tutorial code sample
  876.             applications that study themselves. This function uses simple
  877.             Hyperlinking to launch the web browser to read an HTML web
  878.             page that contains a tutorial covering the sample. If no HTM
  879.             file (in a sibling or parent directory) is specified, this
  880.             function assumes a family-named <sample>.HTM tutorial HTML
  881.             file that is located next to the main .EXE file of the
  882.             application calling ReadTutorial. "Family-named" means that if
  883.             the EXE program calling this function is MYAPP.EXE then the
  884.             associated family-named HTML file is constructed as MYAPP.HTM.
  885.  
  886.   Args:     HINSTANCE hInst,
  887.               Handle of the executable module instance.
  888.             HWND hWndOwner,
  889.               Handle to owner parent window.
  890.             LPTSTR pszHTMLFile,
  891.               Pointer to an optional HTML FileName string. If this pointer
  892.               is NULL, then the family-named file is assumed for the HTML
  893.               file and is assumed to be located next to the main .EXE file
  894.               of the program executing this function. Non-NULL values are
  895.               of the form "MySiblingDirectory\MyHTMLFile.HTM" or of the
  896.               form "MyHTMLFileInTheParentDirectory.HTM". Special non-NULL
  897.               values beginning with '.' (eg. ".HTM" or ".ASP") specify
  898.               that the family-named file is assumed to be located in the
  899.               parent directory. In this case, the specified file extension
  900.               is used.
  901.  
  902.   Returns:  void
  903. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  904. void ReadTutorial(
  905.        HINSTANCE hInst,
  906.        HWND hWndOwner,
  907.        LPTSTR pszHTMLFile);
  908.  
  909.  
  910. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  911.   Function: RunTutorial
  912.  
  913.   Summary:  The RunTutorial function is for use by tutorial code sample
  914.             applications that study themselves. This function runs the
  915.             TUTORIAL.EXE application in the main tutorial directory which
  916.             in turn runs the web browser to read an HTML web page that
  917.             contains a tutorial covering the sample. If no HTM file (in a
  918.             sibling or parent directory) is specified, this function
  919.             assumes a family-named <sample>.HTM tutorial HTML file that is
  920.             located next to the .EXE file calling RunTutorial.
  921.             "Family-named" means that if the EXE program calling this
  922.             function is MYAPP.EXE then the associated family-named HTML
  923.             file is constructed as MYAPP.HTM.
  924.  
  925.   Args:     HINSTANCE hInst,
  926.               Handle of the executable module instance.
  927.             HWND hWndOwner,
  928.               Handle to owner parent window.
  929.             LPTSTR pszHTMLFile,
  930.               Pointer to an optional HTML FileName string. If this pointer
  931.               is NULL, then the family-named file is assumed for the HTML
  932.               file and is assumed to be located next to the main .EXE file
  933.               of the program executing this function. Non-NULL values are
  934.               of the form "MySiblingDirectory\MyHTMLFile.HTM" or of the
  935.               form "MyHTMLFileInTheParentDirectory.HTM". Special non-NULL
  936.               values beginning with '.' (eg. ".HTM" or ".ASP") specify
  937.               that the family-named file is assumed to be located in the
  938.               parent directory. In this case, the specified file extension
  939.               is used.
  940.  
  941.   Returns:  void
  942. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  943. void RunTutorial(
  944.        HINSTANCE hInst,
  945.        HWND hWndOwner,
  946.        LPTSTR pszHTMLFile);
  947.  
  948.  
  949. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  950.   Function: GoWeb
  951.  
  952.   Summary:  General utility function to launch a web browser on a
  953.             specified HTML file via either a URL or a full file path/name.
  954.  
  955.   Args:     HINSTANCE hInst,
  956.               Handle of the executable module instance.
  957.             LPSTR pszTarget
  958.               Pointer to the Target specification string (must be ANSI).
  959.               If null then call the ReadTutorial function. If pszTarget
  960.               starts with '//' then the target is assumed to be a www URL
  961.               trailer of the form: //www.microsoft.com. If any other
  962.               string, then it is assumed to be a full path/file name.
  963.  
  964.   Returns:  void
  965. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  966. void GoWeb(
  967.        HINSTANCE hInst,
  968.        LPSTR pszTarget);
  969.  
  970.  
  971. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  972.   Function: ReadSource
  973.  
  974.   Summary:  For use by code sample applications that study themselves
  975.             as it were.  This function allows you to select one of the
  976.             source files of this code sample and launch a reader to
  977.             edit/read it.  NOTEPAD.EXE is the default editor/reader.
  978.             You can change this by changing EDITOR_FILE_STR in
  979.             APPUTIL.H above.
  980.  
  981.   Args:     HWND hWndOwner
  982.               Handle of parent window.
  983.             OPENFILENAME* pofn,
  984.               Pointer to the Open File Name Common Dialog structure.
  985.  
  986.   Returns:  void
  987. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  988. void ReadSource(
  989.        HWND hWndOwner,
  990.        OPENFILENAME* pOfn);
  991.  
  992.  
  993. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  994.   Function: OutputDebugFmt
  995.  
  996.   Summary:  Wraps the Win32 OutputDebugString API call to provide
  997.             printf-style formatted (and variable argument) output.
  998.  
  999.   Args:     LPTSTR szFmt,
  1000.               Format string.
  1001.             [...]
  1002.               Arguments to match those specified in the format string.
  1003.  
  1004.   Returns:  void
  1005. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  1006. void OutputDebugFmt(
  1007.        LPTSTR szFmt,
  1008.        ...);
  1009.  
  1010.  
  1011. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  1012.   Function: GetErrorMsg
  1013.  
  1014.   Summary:  Accepts a Win32 error code and retrieves a human readable
  1015.             system message for it.
  1016.  
  1017.   Args:     HRESULT hr
  1018.               SCODE error code.
  1019.             LPTSTR pszMsg
  1020.               Pointer string where message will be placed.
  1021.             UINT uiSize
  1022.               Max size of the msg string.
  1023.  
  1024.   Returns:  BOOL
  1025.               TRUE if hr was error; FALSE if not.
  1026. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  1027. BOOL GetErrorMsg(
  1028.        HRESULT hr,
  1029.        LPTSTR pszMsg,
  1030.        UINT uiSize);
  1031.  
  1032.  
  1033. #define TID GetCurrentThreadId()
  1034.  
  1035. #if defined(DEBUG)
  1036.  
  1037. //Basic debug and logging macros
  1038.  
  1039. // Output debug string; literal or variable.
  1040. #define ODS(sMsg) \
  1041. {\
  1042.   TCHAR szDebug[MAXLOGST];\
  1043.   OutputDebugFmt(TEXT("%s"),TEXT(sMsg));\
  1044.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1045.   OutputDebugString(szDebug);\
  1046. }
  1047.  
  1048. // Output debug string formatted; one argument.
  1049. #define ODF1(sFmt,x) \
  1050. {\
  1051.   TCHAR szDebug[MAXLOGST];\
  1052.   OutputDebugFmt(TEXT(sFmt),x);\
  1053.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1054.   OutputDebugString(szDebug);\
  1055. }
  1056.  
  1057. // Output debug string formatted; two argument.
  1058. #define ODF2(sFmt,x,y) \
  1059. {\
  1060.   TCHAR szDebug[MAXLOGST];\
  1061.   OutputDebugFmt(TEXT(sFmt),x,y);\
  1062.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1063.   OutputDebugString(szDebug);\
  1064. }
  1065.  
  1066. // Output debug string formatted; three argument.
  1067. #define ODF3(sFmt,x,y,z) \
  1068. {\
  1069.   TCHAR szDebug[MAXLOGST];\
  1070.   OutputDebugFmt(TEXT(sFmt),x,y,z);\
  1071.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1072.   OutputDebugString(szDebug);\
  1073. }
  1074.  
  1075. // Check condition and Output assertion failed message to debugger.
  1076. #define ASSERT(condition) \
  1077. {\
  1078.   if (!(condition))\
  1079.     ODS(TEXT("Assertion Failed"));\
  1080. }
  1081.  
  1082. // Check standard HRESULT for error and put up message box if error.
  1083. // Two arguments. Pfx = Prefix msg string; Ec = error code.
  1084. // Eg: CKHR("MyFunction:",hr);
  1085. #define CKHR(Pfx,Ec) \
  1086. {\
  1087.   TCHAR szMsg[MAX_PATH];\
  1088.   if (GetErrorMsg(Ec,szMsg,MAX_PATH))\
  1089.   {\
  1090.     HrMsg(NULL,TEXT(Pfx),Ec);\
  1091.     wsprintf(szMsg, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1092.     OutputDebugString(szMsg);\
  1093.   }\
  1094. }
  1095.  
  1096. // Log debug string (output both to Message Log and to Debugger)
  1097. #define LOG(sMsg) \
  1098. {\
  1099.   TCHAR szDebug[MAXLOGST];\
  1100.   if (NULL!=g_pMsgLog)\
  1101.     g_pMsgLog->Msg(TEXT(sMsg));\
  1102.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1103.   OutputDebugString(szDebug);\
  1104. }
  1105.  
  1106. // Log debug string (output both to Message Log and to Debugger).
  1107. // One argument.
  1108. #define LOGF1(sFmt,x) \
  1109. {\
  1110.   TCHAR szDebug[MAXLOGST];\
  1111.   if (NULL!=g_pMsgLog)\
  1112.     g_pMsgLog->MsgFmt(TEXT(sFmt),x);\
  1113.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1114.   OutputDebugString(szDebug);\
  1115. }
  1116.  
  1117. // Log debug string (output both to Message Log and to Debugger).
  1118. // Two argument.
  1119. #define LOGF2(sFmt,x,y) \
  1120. {\
  1121.   TCHAR szDebug[MAXLOGST];\
  1122.   if (NULL!=g_pMsgLog)\
  1123.     g_pMsgLog->MsgFmt(TEXT(sFmt),x,y);\
  1124.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1125.   OutputDebugString(szDebug);\
  1126. }
  1127.  
  1128. // Log debug string (output both to Message Log and to Debugger).
  1129. // Three argument.
  1130. #define LOGF3(sFmt,x,y,z) \
  1131. {\
  1132.   TCHAR szDebug[MAXLOGST];\
  1133.   if (NULL!=g_pMsgLog)\
  1134.     g_pMsgLog->MsgFmt(TEXT(sFmt),x,y,z);\
  1135.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1136.   OutputDebugString(szDebug);\
  1137. }
  1138.  
  1139. // Log error message string (output both to Message Log and to Debugger).
  1140. // Two arguments. Pfx = Prefix msg string; Ec = error code.
  1141. // Eg: LOGERROR("MyFunction:",hr);
  1142. #define LOGERROR(Pfx,Ec) \
  1143. {\
  1144.   TCHAR szMsg[MAX_PATH];\
  1145.   if (NULL!=g_pMsgLog && GetErrorMsg(Ec,szMsg,MAX_PATH))\
  1146.   {\
  1147.     g_pMsgLog->MsgFmt(TEXT("%s Error=0x%X: %s"),TEXT(Pfx),Ec,szMsg);\
  1148.     wsprintf(szMsg, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1149.     OutputDebugString(szMsg);\
  1150.   }\
  1151. }
  1152.  
  1153. // Log debug string (output both to Message Log and to Debugger).
  1154. // Use a string resource ID to retrieve the display string.
  1155. #define LOGID(id) \
  1156. {\
  1157.   TCHAR szDebug[MAXLOGST];\
  1158.   if (NULL!=g_pMsgLog)\
  1159.     g_pMsgLog->MsgID(id);\
  1160.   wsprintf(szDebug, TEXT(" [%s, %u]\r\n"), (LPTSTR)__FILE__, __LINE__);\
  1161.   OutputDebugString(szDebug);\
  1162. }
  1163.  
  1164. // Log assertion failure.
  1165. #define LOGASSERT(condition) \
  1166. {\
  1167.   if (!(condition))\
  1168.     LOGID(IDS_ASSERT_FAIL);\
  1169. }
  1170.  
  1171. #else  // !defined(DEBUG)
  1172.  
  1173. #define ODS(x)
  1174.  
  1175. #define ODF1(sFmt,x)
  1176.  
  1177. #define ODF2(sFmt,x,y)
  1178.  
  1179. #define ODF3(sFmt,x,y,z)
  1180.  
  1181. #define ASSERT(condition)
  1182.  
  1183. #define CKHR(Pfx,Ec)
  1184.  
  1185. #define LOG(sMsg) \
  1186. {\
  1187.   if (NULL!=g_pMsgLog)\
  1188.     g_pMsgLog->Msg(TEXT(sMsg));\
  1189. }
  1190.  
  1191. // Log debug string (output both to Message Log and not to Debugger).
  1192. // One argument.
  1193. #define LOGF1(sFmt,x) \
  1194. {\
  1195.   if (NULL!=g_pMsgLog)\
  1196.     g_pMsgLog->MsgFmt(TEXT(sFmt),x);\
  1197. }
  1198.  
  1199. // Log debug string (output both to Message Log and not to Debugger).
  1200. // Two argument.
  1201. #define LOGF2(sFmt,x,y) \
  1202. {\
  1203.   if (NULL!=g_pMsgLog)\
  1204.     g_pMsgLog->MsgFmt(TEXT(sFmt),x,y);\
  1205. }
  1206.  
  1207. // Log debug string (output both to Message Log and not to Debugger).
  1208. // Three argument.
  1209. #define LOGF3(sFmt,x,y,z) \
  1210. {\
  1211.   if (NULL!=g_pMsgLog)\
  1212.     g_pMsgLog->MsgFmt(TEXT(sFmt),x,y,z);\
  1213. }
  1214.  
  1215. // Log error message string (output both to Message Log and not to Debugger).
  1216. // Two arguments. Pfx = Prefix msg string; Ec = error code.
  1217. // Eg: LOGERROR("MyFunction:",hr);
  1218. #define LOGERROR(Pfx,Ec) \
  1219. {\
  1220.   TCHAR szMsg[MAX_PATH];\
  1221.   if (NULL!=g_pMsgLog && GetErrorMsg(Ec,szMsg,MAX_PATH))\
  1222.     g_pMsgLog->MsgFmt(TEXT("%s Error=0x%X: %s"),TEXT(Pfx),Ec,szMsg);\
  1223. }
  1224.  
  1225. // Log debug string (output both to Message Log and not to Debugger).
  1226. // Use a string resource ID to retrieve the display string.
  1227. #define LOGID(id) \
  1228. {\
  1229.   if (NULL!=g_pMsgLog)\
  1230.     g_pMsgLog->MsgID(id);\
  1231. }
  1232.  
  1233. // Log assertion failure.
  1234. #define LOGASSERT(condition)\
  1235. {\
  1236.   if (!(condition))\
  1237.     LOGID(IDS_ASSERT_FAIL);\
  1238. }
  1239.  
  1240. #endif // DEBUG
  1241.  
  1242. #endif //APPUTIL_H
  1243.