Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

Visual C++ 2008 Feature Pack Beta

Вышла Visual C++ 2008 Feature Pack Beta вместе с Visual C++ 2008 Feature Pack Beta Documentation.

Размер апдейта несколько смущает - 303.51М. В составе:

  1. Standard C++ Library TR1 Extensions

    Microsoft's implementation includes support for fixed size arrays, function objects, hash tables, regular expressions, template metaprogramming, template types for aggregating related objects, and random number generation.

    Some features of TR1, such as the mathematical functions and certain C99 additions, are not included in the Visual C++ implementation of TR1.

  2. MFC Feature Pack for Visual C++ 2008

    MSOffice2007Demo

This Feature Pack Beta release may fail to install if you do not have a complete installation of Visual Studio 2008 on your system. To workaround this issue, ensure your original Visual Studio 2008 installation source (network path or DVD) is available when installing the Feature Pack.

Напомню, что MFC стала expanded за счет библиотеки BCGControlBar Pro и при беглом взгляде она хорошо ощущается - внешний вид, функционал, дизайн, производительность, переделанные примеры. Классы переименованы в CMFCXyz.

Примеры, кстати, находятся в каталоге C:\Program Files\Microsoft Visual Studio 9.0\Samples\1033\AllVCLanguageSamples.zip\C++\MFC\Visual C++ 2008 Feature Pack.

На блоге Visual C++ Team Blog есть интересный пост Q&A on our TR1 implementation о Feature Pack TR1.

Google KAK

Firefox 2. Похоже, проблемы целлюлита, месячных и плохих зубов уже не актуальны. Google знает!

как заткнуть эту ебучую телегу

  • как завязать галстук
  • как разрушить свой моск
  • как похудеть
  • как встречать 2008 год
  • как убивали спартак
  • как правильно целоваться

Run as interactive user from service

The code below runs a program on interactive desktop with logged on user privileges, as it was started by user himself. Must be executed by Local System, for example, by Windows service.

stdafx.h:

#include <WtsApi32.h>
#pragma comment(lib, "WtsApi32.lib")

#include <Userenv.h>
#pragma comment(lib, "Userenv.lib")

RunAsInteractiveUser function:

BOOL bRet;
HRESULT hr;

HANDLE processToken = NULL;
TOKEN_PRIVILEGES oldTokenPrivileges = { 0 };

HANDLE impersonationToken = NULL;
HANDLE userToken = NULL;

LPVOID pEnvironment = NULL;
PROCESS_INFORMATION processInformation = { 0 };

__try {
    bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &processToken);
    if (!bRet) {
        hr = GetLastError();
        return hr;
    }

    // This step might not be necessary because SeTcbPrivilege is enabled by default for Local System
    LUID luid;
    bRet = LookupPrivilegeValue(NULL, _T("SeTcbPrivilege"), &luid);
    if (!bRet) {
        hr = GetLastError();
        return hr;
    }

    TOKEN_PRIVILEGES adjTokenPrivileges = { 0 };
    adjTokenPrivileges.PrivilegeCount = 1;
    adjTokenPrivileges.Privileges[0].Luid = luid;
    adjTokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    DWORD dwOldTPLen;
    bRet = AdjustTokenPrivileges(processToken, FALSE, &adjTokenPrivileges, sizeof(TOKEN_PRIVILEGES), &oldTokenPrivileges, &dwOldTPLen);
    if (bRet) {
        hr = GetLastError();
        if (hr == ERROR_SUCCESS);
        else if (hr == ERROR_NOT_ALL_ASSIGNED) {
            // Enabled by default
        }
    }
    else {
        hr = GetLastError();
        return hr;
    }

    DWORD conSessId = WTSGetActiveConsoleSessionId();
    if (conSessId == 0xFFFFFFFF) {
        // There is no session attached to the console
        return ERROR_SUCCESS;
    }

    bRet = WTSQueryUserToken(conSessId, &impersonationToken);
    if (!bRet) {
        hr = GetLastError();
        return hr;
    }

    bRet = DuplicateTokenEx(impersonationToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &userToken);
    if (!bRet) {
        hr = GetLastError();
        return hr;
    }

    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    si.lpDesktop = _T("winsta0\\default");

    bRet = CreateEnvironmentBlock(&pEnvironment, userToken, TRUE);
    if (!bRet) {
        hr = GetLastError();
        return hr;
    }

    bRet = CreateProcessAsUser(userToken, _T("C:\\Windows\\notepad.exe"), NULL, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, pEnvironment, NULL, &si, &processInformation);
    if (!bRet) {
        hr = GetLastError();
        return hr;
    }
}
__finally {
    if (processInformation.hThread) {
        CloseHandle(processInformation.hThread);
    }
    if (processInformation.hProcess) {
        CloseHandle(processInformation.hProcess);
    }
    if (pEnvironment) {
        bRet = DestroyEnvironmentBlock(pEnvironment);
    }
    if (userToken) {
        CloseHandle(userToken);
    }
    if (impersonationToken) {
        CloseHandle(impersonationToken);
    }
    if (processToken) {
        bRet = AdjustTokenPrivileges(processToken, FALSE, &oldTokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
        CloseHandle(processToken);
    }
}

Windows Vista Security Model Analysis

Symantec, как всегда, на высоте. Документ Windows Vista Security Model Analysis ооочень полезен для разработчиков, которые занимаются низкоуровневым и/или WinAPI программированием.

Документ покрывает темы:

  • Computer security
  • Windows Vista
  • Windows Resource Protection
  • File Virtualization
  • Registry Virtualization
  • Interrity Level
  • UAP
  • LUA
  • UIPI

Weak Static and Strong Dynamic typing

Сравнение языков программирования - задача нетривиальная. Многие сравнивают их в разрезе синтаксических конструкций, базовых библиотек, современности, популярности, производительности и т.д. При этом полезной нагрузки от таких процедур минимум - каждый хвалит свое корыто.

Типизация языков программирования - одна из немногих основополагающих концепций, которыми языки отличаются. Она влияет на все составляющие части - от семантики до компиляторов и средств разработки.

На данный момент различают статическую, динамическую, строгую и нестрогую типизицию языков. В этой статье я попытаюсь обьяснить свое виденье этих понятий.

О типах и типизации

Прежде чем разговаривать о типизации и ее видах необходимо разобраться с самими понятиями типа и типизации.

Тип - это некая информация о участке памяти.

Это определение можно счесть нечетким и слишком низкоуровневым, но, в конечном итоге код на любом языке превращается в байты и выполняется вентилями. Можно возразить, что типы больше асоциируются с переменными, но это не всегда так. Я хочу свести типизацию языков программирования к одному уровню, с которым будет проще всего оперировать.

Как ни крути, а екземпляр любого типа T представляет собой кусок памяти размером sizeof(T) или что-то в этом духе. Задача компилятора состоит в трансляции конструкций языка с определенной семантикой в последовательность инструкций процессора.

Типизацией назовем совокупность правил, которыми обязан руководствоваться компилятор при трансляции операций соответствующего языка над типами данных в машинный код.

Строгая (strong) и нестрогая (weak) типизация

Мне кажется, что эти два противоположных понятия следует объединить в одно - строгость типизации. Рассмотрим похожие фрагменты кода различных языков:

// PHP - говорят, что это язык с нестрогой типизацией
$a = "1";
$b =  2;
$c = a + b;
// $c == 3
// C# 3.0 - говорят, что это язык со строгой типизацией
String a = "1";
Int32 b =  2;
var c = a + b;
// $c == "12"

Что же я вижу здесь? Первое: переменные могут быть связаны с типом данных (C# 3.0) или не связаны (PHP). Это влияет на возможность определить тип результата или легитимность операций во время обработки исходного кода (компилятором или средой разработки). Многие утверждают, что именно это указывает на строгую или нестрогую типизацию, а я считаю, что привязанность переменных к типам языка напрямую связана с разделением на статическую и динамическую типизацию. Второе: компилятор имеет некие правила преобразования конструкций, которые вызывают нестыковку с системой типов языка или представлением разработчика о их логичности. Чем больше этих правил - тем меньше строгость типизации. Насколько мне известно, все языки имеют поддержку минимум одного неявного преобразования типов (coercion), поэтому языка с 100%-но строгой типизацией не существует.

Статическая (static) и динамическая (dynamic) типизация

Это уже намного интереснее и более важно. Я склонен относить язык к статически типизированным, если информация о типах операндов известна на этапе компиляции, и типизированным динамически, если утверждение не верно.

Статическая типизация (static typing)

Рассмотрим пример на языке С++:

class CppClass
{
public:
    void SomeOperation() {}
};

void PerformOperation(CppClass &c) {
    c.SomeOperation();
}

...

CppClass c;
PerformOperation(c);

Компилятор С++ знает все, что ему требуется для трансляции этого кода в машинные инструкции - адрес переменной c, ее тип - CppClass, наличие метода SomeOperation и его точный адрес в памяти. Информация о типах используется компилятором и, как правило, не добавляется в выходной модуль.

Статическая типизация не запрещает компилятору встраивать информацию о типах:

// C++ с включенной поддержкой RTTI
DerivedCppClass derived;
BaseCppClass &base = derived;

...

DerivedCppClass &derived = dynamic_cast<DerivedCppClass&>(base);

Пользы от RTTI в С++ практически нет, поскольку единственное, что можно узнать о типе во время выполнения, - это его строковое имя, а наличие в коде операторов dynamic_cast свидетельствует о плохом понимании программистом принципов ООП.

В управляемых языках, таких как Java или C#, подробная информация о типе зашивается в выходной модуль и доступна для использования во время выполнения программы. Этот механизм называется интроспекцией (reflection) и имеет свою довольно высокую цену в виде многократной потери производительности.

Динамическая типизация (dynamic typing)

Python - хороший пример динамически типизированного языка:

class C(object):
   def hello():
      print 'Hello!'

def x(c):
   c.hello # WTF?!

c = C()
x(c)

Итак, информация о типах на этапе компиляции неизвестна. Компилятор спокойно проглатывает даже самый бредовый, но синтаксически корректный код. При этом строгая проверка типов делается, но во время выполнения программы. Компилятор, естественно, добавляет такую возможность. Правильно, путем встраивания информации о типах! Потеря производительности при этом может даже превышать таковую в управляемых языках.

Преимущества и недостатки статической (static) и динамической (dynamic) типизаций

Статическая (static) типизация

Преимущества:

  • Легче ориентироваться в коде
  • Хорошая поддержка со стороны средств разработки (рефакторинг, подсказки)
  • Скорость выполнения
  • Скорость выполнения
  • Скорость выполнения

Недостатки:

  • Усложнение языка (и, как последствие, увеличение стоимости разработки и поддержки)
  • Реализация полиморфизма через наследование
  • Ложное впечатление о корректности кода (компилируется - значит работает)
  • И еще

Динамическая (dynamic) типизация

Преимущества:

  • Хорошая поддержка современных стандартов и технологий (SOA, например)
  • Выразительность и простота кода
  • Скорость разработки
  • И еще

Недостатки:

  • Низкая производительность
  • Необходимость качественного и обширного тестирования

Дополнительные ссылки по теме:

Copyright 2007-2011 Chabster