APISpy32.cpp
上传用户:tzh4061
上传日期:2007-01-08
资源大小:309k
文件大小:18k
源码类别:

钩子与API截获

开发平台:

Visual C++

  1. // ----------------------------------- //
  2. //            APISpy32 v2.0            //
  3. //     Copyright 1999 Yariv Kaplan     //
  4. //          WWW.INTERNALS.COM          //
  5. // ----------------------------------- //
  6. #include <windows.h>
  7. #include "APISpy32.h"
  8. #include "LinkList.h"
  9. #include "LogAPI.h"
  10. #pragma check_stack(off)
  11. #ifdef WIN95
  12. #pragma comment(linker, "/section:.data,RWS /section:.idata,RWS /section:.bss,RWS")
  13. #pragma comment(linker, "/base:0xBFF70000")
  14. #include "Ring0.h"
  15. #endif
  16. PSTR TrimString(PSTR pszStr);
  17. char *GetParamFormat(tagParamType ParamType);
  18. char *GetParamName(tagParamType ParamType);
  19. tagParamType GetParamType(PSTR pszParameter);
  20. DWORD GetParamMask(tagParamType ParamType);
  21. void FormatString(PSTR pszSrcStr, PSTR pszDstStr, DWORD dwMaxSize);
  22. tagParamSpec ParamSpec[] = {{"INT",    PARAM_INT,    "%d",  0xFFFFFFFF},
  23.                             {"DWORD",  PARAM_DWORD,  "%u",  0xFFFFFFFF},
  24.                             {"WORD",   PARAM_WORD,   "%u",  0x0000FFFF},
  25.                             {"BYTE",   PARAM_BYTE,   "%u",  0x000000FF},
  26.                             {"PSTR",   PARAM_PSTR,   "%#x", 0xFFFFFFFF},
  27.                             {"PVOID",  PARAM_PVOID,  "%#x", 0xFFFFFFFF},
  28.                             {"PINT",   PARAM_PINT,   "%#x", 0xFFFFFFFF},
  29.                             {"PDWORD", PARAM_PDWORD, "%#x", 0xFFFFFFFF},
  30.                             {"PWORD",  PARAM_PWORD,  "%#x", 0xFFFFFFFF},
  31.                             {"PBYTE",  PARAM_PBYTE,  "%#x", 0xFFFFFFFF},
  32.                             {"HANDLE", PARAM_HANDLE, "%#x", 0xFFFFFFFF},
  33.                             {"HWND",   PARAM_HWND,   "%#x", 0xFFFFFFFF},
  34.                             {"BOOL",   PARAM_BOOL,   "%u",  0xFFFFFFFF},
  35.                             {"PWSTR",  PARAM_PWSTR,  "%#x", 0xFFFFFFFF},
  36.                             {"UNKNOWN",PARAM_UNKNOWN,"%u",  0xFFFFFFFF}};
  37. #ifdef WIN95
  38. __declspec(naked) void Ring0ModifyPageProtection()
  39. {
  40.   _asm
  41.   {
  42.     Mov EAX, ECX
  43.     Shr EAX, 22
  44.     Test DWORD PTR [0FFBFE000h + EAX * 4], 1
  45.     Jz Fail
  46.     Mov EAX, ECX
  47.     Shr EAX, 12
  48.     Mov EBX, EAX
  49.     Mov EAX, DWORD PTR [0FF800000h + EAX * 4]
  50.     Test EAX, 1
  51.     Jz Fail
  52.     Mov EAX, 1
  53.     Cmp EDX, PAGE_READWRITE
  54.     Je PageReadWrite
  55.     And DWORD PTR [0FF800000h + EBX * 4], 0xFFFFFFFD
  56.     Jmp Done
  57. PageReadWrite:
  58.     Or DWORD PTR [0FF800000h + EBX * 4], 2
  59.     Jmp Done
  60. Fail:
  61.     Xor EAX, EAX
  62. Done:
  63.     Retf
  64.   }
  65. }
  66. bool CallRing0(PVOID pvRing0FuncAddr, PVOID pvAddr, DWORD dwPageProtection)
  67. {
  68.   GDT_DESCRIPTOR *pGDTDescriptor;
  69.   GDTR gdtr;
  70.   bool Result;
  71.   _asm Sgdt [gdtr]
  72.   // Skip the null descriptor
  73.   pGDTDescriptor = (GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8);
  74.   // Search for a free GDT descriptor
  75.   for (WORD wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++)
  76.   {
  77.     if (pGDTDescriptor->Type == 0     &&
  78.         pGDTDescriptor->System == 0   &&
  79.         pGDTDescriptor->DPL == 0      &&
  80.         pGDTDescriptor->Present == 0)
  81.     {
  82.       // Found one !
  83.       // Now we need to transform this descriptor into a callgate.
  84.       // Note that we're using selector 0x28 since it corresponds
  85.       // to a ring 0 segment which spans the entire linear address
  86.       // space of the processor (0-4GB).
  87.       CALLGATE_DESCRIPTOR *pCallgate;
  88.       pCallgate = (CALLGATE_DESCRIPTOR *) pGDTDescriptor;
  89.       pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr);
  90.       pCallgate->Selector = 0x28;
  91.       pCallgate->ParamCount = 0;
  92.       pCallgate->Unused = 0;
  93.       pCallgate->Type = 0xc;
  94.       pCallgate->System = 0;
  95.       pCallgate->DPL = 3;
  96.       pCallgate->Present = 1;
  97.       pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr);
  98.       // Prepare the far call parameters
  99.       WORD CallgateAddr[3];
  100.       CallgateAddr[0] = 0x0;
  101.       CallgateAddr[1] = 0x0;
  102.       CallgateAddr[2] = (wGDTIndex << 3) | 3;
  103.       // Please fasten your seat belts!
  104.       // We're about to make a hyperspace jump into RING 0.
  105.       _asm
  106.       {
  107.         Mov ECX, [pvAddr]
  108.         Mov EDX, [dwPageProtection]
  109.         Cli
  110.         Call FWORD PTR [CallgateAddr]
  111.         Sti
  112.         Mov DWORD PTR [Result], EAX
  113.       }
  114.       
  115.       // Now free the GDT descriptor
  116.       memset(pGDTDescriptor, 0, 8);
  117.       return Result;
  118.     }
  119.     // Advance to the next GDT descriptor
  120.     pGDTDescriptor++;
  121.   }
  122.   // Whoops, the GDT is full
  123.   return false;
  124. }
  125. bool RemovePageProtection(PVOID pvAddr)
  126. {
  127.   return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READWRITE);
  128. }
  129. bool SetPageProtection(PVOID pvAddr)
  130. {
  131.   return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READONLY);
  132. }
  133. #endif
  134. void APILogFunction(tagAPIInfo *pAPIInfo, PSTR pszLogString, ...)
  135. {
  136.   va_list Marker;
  137.   DWORD dwParamValue;
  138.   char szParamStr[MAX_TEXT_LEN + 6];
  139.   char szUnicodeStr[MAX_TEXT_LEN + 1];
  140.   char cIndex;
  141.   va_start(Marker, pszLogString);
  142.   
  143.   strcpy(pszLogString, pAPIInfo->szAPIName);
  144.   strcat(pszLogString, "(");
  145.   for (cIndex = 0; cIndex < pAPIInfo->ParamCount; cIndex++)
  146.   {
  147.     dwParamValue = va_arg(Marker, DWORD);
  148.     dwParamValue &= GetParamMask(pAPIInfo->ParamList[cIndex]);
  149.     
  150.     strcat(pszLogString, GetParamName(pAPIInfo->ParamList[cIndex]));
  151.     strcat(pszLogString, ":");
  152.     wsprintf(szParamStr, GetParamFormat(pAPIInfo->ParamList[cIndex]), dwParamValue);
  153.     strcat(pszLogString, szParamStr);
  154.     switch (pAPIInfo->ParamList[cIndex])
  155.     {
  156.       case PARAM_PSTR:
  157.         strcat(pszLogString, ":");
  158.         FormatString((PSTR)dwParamValue, szParamStr, MAX_TEXT_LEN);
  159.         strcat(pszLogString, szParamStr);
  160.       break;
  161.       
  162.       case PARAM_PINT:
  163.         strcat(pszLogString, ":");
  164.         
  165.         if (IsBadReadPtr((PVOID)dwParamValue, 4) == 0)
  166.         {
  167.           wsprintf(szParamStr, "%d", *(int *)dwParamValue);
  168.           strcat(pszLogString, szParamStr);
  169.         }
  170.         else strcat(pszLogString, "?");
  171.       break;
  172.       case PARAM_PDWORD:
  173.         strcat(pszLogString, ":");
  174.         if (IsBadReadPtr((PVOID)dwParamValue, 4) == 0)
  175.         {
  176.           wsprintf(szParamStr, "%u", *(DWORD *)dwParamValue);
  177.           strcat(pszLogString, szParamStr);
  178.         }
  179.         else strcat(pszLogString, "?");
  180.       break;
  181.       case PARAM_PWORD:
  182.         strcat(pszLogString, ":");
  183.         if (IsBadReadPtr((PVOID)dwParamValue, 2) == 0)
  184.         {
  185.           wsprintf(szParamStr, "%u", LOWORD(*(WORD *)dwParamValue));
  186.           strcat(pszLogString, szParamStr);
  187.         }
  188.         else strcat(pszLogString, "?");
  189.       break;
  190.       case PARAM_PBYTE:
  191.         strcat(pszLogString, ":");
  192.         if (IsBadReadPtr((PVOID)dwParamValue, 1) == 0)
  193.         {
  194.           wsprintf(szParamStr, "%u", LOBYTE(*(BYTE *)dwParamValue));
  195.           strcat(pszLogString, szParamStr);
  196.         }
  197.         else strcat(pszLogString, "?");
  198.       break;
  199.       case PARAM_PWSTR:
  200.         strcat(pszLogString, ":");
  201.         if (IsBadReadPtr((PVOID)dwParamValue, 2) == 0 &&
  202.             IsBadStringPtrW((LPCWSTR)dwParamValue, MAX_TEXT_LEN) == 0)
  203.         {
  204.           WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)dwParamValue, MAX_TEXT_LEN, szUnicodeStr, sizeof(szUnicodeStr), NULL, NULL);
  205.           szUnicodeStr[MAX_TEXT_LEN] = '';
  206.           FormatString(szUnicodeStr, szParamStr, MAX_TEXT_LEN);
  207.           strcat(pszLogString, szParamStr);
  208.         }
  209.         else strcat(pszLogString, "?");
  210.       break;
  211.     }
  212.     strcat(pszLogString, ", ");
  213.   }
  214.   if (pAPIInfo->ParamCount > 0)
  215.     pszLogString[strlen(pszLogString) - 2] = ')';
  216.   else
  217.     strcat(pszLogString, ")");
  218.   va_end(Marker);
  219. }
  220. bool ParseAPIFile(PSTR pszFileName)
  221. {
  222.   HANDLE hFile;
  223.   HANDLE hMap;
  224.   DWORD dwIndex;
  225.   PSTR pszParameterList;
  226.   PSTR pszParameter;
  227.   PSTR pszModuleName;
  228.   PSTR pszAPIName;
  229.   PCHAR pcFile;
  230.   DWORD dwFileSize;
  231.   char cParamIndex;
  232.   tagAPIInfo *pAPIInfo;
  233.   char szAPIDefinition[1024];
  234.   
  235.   hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  236.                      OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  237.   if (hFile == INVALID_HANDLE_VALUE)
  238.     return false;
  239.   dwFileSize = GetFileSize(hFile, NULL);
  240.   if (dwFileSize == 0xFFFFFFFF)
  241.     return false;
  242.   hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  243.   if (hMap == NULL) 
  244.   {
  245.     CloseHandle(hFile);
  246.     return false;
  247.   }
  248.   pcFile = (PCHAR)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  249.   if (pcFile == NULL) 
  250.   {
  251.     CloseHandle(hMap);
  252.     CloseHandle(hFile);
  253.     return false;
  254.   }
  255.   while (dwFileSize)
  256.   {
  257.     for (dwIndex = 0; *pcFile != 13 && dwFileSize; dwIndex++)
  258.     {
  259.       szAPIDefinition[dwIndex] = *pcFile;
  260.       pcFile++;
  261.       dwFileSize--;
  262.     }
  263.     
  264.     szAPIDefinition[dwIndex] = '';
  265.     if (szAPIDefinition[0] != '')
  266.     {
  267.       pszModuleName = szAPIDefinition;
  268.       pszAPIName = strchr(pszModuleName, ':');
  269.       if (pszAPIName != NULL)
  270.       {
  271.         pszAPIName[0] = '';
  272.         pszAPIName++;
  273.         
  274.         pszParameterList = strchr(pszAPIName, '(');
  275.         if (pszParameterList != NULL)
  276.         {
  277.           pszParameterList[0] = '';
  278.           pszParameterList++;
  279.           pAPIInfo = HookAPIFunction(pszModuleName, pszAPIName, APILogFunction);
  280.           if (pAPIInfo != NULL)
  281.           {
  282.             #ifdef WINNT
  283.             pAPIInfo->szAPIName = (PSTR)malloc(strlen(pszAPIName) + 1);
  284.             #endif
  285.             if (pAPIInfo->szAPIName == NULL)
  286.             {
  287.               UnmapViewOfFile(pcFile);
  288.               CloseHandle(hMap);
  289.               CloseHandle(hFile);
  290.               return false;
  291.             }
  292.             
  293.             strcpy(pAPIInfo->szAPIName, pszAPIName);
  294.             #ifdef WIN95
  295.             pAPIInfo->hMutex = CreateMutex(NULL, FALSE, pszAPIName);
  296.             #endif
  297.             #ifdef WINNT
  298.             InitializeCriticalSection(&pAPIInfo->CriticalSection);
  299.             #endif
  300.             cParamIndex = 0;
  301.             pszParameter = strtok(pszParameterList, ",;)");
  302.             while (pszParameter != NULL)
  303.             {
  304.               pszParameter = TrimString(pszParameter);
  305.               pAPIInfo->ParamList[cParamIndex] = GetParamType(pszParameter);
  306.               cParamIndex++;
  307.               if (cParamIndex == MAX_PARAM)
  308.                 break;
  309.               pszParameter = strtok(NULL, ",;)");
  310.             }
  311.             
  312.             if (cParamIndex == MAX_PARAM)
  313.               UnhookAPIFunction(pAPIInfo);
  314.             else
  315.               pAPIInfo->ParamCount = cParamIndex;
  316.           }  
  317.         }
  318.       }
  319.     }
  320.     if (dwFileSize == 0) 
  321.       break;
  322.     pcFile += 2;
  323.     dwFileSize -= 2;
  324.   }
  325.   UnmapViewOfFile(pcFile);
  326.   CloseHandle(hMap);
  327.   CloseHandle(hFile);
  328.   return true;
  329. }
  330. void APIHandler()
  331. {
  332.   PBYTE pbAPI;
  333.   PDWORD pdwAPI;
  334.   tagAPIInfo *pAPIInfo;
  335.   PBYTE pbAfterCall;
  336.   PDWORD pdwParam;
  337.   DWORD dwParamSize;
  338.   PDWORD pdwESP;
  339.   void *pvReturnAddr;
  340.   DWORD dwReturnValue;
  341.   char szLogString[2048];
  342.   #ifdef WIN95
  343.   HANDLE hMutex;
  344.   #endif
  345.   _asm
  346.   {
  347.     Mov EAX, [EBP + 4]
  348.     Mov [pbAfterCall], EAX
  349.     Mov EAX, [EBP + 8]
  350.     Mov [pvReturnAddr], EAX
  351.     Lea EAX, [EBP + 12]
  352.     Mov [pdwParam], EAX
  353.   }
  354.   pAPIInfo = Head;
  355.   while (pAPIInfo != NULL)
  356.   {
  357.     if ((pbAfterCall - 5) == (PBYTE)pAPIInfo->APIAddress)
  358.     {
  359.       #ifdef WIN95
  360.       hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, pAPIInfo->szAPIName);
  361.       if (hMutex)
  362.         WaitForSingleObject(hMutex, INFINITE);
  363.       #endif
  364.       #ifdef WINNT
  365.       EnterCriticalSection(&pAPIInfo->CriticalSection);
  366.       #endif
  367.       
  368.       memcpy(pAPIInfo->APIAddress, pAPIInfo->Opcodes, 5);
  369.       break;
  370.     }
  371.     pAPIInfo = pAPIInfo->Next;
  372.   }
  373.   dwParamSize = pAPIInfo->ParamCount * 4;
  374.   _asm
  375.   {
  376.     Sub ESP, [dwParamSize]
  377.     Mov [pdwESP], ESP
  378.   }
  379.   memcpy(pdwESP, pdwParam, dwParamSize);
  380.   pAPIInfo->APIEnterHandler(pAPIInfo, szLogString);
  381.   pAPIInfo->APIAddress();
  382.   _asm
  383.   {
  384.     Push EAX
  385.     Mov [dwReturnValue], EAX
  386.   }
  387.   
  388.   AddLogEntry(GetCurrentProcessId(), szLogString, dwReturnValue, (PBYTE)pvReturnAddr - 5);
  389.   pbAPI = (PBYTE)pAPIInfo->APIAddress;
  390.   pbAPI[0] = 0xE8;
  391.   pdwAPI = (DWORD *)&pbAPI[1];
  392.   pdwAPI[0] = (DWORD)APIHandler - (DWORD)pbAPI - 5;
  393.   #ifdef WIN95
  394.   if (hMutex)
  395.   {
  396.     ReleaseMutex(hMutex);
  397.     CloseHandle(hMutex);
  398.   }
  399.   #endif
  400.   #ifdef WINNT
  401.   LeaveCriticalSection(&pAPIInfo->CriticalSection);
  402.   
  403.   #endif
  404.   _asm
  405.   {
  406.     Pop EAX
  407.     Mov ECX, [dwParamSize]
  408.     Mov EDX, [pvReturnAddr]
  409.     
  410.     Pop EDI
  411.     Pop ESI
  412.     Pop EBX
  413.     Mov ESP, EBP
  414.     Pop EBP
  415.     Add ESP, 8
  416.     Add ESP, ECX
  417.     Push EDX
  418.     Ret
  419.   }
  420. }
  421. bool RemoveProtection(PVOID pvAddress, tagAPIInfo *pAPIInfo)
  422. {
  423.   #ifdef WIN95
  424.   bool Result;
  425.   Result = RemovePageProtection(pvAddress);
  426.   if (Result == false)
  427.     return false;
  428.   #endif
  429.   #ifdef WINNT
  430.   MEMORY_BASIC_INFORMATION mbi;
  431.   DWORD dwProtectionFlags;
  432.   DWORD dwScratch;
  433.   BOOL Result;
  434.   // Get page protection of API
  435.   VirtualQuery(pvAddress, &mbi, sizeof(mbi));
  436.   dwProtectionFlags = mbi.Protect;
  437.   pAPIInfo->dwOldProtectionFlags = dwProtectionFlags;
  438.   // Remove page protection from API
  439.   dwProtectionFlags &= ~PAGE_READONLY;
  440.   dwProtectionFlags &= ~PAGE_EXECUTE_READ;
  441.   dwProtectionFlags |= PAGE_READWRITE;
  442.   Result = VirtualProtect(pvAddress, 4096, dwProtectionFlags, &dwScratch);
  443.   if (Result == FALSE)
  444.     return false;
  445.   #endif
  446.   return true;
  447. }
  448. tagAPIInfo *HookAPIFunction(PSTR pszModuleName,
  449.                             PSTR pszAPIName,
  450.                             tagHandlerAddr APIEnterHandler)
  451. {
  452.   HMODULE hModule;
  453.   tagAPIInfo *pAPIInfo;
  454.   tagAPIInfo *pTempAPIInfo;
  455.   PBYTE pbAPI;
  456.   PDWORD pdwAPI;
  457.   bool Result;
  458.     
  459.   hModule = GetModuleHandle(pszModuleName);
  460.   
  461.   if (hModule == NULL)
  462.     return NULL;
  463.   pbAPI = (PBYTE)GetProcAddress(hModule, pszAPIName);
  464.   if (pbAPI == NULL)
  465.     return NULL;
  466.   // Is it already hooked ?
  467.   pTempAPIInfo = Head;
  468.   while (pTempAPIInfo != NULL)
  469.   {
  470.     if (pTempAPIInfo->APIAddress == (tagAPIAddr)pbAPI)
  471.       return NULL;
  472.     pTempAPIInfo = pTempAPIInfo->Next;
  473.   }
  474.   // No, so add a new item
  475.   pAPIInfo = AddItem();
  476.   
  477.   if (pAPIInfo == NULL)
  478.     return NULL;
  479.   pAPIInfo->APIAddress = NULL;
  480.   Result = RemoveProtection(pbAPI, pAPIInfo);
  481.   if (Result == false)
  482.   {
  483.     #ifdef WINNT
  484.     RemoveItem(pAPIInfo);
  485.     #endif
  486.     return NULL;
  487.   }
  488.   // Save first 5 bytes of API
  489.   memcpy(pAPIInfo->Opcodes, pbAPI, 5);
  490.   
  491.   pAPIInfo->APIAddress = (tagAPIAddr)pbAPI;
  492.   pAPIInfo->APIEnterHandler = APIEnterHandler;
  493.   
  494.   // Write a call to the hook function
  495.   pbAPI[0] = 0xE8;
  496.   pdwAPI = (DWORD *)&pbAPI[1];
  497.   pdwAPI[0] = (DWORD)APIHandler - (DWORD)pbAPI - 5;
  498.   return pAPIInfo;
  499. }
  500. void UnhookAPIFunction(tagAPIInfo *pAPIInfo)
  501. {
  502.   bool Result;
  503.   Result = RemoveProtection(pAPIInfo->APIAddress, pAPIInfo);
  504.   if (Result == true)
  505.     memcpy(pAPIInfo->APIAddress, pAPIInfo->Opcodes, 5);
  506.   #ifdef WIN95
  507.   SetPageProtection(pAPIInfo->APIAddress);
  508.   if (pAPIInfo->hMutex)
  509.     CloseHandle(pAPIInfo->hMutex);
  510.   #endif
  511.   #ifdef WINNT
  512.   DWORD dwScratch;
  513.   DeleteCriticalSection(&pAPIInfo->CriticalSection);
  514.   VirtualProtect(pAPIInfo->APIAddress, 4096, pAPIInfo->dwOldProtectionFlags, &dwScratch);
  515.   free(pAPIInfo->szAPIName);
  516.   RemoveItem(pAPIInfo);
  517.   #endif
  518. }
  519. void UnhookAllAPIFunctions()
  520. {
  521.   tagAPIInfo *pAPIInfo;
  522.   tagAPIInfo *pTempAPIInfo;
  523.   pAPIInfo = Head;
  524.   while (pAPIInfo != NULL)
  525.   {
  526.     pTempAPIInfo = pAPIInfo->Next;
  527.     
  528.     UnhookAPIFunction(pAPIInfo);
  529.         
  530.     pAPIInfo = pTempAPIInfo;
  531.   }
  532. }
  533. PSTR TrimString(PSTR pszStr)
  534. {
  535.   PCHAR pcBlankChar;
  536.   pcBlankChar = pszStr + strlen(pszStr) - 1;
  537.   while (*pcBlankChar == ' ') 
  538.   {
  539.     pcBlankChar[0] = '';
  540.     pcBlankChar--;
  541.   }
  542.   while (*pszStr == ' ') pszStr++;
  543.   return pszStr;
  544. }
  545. char *GetParamFormat(tagParamType ParamType)
  546. {
  547.   char cIndex;
  548.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  549.     if (ParamSpec[cIndex].ParamType == ParamType)
  550.       return ParamSpec[cIndex].ParamFormat;
  551.   return ParamSpec[cIndex].ParamFormat;
  552. }
  553. char *GetParamName(tagParamType ParamType)
  554. {
  555.   char cIndex;
  556.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  557.     if (ParamSpec[cIndex].ParamType == ParamType)
  558.       return ParamSpec[cIndex].ParamName;
  559.   return ParamSpec[cIndex].ParamName;
  560. }
  561. tagParamType GetParamType(PSTR pszParameter)
  562. {
  563.   char cIndex;
  564.   strupr(pszParameter);
  565.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  566.     if (strcmp(pszParameter, ParamSpec[cIndex].ParamName) == 0)
  567.       return ParamSpec[cIndex].ParamType;
  568.   return PARAM_UNKNOWN;
  569. }
  570. DWORD GetParamMask(tagParamType ParamType)
  571. {
  572.   char cIndex;
  573.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  574.     if (ParamSpec[cIndex].ParamType == ParamType)
  575.       return ParamSpec[cIndex].dwParamMask;
  576.   return ParamSpec[cIndex].dwParamMask;
  577. }
  578. void FormatString(PSTR pszSrcStr, PSTR pszDstStr, DWORD dwMaxSize)
  579. {
  580.   DWORD dwDstSize = 0;
  581.   if (IsBadStringPtr(pszSrcStr, dwMaxSize) != 0)
  582.   {
  583.     *pszDstStr++ = '?';
  584.     *pszDstStr = '';
  585.     return;
  586.   }
  587.   *pszDstStr++ = '"';
  588.   while (*pszSrcStr != '')
  589.   {
  590.     if (*pszSrcStr == 'n')
  591.     {
  592.       *pszDstStr++ = '\';
  593.       *pszDstStr = 'n';
  594.     }
  595.     else if (*pszSrcStr == 't')
  596.     {
  597.       *pszDstStr++ = '\';
  598.       *pszDstStr = 't';
  599.     }
  600.     else if (*pszSrcStr == 'r')
  601.     {
  602.       *pszDstStr++ = '\';
  603.       *pszDstStr = 'r';
  604.     }
  605.     else *pszDstStr = *pszSrcStr;
  606.     dwDstSize++;
  607.     pszSrcStr++;
  608.     pszDstStr++;
  609.     if (dwDstSize == dwMaxSize)
  610.     {
  611.       *pszDstStr++ = '.';
  612.       *pszDstStr++ = '.';
  613.       *pszDstStr++ = '.';
  614.       break;
  615.     }
  616.   }
  617.   *pszDstStr++ = '"';
  618.   *pszDstStr = '';
  619. }
  620. BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, PVOID pvReserved)
  621. {
  622.   DWORD dwResult;
  623.   char szAPIFileName[MAX_PATH];
  624.   switch (dwReason)
  625.   {
  626.     case DLL_PROCESS_ATTACH:
  627.       dwResult = GetWindowsDirectory(szAPIFileName, MAX_PATH);
  628.       if (dwResult == 0) return false;
  629.       strcat(szAPIFileName, "\APISpy32.api");
  630.       DisableThreadLibraryCalls(hInstDLL);
  631.       ParseAPIFile(szAPIFileName);
  632.     break;
  633.     case DLL_PROCESS_DETACH:
  634.       UnhookAllAPIFunctions();
  635.       
  636.     break;
  637.   }
  638.   return TRUE;
  639. }