Показаны сообщения с ярлыком system. Показать все сообщения
Показаны сообщения с ярлыком system. Показать все сообщения

6 июн. 2010 г.

JScript: How to get AllUsers AppData directory

var osXP = 0;
var osVista = 1;
var osWin7 = 2;

function getOsVersionString()
{
    var wbemFlagReturnImmediately = 0x10;
    var wbemFlagForwardOnly = 0x20;
    var objWMIService = GetObject("winmgmts:\\\\.\\root\\CIMV2");
    var colItems = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem", "WQL", wbemFlagReturnImmediately | wbemFlagForwardOnly);
    
    var enumItems = new Enumerator(colItems);
    var objItem = enumItems.item();
    
    return objItem.Caption;
}

function getOsVersion()
{
    var osVersionString = getOsVersionString();

    if (osVersionString.indexOf("Windows Vista") != -1)
    {
        return osVista;
    }

    if (osVersionString.indexOf("Windows 7") != -1)
    {
        return osWin7;
    }

    return osXP;
}

function getAllUsersAppData()
{
    var result;
    
    var wsShell = new ActiveXObject("WScript.Shell");
    result = wsShell.ExpandEnvironmentStrings("%ALLUSERSPROFILE%");
    
    try
    {
        var osVersion = getOsVersion();
        
        if (osVersion == osXP)
            result += "\\Application Data";
    }
    catch(err)
    {
    }

    return result;
}

2 апр. 2009 г.

Организация доступа к 32-bit DLL из 64-bit приложения.

Перенос 32-битных Windows приложений на 64-битную машину может быть весьма проблематичным, если у вас есть 32-разрядные библиотеки DLL, которые вы не можете переписать и портировать для 64-bit. Майк Беккер покажет вам, как можно получить доступ к 32-bit DLL из 64-битного кода с помощью встроенных механизмов IPC.

64-разрядные технологии Microsoft впервые появились в Windows Server 2003 для процессоров Itanium 2 (архитектура ихвестна как "IA64") а также для eXtended CPUs (архитектура известна как "x64"). 64-bit технология имеет много преимуществ, но также поднимает новые вопросы для разработчиков программного обеспечения. Например, вам может понадобиться необходимость доступа к существующим 32-разрядным библиотекам DLL из 64-битного процесса.

Главное преимущество технологии 64-бит состоит в способности адресовать до 8 ТБ памяти, против максимальных 2 Гб для 32-битных процессов. Как результат, 64-разрядная технология позволяет проводить операции с большим объёмом данных в оперативной памяти без необходимости временного сброса памяти на жётский диск. Это может значительно повысить производительность и открыть новые алгоритмы обработки данных базирующихся на очень больших доступных объёмов оперативной памяти. Как бы то ни было аргументы для миграции существующего программного обеспечения на 64-битную платформу имеют место быть.

Многие приложения, написанные с помощью C/C++ могут быть легко портированы под 64-битную платформу, особенно если они написаны в виде монолитного модуля. Иногда достаточно просто пересобрать исходные коды с использованием x64/IA64 компилятора. Однако уже опубликованное или базирующееся на модулях ПО может вызвать проблемы.

Конфликт: 64-bit против 32-bit

Основная проблема миграции возникает при необходимости портирования 32-разрядных программных компонентов, которые не могут быть пересобраны, возможно, потому что исходный код потерян, к нему нет доступа или одна из зависимостей этого модуля не можeт быть перенесена на 64-bit платформу.

32-битное ПО по-прежнему поддерживается на 64-битной платформе. Так 32-битные процессы могут выполняться внутри Windows WOW64-подсистемы, которая является частью всех 64-битных систем Windows. Однако 64-разрядный процесс не может загружать 32-разрядные модули в своё адресное пространство, также и 32-разрядные процессы не могут загружать 64-разрядные модули в своё адресное пространство. Единственный способ общения между 32-битными и 64-битными модулями возможен путём межпроцессного взаимодействия (IPC). Другими словами, 32-разрядные и 64-разрядные процессы могут обмениваться данными с использованием IPC-механизмов, например такие как out-of-proc COM, сокеты, сообщения Windows или MMF (Memory mapped files).

Например, 32-битный программный продукт содержит основной модуль WeatherReport (см. рисунок выше), который внутри обращается к DLL WeatherStationControl. Пока основной модуль и DLL являются 32-разрядными, продукт может работать как на 32-битных, так и 64-битных платформах (внутри WOW64). Если основной модуль и DLL переносятся на 64-битную платформу, то они могут работать в рамках 64-битных процессов. Однако, если только основной модуль переносится на 64-bit, он не сможет загружать 32-разрядные DLL.

Лучшим способом переноса такого продукта на 64-битную платформу является миграция как основного модуля, так и всех его зависимостей, но если хоть одна зависимая DLL не может быть перенесена, то продукт не может быть загружен в 64-битном процессе, следовательно приложение работать не будет.

Решение: суррогатный процесс

Эта проблема может быть решена путем загрузки зависимой 32-битной DLL в отдельном пространстве 32-разрядного процесса. Основной модуль, работая в качестве 64-битного процесса, может получить доступ к зависимым DLL'ям через границы процессов, используя IPC (Смотри MSDN reference).

64-битный процесс может получить доступ к 32-разрядной DLL используя механизмы межпроцессного взаимодействия. То бишь 32-разрядные DLL загружаются в отдельный 32-битный суррогатный процесс, и тогда 64-битное приложение использует встроенные механизмы IPC для того, чтобы обмениваться данными 32-битным процессом.

Это решение требует дополнительной работы, например необходимо создать 32-разрядный суррогатный процесс, который загрузит 32-разрядные DLL и предоставит API для работы с ними. Кроме того, некоторые изменения будет необходимо стелать со стороны 64-битного клиента, т.к. клиент будет вынужден использовать методы IPC вместо непосредственного доступа к 32-разрядной DLL. Стоит отметить, что, в крайнем случае, эта дополнительная работа может быть сравнима с работой, которую необходимо выполнить при разработке 64-разрядной версию 32-битной DLL с нуля.

Одним из возможных путей сокращения этих расходов является реализация 64-разрядной DLL обертки, которая предоставит те же функции, что и оригинальная 32-битная DLL. Эта обёртка уже внутри себя скроет детали IPC вызовов оригинальной 32-битной DLL, загруженной в 32-битный суррогатный процесс.

64-битная обёртка (WeatherStationControl64.DLL) экспортирует тот же интерфейс, что и оригинальная 32-битная DLL (WeatherStationControl.DLL), то бишь предоставляет главному модулю WeatherReport те же сервисы без необходимости внесения изменений в код модуля WeatherReport.

Основные затраты этого решения связаны с реализацией суррогатного процесса, загружающего 32-битную DLL и реализаццей 64-битной DLL оболочки. Фактически затраты будут зависеть от того, какая из IPC технологий будет использоваться для обмена данными между 64-битным и 32-битным процессами.

Использование COM для межпроцессного взаимодействия

Один из самых популярных методов IPC - это DCOM (Distributed COM). Первоначально разработанная для распределенных систем, DCOM по-прежнему поддерживается как на 64-битных платформах Windows. Модули COM могут быть собраны как 32-разрядные так и 64-разрядные. Единственным ограничением является то, что 64-битные и 32-битные модули не могут находиться в одном и том же процессе, следовательно они должны взаимодействовать через границы процессов. Это делается с помощью out-of-process (OOP) COM компонентов, следующим образом:

  1. Создаём 32-битный COM-Сервер, который загрузит 32-битную DLL и опубликует 32-bit DLL интерфейс как COM-интерфейс, реализованный внутри через делегирование к API исходной 32-битной DLL.
  2. Конфигурируем этот COM-Сервер для out-of-proc загрузки любым способом создания COM+ приложений (используя dllhost.exe в качестве суррогата).
    Также можно реализовать этот COM-компонент как специальный COM-Сервер EXE, используя ATL COM Server в качестве хостящего процесса.
    Можно также помеcтить этот COM-компонент внутрь Win32-сервиса.
  3. Создаём 64-разрядную DLL оболочку, реализующую тот же интерфейс, как оригинальная 32-битная DLL. Обёртка будет импортировать COM-интерфейс из COM-объекта, созданного выше, и транслировать каждый API вызов в обращение к COM-интерфейсу, передавая параметры вызова и получая возвращаемые значения.

32-разрядная DLL (WeatherStationControl.DLL) используется СОМ-объектом (WeatherStationWrapper), который предоставляет интерфейс 32-битной DLL в качестве COM-интерфейса. 64-битная DLL обёртка (WeatherStationControl64.DLL) делает вызовы COM-интерфейса, которые уже делегируют всю работу оригинальным API вызовам исходной 32-битой DLL. Основной процесс (WeatherReport) использует интерфейс, предоставляемый 64-разрядной DLL обёрткой, но на самом деле работа выполняется в оригинальной 32-битной DLL.

Это решение должно быть значительно дешевле, чем создание 64-разрядную версию 32-битных DLL с нуля. Библиотека ATL, поддерживающаяся Visual Studio, вкупе со всеми своими визардами и готовыми фрагментами кода, также должны помочь снизить затраты миграции за счет экономии времени и снижения вероятности ошибок.

Последствия

Однако существует ряд вещей, которые вам все еще нужно иметь в виду:

  1. Выравнивание
    Выравнивание данных в памяти отличается в 32-bit и 64-bit процессах. Это означает, что более сложные пользовательские структуры данных могут быть сериализованы 32-разрядным процессом иначе, чем ожидается в 64-битном проыцессе, и наоборот. Microsoft Windows Platform SDK включает документацию о различиях в соответствие памяти данными между 32-битной и 64-битных процессов.
  2. Типы данных
    В большинстве случаев, 64-разрядная Windows использует те же типы данных, как 32-битной версии. Различия в основном в указателях, которые 32-битные в 32-битной версий Windows и 64-битные в 64-битных Windows.
    Указатель полученных данных типов, таких как HANDLE и HWND также различны между 32-битной и 64-разрядных версиях. Windows позволяет вести единый базовый код для 32-разрядных версиях и 64-битного программного обеспечения, предлагая полиморфные типы данных, которые имеют различную длину в зависимости от целевой платформы, например INT_PTR представляет целое с таким же размером, как и указатель. Любая переменная этого типа будет целым числом, которое составляет 32 бита на 32-битной платформе и 64 бита на 64-битной платформе.
  3. COM инициализации
    Вы можете получить доступ к СОМ-объекту, если он был успешно инициализирован. Функция COM API CoInitialize() должна вызываться для каждого потока, который собирается работать с COM-объектом, т.е. делать вызовы COM-интерфейсов, также должна вызываться CoUninitialize() перед завершением потока.(см. MSDN). Это правило должно строго соблюдаться, если основной процесс вызывает оригинальные 32-битные DLL из разных потоков выполнения.
  4. Безопасность
    При использовании out-of-proc, экземпляры COM-объектов находятся в отдельном процессе, независимо от того используете вы стандартный суррогатной процесс, EXE COM-Сервер или Win32 сервис. Это может означать, что вызовы 32-битной DLL могут произойти в другом контексте безопасности, чем у основного процесса, особенно если основной процесс интенсивно использует имперсонирование. Если это так, вы можете настроить собственные параметры доступа для out-of-proc компонента, или осуществлять внутреннее имперсонирование внутри COM-объекта.
  5. Производительность
    IPC-решение почти наверняка будет медленнее, чем прямые вызовы DLL. Маршалинг данных за границы процессов, автоматическое преобразование данных между 32 и 64 бит, WOW64 особенности, задержки инстанцирования экземпляров COM-объектов - всё это будет влиять на производительность. Однако есть много методов оптимизации, которые можно использовать, таких как COM pooling, кэширование данных внутри DLL-оболочки, реализация критичных к производительности интерфейсов в 64-битной DLL, и так далее.
  6. Перенаправление
    Подсистема WOW64 отвечает за поддержку 32-битных модулей на 64-битных Windows. Чтобы избежать нежелательных коллизий между 32-битным и 64-битным ПО, особенно при доступе к файловой системы и реестру, WOW64 изолирует 32-разрядные модули, используя механизм, называемый перенаправление (см. MSDN).
    Например, для 64-битного процесса при получении пути системной папки возвращается %WINDOWS%\System32, а для 32-разрядного процесса возвращается %WINDOWS%\SysWOW64.
    Путь к папке исполняемого файла будет "Program Files" для 64-битного процесса, но для 32-разрядного процесса это будет "Program Files (x86)".
    Раздел реестра HKEY_LOCAL_MACHINE\Software содержит настройки и данные для 64-разрядных процессов, а ключ HKEY_LOCAL_MACHINE\Software\WOW6432Node содержит настройки и данные для 32-разрядных процессов.
    Это перенаправление активируется автоматически, когда программные модули пытаются получить предопределённые системные пути или ключи реестра.
  7. Модули ядра
    Предложенное здесь решение работает для 32-разрядных DLL, использующихся в user mode, но не работает с 32-битными драйверами. Это происходит, потому что 32-битные модули ядра не могут быть использованы на 64-битной платформе, без исключений или обходных путей. Если ваш продукт включает в себя любой модуль уровня ядра, таких как драйвер устройства, то единственно возможный путь миграции - это портировать модуль ядра на 64-битную платформу.
  8. Установка.
    Использование out-of-proc COM-компонента требует изменений в процедуре установки вашего ПО, т.к. COM-компонент должен быть установлен и зарегистрирован в системе. Как уже говорилось выше в пункте Безопасность, для этого может потребоваться настройка специальных параметров доступа для COM-компонента.
Тыкните сюда дабы скачать пример кода

Оригинал статьи здесь: Mike Becker: "Accessing 32-bit DLLs from 64-bit code", Jun 2007

Литература: