Ejemplo n.º 1
0
BOOL CNktStringW::Concat(__in double nSrc, __in int nDigits)
{
  WCHAR szTempW[128], szFmtW[16];

  if (nDigits < 0)
    nDigits = 0;
  if (nDigits > 15)
    nDigits = 15;
  swprintf_s(szFmtW, X_ARRAYLEN(szFmtW), L"%%.%ldf", (long)nDigits);
  swprintf_s(szTempW, X_ARRAYLEN(szTempW), szFmtW, nSrc);
  return Concat(szTempW);
}
Ejemplo n.º 2
0
BOOL CNktStringW::AppendFormatV(__in LPCSTR szFormatA, __in va_list argptr)
{
  CHAR szTempBufA[512], *szTempA;
  int nChars;
  BOOL b;

  if (szFormatA == NULL)
    return FALSE;
  nChars = _vscprintf(szFormatA, argptr);
  if (nChars > 0)
  {
    if (nChars+1 >= X_ARRAYLEN(szTempBufA))
    {
      szTempA = (LPSTR)NKT_MALLOC((size_t)(nChars+1) * sizeof(CHAR));
      if (szTempA == NULL)
        return FALSE;
    }
    else
    {
      szTempA = szTempBufA;
    }
    vsprintf_s(szTempA, (size_t)nChars+1, szFormatA, argptr);
    b = ConcatN(szTempA, (size_t)nChars);
    if (szTempA != szTempBufA)
    {
      NKT_FREE(szTempA);
    }
    if (b == FALSE)
      return FALSE;
  }
  return TRUE;
}
Ejemplo n.º 3
0
BOOL CNktStringW::Concat(__in ULONGLONG nSrc)
{
  WCHAR szTempW[128];

  swprintf_s(szTempW, X_ARRAYLEN(szTempW), L"%I64u", nSrc);
  return Concat(szTempW);
}
Ejemplo n.º 4
0
static HRESULT ProcessVariable(__in FILE *fp, __in WORD nIndex, __in TYPEATTR* lpTypeAttr,
                               __in ITypeInfo *lpTypeInfo, __in SIZE_T nIndent)
{
  CAutoVarDesc cVarDesc;
  CNktStringW cStrTempW;
  CNktComBStr bstrMemberName;
  BSTR bstr;
  HRESULT hRes;
  UINT nNamesCount;
  WORD i;
  char szBufA[32];

  hRes = cVarDesc.Set(lpTypeInfo, nIndex);
  EXIT_ON_ERROR(hRes);
  if (cVarDesc->varkind == VAR_CONST)
  {
    _tprintf_s(_T("Error: Variables should not be constants.\n"));
    return E_NOTIMPL;
  }
  hRes = lpTypeInfo->GetNames(cVarDesc->memid, &bstr, 1, &nNamesCount);
  EXIT_ON_ERROR(hRes);
  if (nNamesCount == 0 || bstr == NULL)
  {
    _tprintf_s(_T("Error: Unnamed variables are not supported.\n"));
    return E_NOTIMPL;
  }
  bstrMemberName.Attach(bstr);
  WRITEINDENT_AND_CHECK(fp, nIndent);
  if ((cVarDesc->elemdescVar.tdesc.vt & 0x0FFF) == VT_CARRAY)
  {
    // type name[n]
    cStrTempW.Empty();
    hRes = TypeDescToString(cStrTempW, &(cVarDesc->elemdescVar.tdesc.lpadesc->tdescElem), lpTypeInfo,
                            FALSE);
    EXIT_ON_ERROR(hRes);
    WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
    WRITEANSI_AND_CHECK(fp, " ");
    WRITEBSTR_AND_CHECK(fp, bstrMemberName);
    for (i=0; i<cVarDesc->elemdescVar.tdesc.lpadesc->cDims; i++)
    {
      _snprintf_s(szBufA, X_ARRAYLEN(szBufA), _TRUNCATE, "[%d]",
                  cVarDesc->elemdescVar.tdesc.lpadesc->rgbounds[i].cElements);
      WRITEANSI_AND_CHECK(fp, szBufA);
    }
  }
  else
  {
    cStrTempW.Empty();
    hRes = TypeDescToString(cStrTempW, &(cVarDesc->elemdescVar.tdesc), lpTypeInfo, FALSE);
    EXIT_ON_ERROR(hRes);
    WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
    WRITEANSI_AND_CHECK(fp, " ");
    WRITEBSTR_AND_CHECK(fp, bstrMemberName);
  }
  WRITEANSI_AND_CHECK(fp, ";\r\n");
  return S_OK;
}
Ejemplo n.º 5
0
static HRESULT GetTypeLibVersion(__in REFGUID rGuid, __out WORD &wVerMajor, __out WORD &wVerMinor)
{
  TCHAR szBuf[256], *sT;
  LONG lRes;
  DWORD dwIndex;
  WORD wMj, wMi;
  HKEY hTypeLibKey;

  wVerMajor = wVerMinor = 0;
  _sntprintf_s(szBuf, X_ARRAYLEN(szBuf), _TRUNCATE,
               _T("TypeLib\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
               rGuid.Data1, rGuid.Data2, rGuid.Data3,
               rGuid.Data4[0], rGuid.Data4[1], rGuid.Data4[2], rGuid.Data4[3],
               rGuid.Data4[4], rGuid.Data4[5], rGuid.Data4[6], rGuid.Data4[7]);
  lRes = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, szBuf, 0, KEY_READ, &hTypeLibKey);
  if (lRes != ERROR_SUCCESS)
  {
    if (lRes == ERROR_NOT_FOUND ||
        lRes == ERROR_FILE_NOT_FOUND ||
        lRes == ERROR_PATH_NOT_FOUND)
      return TYPE_E_LIBNOTREGISTERED;
    return HRESULT_FROM_WIN32(lRes);
  }
  for (dwIndex=0; ::RegEnumKey(hTypeLibKey, dwIndex, szBuf, X_ARRAYLEN(szBuf))==ERROR_SUCCESS; dwIndex++)
  {
    wMj = (WORD)_ttoi(szBuf);
    sT = _tcsrchr(szBuf, _T('.'));
    wMi = (sT != NULL) ? (WORD)_ttoi(sT+1) : 0;
    if (wMj > wVerMajor ||
        (wMj == wVerMajor && wMi > wVerMinor))
    {
      wVerMajor = wMj;
      wVerMinor = wMi;
    }
  }
  ::RegCloseKey(hTypeLibKey);
  return (wVerMajor != 0) ? S_OK : TYPE_E_LIBNOTREGISTERED;
}
Ejemplo n.º 6
0
static HRESULT ProcessHeader(__in FILE *fp, __in ITypeLib *lpTypeLib)
{
  TLIBATTR *lpLibAttr;
  CHAR szBufA[256];
  CNktComBStr bstrName, bstrDoc;
  LPWSTR sW;
  GUID sLibGuid;
  HRESULT hRes;

  WRITEANSI_AND_CHECK(fp, "// Generated .H file using Deviare's TLB-to-Header application\r\n");
  WRITEANSI_AND_CHECK(fp, "//------------------------------------------------------------\r\n");
  hRes = lpTypeLib->GetLibAttr(&lpLibAttr);
  EXIT_ON_ERROR(hRes);
  memcpy(&sLibGuid, &(lpLibAttr->guid), sizeof(sLibGuid));
  lpTypeLib->ReleaseTLibAttr(lpLibAttr);
  //----
  hRes = lpTypeLib->GetDocumentation(MEMBERID_NIL, &bstrName, &bstrDoc, 0, 0);
  EXIT_ON_ERROR(hRes);
  //----
  sW = (LPWSTR)(BSTR)bstrDoc;
  if (sW == NULL || sW[0] == 0)
    sW = (LPWSTR)(BSTR)bstrName;
  if (sW != NULL && sW[0] != 0)
  {
    WRITEANSI_AND_CHECK(fp, "// Name: ");
    WRITEWIDE_AND_CHECK(fp, sW);
    WRITEANSI_AND_CHECK(fp, "\r\n");
  }
  WRITEANSI_AND_CHECK(fp, "// Guid: ");
  _snprintf_s(szBufA, X_ARRAYLEN(szBufA), _TRUNCATE, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
              sLibGuid.Data1, sLibGuid.Data2, sLibGuid.Data3,
              sLibGuid.Data4[0], sLibGuid.Data4[1], sLibGuid.Data4[2], sLibGuid.Data4[3],
              sLibGuid.Data4[4], sLibGuid.Data4[5], sLibGuid.Data4[6], sLibGuid.Data4[7]);
  WRITEANSI_AND_CHECK(fp, szBufA);
  WRITEANSI_AND_CHECK(fp, "\r\n");
  //done
  return S_OK;
}
Ejemplo n.º 7
0
HRESULT CXmlHelper::Initialize(IXMLDOMElement *lpRootElem)
{
  TNktComPtr<IXMLDOMElement> cCurrElem, cNextElem;
  CNktComBStr cElemAttrIdBStr, cNameBstr;
  HRESULT hRes;
  SIZE_T i;
  LONG k;

  nktMemSet(aFundTypesIndexes, 0, sizeof(aFundTypesIndexes));
  hRes = GetFirstChildElement(lpRootElem, &cCurrElem);
  if (FAILED(hRes))
    return hRes;
  while (cCurrElem != NULL)
  {
    cElemAttrIdBStr.Reset();
    hRes = GetAttributeValue(cCurrElem, L"id", &cElemAttrIdBStr);
    if (FAILED(hRes))
    {
init_on_error:
      Reset();
      return hRes;
    }
    if (cElemAttrIdBStr[0] != 0)
    {
      //add this element
      if (nIdElemMapEntriesCount >= nIdElemMapEntriesSize)
      {
        ID_ELEM_MAP_ENTRY *lpNew;

        lpNew = (ID_ELEM_MAP_ENTRY*)nktMemMalloc((nIdElemMapEntriesSize+10240)*sizeof(ID_ELEM_MAP_ENTRY));
        if (lpNew == NULL) {
          hRes = E_OUTOFMEMORY;
          goto init_on_error;
        }
        nIdElemMapEntriesSize += 10240;
        if (lpIdElemMapEntries != NULL)
        {
          nktMemCopy(lpNew, lpIdElemMapEntries, nIdElemMapEntriesCount*sizeof(ID_ELEM_MAP_ENTRY));
          nktMemFree(lpIdElemMapEntries);
        }
        lpIdElemMapEntries = lpNew;
      }
      wcsncpy_s(lpIdElemMapEntries[nIdElemMapEntriesCount].szIdW, cElemAttrIdBStr, 16);
      lpIdElemMapEntries[nIdElemMapEntriesCount].szIdW[15] = 0;
      k = GetDbObjectClass(cCurrElem, 1);
      if (k == -1)
      {
        hRes = E_OUTOFMEMORY;
        goto init_on_error;
      }
      if (k == NKT_DBOBJCLASS_Fundamental)
      {
        cNameBstr.Reset();
        hRes = GetAttributeValue(cCurrElem, L"name", &cNameBstr);
        if (FAILED(hRes))
          goto init_on_error;
        if (_wcsicmp((LPWSTR)cNameBstr, L"signed char") == 0)
          k = NKT_DBFUNDTYPE_SignedByte;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"char") == 0)
          k = NKT_DBFUNDTYPE_AnsiChar;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"unsigned char") == 0)
          k = NKT_DBFUNDTYPE_UnsignedByte;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"short int") == 0)
          k = NKT_DBFUNDTYPE_SignedWord;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"short unsigned int") == 0)
          k = NKT_DBFUNDTYPE_UnsignedWord;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"int") == 0 ||
                 _wcsicmp((LPWSTR)cNameBstr, L"long int") == 0 ||
                 _wcsicmp((LPWSTR)cNameBstr, L"bool") == 0)
          k = NKT_DBFUNDTYPE_SignedDoubleWord;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"unsigned int") == 0 ||
                 _wcsicmp((LPWSTR)cNameBstr, L"long unsigned int") == 0)
          k = NKT_DBFUNDTYPE_UnsignedDoubleWord;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"long long int") == 0)
          k = NKT_DBFUNDTYPE_SignedQuadWord;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"long long unsigned int") == 0)
          k = NKT_DBFUNDTYPE_UnsignedQuadWord;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"float") == 0)
          k = NKT_DBFUNDTYPE_Float;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"double") == 0)
          k = NKT_DBFUNDTYPE_Double;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"long double") == 0)
          k = NKT_DBFUNDTYPE_LongDouble;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"wchar_t") == 0)
          k = NKT_DBFUNDTYPE_WideChar;
        else if (_wcsicmp((LPWSTR)cNameBstr, L"void") == 0)
          k = NKT_DBFUNDTYPE_Void;
        else {
          hRes = E_FAIL;
          goto init_on_error;
        }
        aFundTypesIndexes[k-NKT_DBFUNDTYPE_MIN] = 1;
      }
      else
        k = 0;
      lpIdElemMapEntries[nIdElemMapEntriesCount].nFundamentalType = (ULONG)k;
      lpIdElemMapEntries[nIdElemMapEntriesCount].lpElem = cCurrElem;
      lpIdElemMapEntries[nIdElemMapEntriesCount].lpElem->AddRef();
      nIdElemMapEntriesCount++;
    }
    //get next element
    hRes = GetNextElement(cCurrElem, &cNextElem);
    if (FAILED(hRes))
      goto init_on_error;
    cCurrElem.Attach(cNextElem.Detach());
  }
  //fast fundamental quick check
  for (k=0; k<X_ARRAYLEN(aFundTypesIndexes); k++) {
    if (aFundTypesIndexes[k] == 0) {
      hRes = E_FAIL;
      goto init_on_error;
    }
  }
  //sort elements by id
  qsort_s(lpIdElemMapEntries, nIdElemMapEntriesCount, sizeof(ID_ELEM_MAP_ENTRY), IdElemMapEntry_Compare,
          NULL);
  //find each fundamental
  nktMemSet(aFundTypesIndexes, 0, sizeof(aFundTypesIndexes));
  for (i=0; i<nIdElemMapEntriesCount; i++)
  {
    if (lpIdElemMapEntries[i].nFundamentalType != 0)
      aFundTypesIndexes[lpIdElemMapEntries[i].nFundamentalType - NKT_DBFUNDTYPE_MIN] = i;
  }
  //fast fundamental quick check (should not happen)
  for (k=0; k<X_ARRAYLEN(aFundTypesIndexes); k++) {
    if (aFundTypesIndexes[k] == 0) {
      hRes = E_FAIL;
      goto init_on_error;
    }
  }
  return S_OK;
}
Ejemplo n.º 8
0
static HRESULT ProcessFunction(__in FILE *fp, __in WORD nIndex, __in TYPEATTR* lpTypeAttr,
                               __in ITypeInfo *lpTypeInfo, __in SIZE_T nIndent, __in LPWSTR szParentThisW)
{
  CAutoFuncDesc cFuncDesc;
  CNktStringW cStrTempW;
  CNktComBStr bstrNames[MAX_FUNCTION_NAMES];
  BSTR bstr[MAX_FUNCTION_NAMES];
  HRESULT hRes;
  CNktComVariant vtValue;
  UINT i, j, nNamesCount;
  char szBufA[32];

  hRes = cFuncDesc.Set(lpTypeInfo, nIndex);
  EXIT_ON_ERROR(hRes);
  //Write return type
  cStrTempW.Empty();
  hRes = TypeDescToString(cStrTempW, &(cFuncDesc->elemdescFunc.tdesc), lpTypeInfo, FALSE);
  EXIT_ON_ERROR(hRes);
  WRITEINDENT_AND_CHECK(fp, nIndent);
  WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
  WRITEANSI_AND_CHECK(fp, " (");
  if (lpTypeAttr->typekind != TKIND_DISPATCH)
  {
    // Write calling convention
    switch (cFuncDesc->callconv)
    {
      case CC_CDECL:
        WRITEANSI_AND_CHECK(fp, "_cdecl ");
        break;
      case CC_PASCAL:
        WRITEANSI_AND_CHECK(fp, "__pascal ");
        break;
      case CC_STDCALL:
        WRITEANSI_AND_CHECK(fp, "__stdcall ");
        break;
      default:
        _tprintf_s(_T("Error: Unsupported calling convetion '%04X'.\n"), cFuncDesc->callconv);
        return E_NOTIMPL;
    }
  }
  else
  {
    WRITEANSI_AND_CHECK(fp, "__stdcall ");
  }
  WRITEANSI_AND_CHECK(fp, "*");
  // Write methodname
  //
  // Problem:  If a property has the propput or propputref attributes the
  // 'right hand side' (rhs) is *always* the last parameter and MkTypeLib
  // strips the parameter name.  Thus you will always get 1 less name
  // back from ::GetNames than normal.
  //
  // Thus for the example below
  //  [propput] void Color([in] VARIANT rgb, [in] VARIANT rgb2 );
  // without taking this into consderation the output would be
  //  [propput] void Color([in] VARIANT rgb, [in] VARIANT );
  // when it should be
  //  [propput] void Color([in] VARIANT rgb, [in] VARIANT rhs );
  //
  // Another weirdness comes from a bug (which will never be fixed)
  // where optional parameters on property functions were allowed.
  // Because they were allowed by accident people used them, so they
  // are still allowed.
  nNamesCount = 0;
  hRes = lpTypeInfo->GetNames(cFuncDesc->memid, bstr, MAX_FUNCTION_NAMES, &nNamesCount);
  EXIT_ON_ERROR(hRes);
  for (i=0; i<nNamesCount; i++)
    bstrNames[i].Attach(bstr[i]);
  // fix for 'rhs' problem
  if (nNamesCount < (UINT)cFuncDesc->cParams+1)
  {
    hRes = bstrNames[nNamesCount++].Set(L"rhs");
    EXIT_ON_ERROR(hRes);
  }
  NKT_ASSERT(nNamesCount == cFuncDesc->cParams+1);
  if ((cFuncDesc->invkind & INVOKE_PROPERTYGET) != 0)
  {
    WRITEANSI_AND_CHECK(fp, "get_");
  }
  else if ((cFuncDesc->invkind & INVOKE_PROPERTYPUT) != 0)
  {
    WRITEANSI_AND_CHECK(fp, "put_");
  }
  else if ((cFuncDesc->invkind & INVOKE_PROPERTYPUTREF) != 0)
  {
    WRITEANSI_AND_CHECK(fp, "putref_");
  }
  WRITEBSTR_AND_CHECK(fp, bstrNames[0]);
  WRITEANSI_AND_CHECK(fp, ")(");
  if (szParentThisW != NULL)
  {
    WRITEWIDE_AND_CHECK(fp, szParentThisW);
    WRITEANSI_AND_CHECK(fp, "* This");
  }
  // params have the format
  //   [attributes] type paramname
  // where attributes can be
  //   in, out, optional, string   (string is not valid for TKIND_MODULE)
  for (i=0; i<(UINT)(cFuncDesc->cParams); i++)
  {
    if (i > 0 || szParentThisW != NULL)
    {
      WRITEANSI_AND_CHECK(fp, ", ");
    }
    // type
    if ((cFuncDesc->lprgelemdescParam[i].tdesc.vt & 0x0FFF) == VT_CARRAY)
    {
      // type name[n]
      cStrTempW.Empty();
      hRes = TypeDescToString(cStrTempW, &(cFuncDesc->lprgelemdescParam[i].tdesc.lpadesc->tdescElem),
                              lpTypeInfo, FALSE);
      EXIT_ON_ERROR(hRes);
      WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
      WRITEANSI_AND_CHECK(fp, " ");
      WRITEBSTR_AND_CHECK(fp, bstrNames[i+1]);
      for (j=0; j<cFuncDesc->lprgelemdescParam[i].tdesc.lpadesc->cDims; j++)
      {
        _snprintf_s(szBufA, X_ARRAYLEN(szBufA), _TRUNCATE, "[%d]",
                    cFuncDesc->lprgelemdescParam[i].tdesc.lpadesc->rgbounds[j].cElements);
        WRITEANSI_AND_CHECK(fp, szBufA);
      }
    }
    else
    {
      cStrTempW.Empty();
      hRes = TypeDescToString(cStrTempW, &(cFuncDesc->lprgelemdescParam[i].tdesc), lpTypeInfo, FALSE);
      EXIT_ON_ERROR(hRes);
      WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
      WRITEANSI_AND_CHECK(fp, " ");
      WRITEBSTR_AND_CHECK(fp, bstrNames[i+1]);
    }
  }
  WRITEANSI_AND_CHECK(fp, ");\r\n");
  return S_OK;
}
Ejemplo n.º 9
0
static BOOL WriteString(__in FILE *fp, __in_z LPCWSTR szStringW, __in_opt SIZE_T nLength)
{
  SIZE_T i, j, nStart;
  WCHAR szTempW[32];

  if (szStringW == NULL)
    return S_OK;
  if (nLength == NKT_SIZE_T_MAX)
    nLength = wcslen(szStringW);
  for (i=0; i<nLength; i++)
  {
    nStart = i;
    for (j=0; j<X_ARRAYLEN(szTempW)-1 && i<nLength; j++)
    {
      if (iswprint(szStringW[i]) == 0 || szStringW[i] == L'\"' || szStringW[i] == L'\\')
        break;
      szTempW[j] = szStringW[i++];
    }
    if (i > nStart)
    {
      szTempW[j] = 0;
      if (fprintf(fp, "%S", szTempW) == 0)
        return FALSE;
    }
    while (i < nLength)
    {
      if (iswprint(szStringW[i]) != 0 && szStringW[i] != L'\"' && szStringW[i] != L'\\')
        break;
      switch (szStringW[i])
      {
        case L'\"':
          if (fprintf(fp, "\\\"") == 0)
            return FALSE;
          break;
        case L'\\':
          if (fprintf(fp, "\\\\") == 0)
            return FALSE;
          break;
        case L'\a':
          if (fprintf(fp, "\\a") == 0)
            return FALSE;
          break;
        case L'\b':
          if (fprintf(fp, "\\b") == 0)
            return FALSE;
          break;
        case L'\f':
          if (fprintf(fp, "\\f") == 0)
            return FALSE;
          break;
        case L'\n':
          if (fprintf(fp, "\\n") == 0)
            return FALSE;
          break;
        case L'\r':
          if (fprintf(fp, "\\r") == 0)
            return FALSE;
          break;
        case L'\t':
          if (fprintf(fp, "\\t") == 0)
            return FALSE;
          break;
        case L'\v':
          if (fprintf(fp, "\\v") == 0)
            return FALSE;
          break;
        case L'\0':
          if (fprintf(fp, "\\0") == 0)
            return FALSE;
          break;
        default:
          if (fprintf(fp, "\\x%02X", szStringW[i]) == 0)
            return FALSE;
          break;
      }
      i++;
    }
  }
  return TRUE;
}
Ejemplo n.º 10
0
DWORD CNktHookLib::RemoteHook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags)
{
  DWORD dwOsErr;

  if (dwPid == 0)
    return ERROR_INVALID_PARAMETER;
  if (lpInternals != NULL)
  {
    NktHookLib::CNktAutoFastMutex cAutoLock(&(int_data->cMtx));
    NktHookLib::CProcessesHandles::CEntryPtr cProcEntry;
    NktHookLib::CHookEntry *lpHookEntry, **lpNewEntriesList;
    BYTE aNewCode[0x80 + HOOKENG_MAX_STUB_SIZE];
    SIZE_T nSize, nHookIdx;
    LPBYTE lpPtr;
    DWORD dw;
    NTSTATUS nNtStatus;

    if (aHookInfo == 0 || nCount == 0)
      return ERROR_INVALID_PARAMETER;
    for (nHookIdx=0; nHookIdx<nCount; nHookIdx++)
    {
      if (aHookInfo[nHookIdx].lpProcToHook == NULL ||
          aHookInfo[nHookIdx].lpNewProcAddr == NULL)
        return ERROR_INVALID_PARAMETER;
      aHookInfo[nHookIdx].nHookId = 0;
      aHookInfo[nHookIdx].lpCallOriginal = NULL;
    }
    //get process handle
    cProcEntry.Attach(int_data->cProcHdrMgr.Get(dwPid));
    if (cProcEntry == NULL)
      return ERROR_ACCESS_DENIED;
    //create entries for each item
    lpNewEntriesList = (NktHookLib::CHookEntry**)NktHookLibHelpers::MemAlloc(nCount*sizeof(NktHookLib::CHookEntry*));
    if (lpNewEntriesList != NULL)
    {
      dwOsErr = NO_ERROR;
      NktHookLibHelpers::MemSet(lpNewEntriesList, 0, nCount * sizeof(NktHookLib::CHookEntry*));
    }
    else
    {
      dwOsErr = ERROR_NOT_ENOUGH_MEMORY;
    }
    for (nHookIdx=0; nHookIdx<nCount && dwOsErr==NO_ERROR; nHookIdx++)
    {
      //allocate new entry
      lpHookEntry = new NktHookLib::CHookEntry(cProcEntry);
      if (lpHookEntry == NULL)
      {
        dwOsErr = ERROR_NOT_ENOUGH_MEMORY;
        continue;
      }
      lpNewEntriesList[nHookIdx] = lpHookEntry;
      lpHookEntry->lpOrigProc = (LPBYTE)(aHookInfo[nHookIdx].lpProcToHook);
      if ((dwFlags & NKTHOOKLIB_DontSkipInitialJumps) == 0)
      {
        lpHookEntry->lpOrigProc = lpHookEntry->SkipJumpInstructions(lpHookEntry->lpOrigProc);
        if (lpHookEntry->lpOrigProc == NULL)
        {
          dwOsErr = ERROR_ACCESS_DENIED;
          continue;
        }
      }
      lpHookEntry->lpNewProc = (LPBYTE)(aHookInfo[nHookIdx].lpNewProcAddr);
      //read original stub and create new one
      dwOsErr = lpHookEntry->CreateStub(int_data->sOptions.bOutputDebug,
                                        ((dwFlags & NKTHOOKLIB_DontSkipAnyJumps) == 0) ? TRUE : FALSE);
      if (dwOsErr != NO_ERROR)
        continue;
      //calculate inject code size and offset to data
      switch (cProcEntry->GetPlatform())
      {
        case NKTHOOKLIB_PRocessPlatformX86:
          lpHookEntry->nInjCodeAndDataSize = 0x2A + lpHookEntry->nNewStubSize;
          break;
#if defined _M_X64
        case NKTHOOKLIB_PRocessPlatformX64:
          lpHookEntry->nInjCodeAndDataSize = 0x41 + lpHookEntry->nNewStubSize;
          break;
#endif //_M_X64
      }
      //allocate memory for inject code in target process
      NKT_ASSERT(lpHookEntry->nInjCodeAndDataSize < NKTHOOKLIB_PROCESS_MEMBLOCK_SIZE);
      lpHookEntry->lpInjCodeAndData = cProcEntry->AllocateStub(lpHookEntry->lpOrigProc);
      if (lpHookEntry->lpInjCodeAndData == NULL)
      {
        dwOsErr = ERROR_NOT_ENOUGH_MEMORY;
        continue;
      }
      //setup code
      switch (cProcEntry->GetPlatform())
      {
        case NKTHOOKLIB_PRocessPlatformX86:
          NktHookLibHelpers::MemSet(aNewCode, 0x00, 8);                            //flags location
          NktHookLibHelpers::MemSet(aNewCode+0x08, 0x90, 8);                       //NOPs for hotpatching double hooks
          aNewCode[0x10] = 0x50;                                                   //push  eax
          aNewCode[0x11] = 0xB8;                                                   //mov   eax, ADDR lpInjCode
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x12)) = (ULONG)(lpHookEntry->lpInjCodeAndData);
          aNewCode[0x16] = 0xF7;                                                   //test  dword ptr [eax], 00000101h
          aNewCode[0x17] = 0x00;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x18)) = 0x00000101;
          aNewCode[0x1C] = 0x75;                                                   //jne   @@1 ;if disabled/uninst
          aNewCode[0x1D] = 0x06;
          aNewCode[0x1E] = 0x58;                                                   //pop   eax
          aNewCode[0x1F] = 0xE9;                                                   //jmp   hooked proc
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x20)) = (ULONG)(lpHookEntry->lpNewProc) -
                                                     (ULONG)(lpHookEntry->lpInjCodeAndData) - 0x24;
          aNewCode[0x24] = 0x58;                                                   //@@1: pop   eax
          lpHookEntry->lpCall2Orig = lpHookEntry->lpInjCodeAndData + 0x25;
          NktHookLibHelpers::MemCopy(aNewCode+0x25, lpHookEntry->aNewStub, lpHookEntry->nNewStubSize); //new stub
          aNewCode[0x25+lpHookEntry->nNewStubSize] = 0xE9;                         //jmp original proc after stub
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x26+lpHookEntry->nNewStubSize)) =
                                         (ULONG)(lpHookEntry->lpOrigProc) + (ULONG)(lpHookEntry->nOriginalStubSize) -
                                         (ULONG)(lpHookEntry->lpInjCodeAndData+0x2A+lpHookEntry->nNewStubSize);
          break;

#if defined _M_X64
        case NKTHOOKLIB_PRocessPlatformX64:
          NktHookLibHelpers::MemSet(aNewCode, 0x00, 8);                            //flags location
          NktHookLibHelpers::MemSet(aNewCode+0x08, 0x90, 8);                       //NOPs for hotpatching double hooks
          aNewCode[0x10] = 0x50;                                                   //push  rax
          aNewCode[0x11] = 0x48;                                                   //mov   rax, ADDR lpInjCode
          aNewCode[0x12] = 0xB8;
          *((ULONGLONG NKT_UNALIGNED*)(aNewCode+0x13)) = (ULONGLONG)(lpHookEntry->lpInjCodeAndData);
          aNewCode[0x1B] = 0xF7;                                                   //test  dword ptr [rax], 00000101h
          aNewCode[0x1C] = 0x00;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x1D)) = 0x00000101;
          aNewCode[0x21] = 0x75;                                                   //jne   @@1 ;if disabled/uninst
          aNewCode[0x22] = 0x0F;
          aNewCode[0x23] = 0x58;                                                   //pop   rax
          aNewCode[0x24] = 0xFF;                                                   //jmp   hooked proc
          aNewCode[0x25] = 0x25;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x26)) = 0;
          *((ULONGLONG NKT_UNALIGNED*)(aNewCode+0x2A)) = (ULONGLONG)(lpHookEntry->lpNewProc);
          aNewCode[0x32] = 0x58;                                                   //@@1: pop   rax
          lpHookEntry->lpCall2Orig = lpHookEntry->lpInjCodeAndData+0x33;
          NktHookLibHelpers::MemCopy(aNewCode+0x33, lpHookEntry->aNewStub, lpHookEntry->nNewStubSize); //new stub
          aNewCode[0x33+lpHookEntry->nNewStubSize] = 0xFF;                         //jmp original proc after stub
          aNewCode[0x34+lpHookEntry->nNewStubSize] = 0x25;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x35+lpHookEntry->nNewStubSize)) = 0;
          *((ULONGLONG NKT_UNALIGNED*)(aNewCode+0x39+lpHookEntry->nNewStubSize)) =
                                             (ULONGLONG)(lpHookEntry->lpOrigProc + lpHookEntry->nOriginalStubSize);
          break;
#endif //_M_X64
      }
      if (NktHookLibHelpers::WriteMem(cProcEntry->GetHandle(), lpHookEntry->lpInjCodeAndData, aNewCode,
                                      lpHookEntry->nInjCodeAndDataSize) == FALSE)
      {
        dwOsErr = ERROR_ACCESS_DENIED;
        continue;
      }
      //replace original proc with a jump
      dw = (DWORD)(lpHookEntry->lpInjCodeAndData+8) - (DWORD)(lpHookEntry->lpOrigProc) - 5;
      lpHookEntry->aJumpStub[0] = 0xE9; //JMP
      lpHookEntry->aJumpStub[1] = (BYTE)( dw        & 0xFF);
      lpHookEntry->aJumpStub[2] = (BYTE)((dw >>  8) & 0xFF);
      lpHookEntry->aJumpStub[3] = (BYTE)((dw >> 16) & 0xFF);
      lpHookEntry->aJumpStub[4] = (BYTE)((dw >> 24) & 0xFF);
      //set id
#if defined _M_IX86
      lpHookEntry->nId = (SIZE_T)lpHookEntry ^ 0x34B68363UL; //odd number to avoid result of zero
#elif defined _M_X64
      lpHookEntry->nId = (SIZE_T)lpHookEntry ^ 0x34B68364A3CE19F3ui64; //odd number to avoid result of zero
#endif
      //done
      aHookInfo[nHookIdx].nHookId = lpHookEntry->nId;
      aHookInfo[nHookIdx].lpCallOriginal = lpHookEntry->lpCall2Orig;
    }
    //hook new items
    if (dwOsErr == NO_ERROR)
    {
      NktHookLib::CNktThreadSuspend::CAutoResume cAutoResume(&(int_data->cThreadSuspender));
      NktHookLib::CNktThreadSuspend::IP_RANGE sIpRanges[MAX_SUSPEND_IPRANGES];
      SIZE_T k, k2, nThisRoundSuspCount;
      MEMORY_BASIC_INFORMATION sMbi;
      HOOK_INFO sHooks[64];
      DWORD dwNewProt, dwOldProt;

      for (nHookIdx=nThisRoundSuspCount=0; nHookIdx<nCount && dwOsErr==NO_ERROR; )
      {
        if (nThisRoundSuspCount == 0)
        {
          //suspend threads
          nThisRoundSuspCount = (nCount-nHookIdx > MAX_SUSPEND_IPRANGES) ? MAX_SUSPEND_IPRANGES : (nCount-nHookIdx);
          for (k=0; k<nThisRoundSuspCount; k++)
          {
            sIpRanges[k].nStart = (SIZE_T)(lpNewEntriesList[nHookIdx+k]->lpOrigProc);
            sIpRanges[k].nEnd = sIpRanges[k].nStart + HOOKENG_JUMP_TO_HOOK_SIZE;
          }
          dwOsErr = NO_ERROR;
          if (int_data->sOptions.bSuspendThreads != FALSE)
            dwOsErr = int_data->cThreadSuspender.SuspendAll(cProcEntry->GetPid(), sIpRanges, nThisRoundSuspCount);
          if (dwOsErr != NO_ERROR)
          {
err_uninstall_and_destroy:
            for (nHookIdx=k2=0; nHookIdx<nCount; nHookIdx++)
            {
              if (lpNewEntriesList[nHookIdx]->nInstalledCode != 0)
              {
                sHooks[k2++].nHookId = lpNewEntriesList[nHookIdx]->nId;
                if (k2 >= X_ARRAYLEN(sHooks))
                {
                  Unhook(sHooks, k2);
                  k2 = 0;
                }
              }
            }
            if (k2 > 0)
              Unhook(sHooks, k2);
            continue;
          }
        }
        for (k=0; k<nThisRoundSuspCount; k++)
        {
          k2 = 0;
          lpPtr = lpNewEntriesList[nHookIdx+k]->lpOrigProc;
          NktHookLibHelpers::MemSet(&sMbi, 0, sizeof(sMbi));
          nNtStatus = NktHookLib::NktNtQueryVirtualMemory(cProcEntry->GetHandle(), lpPtr, MyMemoryBasicInformation,
                                                         &sMbi, sizeof(sMbi), &k2);
          dwNewProt = PAGE_EXECUTE_WRITECOPY;
          if (NT_SUCCESS(nNtStatus))
          {
            switch (sMbi.Protect & 0xFF)
            {
              case PAGE_NOACCESS:
              case PAGE_READONLY:
              case PAGE_READWRITE:
                dwNewProt = PAGE_READWRITE;
                break;
              case PAGE_WRITECOPY:
                dwNewProt = PAGE_WRITECOPY;
                break;
              case PAGE_EXECUTE:
              case PAGE_EXECUTE_READ:
              case PAGE_EXECUTE_READWRITE:
                dwNewProt = PAGE_EXECUTE_READWRITE;
                break;
            }
          }
          //change protection if needed
          if (dwNewProt != (sMbi.Protect & 0xFF))
          {
            dwOldProt = 0;
            nSize = HOOKENG_JUMP_TO_HOOK_SIZE;
            nNtStatus = NktHookLib::NktNtProtectVirtualMemory(cProcEntry->GetHandle(), (PVOID*)&lpPtr, &nSize,
                                                             dwNewProt, &dwOldProt);
            if (!NT_SUCCESS(nNtStatus))
            {
              dwOsErr = NktHookLib::NktRtlNtStatusToDosError(nNtStatus);
              if (dwOsErr == 0)
                dwOsErr = ERROR_NOT_SUPPORTED;
              int_data->cThreadSuspender.ResumeAll();
              goto err_uninstall_and_destroy;
            }
          }
          //replace each entry point
          k2 = (NktHookLibHelpers::WriteMem(cProcEntry->GetHandle(), lpNewEntriesList[nHookIdx+k]->lpOrigProc,
                                            lpNewEntriesList[nHookIdx+k]->aJumpStub,
                                            HOOKENG_JUMP_TO_HOOK_SIZE) != FALSE) ? 1 : 0;
          //restore protection
          if (dwNewProt != (sMbi.Protect & 0xFF))
          {
            lpPtr = lpNewEntriesList[nHookIdx+k]->lpOrigProc;
            nSize = HOOKENG_JUMP_TO_HOOK_SIZE;
            NktHookLib::NktNtProtectVirtualMemory(cProcEntry->GetHandle(), (PVOID*)&lpPtr, &nSize, dwOldProt, &dw);
          }
          //check write operation result
          if (k2 == 0)
          {
            dwOsErr = ERROR_ACCESS_DENIED;
            int_data->cThreadSuspender.ResumeAll();
            goto err_uninstall_and_destroy;
          }
          //flush instruction cache
          NktHookLib::NktNtFlushInstructionCache(cProcEntry->GetHandle(), lpNewEntriesList[nHookIdx+k]->lpOrigProc, 32);
          //mark as installed
          lpNewEntriesList[nHookIdx+k]->nInstalledCode = 1;
        }
        //advance count
        nHookIdx += nThisRoundSuspCount;
        //check if we can proceed with the next hook with this
        nThisRoundSuspCount = 0;
        for (k=nHookIdx; k<nCount; k++)
        {
          k2 = (SIZE_T)(lpNewEntriesList[k]->lpOrigProc);
          if (int_data->cThreadSuspender.CheckIfThreadIsInRange(k2, k2+HOOKENG_JUMP_TO_HOOK_SIZE) == FALSE)
            break;
          nThisRoundSuspCount++;
        }
        if (nThisRoundSuspCount == 0)
        {
          //resume threads
          int_data->cThreadSuspender.ResumeAll();
        }
      }
    }
    //done... move to the final list or delete on error
    if (dwOsErr == NO_ERROR)
    {
      for (nHookIdx=0; nHookIdx<nCount; nHookIdx++)
      {
        lpNewEntriesList[nHookIdx]->dwFlags = dwFlags;
        if (int_data->sOptions.bOutputDebug != FALSE)
        {
          NktHookLibHelpers::DebugPrint("NktHookLib: Hook installed. Proc @ 0x%IX -> 0x%IX (Stub @ 0x%IX) \r\n",
                    (SIZE_T)(lpNewEntriesList[nHookIdx]->lpOrigProc), (SIZE_T)(lpNewEntriesList[nHookIdx]->lpNewProc),
                    (SIZE_T)(lpNewEntriesList[nHookIdx]->lpInjCodeAndData));
        }
        int_data->cHooksList.PushTail(lpNewEntriesList[nHookIdx]);
      }
    }
    else
    {
      for (nHookIdx=0; nHookIdx<nCount; nHookIdx++)
        delete lpNewEntriesList[nHookIdx];
    }
    if (lpNewEntriesList != NULL)
      NktHookLibHelpers::MemFree(lpNewEntriesList);
  }