home *** CD-ROM | disk | FTP | other *** search
- /*++
-
- Copyright (c) 1995 Intel Corp
-
- File Name:
-
- dt_dll.cpp
-
- Abstract:
-
- Contains main and supporting functions for a Debug/Trace
- DLL for the WinSock2 DLL. See the design spec
- for more information.
-
- --*/
-
- //
- // Include Files
- //
-
- #include "nowarn.h" /* turn off benign warnings */
- #ifndef _WINSOCKAPI_
- #define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
- #endif
-
- #include "nowarn.h" /* some warnings may have been turned back on */
- #include <winsock2.h>
- #include <stdarg.h>
- #include <ws2spi.h>
- #include <commdlg.h>
-
- #include "dt_dll.h"
- #include "cstack.h"
- #include "dt.h"
- #include "handlers.h"
-
- //
- // Forward References for Functions
- //
-
- LRESULT APIENTRY
- DTMainWndProc(
- IN HWND WindowHandle,
- IN UINT Message,
- IN WPARAM WParam,
- IN LPARAM LParam);
-
- LRESULT APIENTRY
- DTEditWndProc(
- IN HWND WindowHandle,
- IN UINT Message,
- IN WPARAM WParam,
- IN LPARAM LParam);
-
- BOOL WINAPI
- DllMain(
- HINSTANCE DllInstHandle,
- DWORD Reason,
- LPVOID Reserved);
-
- DWORD
- WindowThreadFunc(LPDWORD TheParam);
-
- BOOL APIENTRY
- DebugDlgProc(
- IN HWND hwndDlg,
- IN UINT message,
- IN WPARAM wParam,
- IN LPARAM lParam);
-
- BOOL
- GetFile(
- IN HWND OwnerWindow,
- OUT LPSTR Buffer,
- IN DWORD BufSize);
-
- void
- AbortAndClose(
- IN HANDLE FileHandle,
- IN HWND WindowHandle);
-
-
-
-
- //
- // Externally Visible Global Variables
- //
-
- HWND DebugWindow; // handle to the child edit control
- HANDLE LogFileHandle; // handle to the log file
- DWORD OutputStyle = WINDOW_ONLY; // where to put output
- char Buffer[TEXT_LEN]; // buffer for building output strings
-
-
-
- //
- // Static Global Variables
- //
-
- // name for my window class
- static char DTWndClass[] = "DTWindow";
-
- static HWND FrameWindow; // handle to frame of debug window
- static WNDPROC EditWndProc; // the edit control's window proc
- static HINSTANCE DllInstHandle; // handle to the dll instance
- static DWORD TlsIndex; // tls index for this module
- static CRITICAL_SECTION CrSec; // critical section for text output
- static HANDLE TextOutEvent; // set when debug window is ready
-
- static char LogFileName[256]; // name of the log file
-
- // handle to and id of the main thread of the DLL which initializes
- // and creates windows, etc
- static HANDLE WindowThread;
- static DWORD WindowThreadId;
-
- // function pointer tables for handler functions.
- static LPFNDTHANDLER HdlFuncTable[MAX_DTCODE + 1];
-
- // static strings
- static char ErrStr1[] = "Couldn't open file. Debug output will go to \
- debug window.";
- static char ErrStr2[] = "An error occurred while trying to get a log \
- filename. Debug output will go to the window only.";
- static char ErrStr3[] = "Had problems writing to file. Aborting file \
- ouput -- all debug output will now go to the debugging window";
-
-
-
-
- //
- // Function Definitions
- //
-
-
- BOOL WINAPI
- DllMain(
- HINSTANCE InstanceHandle,
- DWORD Reason,
- LPVOID Reserved)
- /*++
-
- DllMain()
-
- Function Description:
-
- Please see Windows documentation for DllEntryPoint.
-
- Arguments:
-
- Please see windows documentation.
-
- Return Value:
-
- Please see windows documentation.
-
- --*/
- {
-
- Cstack_c *ThreadCstack; // points to Cstack objects in tls
- PINITDATA InitDataPtr; // to pass to the window creation thread
-
- switch(Reason) {
-
- // Determine the reason for the call and act accordingly.
-
- case DLL_PROCESS_ATTACH:
-
- DllInstHandle = InstanceHandle;
- InitializeCriticalSection(&CrSec);
- TextOutEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- // Fill in the handler function table.
- DTHandlerInit(HdlFuncTable, MAX_DTCODE);
-
- // Allocate a TLS index.
- TlsIndex = TlsAlloc();
-
- // Pop up a dialog box for the user to choose output method.
- DialogBox(DllInstHandle,
- MAKEINTRESOURCE(IDD_DIALOG1),
- NULL,
- (DLGPROC)DebugDlgProc);
-
- if ((OutputStyle == FILE_ONLY) || (OutputStyle == FILE_AND_WINDOW)) {
-
- LogFileHandle = CreateFile(LogFileName,
- GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if (LogFileHandle == INVALID_HANDLE_VALUE) {
- OutputStyle = WINDOW_ONLY;
- MessageBox(NULL, ErrStr1, "Error", MB_OK | MB_ICONSTOP);
- }
- }
-
- // Get some information for later output to the debug window
- // or file -- get the time, PID, and TID of the calling
- // process and put into a INITDATA struct. This memory will
- // be freed by the thread it is passed to.
- InitDataPtr = (PINITDATA) LocalAlloc(0, sizeof(INITDATA));
- GetLocalTime(&(InitDataPtr->LocalTime));
- InitDataPtr->TID = GetCurrentThreadId();
- InitDataPtr->PID = GetCurrentProcessId();
-
- // Create the initialization/window handling thread.
- if ((OutputStyle == WINDOW_ONLY) || (OutputStyle == FILE_AND_WINDOW)) {
- WindowThread =
- CreateThread(NULL,
- 0,
- (LPTHREAD_START_ROUTINE)WindowThreadFunc,
- (LPVOID)InitDataPtr,
- 0,
- &WindowThreadId);
- } else {
-
- // Normally the window thread does a DTTextOut of the time
- // and process info that we saved just above. But in this
- // case, there is no window thread so spit it out to the
- // file.
-
- wsprintf(Buffer, "Log initiated: %d-%d-%d, %d:%d:%d\r\n",
- InitDataPtr->LocalTime.wMonth,
- InitDataPtr->LocalTime.wDay,
- InitDataPtr->LocalTime.wYear,
- InitDataPtr->LocalTime.wHour,
- InitDataPtr->LocalTime.wMinute,
- InitDataPtr->LocalTime.wSecond);
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
- wsprintf(Buffer, "Process ID: 0x%X Thread ID: 0x%X\r\n",
- InitDataPtr->PID,
- InitDataPtr->TID);
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
-
- // Setting this event allows {Pre|Post}ApiNotify to
- // proceed. This event isn't really needed in this case
- // (because there is only one thread, and we know the code
- // above has been executed before WSAPre|PostApiNotify).
- SetEvent(TextOutEvent);
- }
-
- // flow through...
-
- case DLL_THREAD_ATTACH:
-
- // Store a pointer to a new Cstack_c in the slot for this
- // thread.
- ThreadCstack = new Cstack_c();
- TlsSetValue(TlsIndex, (LPVOID)ThreadCstack);
-
- break;
-
- case DLL_PROCESS_DETACH:
-
- // Free up some resources. This is like cleaning up your room
- // before the tornado strikes, but hey, it's good practice.
- TlsFree(TlsIndex);
- DeleteCriticalSection(&CrSec);
-
- if ((OutputStyle == FILE_ONLY) || (OutputStyle == FILE_AND_WINDOW)) {
- CloseHandle(LogFileHandle);
- }
- CloseHandle(WindowThread);
-
- break;
-
- case DLL_THREAD_DETACH:
-
- // Get the pointer to this thread's Cstack, and delete the
- // object.
- ThreadCstack = (Cstack_c *)TlsGetValue(TlsIndex);
- delete ThreadCstack;
-
- break;
-
- default:
-
- break;
- } // switch (Reason)
-
- return TRUE;
- } // DllMain()
-
-
-
-
-
- BOOL WINAPIV
- WSAPreApiNotify(
- IN INT NotificationCode,
- OUT LPVOID ReturnCode,
- IN LPSTR LibraryName,
- ...)
- /*++
-
- Function Description:
-
- Builds a string for output and passes it, along with information
- about the call, to a handler function.
-
- Arguments:
-
- NotificationCode -- specifies which API function called us.
-
- ReturnCode -- a generic pointer to the return value of the API
- function. Can be used to change the return value in the
- case of a short-circuit (see how the return value from
- PreApiNotify works for more information on short-circuiting
- the API function).
-
- LibraryName -- a string pointing to the name of the library that
- called us.
-
- ... -- variable number argument list. These are pointers
- to the actual parameters of the API functions.
-
- Return Value:
-
- Returns TRUE if we want to short-circuit the API function;
- in other words, returning non-zero here forces the API function
- to return immediately before any other actions take place.
-
- Returns FALSE if we want to proceed with the API function.
-
- --*/
- {
- va_list vl; // used for variable arg-list parsing
- Cstack_c *ThreadCstack; // the Cstack_c object for this thread
- int Index = 0; // index into string we are creating
- BOOL ReturnValue; // value to return
- LPFNDTHANDLER HdlFunc; // pointer to handler function
- int Counter; // counter popped off the cstack
- int OriginalError; // any pending error is saved
- int HandlerError; // the error after handler returns
-
- EnterCriticalSection(&CrSec);
- OriginalError = GetLastError();
-
- // Wait until the debug window is ready to receive text for output.
- WaitForSingleObject(TextOutEvent, INFINITE);
- va_start(vl, LibraryName);
-
- // Get the Cstack_c object for this thread.
- ThreadCstack = (Cstack_c *)TlsGetValue(TlsIndex);
- if (!ThreadCstack){
- ThreadCstack = new Cstack_c();
- TlsSetValue(TlsIndex, (LPVOID)ThreadCstack);
- wsprintf(Buffer, "0x%X Foriegn thread\n",
- GetCurrentThreadId());
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
- } //if
-
- // Start building an output string with some info that's
- // independent of which API function called us.
- Index += wsprintf(Buffer, "TID: 0x%X ", GetCurrentThreadId());
- Index += wsprintf(Buffer + Index, "Function call: %d ",
- ThreadCstack->CGetCounter());
-
- // Push the counter & increment.
- ThreadCstack->CPush();
-
- // Reset the error to what it was when the function started.
- SetLastError(OriginalError);
-
- // Call the appropriate handling function, output the buffer.
- if ((NotificationCode < MAX_DTCODE) && HdlFuncTable[NotificationCode]) {
- HdlFunc = HdlFuncTable[NotificationCode];
- ReturnValue = (*HdlFunc)(vl, ReturnCode,
- LibraryName,
- Buffer,
- Index,
- TEXT_LEN,
- TRUE);
- HandlerError = GetLastError();
-
- } else {
-
- wsprintf(Buffer + Index, "Unknown function called!\r\n");
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
- ReturnValue = FALSE;
- }
-
- // If we are returning TRUE, then the API/SPI function will be
- // short-circuited. We must pop the thread stack, since no
- // corresponding WSAPostApiNotify will be called.
- if (ReturnValue) {
- ThreadCstack->CPop(Counter);
- }
-
- // In case the error has changed since the handler returned, we
- // want to set it back to that. So if the handler set the error,
- // the function exits with that value; if not, it exits with the
- // original error.
- SetLastError(HandlerError);
- LeaveCriticalSection(&CrSec);
- return(ReturnValue);
-
- } // WSAPreApiNotify()
-
-
-
-
-
-
- BOOL WINAPIV
- WSAPostApiNotify(
- IN INT NotificationCode,
- OUT LPVOID ReturnCode,
- IN LPSTR LibraryName,
- ...)
- /*++
-
- PostApiNotify()
-
- Function Description:
-
- Like PreApiNotify, builds a string and passes it, along with
- information about the call, to a handler function.
-
- Arguments:
-
- NotificationCode -- specifies which API function called us.
-
- ReturnCode -- a generic pointer to the return value of the API
- function.
-
- ... -- variable number argument list. These are pointers
- to the actual parameters of the API functions.
-
- Return Value:
-
- Returns value is currently meaningless.
-
- --*/
- {
- va_list vl; // used for variable arg-list parsing
- Cstack_c *ThreadCstack; // the Cstack_c object for this thread
- int Index = 0; // index into string we are creating
- int Counter; // counter we pop off the cstack
- LPFNDTHANDLER HdlFunc; // pointer to handler function
- int OriginalError; // any pending error is saved
- int HandlerError; // error after the handler returns
-
- // Lets hope EnterCriticalSection() doesn't change the error...
- EnterCriticalSection(&CrSec);
- OriginalError = GetLastError();
-
- // Wait until it's ok to send output.
- WaitForSingleObject(TextOutEvent, INFINITE);
-
- va_start(vl, LibraryName);
-
- // Get the cstack object from TLS, pop the Counter.
- ThreadCstack = (Cstack_c *) TlsGetValue(TlsIndex);
-
- if (!ThreadCstack){
- ThreadCstack = new Cstack_c();
- TlsSetValue(TlsIndex, (LPVOID)ThreadCstack);
- wsprintf(Buffer, "0x%X Foriegn thread\n",
- GetCurrentThreadId());
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
- } //if
-
- ThreadCstack->CPop(Counter);
-
- // Output some info that's independent of which API called us.
- Index += wsprintf(Buffer, "TID: 0x%X ", GetCurrentThreadId());
- Index += wsprintf(Buffer + Index, "Function Call: %d ", Counter);
-
- // Set the error to what it originally was.
- SetLastError(OriginalError);
-
- // Call the appropriate handling function, output the buffer.
- if ((NotificationCode < MAX_DTCODE) && HdlFuncTable[NotificationCode]) {
- HdlFunc = HdlFuncTable[NotificationCode];
- (*HdlFunc)(vl, ReturnCode,
- LibraryName,
- Buffer,
- Index,
- TEXT_LEN,
- FALSE);
- HandlerError = GetLastError();
-
- } else {
-
- wsprintf(Buffer + Index, "Unknown function returned!\r\n");
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
- }
-
- // In case the error has changed since the handler returned, we
- // want to set it back to that. So if the handler set the error,
- // the function exits with that value; if not, it exits with the
- // original error.
- SetLastError(HandlerError);
- LeaveCriticalSection(&CrSec);
- return(FALSE);
-
- } // WSAPostApiNotify()
-
-
-
-
-
- LRESULT APIENTRY
- DTMainWndProc(
- IN HWND WindowHandle,
- IN UINT Message,
- IN WPARAM WParam,
- IN LPARAM LParam)
- /*++
-
- DTMainWndProc()
-
- Function Description:
-
- Window procedure for the main window of the Dll. This function
- processes WM_CREATE messages in order to create a child
- edit control, which does most of the dirty work. Also processes
- WM_COMMAND to trap notification messages from the edit control,
- as well as WM_SIZE and WM_DESTROY messages.
-
- Arguments:
-
- WindowHandle -- the window.
-
- Message -- the message.
-
- WParam -- first parameter.
-
- LParam -- second parameter.
-
- Return Value:
-
- Message dependent.
-
- --*/
- {
-
- HFONT FixedFontHandle; // self-explanatory
- RECT Rect; // specifies client area of frame window
- DWORD CharIndex1;
- DWORD CharIndex2;
- DWORD LineIndex; // indices into edit control text
- char NullString[] = ""; // self-explanatory
- DWORD OldOutputStyle; // temporary storage for OutputStyle
-
- switch (Message) {
-
- case WM_CREATE:
-
- // Create the debug window as a multiline edit control.
- GetClientRect(WindowHandle, &Rect);
- DebugWindow = CreateWindow("EDIT",
- NULL,
- WS_CHILD | WS_VISIBLE |
- WS_VSCROLL | ES_LEFT |
- ES_MULTILINE | ES_AUTOVSCROLL,
- 0,
- 0,
- Rect.right,
- Rect.bottom,
- WindowHandle,
- (HMENU)EC_CHILD,
- DllInstHandle,
- NULL);
-
- // Subclass the edit control's window procedure to be
- // DTEditWndProc.
- EditWndProc = (WNDPROC) SetWindowLong(DebugWindow,
- GWL_WNDPROC,
- (DWORD)DTEditWndProc);
-
- // Set the edit control's text size to the maximum.
- SendMessage(DebugWindow, EM_LIMITTEXT, 0, 0);
-
- // Set the edit control's font
- FixedFontHandle = (HFONT)GetStockObject(ANSI_FIXED_FONT);
- SendMessage(DebugWindow, WM_SETFONT, (WPARAM)FixedFontHandle,
- MAKELPARAM(TRUE, 0));
-
- return(0);
-
- case WM_COMMAND:
-
- if (LOWORD(WParam) == EC_CHILD) {
-
- // The notification is coming from the edit-control child.
- // Determine which notification it is and act appropriately.
-
- switch (HIWORD(WParam)) {
-
- case EN_ERRSPACE:
-
- // Flow through
-
- case EN_MAXTEXT:
-
- // There's too much text in the edit control. This is
- // a hack to eliminate approximately the first half of
- // the text, so we can then add more...
- CharIndex1 = GetWindowTextLength(DebugWindow) / 2;
- LineIndex = SendMessage(DebugWindow, EM_LINEFROMCHAR,
- (WPARAM)CharIndex1, 0);
- CharIndex2 = SendMessage(DebugWindow, EM_LINEINDEX,
- (WPARAM)LineIndex, 0);
-
- SendMessage(DebugWindow, EM_SETSEL, 0, CharIndex2);
- SendMessage(DebugWindow, EM_REPLACESEL, 0,
- (LPARAM)NullString);
-
- // send this text to the window only...
- OldOutputStyle = OutputStyle;
- OutputStyle = WINDOW_ONLY;
- DTTextOut(DebugWindow, LogFileHandle,
- "----Buffer Overflow...Resetting----\r\n",
- OutputStyle);
- OutputStyle = OldOutputStyle;
- break;
-
- case EN_CHANGE:
- case EN_UPDATE:
-
- // Ignore these notification codes
- return 0;
- break;
-
- default:
-
- // Let the default window procedure handle it.
- return DefWindowProc(WindowHandle, Message, WParam,
- LParam);
- } // switch (HIWORD(WParam))
-
- } // if (LOWORD(WParam) == EC_CHILD)
- else {
-
- // The notification is coming from somewhere else!!!
- return DefWindowProc(WindowHandle, Message, WParam,
- LParam);
- }
-
- return(0);
- break;
-
- case WM_DESTROY:
-
- PostQuitMessage(0);
- return(0);
-
- case WM_SIZE:
-
-
- // Make the edit control the size of the window's client area.
- MoveWindow(DebugWindow, 0, 0, LOWORD(LParam), HIWORD(LParam), TRUE);
- return(0);
-
- default:
-
- // All other messages are taken care of by the default.
- return(DefWindowProc(WindowHandle, Message, WParam, LParam));
-
- } // switch
-
- } // DTMainWndProc()
-
-
-
-
-
- LRESULT APIENTRY
- DTEditWndProc(
- IN HWND WindowHandle,
- IN UINT Message,
- IN WPARAM WParam,
- IN LPARAM LParam)
- /*++
-
- DTEditWndProc()
-
- Function Description:
-
- Subclassed window procedure for the debug window. This function
- disables some edit control functionality, and also responds to a
- user-defined message to print out text in the window.
-
- Arguments:
-
- WindowHandle -- the window.
-
- Message -- the message.
-
- WParam -- first parameter.
-
- LParam -- second parameter.
-
- Return Value:
-
- Message dependent.
-
- --*/
- {
- switch (Message) {
-
- case WM_CHAR:
-
- // Handle control-c so that copy works. Sorry about the magic
- // number!
- if (WParam == 3) {
- return (CallWindowProc((WNDPROC)EditWndProc, WindowHandle, Message,
- WParam, LParam));
- } // else flows through
-
- case WM_KEYDOWN: // Flow through
- case WM_UNDO: // Flow through
- case WM_PASTE: // Flow through
- case WM_CUT:
-
- return (0); // Effectively disables the above messages
-
- default:
-
- return (CallWindowProc(EditWndProc, WindowHandle, Message,
- WParam, LParam));
- } // switch
-
- } // DTEditWndProc()
-
-
-
-
-
- DWORD
- WindowThreadFunc(
- LPDWORD TheParam)
- /*++
-
- WindowThreadFunc()
-
- Function Description:
-
- Thread function for WindowThread created in DllMain during
- process attachment. Registers a window class, creates an
- instance of that class, and goes into a message loop to retrieve
- messages for that window or it's child edit control.
-
- Arguments:
-
- TheParam -- Pointer to the parameter passed in by the function
- that called CreateThread.
-
- Return Value:
-
- Returns the wParam of the quit message that forced us out of the
- message loop.
-
- --*/
- {
-
- WNDCLASS wnd_class; // window class structure to register
- MSG msg; // retrieved message
- PINITDATA InitDataPtr; // casts TheParam into a INITDATA pointer
-
- // Register a window class for the frame window.
- wnd_class.style = CS_HREDRAW | CS_VREDRAW;
- wnd_class.lpfnWndProc = DTMainWndProc;
- wnd_class.cbClsExtra = 0;
- wnd_class.cbWndExtra = 0;
- wnd_class.hInstance = DllInstHandle;
- wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
- wnd_class.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
- wnd_class.lpszMenuName = NULL;
- wnd_class.lpszClassName = DTWndClass;
- RegisterClass(&wnd_class);
-
- // Create a frame window
- FrameWindow = CreateWindow(DTWndClass,
- "Debug Window",
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
- WS_VISIBLE,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- DllInstHandle,
- NULL);
-
- // Send the initialization data to the debug window and/or file.
- InitDataPtr = (PINITDATA)TheParam;
- wsprintf(Buffer, "Log initiated: %d-%d-%d, %d:%d:%d\r\n",
- InitDataPtr->LocalTime.wMonth,
- InitDataPtr->LocalTime.wDay,
- InitDataPtr->LocalTime.wYear,
- InitDataPtr->LocalTime.wHour,
- InitDataPtr->LocalTime.wMinute,
- InitDataPtr->LocalTime.wSecond);
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
- wsprintf(Buffer, "Process ID: 0x%X Thread ID: 0x%X\r\n",
- InitDataPtr->PID,
- InitDataPtr->TID);
- DTTextOut(DebugWindow, LogFileHandle, Buffer, OutputStyle);
- LocalFree(InitDataPtr);
-
- // Setting this event allows {Pre|Post}ApiNotify to proceed. This
- // insures (ensures? what's the difference) that any debugging
- // output by other threads is held up until after this statement.
- SetEvent(TextOutEvent);
-
- // Go into a message loop.
- while (GetMessage(&msg, NULL, 0 , 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return(msg.wParam);
-
- } // WindowThreadFunc()
-
-
-
-
-
- BOOL APIENTRY
- DebugDlgProc(
- HWND DialogWindow,
- UINT Message,
- WPARAM WParam,
- LPARAM LParam)
- /*++
-
- DebugDlgProc()
-
- Function Description:
-
- Window function for the dialog box IDC_DIALOG1, the dialog box
- that pops up when the dll is loaded and prompts the user for the
- output style of his/her choice.
-
- Arguments:
-
- DialogWindow -- handle to the dialog box window.
-
- Message -- the message being received.
-
- WParam -- first parameter.
-
- LParam -- second parameter.
-
- Return Value:
-
- Returns TRUE to indicate message was handled, FALSE otherwise.
-
- --*/
- {
-
- DWORD LogFNSize = sizeof(LogFileName); // size of the file name buffer
-
- switch (Message) {
-
- case WM_COMMAND:
-
- switch (LOWORD(WParam)) {
-
- case IDOK:
-
- // The user clicked the OK button...figure out his choice
- // and act appropriately.
- if (IsDlgButtonChecked(DialogWindow, IDC_RADIO5)) {
-
- // Radio Button 1 was clicked.
- if (!GetFile(DialogWindow, LogFileName, LogFNSize)) {
-
- // Error -- OutputStyle stays WINDOW_ONLY.
- MessageBox(DialogWindow, ErrStr2, "Error.",
- MB_OK | MB_ICONSTOP);
- } else {
- OutputStyle = FILE_ONLY;
- }
-
- } else if (IsDlgButtonChecked(DialogWindow, IDC_RADIO6)) {
-
- // Radio Button 2 was clicked.
- OutputStyle = WINDOW_ONLY;
-
- } else if (IsDlgButtonChecked(DialogWindow, IDC_RADIO7)) {
-
- // Radio Button 3 was clicked.
- if (!GetFile(DialogWindow, LogFileName, LogFNSize)) {
-
- // Error -- OutputStyle stays WINDOW_ONLY.
- MessageBox(DialogWindow, ErrStr2, "Error",
- MB_OK | MB_ICONSTOP);
- } else {
- OutputStyle = FILE_AND_WINDOW;
- }
-
- } else if (IsDlgButtonChecked(DialogWindow, IDC_RADIO8)) {
-
- // Radio Button 4 was clicked.
- OutputStyle = DEBUGGER;
-
- } else {
-
- // No radio buttons were clicked -- pop up a Message
- // box.
- MessageBox(DialogWindow, "You must choose one output method.",
- "Choose or Die.", MB_OK | MB_ICONSTOP);
- break;
-
- }
-
- // flow through
-
- case IDCANCEL:
-
- EndDialog(DialogWindow, WParam);
- return TRUE;
-
- }
-
- case WM_INITDIALOG:
-
- return TRUE;
-
- }
- return FALSE;
-
- } // DebugDlgProc()
-
-
-
-
-
- BOOL
- DTTextOut(
- IN HWND WindowHandle,
- IN HANDLE FileHandle,
- IN char *String,
- DWORD Style)
- /*++
-
- DTTextOut()
-
- Function Description:
-
- This function outputs a string to a debug window and/or file.
-
- Arguments:
-
- WindowHandle -- handle to an edit control for debug output.
-
- FileHandle -- handle to an open file for debug output.
-
- String -- the string to output.
-
- Style -- specifies whether the output should go to the window,
- the file, or both.
-
- Return Value:
-
- Returns TRUE if the output succeeds, FALSE otherwise.
-
- --*/
- {
-
- DWORD NumWritten; // WriteFile takes an address to this
- DWORD Index; // index of end of edit control text
- BOOL Result; // result of WriteFile
- char Output[TEXT_LEN]; // scratch buffer
-
- static DWORD LineCount = 0; // text output line number
- DWORD BufIndex = 0; // index into output string
-
- // Build a new string with the line-number in front.
- BufIndex += wsprintf(Output, "(%d) ", LineCount++);
- strcpy(Output + BufIndex, String);
-
- switch (Style) {
-
- case WINDOW_ONLY:
-
- Index = GetWindowTextLength(WindowHandle);
- SendMessage(WindowHandle, EM_SETSEL, Index, Index);
- SendMessage(WindowHandle, EM_REPLACESEL, 0, (LPARAM)Output);
-
- break;
-
- case FILE_ONLY:
-
- Result = WriteFile(FileHandle, (LPCVOID)Output, strlen(Output),
- &NumWritten, NULL);
- if (!Result) {
-
- AbortAndClose(FileHandle, WindowHandle);
- return FALSE;
- }
- break;
-
- case FILE_AND_WINDOW:
-
- Index = GetWindowTextLength(WindowHandle);
- SendMessage(WindowHandle, EM_SETSEL, Index, Index);
- SendMessage(WindowHandle, EM_REPLACESEL, 0, (LPARAM)Output);
- Result = WriteFile(FileHandle, (LPCVOID)Output, strlen(Output),
- &NumWritten, NULL);
- if (!Result) {
-
- AbortAndClose(FileHandle, WindowHandle);
- return FALSE;
- }
- break;
-
- case DEBUGGER:
-
- OutputDebugString(Output);
- }
- return TRUE;
-
- } // DTTextOut()
-
-
-
-
-
- void
- AbortAndClose(
- IN HANDLE FileHandle,
- IN HWND WindowHandle)
- /*++
-
- AbortAndClose()
-
- Function Description:
-
- Closes a file handle, informs the user via a message box, and
- changes the global variable OutputStyle to WINDOW_ONLY
-
- Arguments:
-
- FileHandle -- handle to a file that caused the error.
-
- WindowHandle -- handle to a window to be the parent of the
- Message Box.
-
- Return Value:
-
- Void.
-
- --*/
- {
- CloseHandle(FileHandle);
- MessageBox(WindowHandle, ErrStr3, "Error", MB_OK | MB_ICONSTOP);
- OutputStyle = WINDOW_ONLY;
-
- } // AbortAndClose()
-
-
-
-
-
- BOOL
- GetFile(
- IN HWND OwnerWindow,
- OUT LPSTR FileName,
- IN DWORD FileNameSize)
- /*++
-
- GetFile()
-
- Function Description:
-
- Uses the predefined "Save As" dialog box style to retrieve a
- file name from the user. The file name the user selects is
- stored in LogFileName.
-
- Arguments:
-
- OwnerWindow -- window which will own the dialog box.
-
- FileName -- address of a buffer in which to store the string.
-
- FileNameSize -- size of the FileName buffer.
-
- Return Value:
-
- Returns whatever GetSaveFileName returns; see documentation for
- that function.
-
- --*/
- {
-
- OPENFILENAME OpenFileName; // common dialog box structure
- char DirName[256]; // directory string
- char FileTitle[256]; // file-title string
-
- FileName[0] = '\0';
-
- FillMemory((PVOID)&OpenFileName, sizeof(OPENFILENAME), 0);
-
- // Retrieve the system directory name and store it in DirName.
- GetCurrentDirectory(sizeof(DirName), DirName);
-
- // Set the members of the OPENFILENAME structure.
- OpenFileName.lStructSize = sizeof(OPENFILENAME);
- OpenFileName.hwndOwner = OwnerWindow;
- OpenFileName.lpstrFilter = OpenFileName.lpstrCustomFilter = NULL;
- OpenFileName.nFilterIndex = 0;
- OpenFileName.lpstrFile = FileName;
- OpenFileName.nMaxFile = FileNameSize;
- OpenFileName.lpstrFileTitle = FileTitle;
- OpenFileName.nMaxFileTitle = sizeof(FileTitle);
- OpenFileName.lpstrInitialDir = DirName;
- OpenFileName.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
-
- // Pop up the dialog box to get the file name.
- return GetSaveFileName(&OpenFileName);
-
- } // GetFile()