|
|
1.1 ! root 1: #include "pwalk.h" ! 2: ! 3: #define BYTE_WIN_WIDTH 77 ! 4: #define CLINESSHOW 8 ! 5: #define ABS(x) ((x) < 0? -(x) : (x)) ! 6: ! 7: /* externally defined system constants */ ! 8: extern int xChar, ! 9: yChar, ! 10: xScreen, ! 11: yScreen, ! 12: yFrame, ! 13: xFrame, ! 14: yCaption, ! 15: xVScrollBar; ! 16: extern HFONT hFont; ! 17: extern HWND hMemWnd; ! 18: ! 19: void WINAPI VScrollBytes (HWND, int, int, LPMEMVIEW); ! 20: void WINAPI KeyToScrollMsg (HWND, WPARAM); ! 21: void WINAPI DisplayBytes (HDC, LPRECT, LPMEMVIEW, LPMEMVIEW); ! 22: void WINAPI GetBytesLine (LPBYTE, UINT, DWORD, int, char *); ! 23: BOOL WINAPI parcmp (LPBYTE, LPBYTE, int, LPBYTE); ! 24: ! 25: ! 26: ! 27: ! 28: HWND WINAPI EnumViewWindows ( ! 29: HWND hWndParent, ! 30: HWND hWndLast) ! 31: { ! 32: ! 33: HMENU hMenu = GetMenu (hWndParent); ! 34: HMENU hViewMenu = GetSubMenu (hMenu, 2); ! 35: char szClass[MAX_PATH]; ! 36: char szCaption[MAX_PATH]; ! 37: HWND hWnd; ! 38: int i; ! 39: ! 40: static int nWindows; ! 41: static ATOM *aMenuItems = NULL; ! 42: static int iWnd; ! 43: ! 44: /* load window class name */ ! 45: LoadString (GetModuleHandle (NULL), IDS_MEMVIEWCLASS, szClass, MAX_PATH); ! 46: ! 47: if (hWndLast == NULL) ! 48: { ! 49: /* start with first window in menu list */ ! 50: iWnd = 0; ! 51: ! 52: /* determine number of windows */ ! 53: nWindows = GetMenuItemCount (hViewMenu) - 5; ! 54: ! 55: /* if no popup windows, just return */ ! 56: if (nWindows <= 0) ! 57: return NULL; ! 58: ! 59: /* free memory from last time, if any */ ! 60: if (aMenuItems != NULL) ! 61: LocalFree ((HANDLE)aMenuItems); ! 62: ! 63: /* get menuitem IDs */ ! 64: aMenuItems = (ATOM *)LocalAlloc (LPTR, nWindows*sizeof (ATOM)); ! 65: for (i=5; i-5<nWindows; i++) ! 66: aMenuItems[i-5] = (ATOM)GetMenuItemID (hViewMenu, i); ! 67: } ! 68: ! 69: else ! 70: if (iWnd >= nWindows) ! 71: return (NULL); ! 72: ! 73: GetAtomName (aMenuItems[iWnd], szCaption, MAX_PATH); ! 74: hWnd = FindWindow (szClass, szCaption); ! 75: iWnd++; ! 76: ! 77: return (hWnd); ! 78: } ! 79: ! 80: ! 81: ! 82: /* activate view window identified by atom */ ! 83: void WINAPI ActivateViewWindow ( ! 84: ATOM aCaption) ! 85: { ! 86: char szClass[MAX_PATH]; ! 87: char szCaption[MAX_PATH]; ! 88: HWND hWnd; ! 89: ! 90: GetAtomName (aCaption, szCaption, MAX_PATH); ! 91: LoadString (GetModuleHandle (NULL), IDS_MEMVIEWCLASS, szClass, MAX_PATH); ! 92: hWnd = FindWindow (szClass, szCaption); ! 93: BringWindowToTop (hWnd); ! 94: } ! 95: ! 96: ! 97: ! 98: /* function creates a window for viewing memory */ ! 99: HWND WINAPI ViewMemory ( ! 100: HWND hWndParent, ! 101: char *lpszObject, ! 102: LPVOID lpMem, ! 103: int nSize, ! 104: int nBase) ! 105: { ! 106: char szClass[MAX_PATH]; ! 107: ! 108: /* load resource strings for class and window title */ ! 109: LoadString (GetModuleHandle (NULL), IDS_MEMVIEWCLASS, szClass, MAX_PATH); ! 110: ! 111: /* create memory view window */ ! 112: return (CreateWindow (szClass, ! 113: lpszObject, ! 114: WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION | ! 115: WS_VSCROLL | WS_THICKFRAME | WS_MAXIMIZEBOX, ! 116: nSize, /* use xposition to pass memory size to window */ ! 117: nBase, /* use yposition to pass base memory location */ ! 118: BYTE_WIN_WIDTH * xChar + xVScrollBar + 2*xFrame, ! 119: yScreen/2, ! 120: hWndParent, ! 121: NULL, ! 122: GetModuleHandle (NULL), ! 123: lpMem)); ! 124: } ! 125: ! 126: ! 127: ! 128: LONG WINAPI MemWndProc ( ! 129: HWND hWnd, ! 130: UINT uMsg, ! 131: WPARAM wParam, ! 132: LPARAM lParam) ! 133: { ! 134: LONG lRet = 1; ! 135: MEMVIEW *pmv = (LPMEMVIEW)GetWindowLong (hWnd, WXB_LPMEMVIEW); ! 136: ! 137: ! 138: switch (uMsg) ! 139: { ! 140: case WM_CREATE: ! 141: pmv = (LPMEMVIEW)LocalAlloc (LPTR, sizeof (MEMVIEW)); ! 142: SetWindowLong (hWnd, WXB_LPMEMVIEW, (LONG)pmv); ! 143: SetWindowLong (hWnd, WXB_LPOLDMEMVIEW, 0); ! 144: ! 145: pmv->lpMem = ((LPCREATESTRUCT)lParam)->lpCreateParams; ! 146: pmv->nSize = ((LPCREATESTRUCT)lParam)->x; ! 147: pmv->nBase = ((LPCREATESTRUCT)lParam)->y; ! 148: pmv->nLines = (pmv->nSize+15)/16; ! 149: pmv->nExtraBytes = (pmv->nSize & 0x0000000F); ! 150: pmv->PosV = 0; ! 151: ! 152: /* reposition window with proper x,y positions */ ! 153: MoveWindow (hWnd, ! 154: 15, ! 155: 15, ! 156: ((LPCREATESTRUCT)lParam)->cx, ! 157: ((LPCREATESTRUCT)lParam)->cy, ! 158: TRUE); ! 159: break; ! 160: ! 161: case WM_SIZE: ! 162: pmv->xWin = LOWORD (lParam); ! 163: pmv->yWin = HIWORD (lParam); ! 164: ! 165: pmv->RangeV = pmv->nLines-pmv->yWin/yChar; ! 166: ! 167: if (pmv->RangeV < 0) ! 168: pmv->RangeV = 0; ! 169: ! 170: if (pmv->PosV > pmv->RangeV) ! 171: pmv->PosV = pmv->RangeV; ! 172: ! 173: SetScrollRange (hWnd, SB_VERT, 0, pmv->RangeV, FALSE); ! 174: SetScrollPos (hWnd, SB_VERT, pmv->PosV, TRUE); ! 175: break; ! 176: ! 177: case WM_PAINT: ! 178: { ! 179: PAINTSTRUCT ps; ! 180: ! 181: BeginPaint (hWnd, &ps); ! 182: DisplayBytes (ps.hdc, ! 183: &(ps.rcPaint), ! 184: pmv, ! 185: (LPMEMVIEW)GetWindowLong (hWnd, WXB_LPOLDMEMVIEW)); ! 186: EndPaint (hWnd, &ps); ! 187: } ! 188: break; ! 189: ! 190: case UM_UPDATE: ! 191: InvalidateRect (hWnd, NULL, TRUE); ! 192: UpdateWindow (hWnd); ! 193: break; ! 194: ! 195: case WM_KEYDOWN: ! 196: KeyToScrollMsg (hWnd, wParam); ! 197: break; ! 198: ! 199: case WM_VSCROLL: ! 200: VScrollBytes (hWnd, LOWORD (wParam), GetScrollPos (hWnd, SB_VERT), pmv); ! 201: break; ! 202: ! 203: case WM_DESTROY: ! 204: { ! 205: char szCaption[MAX_PATH]; ! 206: LPMEMVIEW lpmv; ! 207: ! 208: /* free virtual memory block and local memory buffer */ ! 209: VirtualFree (pmv->lpMem, 0, MEM_RELEASE); ! 210: LocalFree ((HANDLE)pmv); ! 211: ! 212: /* remove any old view memory */ ! 213: if ((lpmv = (LPMEMVIEW)GetWindowLong (hWnd, WXB_LPOLDMEMVIEW)) != NULL) ! 214: { ! 215: VirtualFree (lpmv->lpMem, 0, MEM_RELEASE); ! 216: LocalFree ((HANDLE)lpmv); ! 217: } ! 218: ! 219: /* send message to parent to remove menuitem */ ! 220: GetWindowText (hWnd, szCaption, MAX_PATH); ! 221: SendMessage (GetParent (hWnd), WM_COMMAND, IDM_REMOVEVIEWWND, (LONG)szCaption); ! 222: } ! 223: break; ! 224: ! 225: default: ! 226: return (DefWindowProc(hWnd, uMsg, wParam, lParam)); ! 227: break; ! 228: } ! 229: return 0L; ! 230: } ! 231: ! 232: ! 233: ! 234: ! 235: void WINAPI VScrollBytes ( ! 236: HWND hWnd, ! 237: int cmd, ! 238: int pos, ! 239: LPMEMVIEW lpmv) ! 240: { ! 241: int nScrollInc; ! 242: ! 243: switch (cmd) ! 244: { ! 245: case SB_TOP: ! 246: nScrollInc = -lpmv->PosV; ! 247: break ; ! 248: ! 249: case SB_BOTTOM: ! 250: nScrollInc = lpmv->RangeV - lpmv->PosV; ! 251: break ; ! 252: ! 253: case SB_LINEUP: ! 254: nScrollInc = -1; ! 255: break; ! 256: ! 257: case SB_LINEDOWN: ! 258: nScrollInc = 1; ! 259: break; ! 260: ! 261: case SB_PAGEDOWN: ! 262: nScrollInc = max (1, lpmv->yWin/yChar); ! 263: break; ! 264: ! 265: case SB_PAGEUP: ! 266: nScrollInc = min (-1, -(lpmv->yWin/yChar)); ! 267: break; ! 268: ! 269: case SB_THUMBPOSITION: ! 270: nScrollInc = pos - lpmv->PosV; ! 271: break; ! 272: ! 273: case SB_THUMBTRACK: ! 274: nScrollInc = pos - lpmv->PosV; ! 275: break; ! 276: ! 277: default: ! 278: nScrollInc = 0; ! 279: } ! 280: ! 281: if (nScrollInc > lpmv->RangeV-lpmv->PosV) ! 282: nScrollInc = lpmv->RangeV-lpmv->PosV; ! 283: ! 284: if (nScrollInc < -lpmv->PosV) ! 285: nScrollInc = -lpmv->PosV; ! 286: ! 287: if (nScrollInc) ! 288: { ! 289: lpmv->PosV += nScrollInc; ! 290: ! 291: if (ABS (nScrollInc) < lpmv->yWin/yChar) ! 292: ScrollWindow (hWnd, 0, -(yChar*nScrollInc), NULL, NULL); ! 293: else ! 294: InvalidateRect (hWnd, NULL, TRUE); ! 295: ! 296: SetScrollPos (hWnd, SB_VERT, lpmv->PosV, TRUE); ! 297: UpdateWindow(hWnd); ! 298: } ! 299: } ! 300: ! 301: ! 302: ! 303: void WINAPI KeyToScrollMsg ( ! 304: HWND hWnd, ! 305: WPARAM wParam) ! 306: { ! 307: int i, nKeys; ! 308: static struct ! 309: { ! 310: WORD wVirtKey; ! 311: int iMessage; ! 312: WORD wRequest; ! 313: }key2scroll [] = { ! 314: VK_HOME, WM_VSCROLL, SB_TOP, VK_END, WM_VSCROLL, ! 315: SB_BOTTOM, VK_PRIOR, WM_VSCROLL, SB_PAGEUP, VK_NEXT, ! 316: WM_VSCROLL, SB_PAGEDOWN, VK_UP, WM_VSCROLL, SB_LINEUP, ! 317: VK_DOWN, WM_VSCROLL, SB_LINEDOWN, VK_LEFT, WM_HSCROLL, ! 318: SB_LINEUP, VK_RIGHT, WM_HSCROLL, SB_LINEDOWN, ! 319: }; ! 320: ! 321: nKeys = sizeof key2scroll / sizeof key2scroll[0]; ! 322: ! 323: for (i=0; i<nKeys; i++) ! 324: { ! 325: if (wParam == key2scroll[i].wVirtKey) ! 326: { ! 327: SendMessage (hWnd, key2scroll[i].iMessage, key2scroll[i].wRequest, 0L); ! 328: return; ! 329: } ! 330: } ! 331: } ! 332: ! 333: ! 334: ! 335: void WINAPI DisplayBytes ( ! 336: HDC hDC, ! 337: RECT *pRect, ! 338: LPMEMVIEW lpmv, ! 339: LPMEMVIEW lpmvOld) ! 340: { ! 341: UINT i, r, iFirst, iLast, y; ! 342: char szBuf[MAX_PATH], szText[MAX_PATH]; ! 343: LPBYTE pMem = (LPBYTE)lpmv->lpMem; ! 344: LPBYTE pOldMem; ! 345: BYTE bRes[16]; ! 346: COLORREF crOldColor = 0; ! 347: SIZE sz; ! 348: int cx; ! 349: ! 350: if (lpmvOld != NULL) ! 351: { ! 352: pOldMem = (LPBYTE)lpmvOld->lpMem; ! 353: ! 354: /* normalize to beginning of section relative to current memory */ ! 355: (int)pOldMem += lpmvOld->nBase - lpmv->nBase; ! 356: } ! 357: ! 358: SelectObject (hDC, hFont); ! 359: SetTextColor (hDC, GetSysColor (COLOR_WINDOWTEXT)); ! 360: SetBkColor (hDC, GetSysColor (COLOR_WINDOW)); ! 361: ! 362: y = lpmv->PosV; ! 363: ! 364: iFirst = y + pRect->top/yChar-1; ! 365: ! 366: if (iFirst == 0xFFFFFFFFL) ! 367: iFirst = 0; ! 368: ! 369: iLast = min (y + pRect->bottom/yChar+1, (UINT)lpmv->nLines-1); ! 370: pMem += iFirst << 4; ! 371: pOldMem += iFirst << 4; ! 372: ! 373: if (lpmv->nExtraBytes) ! 374: iLast--; ! 375: ! 376: /* paint complete lines (lines with 16 bytes) */ ! 377: y = (iFirst - y) * yChar; ! 378: for (i = iFirst; i<iLast; i++) ! 379: { ! 380: GetBytesLine (pMem, i, lpmv->nBase, 16, szBuf); ! 381: ! 382: if (lpmvOld != NULL && ! 383: ((int)pMem-(int)lpmv->lpMem + lpmv->nBase) >= lpmvOld->nBase && ! 384: ((int)pMem-(int)lpmv->lpMem + lpmv->nBase) < (lpmvOld->nBase + lpmvOld->nSize) && ! 385: !parcmp (pMem, pOldMem, 16, bRes)) ! 386: { ! 387: /* write line number and leading space */ ! 388: strncpy (szText, szBuf, 12); ! 389: szText[12] = 0; ! 390: GetTextExtentPoint (hDC, szText, 12, &sz); ! 391: cx = xChar; ! 392: SetTextColor (hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)); ! 393: TextOut (hDC, cx, LOWORD (y), szText, 12); ! 394: ! 395: /* check each hex byte for change */ ! 396: for (r=0; r<16; r++) ! 397: { ! 398: if (bRes[r]) ! 399: SetTextColor (hDC, RGB (191, 0, 0)); ! 400: else ! 401: SetTextColor (hDC, GetSysColor(COLOR_WINDOWTEXT)); ! 402: ! 403: /* draw next byte */ ! 404: szText[0] = szBuf[3*r+12]; ! 405: szText[1] = szBuf[3*r+1+12]; ! 406: szText[2] = szBuf[3*r+2+12]; ! 407: szText[3] = 0; ! 408: cx += sz.cx; ! 409: GetTextExtentPoint (hDC, szText, 3, &sz); ! 410: TextOut (hDC, cx, LOWORD (y), szText, 3); ! 411: } ! 412: ! 413: /* check each ascii byte */ ! 414: for (r=0; r<16; r++) ! 415: { ! 416: if (bRes[r]) ! 417: SetTextColor (hDC, RGB (191, 0, 0)); ! 418: else ! 419: SetTextColor (hDC, GetSysColor(COLOR_WINDOWTEXT)); ! 420: ! 421: /* draw next byte */ ! 422: szText[0] = szBuf[r+60]; ! 423: szText[1] = 0; ! 424: cx += sz.cx; ! 425: GetTextExtentPoint (hDC, szText, 1, &sz); ! 426: TextOut (hDC, cx, LOWORD (y), szText, 3); ! 427: } ! 428: } ! 429: ! 430: else ! 431: { ! 432: SetTextColor (hDC, GetSysColor(COLOR_WINDOWTEXT)); ! 433: TextOut (hDC, xChar, LOWORD (y), szBuf, lstrlen (szBuf)); ! 434: } ! 435: ! 436: pMem += 16; ! 437: pOldMem += 16; ! 438: y += yChar; ! 439: } ! 440: ! 441: /* paint last partial line if any (line with less than 16 bytes) */ ! 442: if (lpmv->nExtraBytes) ! 443: { ! 444: GetBytesLine (pMem, i, lpmv->nBase, lpmv->nExtraBytes, szBuf); ! 445: ! 446: if (lpmvOld != NULL && ! 447: ((int)pMem-(int)lpmv->lpMem + lpmv->nBase) >= lpmvOld->nBase && ! 448: ((int)pMem-(int)lpmv->lpMem + lpmv->nBase) < (lpmvOld->nBase + lpmvOld->nSize) && ! 449: !parcmp (pMem, pOldMem, lpmv->nExtraBytes, bRes)) ! 450: { ! 451: /* write line number and leading space */ ! 452: strncpy (szText, szBuf, 12); ! 453: szText[12] = 0; ! 454: GetTextExtentPoint (hDC, szText, 12, &sz); ! 455: cx = xChar; ! 456: SetTextColor (hDC, RGB (191, 0, 0)); ! 457: TextOut (hDC, cx, LOWORD (y), szText, 12); ! 458: ! 459: /* check each hex byte for change */ ! 460: for (r=0; r<(UINT)lpmv->nExtraBytes; r++) ! 461: { ! 462: if (bRes[r]) ! 463: SetTextColor (hDC, RGB (191, 0, 0)); ! 464: else ! 465: SetTextColor (hDC, GetSysColor(COLOR_WINDOWTEXT)); ! 466: ! 467: /* draw next byte */ ! 468: szText[0] = szBuf[3*r+12]; ! 469: szText[1] = szBuf[3*r+1+12]; ! 470: szText[2] = szBuf[3*r+2+12]; ! 471: szText[3] = 0; ! 472: cx += sz.cx; ! 473: GetTextExtentPoint (hDC, szText, 3, &sz); ! 474: TextOut (hDC, cx, LOWORD (y), szText, 3); ! 475: } ! 476: ! 477: /* check each ascii byte */ ! 478: for (r=0; r<(UINT)lpmv->nExtraBytes; r++) ! 479: { ! 480: if (bRes[r]) ! 481: SetTextColor (hDC, RGB (191, 0, 0)); ! 482: else ! 483: SetTextColor (hDC, GetSysColor(COLOR_WINDOWTEXT)); ! 484: ! 485: /* draw next byte */ ! 486: szText[0] = szBuf[r+60]; ! 487: szText[1] = 0; ! 488: cx += sz.cx; ! 489: GetTextExtentPoint (hDC, szText, 1, &sz); ! 490: TextOut (hDC, cx, LOWORD (y), szText, 1); ! 491: } ! 492: } ! 493: ! 494: else ! 495: { ! 496: SetTextColor (hDC, GetSysColor(COLOR_WINDOWTEXT)); ! 497: TextOut(hDC, xChar, y, szBuf, lstrlen (szBuf)); ! 498: } ! 499: } ! 500: ! 501: SelectObject(hDC, GetStockObject(SYSTEM_FONT)); ! 502: } ! 503: ! 504: ! 505: ! 506: ! 507: ! 508: void WINAPI GetBytesLine ( ! 509: LPBYTE pBytes, ! 510: UINT LineNum, ! 511: DWORD dwBase, ! 512: int nBytes, ! 513: char *szLine) ! 514: { ! 515: int j; ! 516: unsigned char ch; ! 517: char szAscii[17]; ! 518: ! 519: wsprintf (szLine, "%#08lx ", dwBase + (LineNum*16)); ! 520: ! 521: for (j = 0; j < nBytes; j++) ! 522: { ! 523: ch = *pBytes++; ! 524: wsprintf (szLine, "%s%02X ", (LPSTR)szLine, (WORD)ch); ! 525: szAscii[j] = ((ch & 0x7F) >= ' ') ? ch : '.'; ! 526: } ! 527: ! 528: szAscii[nBytes] = 0; ! 529: wsprintf(szLine, "%-59s%s", (LPSTR)szLine, (LPSTR)szAscii); ! 530: } ! 531: ! 532: ! 533: ! 534: ! 535: BOOL WINAPI parcmp ( ! 536: LPBYTE pMem, ! 537: LPBYTE pOldMem, ! 538: int nWidth, ! 539: LPBYTE pRes) ! 540: { ! 541: BOOL bResult = TRUE; ! 542: int i; ! 543: ! 544: /* clear result array */ ! 545: for (i=0; i<16; i++) ! 546: pRes[i] = 0; ! 547: ! 548: for (i=0; i<nWidth; i++) ! 549: { ! 550: if (pMem[i] ^ pOldMem[i]) ! 551: { ! 552: pRes[i] = 1; ! 553: bResult = FALSE; ! 554: } ! 555: } ! 556: ! 557: return bResult; ! 558: } ! 559: ! 560: ! 561: ! 562: ! 563: BOOL WINAPI AddrDlgProc ( ! 564: HWND hDlg, ! 565: UINT uMsg, ! 566: WPARAM wParam, ! 567: LPARAM lParam) ! 568: { ! 569: BOOL bRet = TRUE; ! 570: char szAddr[MAX_PATH]; ! 571: int nAddr; ! 572: HWND hAddr = GetDlgItem (hDlg, IDC_ADDR); ! 573: ! 574: switch (uMsg) ! 575: { ! 576: case WM_INITDIALOG: ! 577: SetFocus (hAddr); ! 578: bRet = FALSE; ! 579: break; ! 580: ! 581: case WM_COMMAND: ! 582: switch (LOWORD (wParam)) ! 583: { ! 584: case IDC_HEX: ! 585: if (HIWORD (wParam) == BN_CLICKED) ! 586: { ! 587: GetWindowText (hAddr, szAddr, MAX_PATH); ! 588: ! 589: if (SendMessage (GetDlgItem (hDlg, IDC_HEX), BM_GETCHECK, 0, 0)) ! 590: { ! 591: /* convert to hex and return to control */ ! 592: nAddr = atoi (szAddr); ! 593: wsprintf (szAddr, "%16x", nAddr); ! 594: SetWindowText (hAddr, szAddr); ! 595: } ! 596: else ! 597: { ! 598: /* convert to decimal and return to control */ ! 599: sscanf (szAddr, "%16x", &nAddr); ! 600: SetWindowText (hAddr, itoa (nAddr, szAddr, 10)); ! 601: } ! 602: ! 603: /* select entire string for easy change */ ! 604: SendMessage (hAddr, EM_SETSEL, 0, (LONG)-1); ! 605: SetFocus (hAddr); ! 606: } ! 607: break; ! 608: ! 609: case IDOK: ! 610: GetWindowText (hAddr, szAddr, MAX_PATH); ! 611: ! 612: /* if hex, convert to decimal integer */ ! 613: if (SendMessage (GetDlgItem (hDlg, IDC_HEX), BM_GETCHECK, 0, 0)) ! 614: sscanf (szAddr, "%16x", &nAddr); ! 615: else ! 616: nAddr = atoi (szAddr); ! 617: ! 618: EndDialog (hDlg, nAddr); ! 619: break; ! 620: ! 621: case IDCANCEL: ! 622: EndDialog (hDlg, 0); ! 623: break; ! 624: } ! 625: break; ! 626: ! 627: default: ! 628: bRet = FALSE; ! 629: } ! 630: ! 631: return (bRet); ! 632: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.