home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / w32assist.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  15.9 KB  |  581 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <vd2/system/w32assist.h>
  28. #include <vd2/system/text.h>
  29. #include <vd2/system/vdstl.h>
  30.  
  31. bool VDIsForegroundTaskW32() {
  32.     HWND hwndFore = GetForegroundWindow();
  33.  
  34.     if (!hwndFore)
  35.         return false;
  36.  
  37.     DWORD dwProcessId = 0;
  38.     GetWindowThreadProcessId(hwndFore, &dwProcessId);
  39.  
  40.     return dwProcessId == GetCurrentProcessId();
  41. }
  42.  
  43. LPVOID VDConvertThreadToFiberW32(LPVOID parm) {
  44.     typedef LPVOID (WINAPI *tpConvertThreadToFiber)(LPVOID p);
  45.     static tpConvertThreadToFiber ctof = (tpConvertThreadToFiber)GetProcAddress(GetModuleHandle("kernel32"), "ConvertThreadToFiber");
  46.  
  47.     if (!ctof)
  48.         return NULL;
  49.  
  50.     return ctof(parm);
  51. }
  52.  
  53. void VDSwitchToFiberW32(LPVOID fiber) {
  54.     typedef void (WINAPI *tpSwitchToFiber)(LPVOID p);
  55.     static tpSwitchToFiber stof = (tpSwitchToFiber)GetProcAddress(GetModuleHandle("kernel32"), "SwitchToFiber");
  56.  
  57.     if (stof)
  58.         stof(fiber);
  59. }
  60.  
  61. int VDGetSizeOfBitmapHeaderW32(const BITMAPINFOHEADER *pHdr) {
  62.     int palents = 0;
  63.  
  64.     if ((pHdr->biCompression == BI_RGB || pHdr->biCompression == BI_RLE4 || pHdr->biCompression == BI_RLE8) && pHdr->biBitCount <= 8) {
  65.         palents = pHdr->biClrUsed;
  66.         if (!palents)
  67.             palents = 1 << pHdr->biBitCount;
  68.     }
  69.     int size = pHdr->biSize + palents * sizeof(RGBQUAD);
  70.  
  71.     if (pHdr->biSize < sizeof(BITMAPV4HEADER) && pHdr->biCompression == BI_BITFIELDS)
  72.         size += sizeof(DWORD) * 3;
  73.  
  74.     return size;
  75. }
  76.  
  77. void VDSetWindowTextW32(HWND hwnd, const wchar_t *s) {
  78.     if (VDIsWindowsNT()) {
  79.         SetWindowTextW(hwnd, s);
  80.     } else {
  81.         SetWindowTextA(hwnd, VDTextWToA(s).c_str());
  82.     }
  83. }
  84.  
  85. void VDSetWindowTextFW32(HWND hwnd, const wchar_t *format, ...) {
  86.     va_list val;
  87.  
  88.     va_start(val, format);
  89.     {
  90.         wchar_t buf[512];
  91.         int r = vswprintf(buf, 512, format, val);
  92.  
  93.         if ((unsigned)r < 512) {
  94.             VDSetWindowTextW32(hwnd, buf);
  95.             va_end(val);
  96.             return;
  97.         }
  98.     }
  99.  
  100.     VDStringW s;
  101.     s.append_vsprintf(format, val);
  102.     VDSetWindowTextW32(hwnd, s.c_str());
  103.  
  104.     va_end(val);
  105. }
  106.  
  107. VDStringW VDGetWindowTextW32(HWND hwnd) {
  108.     union {
  109.         wchar_t w[256];
  110.         char a[512];
  111.     } buf;
  112.  
  113.     if (VDIsWindowsNT()) {
  114.         int len = GetWindowTextLengthW(hwnd);
  115.  
  116.         if (len > 255) {
  117.             vdblock<wchar_t> tmp(len + 1);
  118.             len = GetWindowTextW(hwnd, tmp.data(), tmp.size());
  119.  
  120.             VDStringW text(tmp.data(), len);
  121.             return text;
  122.         } else if (len > 0) {
  123.             len = GetWindowTextW(hwnd, buf.w, 256);
  124.  
  125.             VDStringW text(buf.w, len);
  126.             return text;
  127.         }
  128.     } else {
  129.         int len = GetWindowTextLengthA(hwnd);
  130.  
  131.         if (len > 511) {
  132.             vdblock<char> tmp(len + 1);
  133.             len = GetWindowTextA(hwnd, tmp.data(), tmp.size());
  134.  
  135.             VDStringW text(VDTextAToW(tmp.data(), len));
  136.             return text;
  137.         } else if (len > 0) {
  138.             len = GetWindowTextA(hwnd, buf.a, 512);
  139.  
  140.             VDStringW text(VDTextAToW(buf.a, len));
  141.             return text;
  142.         }
  143.     }
  144.  
  145.     return VDStringW();
  146. }
  147.  
  148. void VDAppendMenuW32(HMENU hmenu, UINT flags, UINT id, const wchar_t *text){
  149.     if (VDIsWindowsNT()) {
  150.         AppendMenuW(hmenu, flags, id, text);
  151.     } else {
  152.         AppendMenuA(hmenu, flags, id, VDTextWToA(text).c_str());
  153.     }
  154. }
  155.  
  156. void VDCheckMenuItemByCommandW32(HMENU hmenu, UINT cmd, bool checked) {
  157.     CheckMenuItem(hmenu, cmd, checked ? MF_BYCOMMAND|MF_CHECKED : MF_BYCOMMAND|MF_UNCHECKED);
  158. }
  159.  
  160. void VDCheckRadioMenuItemByCommandW32(HMENU hmenu, UINT cmd, bool checked) {
  161.     MENUITEMINFOA mii;
  162.  
  163.     mii.cbSize = sizeof(MENUITEMINFOA);
  164.     mii.fMask = MIIM_FTYPE | MIIM_STATE;
  165.     if (GetMenuItemInfo(hmenu, cmd, FALSE, &mii)) {
  166.         mii.fType |= MFT_RADIOCHECK;
  167.         mii.fState &= ~MFS_CHECKED;
  168.         if (checked)
  169.             mii.fState |= MFS_CHECKED;
  170.         SetMenuItemInfo(hmenu, cmd, FALSE, &mii);
  171.     }
  172. }
  173.  
  174. void VDEnableMenuItemByCommandW32(HMENU hmenu, UINT cmd, bool checked) {
  175.     EnableMenuItem(hmenu, cmd, checked ? MF_BYCOMMAND|MF_ENABLED : MF_BYCOMMAND|MF_GRAYED);
  176. }
  177.  
  178. VDStringW VDGetMenuItemTextByCommandW32(HMENU hmenu, UINT cmd) {
  179.     VDStringW s;
  180.  
  181.     if (VDIsWindowsNT()) {
  182.         MENUITEMINFOW mmiW;
  183.         vdfastfixedvector<wchar_t, 256> bufW;
  184.  
  185.         mmiW.cbSize        = MENUITEMINFO_SIZE_VERSION_400W;
  186.         mmiW.fMask        = MIIM_TYPE;
  187.         mmiW.fType        = MFT_STRING;
  188.         mmiW.dwTypeData    = NULL;
  189.         mmiW.cch        = 0;        // required to avoid crash on NT4
  190.  
  191.         if (GetMenuItemInfoW(hmenu, cmd, FALSE, &mmiW)) {
  192.             bufW.resize(mmiW.cch + 1, 0);
  193.             ++mmiW.cch;
  194.             mmiW.dwTypeData = bufW.data();
  195.  
  196.             if (GetMenuItemInfoW(hmenu, cmd, FALSE, &mmiW))
  197.                 s = bufW.data();
  198.         }
  199.     } else {
  200.         MENUITEMINFOA mmiA;
  201.         vdfastfixedvector<char, 256> bufA;
  202.  
  203.         mmiA.cbSize        = MENUITEMINFO_SIZE_VERSION_400A;
  204.         mmiA.fMask        = MIIM_TYPE;
  205.         mmiA.fType        = MFT_STRING;
  206.         mmiA.dwTypeData    = NULL;
  207.  
  208.         if (GetMenuItemInfoA(hmenu, cmd, FALSE, &mmiA)) {
  209.             bufA.resize(mmiA.cch + 1, 0);
  210.             ++mmiA.cch;
  211.             mmiA.dwTypeData = bufA.data();
  212.  
  213.             if (GetMenuItemInfoA(hmenu, cmd, FALSE, &mmiA))
  214.                 s = VDTextAToW(bufA.data());
  215.         }
  216.     }
  217.  
  218.     return s;
  219. }
  220.  
  221. void VDSetMenuItemTextByCommandW32(HMENU hmenu, UINT cmd, const wchar_t *text) {
  222.     if (VDIsWindowsNT()) {
  223.         MENUITEMINFOW mmiW;
  224.  
  225.         mmiW.cbSize        = MENUITEMINFO_SIZE_VERSION_400W;
  226.         mmiW.fMask        = MIIM_TYPE;
  227.         mmiW.fType        = MFT_STRING;
  228.         mmiW.dwTypeData    = (LPWSTR)text;
  229.  
  230.         SetMenuItemInfoW(hmenu, cmd, FALSE, &mmiW);
  231.     } else {
  232.         MENUITEMINFOA mmiA;
  233.         VDStringA textA(VDTextWToA(text));
  234.  
  235.         mmiA.cbSize        = MENUITEMINFO_SIZE_VERSION_400A;
  236.         mmiA.fMask        = MIIM_TYPE;
  237.         mmiA.fType        = MFT_STRING;
  238.         mmiA.dwTypeData    = (LPSTR)textA.c_str();
  239.  
  240.         SetMenuItemInfoA(hmenu, cmd, FALSE, &mmiA);
  241.     }
  242. }
  243.  
  244. LRESULT    VDDualCallWindowProcW32(WNDPROC wp, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  245.     return (IsWindowUnicode(hwnd) ? CallWindowProcW : CallWindowProcA)(wp, hwnd, msg, wParam, lParam);
  246. }
  247.  
  248. LRESULT VDDualDefWindowProcW32(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  249.     return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam);
  250. }
  251.  
  252. EXECUTION_STATE VDSetThreadExecutionStateW32(EXECUTION_STATE esFlags) {
  253.     EXECUTION_STATE es = 0;
  254.  
  255.     // SetThreadExecutionState(): requires Windows 98+/2000+.
  256.     typedef EXECUTION_STATE (WINAPI *tSetThreadExecutionState)(EXECUTION_STATE);
  257.     static tSetThreadExecutionState pFunc = (tSetThreadExecutionState)GetProcAddress(GetModuleHandle("kernel32"), "SetThreadExecutionState");
  258.  
  259.     if (pFunc)
  260.         es = pFunc(esFlags);
  261.  
  262.     return es;
  263. }
  264.  
  265. bool VDSetFilePointerW32(HANDLE h, sint64 pos, DWORD dwMoveMethod) {
  266.     LONG posHi = (LONG)(pos >> 32);
  267.     DWORD result = SetFilePointer(h, (LONG)pos, &posHi, dwMoveMethod);
  268.  
  269.     if (result != INVALID_SET_FILE_POINTER)
  270.         return true;
  271.  
  272.     DWORD dwError = GetLastError();
  273.  
  274.     return (dwError == NO_ERROR);
  275. }
  276.  
  277. bool VDGetFileSizeW32(HANDLE h, sint64& size) {
  278.     DWORD dwSizeHigh;
  279.     DWORD dwSizeLow = GetFileSize(h, &dwSizeHigh);
  280.  
  281.     if (dwSizeLow == (DWORD)-1 && GetLastError() != NO_ERROR)
  282.         return false;
  283.  
  284.     size = dwSizeLow + ((sint64)dwSizeHigh << 32);
  285.     return true;
  286. }
  287.  
  288. #if !defined(_MSC_VER) || _MSC_VER < 1300
  289. HMODULE VDGetLocalModuleHandleW32() {
  290.     MEMORY_BASIC_INFORMATION meminfo;
  291.     static HMODULE shmod = (VirtualQuery(&VDGetLocalModuleHandleW32, &meminfo, sizeof meminfo), (HMODULE)meminfo.AllocationBase);
  292.  
  293.     return shmod;
  294. }
  295. #endif
  296.  
  297. bool VDDrawTextW32(HDC hdc, const wchar_t *s, int nCount, LPRECT lpRect, UINT uFormat) {
  298.     RECT r;
  299.     if (VDIsWindowsNT()) {
  300.         // If multiline and vcentered (not normally supported...)
  301.         if (!((uFormat ^ DT_VCENTER) & (DT_VCENTER|DT_SINGLELINE))) {
  302.             uFormat &= ~DT_VCENTER;
  303.  
  304.             r = *lpRect;
  305.             if (!DrawTextW(hdc, s, nCount, &r, uFormat | DT_CALCRECT))
  306.                 return false;
  307.  
  308.             int dx = ((lpRect->right - lpRect->left) - (r.right - r.left)) >> 1;
  309.             int dy = ((lpRect->bottom - lpRect->top) - (r.bottom - r.top)) >> 1;
  310.  
  311.             r.left += dx;
  312.             r.right += dx;
  313.             r.top += dy;
  314.             r.bottom += dy;
  315.             lpRect = &r;
  316.         }
  317.  
  318.         return !!DrawTextW(hdc, s, nCount, lpRect, uFormat);
  319.     } else {
  320.         VDStringA strA(VDTextWToA(s, nCount));
  321.  
  322.         // If multiline and vcentered (not normally supported...)
  323.         if (!((uFormat ^ DT_VCENTER) & (DT_VCENTER|DT_SINGLELINE))) {
  324.             uFormat &= ~DT_VCENTER;
  325.  
  326.             r = *lpRect;
  327.             if (!DrawTextA(hdc, strA.data(), strA.size(), &r, uFormat | DT_CALCRECT))
  328.                 return false;
  329.  
  330.             int dx = ((lpRect->right - lpRect->left) - (r.right - r.left)) >> 1;
  331.             int dy = ((lpRect->bottom - lpRect->top) - (r.bottom - r.top)) >> 1;
  332.  
  333.             r.left += dx;
  334.             r.right += dx;
  335.             r.top += dy;
  336.             r.bottom += dy;
  337.             lpRect = &r;
  338.         }
  339.  
  340.         return !!DrawTextA(hdc, strA.data(), strA.size(), lpRect, uFormat);
  341.     }
  342. }
  343.  
  344. bool VDPatchModuleImportTableW32(HMODULE hmod, const char *srcModule, const char *name, void *pCompareValue, void *pNewValue, void *volatile *ppOldValue) {
  345.     char *pBase = (char *)hmod;
  346.  
  347.     __try {
  348.         // The PEheader offset is at hmod+0x3c.  Add the size of the optional header
  349.         // to step to the section headers.
  350.  
  351.         const uint32 peoffset = ((const long *)pBase)[15];
  352.         const uint32 signature = *(uint32 *)(pBase + peoffset);
  353.  
  354.         if (signature != IMAGE_NT_SIGNATURE)
  355.             return false;
  356.  
  357.         const IMAGE_FILE_HEADER *pHeader = (const IMAGE_FILE_HEADER *)(pBase + peoffset + 4);
  358.  
  359.         // Verify the PE optional structure.
  360.  
  361.         if (pHeader->SizeOfOptionalHeader < 104)
  362.             return false;
  363.  
  364.         // Find import header.
  365.  
  366.         const IMAGE_IMPORT_DESCRIPTOR *pImportDir;
  367.         int nImports;
  368.  
  369.         switch(*(short *)((char *)pHeader + IMAGE_SIZEOF_FILE_HEADER)) {
  370.  
  371. #ifdef _M_AMD64
  372.         case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
  373.             {
  374.                 const IMAGE_OPTIONAL_HEADER64 *pOpt = (IMAGE_OPTIONAL_HEADER64 *)((const char *)pHeader + sizeof(IMAGE_FILE_HEADER));
  375.  
  376.                 if (pOpt->NumberOfRvaAndSizes < 2)
  377.                     return false;
  378.  
  379.                 pImportDir = (const IMAGE_IMPORT_DESCRIPTOR *)(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  380.                 nImports = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
  381.             }
  382.             break;
  383. #else
  384.         case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
  385.             {
  386.                 const IMAGE_OPTIONAL_HEADER32 *pOpt = (IMAGE_OPTIONAL_HEADER32 *)((const char *)pHeader + sizeof(IMAGE_FILE_HEADER));
  387.  
  388.                 if (pOpt->NumberOfRvaAndSizes < 2)
  389.                     return false;
  390.  
  391.                 pImportDir = (const IMAGE_IMPORT_DESCRIPTOR *)(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  392.                 nImports = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
  393.             }
  394.             break;
  395. #endif
  396.  
  397.         default:        // reject PE32+
  398.             return false;
  399.         }
  400.  
  401.         // Hmmm... no imports?
  402.  
  403.         if ((const char *)pImportDir == pBase)
  404.             return false;
  405.  
  406.         // Scan down the import entries.  We are looking for MSVFW32.
  407.  
  408.         int i;
  409.  
  410.         for(i=0; i<nImports; ++i) {
  411.             if (!_stricmp(pBase + pImportDir[i].Name, srcModule))
  412.                 break;
  413.         }
  414.  
  415.         if (i >= nImports)
  416.             return false;
  417.  
  418.         // Found it.  Start scanning MSVFW32 imports until we find DrawDibDraw.
  419.  
  420.         const long *pImports = (const long *)(pBase + pImportDir[i].OriginalFirstThunk);
  421.         void * volatile *pVector = (void * volatile *)(pBase + pImportDir[i].FirstThunk);
  422.  
  423.         while(*pImports) {
  424.             if (*pImports >= 0) {
  425.                 const char *pName = pBase + *pImports + 2;
  426.  
  427.                 if (!strcmp(pName, name)) {
  428.  
  429.                     // Found it!  Reset the protection.
  430.  
  431.                     DWORD dwOldProtect;
  432.  
  433.                     if (VirtualProtect((void *)pVector, sizeof(void *), PAGE_EXECUTE_READWRITE, &dwOldProtect)) {
  434.                         if (ppOldValue) {
  435.                             for(;;) {
  436.                                 void *old = *pVector;
  437.                                 if (pCompareValue && pCompareValue != old)
  438.                                     return false;
  439.  
  440.                                 *ppOldValue = old;
  441.                                 if (old == VDAtomicCompareExchangePointer(pVector, pNewValue, old))
  442.                                     break;
  443.                             }
  444.                         } else {
  445.                             *pVector = pNewValue;
  446.                         }
  447.  
  448.                         VirtualProtect((void *)pVector, sizeof(void *), dwOldProtect, &dwOldProtect);
  449.  
  450.                         return true;
  451.                     }
  452.  
  453.                     break;
  454.                 }
  455.             }
  456.  
  457.             ++pImports;
  458.             ++pVector;
  459.         }
  460.     } __except(1) {
  461.     }
  462.  
  463.     return false;
  464. }
  465.  
  466. bool VDPatchModuleExportTableW32(HMODULE hmod, const char *name, void *pCompareValue, void *pNewValue, void *volatile *ppOldValue) {
  467.     char *pBase = (char *)hmod;
  468.  
  469.     __try {
  470.         // The PEheader offset is at hmod+0x3c.  Add the size of the optional header
  471.         // to step to the section headers.
  472.  
  473.         const uint32 peoffset = ((const long *)pBase)[15];
  474.         const uint32 signature = *(uint32 *)(pBase + peoffset);
  475.  
  476.         if (signature != IMAGE_NT_SIGNATURE)
  477.             return false;
  478.  
  479.         const IMAGE_FILE_HEADER *pHeader = (const IMAGE_FILE_HEADER *)(pBase + peoffset + 4);
  480.  
  481.         // Verify the PE optional structure.
  482.  
  483.         if (pHeader->SizeOfOptionalHeader < 104)
  484.             return false;
  485.  
  486.         // Find export directory.
  487.  
  488.         const IMAGE_EXPORT_DIRECTORY *pExportDir;
  489.  
  490.         switch(*(short *)((char *)pHeader + IMAGE_SIZEOF_FILE_HEADER)) {
  491.  
  492. #ifdef _M_AMD64
  493.         case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
  494.             {
  495.                 const IMAGE_OPTIONAL_HEADER64 *pOpt = (IMAGE_OPTIONAL_HEADER64 *)((const char *)pHeader + sizeof(IMAGE_FILE_HEADER));
  496.  
  497.                 if (pOpt->NumberOfRvaAndSizes < 1)
  498.                     return false;
  499.  
  500.                 DWORD exportDirRVA = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  501.  
  502.                 if (!exportDirRVA)
  503.                     return false;
  504.  
  505.                 pExportDir = (const IMAGE_EXPORT_DIRECTORY *)(pBase + exportDirRVA);
  506.             }
  507.             break;
  508. #else
  509.         case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
  510.             {
  511.                 const IMAGE_OPTIONAL_HEADER32 *pOpt = (IMAGE_OPTIONAL_HEADER32 *)((const char *)pHeader + sizeof(IMAGE_FILE_HEADER));
  512.  
  513.                 if (pOpt->NumberOfRvaAndSizes < 1)
  514.                     return false;
  515.  
  516.                 DWORD exportDirRVA = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  517.  
  518.                 if (!exportDirRVA)
  519.                     return false;
  520.  
  521.                 pExportDir = (const IMAGE_EXPORT_DIRECTORY *)(pBase + exportDirRVA);
  522.             }
  523.             break;
  524. #endif
  525.  
  526.         default:        // reject PE32+
  527.             return false;
  528.         }
  529.  
  530.         // Scan for the export name.
  531.         DWORD nameCount = pExportDir->AddressOfNames;
  532.         const DWORD *nameRVAs = (const DWORD *)(pBase + pExportDir->AddressOfNames);
  533.         const WORD *nameOrdinals = (const WORD *)(pBase + pExportDir->AddressOfNameOrdinals);
  534.         DWORD *functionTable = (DWORD *)(pBase + pExportDir->AddressOfFunctions);
  535.  
  536.         for(DWORD i=0; i<nameCount; ++i) {
  537.             DWORD nameRVA = nameRVAs[i];
  538.             const char *pName = (const char *)(pBase + nameRVA);
  539.  
  540.             // compare names
  541.             if (!strcmp(pName, name)) {
  542.  
  543.                 // name matches -- look up the function entry
  544.                 WORD ordinal = nameOrdinals[i];
  545.                 DWORD *pRVA = &functionTable[ordinal];
  546.                 
  547.                 // Reset the protection.
  548.  
  549.                 DWORD newRVA = (DWORD)pNewValue - (DWORD)pBase;
  550.  
  551.                 DWORD dwOldProtect;
  552.                 if (VirtualProtect((void *)pRVA, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &dwOldProtect)) {
  553.                     if (ppOldValue) {
  554.                         for(;;) {
  555.                             DWORD oldRVA = *pRVA;
  556.                             void *old = pBase + oldRVA;
  557.                             if (pCompareValue && pCompareValue != old)
  558.                                 return false;
  559.  
  560.                             *ppOldValue = pBase + oldRVA;
  561.                             if (oldRVA == VDAtomicInt::staticCompareExchange((volatile int *)pRVA, newRVA, oldRVA))
  562.                                 break;
  563.                         }
  564.                     } else {
  565.                         *pRVA = newRVA;
  566.                     }
  567.  
  568.                     VirtualProtect((void *)pRVA, sizeof(DWORD), dwOldProtect, &dwOldProtect);
  569.  
  570.                     return true;
  571.                 }
  572.  
  573.                 break;
  574.             }
  575.         }
  576.     } __except(1) {
  577.     }
  578.  
  579.     return false;
  580. }
  581.