最近突发奇想,想做一个刷IP的软件,由于一直使用C#编程,基本框架做起来相当简单,唯一比较郁闷的是c#中没有现成的清除本地cookie和IE临时文件夹的方法(用来清除统计代码的cookies,^_^很邪恶吧),话说回来,c#好用,可惜权限比较低,一些涉及系统内部的操作,只好使用c++和c#混合编程的方法了。

本文中涉及到的dll文件下载

在window xp SP3+vs2008 中测试成功~

如果直接用c++写dll,在c#中调用起来比较麻烦,我选择使用ATL的方式编写一个com库,写好后直接在c#或者其他编程语言(VB,Delphi等)中直接引用库就可以了~

以下代码提供了几个封装好的方法:

  1. ClearCookie 清除cookie
  2. ClearInternetTempFile 清除Temporary Internet Files中的临时文件
  3. ClearSystemTemp 清除系统缓存
  4. ClearIEUrlHistory 清除IE地址栏历史记录
  5. ClearAutoFormHistory 清除自动表单记录
  6. ClearAutoPasswordHistory 清除自动密码记录
  7. ClearFavoriteFolder 清理收藏夹
  8. ClearAutoRASHistory 清除ADSL拨号历史记录
create-new-atl-project

新建一个ATL项目

随后添加一个ATL 简单对象和一个C++类,ATL对象用来为c#提供接口,c++类则存放基本算法代码。

create-new-atl-simple-object

新建一个ATL简单对象

c++代码中编写了一些辅助函数,用于在ATL中调用

#include "StdAfx.h"
#include "innerapi.h"

innerapi::innerapi(void)
{
}

innerapi::~innerapi(void)
{
}

BOOL innerapi::EmptyDirectory(LPCTSTR szPath, BOOL bDeleteDesktopIni, BOOL bWipeIndexDat)
{
 WIN32_FIND_DATA wfd;
 HANDLE hFind;
 CString sFullPath;
 CString sFindFilter;
 DWORD dwAttributes = 0;

 sFindFilter = szPath;
 sFindFilter += _T("\\*.*");
 if ((hFind = FindFirstFile(sFindFilter, &wfd)) == INVALID_HANDLE_VALUE)
 {
  return FALSE;
 }

 do
 {
  if (_tcscmp(wfd.cFileName, _T(".")) == 0 ||
   _tcscmp(wfd.cFileName, _T("..")) == 0 ||
   (bDeleteDesktopIni == FALSE && _tcsicmp(wfd.cFileName, _T("desktop.ini")) == 0))
  {
   continue;
  }

  sFullPath = szPath;
  sFullPath += _T('\\');
  sFullPath += wfd.cFileName;

  //去掉只读属性
  dwAttributes = GetFileAttributes(sFullPath);
  if (dwAttributes & FILE_ATTRIBUTE_READONLY)
  {
   dwAttributes &= ~FILE_ATTRIBUTE_READONLY;
   SetFileAttributes(sFullPath, dwAttributes);
  }

  if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  {
   EmptyDirectory(sFullPath, bDeleteDesktopIni, bWipeIndexDat);
   RemoveDirectory(sFullPath);
  }
  else
  {
   if (bWipeIndexDat && _tcsicmp(wfd.cFileName, _T("index.dat")) == 0)
   {
    WipeFile(szPath, wfd.cFileName);
   }
   DeleteFile(sFullPath);
  }
 }
 while (FindNextFile(hFind, &wfd));
 FindClose(hFind);

 return TRUE;
}

BOOL innerapi::WipeFile(LPCTSTR szDir, LPCTSTR szFile)
{
 CString sPath;
 HANDLE hFile;
 DWORD dwSize;
 DWORD dwWrite;
 char sZero[SWEEP_BUFFER_SIZE];
 memset(sZero, 0, SWEEP_BUFFER_SIZE);

 sPath = szDir;
 sPath += _T('\\');
 sPath += szFile;

 hFile = CreateFile(sPath, GENERIC_WRITE,
  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
  FILE_ATTRIBUTE_NORMAL, NULL);
 if (hFile == INVALID_HANDLE_VALUE)
 {
  return FALSE;
 }

 dwSize = GetFileSize(hFile, NULL);

 //skip file header (actually, I don't know the file format of index.dat)
 dwSize -= 64;
 SetFilePointer(hFile, 64, NULL, FILE_BEGIN);

 while (dwSize > 0)
 {
  if (dwSize > SWEEP_BUFFER_SIZE)
  {
   WriteFile(hFile, sZero, SWEEP_BUFFER_SIZE, &dwWrite, NULL);
   dwSize -= SWEEP_BUFFER_SIZE;
  }
  else
  {
   WriteFile(hFile, sZero, dwSize, &dwWrite, NULL);
   break;
  }
 }

 CloseHandle(hFile);
 return TRUE;
}

BOOL innerapi::DeleteUrlCache(DEL_CACHE_TYPE type)
{
    BOOL bRet = FALSE;
 HANDLE hEntry;
    LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry = NULL; 
    DWORD dwEntrySize;

  //delete the files
 dwEntrySize = 0;
    hEntry = FindFirstUrlCacheEntry(NULL, NULL, &dwEntrySize);
 lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
    hEntry = FindFirstUrlCacheEntry(NULL, lpCacheEntry, &dwEntrySize);
 if (!hEntry)
 {
  goto cleanup;
 }

 do
    {
  if (type == File &&
   !(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
  {
   DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
  }
  else if (type == Cookie &&
   (lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
  {
   DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
  }

  dwEntrySize = 0;
  FindNextUrlCacheEntry(hEntry, NULL, &dwEntrySize);
  delete [] lpCacheEntry;
  lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
 }
 while (FindNextUrlCacheEntry(hEntry, lpCacheEntry, &dwEntrySize));

 bRet = TRUE;
cleanup:
 if (lpCacheEntry)
 {
  delete [] lpCacheEntry;
 }
    return bRet;
}

BOOL innerapi::RegSetPrivilege(HKEY hKey, LPCTSTR pszSubKey,
         SECURITY_DESCRIPTOR* pSD, BOOL bRecursive)
{
 BOOL bRet = FALSE;
    HKEY hSubKey = NULL;
    LONG lRetCode;
 LPTSTR pszKeyName = NULL;;
 DWORD dwSubKeyCnt;
 DWORD dwMaxSubKey;
 DWORD dwValueCnt;
 DWORD dwMaxValueName;
 DWORD dwMaxValueData;
 DWORD i;

 if (!pszSubKey)
  goto cleanup;

 // open the key for WRITE_DAC access
 lRetCode = RegOpenKeyEx(hKey, pszSubKey, 0, WRITE_DAC, &hSubKey);
 if(lRetCode != ERROR_SUCCESS)
  goto cleanup;

 // apply the security descriptor to the registry key
 lRetCode = RegSetKeySecurity(hSubKey,
  (SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, pSD);
 if( lRetCode != ERROR_SUCCESS )
  goto cleanup;

 if (bRecursive)
 {
  // reopen the key for KEY_READ access
  RegCloseKey(hSubKey);
  hSubKey = NULL;
  lRetCode = RegOpenKeyEx(hKey, pszSubKey, 0, KEY_READ, &hSubKey);
  if(lRetCode != ERROR_SUCCESS)
   goto cleanup;

  // first get an info about this subkey ...
  lRetCode = RegQueryInfoKey(hSubKey, 0, 0, 0, &dwSubKeyCnt, &dwMaxSubKey,
   0, &dwValueCnt, &dwMaxValueName, &dwMaxValueData, 0, 0);
  if( lRetCode != ERROR_SUCCESS )
   goto cleanup;

  // enumerate the subkeys and call RegTreeWalk() recursivly
  pszKeyName = new TCHAR [MAX_PATH + 1];
  for (i=0 ; i<dwSubKeyCnt; i++)
  {
   lRetCode = RegEnumKey(hSubKey, i, pszKeyName, MAX_PATH + 1);
   if(lRetCode == ERROR_SUCCESS)
   {
    RegSetPrivilege(hSubKey, pszKeyName, pSD, TRUE);
   }
   else if(lRetCode == ERROR_NO_MORE_ITEMS)
   {
    break;
   }
  }
  delete [] pszKeyName ;
 }

 bRet = TRUE; // indicate success

cleanup:
 if (hSubKey)
 {
  RegCloseKey(hSubKey);
 }
    return bRet;
}

//判断系统类型
BOOL innerapi::IsWindowsNT()
{
 BOOL bRet = FALSE;
 BOOL bOsVersionInfoEx;
 OSVERSIONINFOEX osvi;

 // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
 // If that fails, try using the OSVERSIONINFO structure.
 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
 {
  // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
   return bRet;
 }

 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion <= 4)
 {
  bRet = TRUE;
 }

 return bRet;
}

BOOL innerapi::IsWindows2k()
{
 BOOL bRet = FALSE;
 BOOL bOsVersionInfoEx;
 OSVERSIONINFOEX osvi;

 // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
 // If that fails, try using the OSVERSIONINFO structure.
 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
 {
  // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
   return bRet;
 }

 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5)
 {
  bRet = TRUE;
 }

 return bRet;
}

BOOL innerapi::GetUserSid(PSID* ppSid)
{
 HANDLE hToken;
 BOOL bRes;
 DWORD cbBuffer, cbRequired;
 PTOKEN_USER pUserInfo;

 // The User's SID can be obtained from the process token
 bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
 if (FALSE == bRes)
 {
  return FALSE;
 }

 // Set buffer size to 0 for first call to determine
 // the size of buffer we need.
 cbBuffer = 0;
 bRes = GetTokenInformation(hToken, TokenUser, NULL, cbBuffer, &cbRequired);
 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
 {
  return FALSE;
 }

 // Allocate a buffer for our token user data
 cbBuffer = cbRequired;
 pUserInfo = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbBuffer);
 if (NULL == pUserInfo)
 {
  return FALSE;
 }

 // Make the "real" call
 bRes = GetTokenInformation(hToken, TokenUser, pUserInfo, cbBuffer, &cbRequired);
 if (FALSE == bRes)
 {
  return FALSE;
 }

 // Make another copy of the SID for the return value
 cbBuffer = GetLengthSid(pUserInfo->User.Sid);

 *ppSid = (PSID) HeapAlloc(GetProcessHeap(), 0, cbBuffer);
 if (NULL == *ppSid)
 {
  return FALSE;
 }

 bRes = CopySid(cbBuffer, *ppSid, pUserInfo->User.Sid);
 if (FALSE == bRes)
 {
     HeapFree(GetProcessHeap(), 0, *ppSid);
  return FALSE;
 }

 bRes = HeapFree(GetProcessHeap(), 0, pUserInfo);

 return TRUE;
}

void innerapi::GetSidString(PSID pSid, LPTSTR szBuffer)
{
 //convert SID to string
 SID_IDENTIFIER_AUTHORITY *psia = ::GetSidIdentifierAuthority( pSid );
 DWORD dwTopAuthority = psia->Value[5];
 _stprintf(szBuffer, _T("S-1-%lu"), dwTopAuthority);

 TCHAR szTemp[32];
 int iSubAuthorityCount = *(GetSidSubAuthorityCount(pSid));
 for (int i = 0; i<iSubAuthorityCount; i++)
 {
  DWORD dwSubAuthority = *(GetSidSubAuthority(pSid, i));
  _stprintf(szTemp, _T("%lu"), dwSubAuthority);
  _tcscat(szBuffer, _T("-"));
  _tcscat(szBuffer, szTemp);
 }
}

BOOL innerapi::GetOldSD(HKEY hKey, LPCTSTR pszSubKey, BYTE** pSD)
{
 BOOL bRet = FALSE;
 HKEY hNewKey = NULL;
 DWORD dwSize = 0;
    LONG lRetCode;
 *pSD = NULL;

 lRetCode = RegOpenKeyEx(hKey, pszSubKey, 0, READ_CONTROL, &hNewKey);
 if(lRetCode != ERROR_SUCCESS)
  goto cleanup;

 lRetCode = RegGetKeySecurity(hNewKey,
  (SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, *pSD, &dwSize);
 if (lRetCode == ERROR_INSUFFICIENT_BUFFER)
 {
  *pSD = new BYTE[dwSize];
  lRetCode = RegGetKeySecurity(hNewKey,
   (SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, *pSD, &dwSize);
  if(lRetCode != ERROR_SUCCESS)
  {
   delete *pSD;
   *pSD = NULL;
   goto cleanup;
  }
 }
 else if (lRetCode != ERROR_SUCCESS)
  goto cleanup;

 bRet = TRUE; // indicate success

cleanup:
 if (hNewKey)
 {
  RegCloseKey(hNewKey);
 }
    return bRet;
}

BOOL innerapi::CreateNewSD(PSID pSid, SECURITY_DESCRIPTOR* pSD, PACL* ppDacl)
{
 BOOL bRet = FALSE;
    PSID pSystemSid = NULL;
    SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
 ACCESS_ALLOWED_ACE* pACE = NULL;
    DWORD dwAclSize;
 DWORD dwAceSize;

    // prepare a Sid representing local system account
    if(!AllocateAndInitializeSid(&sia, 1, SECURITY_LOCAL_SYSTEM_RID,
        0, 0, 0, 0, 0, 0, 0, &pSystemSid))
 {
        goto cleanup;
    }

    // compute size of new acl
    dwAclSize = sizeof(ACL) + 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
  GetLengthSid(pSid) + GetLengthSid(pSystemSid);

    // allocate storage for Acl
    *ppDacl = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize);
    if(*ppDacl == NULL)
  goto cleanup;

    if(!InitializeAcl(*ppDacl, dwAclSize, ACL_REVISION))
        goto cleanup;

//    if(!AddAccessAllowedAce(pDacl, ACL_REVISION, KEY_WRITE, pSid))
//  goto cleanup;

    // add current user
 dwAceSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid);
 pACE = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAceSize);

 pACE->Mask = KEY_READ | KEY_WRITE | KEY_ALL_ACCESS;
 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
 pACE->Header.AceSize = dwAceSize;

 memcpy(&pACE->SidStart, pSid, GetLengthSid(pSid));
 if (!AddAce(*ppDacl, ACL_REVISION, MAXDWORD, pACE, dwAceSize))
  goto cleanup;

    // add local system account
 HeapFree(GetProcessHeap(), 0, pACE);
 pACE = NULL;
 dwAceSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSystemSid);
 pACE = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAceSize);

 pACE->Mask = KEY_READ | KEY_WRITE | KEY_ALL_ACCESS;
 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
 pACE->Header.AceSize = dwAceSize;

 memcpy(&pACE->SidStart, pSystemSid, GetLengthSid(pSystemSid));
 if (!AddAce(*ppDacl, ACL_REVISION, MAXDWORD, pACE, dwAceSize))
  goto cleanup;

 if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
        goto cleanup;

    if(!SetSecurityDescriptorDacl(pSD, TRUE, *ppDacl, FALSE))
        goto cleanup;

 bRet = TRUE; // indicate success

cleanup:
 if(pACE != NULL)
  HeapFree(GetProcessHeap(), 0, pACE);
    if(pSystemSid != NULL)
        FreeSid(pSystemSid);

    return bRet;
}

ATL中的代码

// histroy.cpp : Chistroy 的实现

#include "stdafx.h"
#include "histroy.h"

// Chistroy

STDMETHODIMP Chistroy::ClearCookie(VARIANT_BOOL* ret)
{
 // TODO: 在此添加实现代码
 TCHAR szPath[MAX_PATH]; 

 api.DeleteUrlCache(api.Cookie);
  if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_COOKIES, FALSE))
  {//得到目录,并清空
   api.EmptyDirectory(szPath);
  }
 return S_OK;
}

STDMETHODIMP Chistroy::ClearInternetTempFile(VARIANT_BOOL* ret)
{
 // TODO: 在此添加实现代码
 // //清internet临时文件
    TCHAR szPath[MAX_PATH];
 api.DeleteUrlCache(api.File);
  if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_INTERNET_CACHE, FALSE))
  {  //得到临时目录,并清空它.
   api.EmptyDirectory(szPath);
  }
 return S_OK;
}

STDMETHODIMP Chistroy::ClearSystemTemp(VARIANT_BOOL* ret)
{
 // TODO: 在此添加实现代码
 // //清系统临时文件夹
 TCHAR szPath[MAX_PATH]; 
 if (GetTempPath(MAX_PATH, szPath))//得到系统临时目录
  {
   api.EmptyDirectory(szPath, TRUE);
  }

 return S_OK;
}

STDMETHODIMP Chistroy::ClearIEUrlHistory(VARIANT_BOOL* ret)
{
 //浏览器地址栏历史地址的清除
 SHDeleteKey(HKEY_CURRENT_USER,
   _T("Software\\Microsoft\\Internet Explorer\\TypedURLs"));
 return S_OK;
}

STDMETHODIMP Chistroy::ClearAutoFormHistory(VARIANT_BOOL* ret)
{
 // 清除表单自动完成历史记录
      CString sKey;
      DWORD dwRet;

 if (api.IsWindows2k() || api.IsWindowsNT())//先判断系统
  {
   CString sBaseKey;
   SECURITY_DESCRIPTOR NewSD;
   BYTE* pOldSD;
   PACL pDacl = NULL;
   PSID pSid = NULL;
   TCHAR szSid[256];
   if (api.GetUserSid(&pSid))
   {
    //get the hiden key name
    api.GetSidString(pSid, szSid);

    sKey = _T("Software\\Microsoft\\Protected Storage System Provider\\");
    sKey += szSid;

    //get old SD
    sBaseKey = sKey;
    api.GetOldSD(HKEY_CURRENT_USER, sBaseKey, &pOldSD);

    //set new SD and then clear
    if (api.CreateNewSD(pSid, &NewSD, &pDacl))
    {
     api.RegSetPrivilege(HKEY_CURRENT_USER, sKey, &NewSD, FALSE);

     sKey += _T("\\Data");
     api.RegSetPrivilege(HKEY_CURRENT_USER, sKey, &NewSD, FALSE);

     sKey += _T("\\e161255a-37c3-11d2-bcaa-00c04fd929db");
     api.RegSetPrivilege(HKEY_CURRENT_USER, sKey, &NewSD, TRUE);

     dwRet = SHDeleteKey(HKEY_CURRENT_USER, sKey);
    }

    if (pDacl != NULL)
     HeapFree(GetProcessHeap(), 0, pDacl);

    //restore old SD
    if (pOldSD)
    {
     api.RegSetPrivilege(HKEY_CURRENT_USER, sBaseKey,
      (SECURITY_DESCRIPTOR*)pOldSD, FALSE);
     delete pOldSD;
    }
   }
   if (pSid)
    HeapFree(GetProcessHeap(), 0, pSid);
  }

  //win9x
  DWORD dwSize = MAX_PATH;
  TCHAR szUserName[MAX_PATH];
  GetUserName(szUserName, &dwSize);

  sKey = _T("Software\\Microsoft\\Protected Storage System Provider\\");
  sKey += szUserName;
  sKey += _T("\\Data\\e161255a-37c3-11d2-bcaa-00c04fd929db");
  dwRet = SHDeleteKey(HKEY_LOCAL_MACHINE, sKey);
 return S_OK;
}

STDMETHODIMP Chistroy::ClearAutoPasswordHistory(VARIANT_BOOL* ret)
{
 // 清除自动密码历史记录
SHDeleteKey(HKEY_CURRENT_USER,
   _T("Software\\Microsoft\\Internet Explorer\\IntelliForms"));
 return S_OK;
}

STDMETHODIMP Chistroy::ClearFavoriteFolder(VARIANT_BOOL* ret)
{
 //清收藏夹中的内容
 TCHAR szPath[MAX_PATH]; 
 if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, FALSE))
 { //得到目录,并清空
   api.EmptyDirectory(szPath);
 }
 return S_OK;
}

STDMETHODIMP Chistroy::ClearAutoRASHistory(VARIANT_BOOL* ret)
{
 // 清RAS自动拨号历史记录
 SHDeleteKey(HKEY_CURRENT_USER,
   _T("Software\\Microsoft\\RAS Autodial\\Addresses"));
 return S_OK;
}

可以在c#中直接调用就可以了

add-in-csharp

在c#中添加引用

c#清除cookies

最后提供一个dll文件下载