// Borland C++ - (C) Copyright 1991, 1994 by Borland International //******************************************************************* // // program - Hdump.c // purpose - a windows program to dump a file in hex. // //******************************************************************* #define STRICT #include #pragma hdrstop #include #include #include #include #include #include #include #include #include #include #include "hdump.h" typedef struct scrollkeys { WORD wVirtkey; int iMessage; WORD wRequest; } SCROLLKEYS; SCROLLKEYS key2scroll [] = { { VK_HOME, WM_COMMAND, IDM_HOME }, { VK_END, WM_VSCROLL, SB_BOTTOM }, { VK_PRIOR, WM_VSCROLL, SB_PAGEUP }, { VK_NEXT, WM_VSCROLL, SB_PAGEDOWN }, { VK_UP, WM_VSCROLL, SB_LINEUP }, { VK_DOWN, WM_VSCROLL, SB_LINEDOWN }, { VK_LEFT, WM_HSCROLL, SB_PAGEUP }, { VK_RIGHT, WM_HSCROLL, SB_PAGEDOWN } }; # define NUMKEYS (sizeof key2scroll / sizeof key2scroll[0]) // data initialized by first instance typedef struct tagSETUPDATA { char szAppName[10]; // name of application } SETUPDATA; SETUPDATA SetUpData; // Data that can be referenced throughout the // program but not passed to other instances HINSTANCE hInst; // hInstance of application HWND hWndMain; // hWnd of main window int xChar, yChar, yCharnl; // character size int xClient, yClient; // client window size LOGFONT cursfont; // font structure HFONT holdsfont; // handle of original font HFONT hnewsfont; // handle of new fixed font // window scroll/paint stuff int nVscrollMax, nHscrollMax; // scroll ranges int nVscrollPos, nHscrollPos; // current scroll positions int numlines; // number of lines in file int maxwidth; // width of display format int nVscrollInc, nHscrollInc; // scroll increments int nPageMaxLines; // max lines on screen // file open dialog stuff char szFileSpec[80]; // file spec for initial search char szDefExt[5]; // default extension char szFileName[80]; // file name char szFilePath[80]; // file path WORD wFileAttr; // attribute for search WORD wStatus; // status of search // dump file stuff char szFName[64]; // file to display FILE *fh; // handle of open file LONG fsize; // size of file // function prototypes int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow); void InitHdump(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow); void InitHdumpFirst(HINSTANCE hInstance); void InitHdumpEvery(HINSTANCE hInstance, int cmdShow); void CloseHdump(void); BOOL CALLBACK _export About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK _export HdumpWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void SetupScroll(HWND hWnd); void HdumpPaint(HWND hWnd); char *SnapLine(char *szBuf, LPSTR mem, int len, int dwid, char *olbl); int DoFileOpenDlg(HINSTANCE hInst, HWND hWnd, char *szFileSpecIn, char *szDefExtIn, WORD wFileAttrIn, char *szFilePathOut, char *szFileNameOut); extern BOOL CALLBACK _export FileOpenDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); //******************************************************************* // WinMain - Hdump main // // paramaters: // hInstance - The instance of this instance of this // application. // hPrevInstance - The instance of the previous instance // of this application. This will be 0 // if this is the first instance. // lpszCmdLine - A long pointer to the command line that // started this application. // cmdShow - Indicates how the window is to be shown // initially. ie. SW_SHOWNORMAL, SW_HIDE, // SW_MIMIMIZE. // // returns: // wParam from last message. // //******************************************************************* int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow) { MSG msg; // Go init this application. InitHdump(hInstance, hPrevInstance, lpszCmdLine, cmdShow); // Get and dispatch messages for this applicaton. while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return(msg.wParam); } #if !defined(__WIN32__) //******************************************************************* // InitHdumpAdded - done only for added instances of Hdump // // paramaters: // hPrevInstance - The instance of the previous instance // of this application. // //******************************************************************* void InitHdumpAdded(HINSTANCE hPrevInstance) { // get the results of the initialization of first instance GetInstanceData(hPrevInstance, (BYTE*) &SetUpData, sizeof(SETUPDATA)); } #endif //******************************************************************* //******************************************************************* // InitHdump - init the Hdump application // // paramaters: // hInstance - The instance of this instance of this // application. // hPrevInstance - The instance of the previous instance // of this application. This will be 0 // if this is the first instance. // lpszCmdLine - A long pointer to the command line that // started this application. // cmdShow - Indicates how the window is to be shown // initially. ie. SW_SHOWNORMAL, SW_HIDE, // SW_MIMIMIZE. // //******************************************************************* #pragma argsused void InitHdump(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow) { if (! hPrevInstance) // if no previous instance, this is first InitHdumpFirst(hInstance); #if !defined(__WIN32__) else InitHdumpAdded(hPrevInstance); // this is not first instance #endif InitHdumpEvery(hInstance, cmdShow); // initialization for all instances } //******************************************************************* // InitHdumpFirst - done only for first instance of Hdump // // paramaters: // hInstance - The instance of this instance of this // application. // //******************************************************************* void InitHdumpFirst(HINSTANCE hInstance) { WNDCLASS wcHdumpClass; // Get string from resource with application name. LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 10); // Define the window class for this application. wcHdumpClass.lpszClassName = SetUpData.szAppName; wcHdumpClass.hInstance = hInstance; wcHdumpClass.lpfnWndProc = HdumpWndProc; wcHdumpClass.hCursor = LoadCursor(NULL, IDC_ARROW); wcHdumpClass.hIcon = LoadIcon(hInstance, SetUpData.szAppName); wcHdumpClass.lpszMenuName = (LPSTR) SetUpData.szAppName; wcHdumpClass.hbrBackground = GetStockObject(WHITE_BRUSH); wcHdumpClass.style = CS_HREDRAW | CS_VREDRAW; wcHdumpClass.cbClsExtra = 0; wcHdumpClass.cbWndExtra = 0; // Register the class RegisterClass(&wcHdumpClass); } //******************************************************************* // InitHdumpEvery - done for every instance of Hdump // // paramaters: // hInstance - The instance of this instance of this // application. // cmdShow - Indicates how the window is to be shown // initially. ie. SW_SHOWNORMAL, SW_HIDE, // SW_MIMIMIZE. // //******************************************************************* void InitHdumpEvery(HINSTANCE hInstance, int cmdShow) { TEXTMETRIC tm; HDC hDC; hInst = hInstance; // save for use by window procs // Create applications main window. hWndMain = CreateWindow( SetUpData.szAppName, // window class name SetUpData.szAppName, // window title WS_OVERLAPPEDWINDOW | // type of window WS_HSCROLL | WS_VSCROLL, CW_USEDEFAULT, // x window location CW_USEDEFAULT, // y CW_USEDEFAULT, // cx and size CW_USEDEFAULT, // cy NULL, // no parent for this window NULL, // use the class menu hInstance, // who created this window NULL // no parms to pass on ); // Get the display context. hDC = GetDC(hWndMain); // Build fixed screen font. Needed to display hex formated dump. cursfont.lfHeight = 14; cursfont.lfWidth = 9; cursfont.lfEscapement = 0; cursfont.lfOrientation = 0; cursfont.lfWeight = FW_NORMAL; cursfont.lfItalic = FALSE; cursfont.lfUnderline = FALSE; cursfont.lfStrikeOut = FALSE; cursfont.lfCharSet = ANSI_CHARSET; cursfont.lfOutPrecision = OUT_DEFAULT_PRECIS; cursfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; cursfont.lfQuality = DEFAULT_QUALITY; cursfont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE; strcpy((char *)cursfont.lfFaceName, "System"); hnewsfont = CreateFontIndirect((LPLOGFONT) &cursfont); // Install the font in the current display context. holdsfont = SelectObject(hDC, hnewsfont); // get text metrics for paint GetTextMetrics(hDC, &tm); xChar = tm.tmAveCharWidth; yChar = tm.tmHeight + tm.tmExternalLeading; yCharnl = tm.tmHeight; // Release the display context. ReleaseDC(hWndMain, hDC); // Update display of main window. ShowWindow(hWndMain, cmdShow); UpdateWindow(hWndMain); } //******************************************************************* // CloseHdump - done at termination of every instance of Hdump // //******************************************************************* void CloseHdump() { DeleteObject(hnewsfont); } //******************************************************************* // About - handle about dialog messages // // paramaters: // hDlg - The window handle for this message // message - The message number // wParam - The WPARAM parameter for this message // lParam - The LPARAM parameter for this message // //******************************************************************* #pragma argsused BOOL CALLBACK _export About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_INITDIALOG) return(TRUE); else if (message == WM_COMMAND) { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: EndDialog(hDlg, TRUE); return(TRUE); default: return(TRUE); } } return(FALSE); } //******************************************************************* //******************************************************************* // HdumpWndProc - handles messages for this application // // paramaters: // hWnd - The window handle for this message // message - The message number // wParam - The WPARAM parameter for this message // lParam - The LPARAM parameter for this message // // returns: // depends on message. // //******************************************************************* #pragma warn -eff LRESULT CALLBACK _export HdumpWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static char sztFilePath[64]; // we remember last directory searched static char sztFileExt[5]; static char sztFileSpec[64]; static char sztFileName[64]; DLGPROC lpproc; // pointer to thunk for dialog box char buf[128]; // temp buffer int i; FILE *fh; switch (message) { case WM_CREATE: // Start file search at current directory getcwd(sztFilePath, sizeof(sztFilePath)); strcat(sztFilePath, "\\"); strcpy(sztFileExt, ".*"); strcpy(sztFileName, ""); return(DefWindowProc(hWnd, message, wParam, lParam)); case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDM_QUIT: // User selected Quit on menu PostMessage(hWnd, WM_CLOSE, 0, 0L); break; case IDM_HOME: // Used to implement home to topleft from keyboard. SendMessage(hWnd, WM_HSCROLL, GET_WM_HSCROLL_MPS (SB_TOP, 0, 0)); SendMessage(hWnd, WM_VSCROLL, GET_WM_VSCROLL_MPS (SB_TOP, 0, 0)); break; case IDM_ABOUT: // Display about box. lpproc = (DLGPROC)MakeProcInstance((FARPROC)About, hInst); DialogBox(hInst, MAKEINTRESOURCE(ABOUT), hWnd, lpproc); FreeProcInstance((FARPROC)lpproc); break; case IDM_OPEN: // Setup initial search path for open dialog box. strcpy(sztFileSpec, sztFilePath); strcat(sztFileSpec, "*"); strcat(sztFileSpec, sztFileExt); // Go ask user to select file to display. if (DoFileOpenDlg(hInst, hWnd, sztFileSpec, sztFileExt, 0x4010, // drives & subdirectories sztFilePath, sztFileName)) { // If user said OK construct file path/file name // to open. strcpy(szFName, sztFilePath); strcat(szFName, sztFileName); // Show file name in window caption. sprintf(buf, "hdump - %s", szFName); SetWindowText(hWnd, buf); // Determine file size and some display paramaters. fh = fopen(szFName, "r+b"); if (fh) { fsize = filelength(fileno(fh)); numlines = (int) ((fsize + 16L - 1L) / 16L); SnapLine(buf, szFName, 16, 16,NULL); // display width maxwidth = strlen(buf); nVscrollPos = 0; nHscrollPos = 0; fclose(fh); } else // if file open failed. { SetWindowText(hWnd, "hdump"); numlines = 0; maxwidth = 0; } // Go setup scroll ranges for this file. SetupScroll(hWnd); // Show first part of file. InvalidateRect(hWnd, NULL, TRUE); UpdateWindow(hWnd); } break; default: break; } break; case WM_SIZE: // Save size of window client area. if (lParam) { yClient = HIWORD(lParam); xClient = LOWORD(lParam); yClient = (yClient / yCharnl + 1) * yCharnl; lParam = MAKELONG(xClient, yClient); // Go setup scroll ranges and file display area based upon // client area size. SetupScroll(hWnd); return(DefWindowProc(hWnd, message, wParam, lParam)); } break; case WM_VSCROLL: // React to the various vertical scroll related actions. switch (GET_WM_VSCROLL_CODE(wParam, lParam)) { case SB_TOP: nVscrollInc = -nVscrollPos; break; case SB_BOTTOM: nVscrollInc = nVscrollMax - nVscrollPos; break; case SB_LINEUP: nVscrollInc = -1; break; case SB_LINEDOWN: nVscrollInc = 1; break; case SB_PAGEUP: nVscrollInc = -max(1, yClient / yChar); break; case SB_PAGEDOWN: nVscrollInc = max(1, yClient / yChar); break; case SB_THUMBPOSITION: nVscrollInc = GET_WM_VSCROLL_POS(wParam, lParam) - nVscrollPos; break; case SB_THUMBTRACK: nVscrollInc = GET_WM_VSCROLL_POS(wParam, lParam) - nVscrollPos; break; default: nVscrollInc = 0; } nVscrollInc = max(-nVscrollPos, min(nVscrollInc, nVscrollMax - nVscrollPos)); if (nVscrollInc) { nVscrollPos += nVscrollInc; ScrollWindow(hWnd, 0, -yChar * nVscrollInc, NULL, NULL); SetScrollPos(hWnd, SB_VERT, nVscrollPos, TRUE); UpdateWindow(hWnd); } break; case WM_HSCROLL: // React to the various horizontal scroll related actions. switch (GET_WM_HSCROLL_CODE(wParam, lParam)) { case SB_LINEUP: nHscrollInc = -1; break; case SB_LINEDOWN: nHscrollInc = 1; break; case SB_PAGEUP: nHscrollInc = -8; break; case SB_PAGEDOWN: nHscrollInc = 8; break; case SB_THUMBPOSITION: nHscrollInc = GET_WM_HSCROLL_POS(wParam, lParam) - nHscrollPos; break; case SB_THUMBTRACK: nHscrollInc = GET_WM_HSCROLL_POS(wParam, lParam) - nHscrollPos; break; default: nHscrollInc = 0; } nHscrollInc = max(-nHscrollPos, min(nHscrollInc, nHscrollMax - nHscrollPos)); if (nHscrollInc) { nHscrollPos += nHscrollInc; ScrollWindow(hWnd, -xChar * nHscrollInc, 0, NULL, NULL); SetScrollPos(hWnd, SB_HORZ, nHscrollPos, TRUE); UpdateWindow(hWnd); } break; case WM_KEYDOWN: // Translate various keydown messages to appropriate horizontal // and vertical scroll actions. for (i = 0; i < NUMKEYS; i++) { if (wParam == key2scroll[i].wVirtkey) { SendMessage(hWnd, key2scroll[i].iMessage, key2scroll[i].wRequest, 0L); break; } } break; case WM_PAINT: // Go paint the client area of the window with the appropriate // part of the selected file. HdumpPaint(hWnd); break; case WM_DESTROY: // This is the end if we were closed by a DestroyWindow call. CloseHdump(); // take any necessary wrapup action. PostQuitMessage(0); // this is the end... break; case WM_QUERYENDSESSION: // If we return TRUE we are saying it's ok with us to end the // windows session. CloseHdump(); // take any necessary wrapup action. return((long) TRUE); // we agree to end session. case WM_CLOSE: // Tell windows to destroy our window. DestroyWindow(hWnd); break; default: // Let windows handle all messages we choose to ignore. return(DefWindowProc(hWnd, message, wParam, lParam)); } return(0L); } #pragma warn .eff //******************************************************************* // SetupScroll - setup scroll ranges // // Setup the vertical and horizontal scroll ranges and positions // of the applicatons main window based on: // // numlines - The maximum number of lines to display in a hexdump // of the selected file. // maxwidth - The width of each line to display as formated for // the hexdump. // // The resulting variables, nVscrollPos and nPageMaxLines, are used // by the function HdumpPaint to determine what part of the selected // file to display in the window. // // paramaters: // hWnd - The callers window handle // //******************************************************************* void SetupScroll(HWND hWnd) { // numlines established during open nVscrollMax = max(0, numlines - yClient / yChar); nVscrollPos = min(nVscrollPos, nVscrollMax); nHscrollMax = max(0, maxwidth - xClient / xChar); nHscrollPos = min(nHscrollPos, nHscrollMax); SetScrollRange (hWnd, SB_VERT, 0, nVscrollMax, FALSE); SetScrollPos (hWnd, SB_VERT, nVscrollPos, TRUE); SetScrollRange (hWnd, SB_HORZ, 0, nHscrollMax, FALSE); SetScrollPos (hWnd, SB_HORZ, nHscrollPos, TRUE); nPageMaxLines = min(numlines, yClient / yChar); } //******************************************************************* // HdumpPaint - paint the main window // // If a file has been selected, as indicated by numlines being // greater than 0, this module will read and display a portion // of the file as determined by the current size and scroll // position of the window. // // paramaters: // hWnd - The callers window handle // //******************************************************************* void HdumpPaint(HWND hWnd) { PAINTSTRUCT ps; HDC hDC; LONG offset; int tlen; int lpos; char buf[128]; int i; int len; int hfile; HANDLE hbuff; LPSTR lpbuff; LPSTR lcp; BeginPaint(hWnd, (LPPAINTSTRUCT) &ps); hDC = ps.hdc; // Establish fixed font in display context. SelectObject(hDC, hnewsfont); if (numlines) { // Open the file to display // (files should not stay open over multiple windows messages) if ((hfile = _lopen(szFName, OF_READ)) != -1) { // Get a buffer to hold data to fill screen. len = nPageMaxLines * 16; hbuff = GlobalAlloc(GMEM_MOVEABLE, (DWORD) len); if (hbuff) { // Lock the buffer to get a pointer to it. lpbuff = GlobalLock(hbuff); if (lpbuff) { // Get offset into file to start display. offset = (LONG) nVscrollPos * 16L; if (_llseek(hfile, offset, 0) != -1L) { tlen = _lread(hfile, lpbuff, len); if (tlen != -1) { lpos = 0; lcp = lpbuff; for (i = nVscrollPos; i < (nVscrollPos + nPageMaxLines); i++) { if (tlen > 16) len = 16; else len = tlen; tlen -= len; SnapLine(buf, lcp, len, 16, (char *) (i * 16)); TextOut(hDC, xChar * (-nHscrollPos + 0), yChar * lpos++, buf, strlen(buf)); lcp += 16; } } } GlobalUnlock(hbuff); } GlobalFree(hbuff); } _lclose(hfile); } } EndPaint(hWnd, (LPPAINTSTRUCT) &ps); } //******************************************************************* // SnapLine - dump a line of memory // // paramaters: // szBuf - buffer to hold result // mem - pointer to memory to format // len - length to format // dwid - max display width (8 or 16 recomended) // olbl - label to put at start of line // // returns: // A pointer to szBbuf. // //******************************************************************* char *SnapLine(char *szBuf, LPSTR mem, int len, int dwid, char *olbl) { int i; int j; unsigned char c; unsigned char buff[80]; unsigned char tbuf[80]; if (len > dwid) len = dwid; *szBuf = 0; // Show offset for this line. sprintf((char *)tbuf, "%04X ", olbl); strcpy(szBuf, (char *)tbuf); // Format hex portion of line and save chars for ascii portion for (i = 0; i < len; i++) { c = *mem++; sprintf((char *)tbuf, "%02X ", c); strcat(szBuf, (char *)tbuf); if (c >= 32 && c < 127) buff[i] = c; else buff[i] = 46; } j = dwid - i; buff[i] = 0; // Fill out hex portion of short lines. for (i = j; i > 0; i--) strcat(szBuf, " "); // Add ascii portion to line. sprintf((char *)tbuf, " |%s|", (char *)buff); strcat(szBuf, (char *)tbuf); // Fill out end of short lines. for (i = j; i > 0; i--) strcat(szBuf, " "); return(szBuf); } //******************************************************************* // DoFileOpenDlg - invoke FileOpenDlgProc to get name of file to open // // Setup call to FileOpenDlgProc to let user select path/filename // // paramaters: // hInst - instance of caller // hWnd - window of caller // szFileSpecIn - file path to search initially // szDefExtIn - file extension search initially // wFileAttrIn - attribute for 'DlgDirList' to use in search // szFilePathOut - path of selected file // szFileNameOut - name of selected file // // returns: // 1 - if a file selected // 0 - if file not selected // //******************************************************************* #pragma warn -eff DoFileOpenDlg(HINSTANCE hInst, HWND hWnd, char *szFileSpecIn, char *szDefExtIn, WORD wFileAttrIn, char *szFilePathOut, char *szFileNameOut) { DLGPROC lpfnFileOpenDlgProc; int iReturn; // Save starting file spec. strcpy(szFileSpec, szFileSpecIn); strcpy(szDefExt, szDefExtIn); strcpy(szFilePath, szFilePathOut); wFileAttr = wFileAttrIn; lpfnFileOpenDlgProc = (DLGPROC)MakeProcInstance((FARPROC)FileOpenDlgProc, hInst); iReturn = DialogBox(hInst, MAKEINTRESOURCE(OPENFILE), hWnd, lpfnFileOpenDlgProc); FreeProcInstance((FARPROC)lpfnFileOpenDlgProc); // Return selected file spec. strcpy(szFilePathOut, szFilePath); strcpy(szFileNameOut, szFileName); return(iReturn); } #pragma warn .eff //******************************************************************* // FileOpenDlgProc - get the name of a file to open // // paramaters: // hDlg - The window handle of this dialog box // message - The message number // wParam - The WPARAM parameter for this message // lParam - The LPARAM parameter for this message // // returns: // depends on message. // //******************************************************************* BOOL CALLBACK _export FileOpenDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) { static char curpath[64]; char tempDir[80], *tempStr = NULL; unsigned attrib; char cLastChar; int nLen; struct ffblk fileinfo; switch (iMessage) { case WM_INITDIALOG: // Save current working directory (will be restored on exit) getcwd(curpath, sizeof(curpath)); SendDlgItemMessage(hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L); // Fill list box with files from starting file spec. DlgDirList(hDlg, szFileSpec, IDD_FLIST, IDD_FPATH, wFileAttr); // Save starting file spec. SetDlgItemText(hDlg, IDD_FNAME, szFileSpec); return(TRUE); case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDD_FLIST: switch (GET_WM_COMMAND_CMD(wParam, lParam)) { case LBN_SELCHANGE: if (DlgDirSelectEx(hDlg, szFileName, sizeof (szFileName), IDD_FLIST)) strcat(szFileName, szFileSpec); SetDlgItemText(hDlg, IDD_FNAME, szFileName); break; case LBN_DBLCLK: if (DlgDirSelectEx(hDlg, szFileName, sizeof (szFileName), IDD_FLIST)) { SendMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS (IDOK, 0, 0)); } else { SetDlgItemText(hDlg, IDD_FNAME, szFileName); SendMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS (IDOK, 0, 0)); } break; } break; case IDD_FNAME: if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { EnableWindow(GetDlgItem(hDlg, IDOK), (BOOL) SendMessage((HWND)lParam, WM_GETTEXTLENGTH, 0, 0L)); } break; case IDOK: GetDlgItemText(hDlg, IDD_FNAME, szFileName, 80); nLen = strlen(szFileName); // Save new spec. & directory strcpy(tempDir, szFileName); #ifdef __FLAT__ attrib = GetFileAttributes( (LPCTSTR) tempDir ); #else _dos_getfileattr(tempDir, &attrib); #endif if(!(attrib == _A_SUBDIR) ) { tempStr = strrchr(tempDir, '\\'); if(tempStr) tempStr[1] = 0; } if(tempStr || (attrib == _A_SUBDIR)) { strcat(szFilePath, tempDir); } cLastChar = *AnsiPrev(szFileName, szFileName + nLen); if (cLastChar == '\\' || cLastChar == ':') { strcpy(szFilePath, szFileName); chdir(szFilePath); SetDlgItemText(hDlg, IDD_FPATH, szFilePath); strcat(szFileName, szFileSpec); } if( szFileName[ 1 ] == ':' && strcmp( "*.*", &szFileName[ 2 ] ) == 0 ) { strcpy( szFilePath, szFileName ); szFilePath[ 2 ] = 0x0; chdir(szFilePath); SetDlgItemText(hDlg, IDD_FPATH, szFilePath); } if (strchr(szFileName, '*') || strchr(szFileName, '?')) { if (DlgDirList(hDlg, szFileName, IDD_FLIST, IDD_FPATH, wFileAttr)) { strcpy(szFileSpec, szFileName); SetDlgItemText(hDlg, IDD_FNAME, szFileSpec); } else MessageBeep(0); break; } // Fill list with new spec. if (DlgDirList(hDlg, szFileName, IDD_FLIST, IDD_FPATH, wFileAttr)) { strcpy(szFileSpec, szFileName); SetDlgItemText(hDlg, IDD_FNAME, szFileSpec); break; } // Since we fell through, szFileName was not a search path. szFileName[nLen] = '\0'; // Make sure file exists. if (findfirst(szFileName, &fileinfo, 0)) { strcat(szFileName, szDefExt); // Make sure file exists. if (findfirst(szFileName, &fileinfo, 0)) { // No, beep and break. MessageBeep(0); break; } } strupr(szFilePath); nLen = strlen( szFilePath ) - 1; if (szFilePath[ nLen ] != '\\' && szFilePath[ nLen ] != ':' ) strcat(szFilePath, "\\"); // Return selected file name. strcpy(szFileName, fileinfo.ff_name); // Restore current working directory. chdir(curpath); // Terminate this dialog box. EndDialog(hDlg, TRUE); break; case IDCANCEL: // Restore current working directory chdir(curpath); // Terminate this dialog box. EndDialog(hDlg, FALSE); break; default: return(FALSE); } break; default: return(FALSE); } return(TRUE); } //*******************************************************************