Показать сообщение отдельно
Старый 24.09.2007, 11:55   #3  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,657 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Спасибо за "наводку" с UNICOD. После устранения ненужного дублирования ссылок получилcя такой код:

X++:
static void get_GUID(Args _args)
{

   #define.MAX_PATH(260)
    
    Dll             ole32,
                    kernel32;

    DllFunction     coCreateGuid,
                    stringFromGUID2,
                    wideCharToMultiByte;

    Binary          getGUID,
                    getUnicodeCUID,
                    getStrGUID;

    int             lenGUID,
                    lenConvert,
                    isNotOk;
    ;

    // Используемые DLL-библиотеки
    ole32       = new Dll("OLE32");
    kernel32    = new Dll("Kernel32");

    // Определение параметров и возвращаемых значений API-функций

    // CoCreateGuid - собственно формирование GUID
    coCreateGuid        = new DllFunction(ole32, "CoCreateGuid");
    coCreateGuid.arg(ExtTypes::POINTER);        // GUID* pguid              // [out] Pointer to the requested GUID on return
    // Return Value
    // S_OK - The GUID was successfully created
    // Microsoft Win32® errors are returned by UuidCreate but wrapped as an HRESULT
    coCreateGuid.returns(ExtTypes::DWORD);     


    // StringFromGUID2 - конвертация сформированного GUID в строку в формате UNICOD
    stringFromGUID2     = new DllFunction(ole32, "StringFromGUID2");
    stringFromGUID2.arg(ExtTypes::POINTER,      // REFGUID rguid            // [in] GUID to be converted
                        ExtTypes::POINTER,      // LPOLESTR lpsz            // [out] Pointer to a caller-allocated string variable to contain the resulting string on return
                        ExtTypes::DWORD);       // int cchMax               // [in] Number of characters available in the buffer indicated by lpsz
    // Return Value
    // 0 (zero)         - Array at lpsz is too small to contain a string representation of a GUID.
    // Non-zero value   - The number of bytes (not characters) in the returned string, including the null terminator.
    stringFromGUID2.returns(ExtTypes::DWORD);

    // WideCharToMultiByte - преобразование строки из UNICOD в строку текущей кодовой страницы
    // Если соответсвующие флаги не установлены (равны 0), то используются текущие настройки системы
    wideCharToMultiByte = new DllFunction(kernel32, "WideCharToMultiByte");
    wideCharToMultiByte.arg(ExtTypes::DWord,    // UINT CodePage,            // [in] Code page to use in performing the conversion
                            ExtTypes::DWord,    // DWORD dwFlags,            // [in] Flags indicating the conversion type
                            ExtTypes::POINTER,  // LPCWSTR lpWideCharStr,    // [in] Pointer to the wide character string to convert
                            ExtTypes::DWord,    // int cchWideChar,          // [in] Size, in WCHAR values, of the string indicated by lpWideCharStr
                            ExtTypes::POINTER,  // LPSTR lpMultiByteStr,     // [out] Pointer to a buffer that receives the converted string
                            ExtTypes::DWord,    // int cbMultiByte,          // [in] Size, in bytes, of the buffer indicated by lpMultiByteStr
                            ExtTypes::DWORD,    // LPCSTR lpDefaultChar,     // [in] Pointer to the character to use if a wide character cannot be represented in the specified code page
                            ExtTypes::DWord);   // LPBOOL lpUsedDefaultChar  // [out] Pointer to a flag that indicates if the function has used a default character in the conversion

    // Return value
    // Returns the number of bytes written to the buffer pointed to by lpMultiByteStr if successful. The number includes the byte for the terminating null character
    // If the function succeeds and cbMultiByte is 0, the return value is the required size, in bytes, for the buffer indicated by lpMultiByteStr
    // The function returns 0 if it does not succeed
    wideCharToMultiByte.returns(ExtTypes::DWord);


    // Формирую сам GUID
    getGUID = new Binary(#MAX_PATH);
    isNotOk = coCreateGuid.call(getGUID);
    if (isNotOk)
    {
        throw error(strFmt("При попытке сформировать GUID произошла ошибка %1", isNotOk));
    }

    // Перевожу в строку UNICOD
    getUnicodeCUID = new Binary(#MAX_PATH);
    lenGUID = stringFromGUID2.call(getGUID,getUnicodeCUID,#MAX_PATH);
    if (! lenGUID)
    {
        throw error("В буфере выделено недостаточно места для сформированной строки");
    }

    // Перевожу UNICOD в текущую кодовую страницу
    // Поскольку содержимое строки GUID - это код в 16-ричной системе, 
    // то количество знаков в строке UNICOD будет совпадать с количеством символов в текущей кодовой странице
    // Поэтому нет необходимости в предварительном вычислении длины формируемой строки
    getStrGUID  = new Binary(lenGUID);
    lenConvert  = wideCharToMultiByte.call(0, 0, getUnicodeCUID, lenGUID, getStrGUID, lenGUID, 0, 0);
    if (! lenConvert)
    {
        throw error(strFmt("При переводе сформированной строки из UNICOD в текущую кодовую страницу произошла ошибка %1", WinApi::getLastError()));
    }


    print "Сформированный GUID ",getGUID.string(0);
    print "GUID переведенный в UNICOD содержит символов (включая null-terminate) ", lenGUID;
    print "GUID в текущей кодовой странице ",getStrGUID.string(0);
    print "Содержит символов (включая null-terminate) ", lenConvert;

    pause;
}