Проблема с очисткой стуктуры.

 
0
 
C++
ava
CynicRus | 21.03.2013, 11:09
Добрый день госопда. Возникла проблема следующего рода: имеются 2 структуры

struct usbInfo {
    TCHAR        cKeyName[MAX_KEY_LENGTH] ;
    TCHAR        cDeviceID[MAX_KEY_LENGTH] ;
    SYSTEMTIME    stStamp ;
    struct instanceInfo * instance;
} ;

struct instanceInfo {
    TCHAR        cInstanceID[MAX_KEY_LENGTH] ;
    TCHAR        cFriendlyName[MAX_VALUE] ;
    TCHAR        cDriver[MAX_VALUE] ;
    TCHAR        cParentIdPrefix[MAX_VALUE] ;
    TCHAR        cHardwareID[MAX_VALUE] ;
    TCHAR        cLastDriveLetter[MAX_VALUE_NAME] ;
    SYSTEMTIME    stDiskStamp ;
    SYSTEMTIME  stVolumeStamp ;
    struct instanceInfo * next ;
} ;

Я из заполняю некими данными, отображаю в TreeView через WinApi - все здорово. Но как только я пытаюсь очистить эту структуру я ловлю крайне мутный SIGSEGV.

Код функции очистки:

void cleanDeviceList( struct usbInfo * usbList, int Count)
{
    struct instanceInfo * next, * current ;

    for (int i = 0; i < Count; i++) {
        current = usbList[i].instance ;
        while (current->next != NULL) {
            next = current->next ;
            free(current) ;
            current = next ;
        }
    }

}


и в качестве дополнительного описания проблемы - скрин call stack:
[img]http://s2.ipicture.ru/uploads/20130321/73frG6sV.png[/img]

В каком направлении копать?

Comments (25)
ava
math64 | 21.03.2013, 10:46 #

while(current != NULL) {
            next = current->next ;
            free(current) ;
            current = next ;
}
ava
CynicRus | 21.03.2013, 11:37 #
В результате имеем тоже самое.
ava
math64 | 21.03.2013, 12:09 #
Значит, заполняешь неправильно или где-то портишь.
ava
feodorv | 21.03.2013, 12:10 #
Ну а потом 

        usbList[i].instance = NULL;

делаете? Или usbList[i].instance так и указывает на освобождённую память? Или это не критично?

На мой взгляд, ошибка где-то в лишнем free (портится хип). Вы точно при добавлении новой структуры instanceInfo инициализируете поле next нуллом?
ava
CynicRus | 21.03.2013, 13:00 #
Вроде бы да. Но приведу ка я на всякий случай монстроуозный код заполнения структуры. Вдруг там кто углядит то, что не углядел я:


void getDeviceList( struct usbInfo * usbList )
{

    HKEY        hKey, hInstanceKey, hControlKey ;
    DWORD        dwName = MAX_KEY_LENGTH ;
    TCHAR        cSubKeyName[MAX_PATH +1] ;                // buffer for subkey name
    DWORD        dwSubKeys = 0 ;                            // number of subkeys
    DWORD        dwValues = 0 ;                            // number of Values
    DWORD        dwMaxValueNameLen = MAX_VALUE_NAME;        // Max Value Name Length
    DWORD        dwMaxValueLen = MAX_VALUE;                // Max Value Length
    FILETIME    ft ;                                    // last write time (file time structure)
    SYSTEMTIME    stGMT, stLocal ; // system time for readability
    DWORD        ValType, ValNameLen, ValLen;
    LPTSTR        ValName;
    LPBYTE        Val;
    int iSubKeyCount = countSubKeys( USBSTOR ) ;

    struct instanceInfo * prev, * current ;

    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT(USBSTOR), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey ( hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ;

        if (dwSubKeys) {

            for (int i = 0; i < dwSubKeys; i++){

                dwName = MAX_KEY_LENGTH ;

                if ( RegEnumKeyEx(hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) {
                    TCHAR deviceKeyName[MAX_KEY_LENGTH] = USBSTOR ;
                    _tcscat(deviceKeyName, TEXT("\\") ) ;
                    _tcscat(deviceKeyName, cSubKeyName) ;
                    _tcscpy( usbList[i].cDeviceID, cSubKeyName) ;
                    _tcsncpy( usbList[i].cKeyName, deviceKeyName, MAX_KEY_LENGTH - 1 ) ;
                    FileTimeToSystemTime( &ft, &stGMT) ;
                    SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                    usbList[i].stStamp.wMonth = stLocal.wMonth ;
                    usbList[i].stStamp.wDay = stLocal.wDay ;
                    usbList[i].stStamp.wYear = stLocal.wYear ;
                    usbList[i].stStamp.wHour = stLocal.wHour ;
                    usbList[i].stStamp.wMinute = stLocal.wMinute ;
                    usbList[i].instance = NULL ;
                }
            }
        }
        RegCloseKey( hKey ) ;
    }

    // now we move on to getting the instance info from registry
    for (int i = 0; i < iSubKeyCount; i++) {

        TCHAR    instanceIdKeyName[MAX_KEY_LENGTH] ;


        if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, usbList[i].cKeyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {

            RegQueryInfoKey ( hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ;

            if (dwSubKeys) {
                for (int n = 0; n < dwSubKeys; n++){
                    dwName = MAX_KEY_LENGTH ; 
                    current = reinterpret_cast<instanceInfo *> malloc(sizeof(struct instanceInfo)) ;
                    if (RegEnumKeyEx(hKey, n, cSubKeyName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {

                        // fill out each instanceInfo
                        _tcscpy( current->cInstanceID, cSubKeyName) ;
                        _tcscpy(instanceIdKeyName, usbList[i].cKeyName) ;
                        _tcscat(instanceIdKeyName, TEXT("\\") ) ;
                        _tcscat(instanceIdKeyName, current->cInstanceID) ;
                        // open each instanceID Registry Key to get the value data

                        if ( RegOpenKeyEx( hKey, cSubKeyName, 0, KEY_READ, &hInstanceKey) == ERROR_SUCCESS) {

                            RegQueryInfoKey(hInstanceKey, NULL, NULL, NULL, NULL, NULL, NULL,
                                    &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL ) ;
                            ValName =static_cast<LPSTR>( malloc (dwMaxValueNameLen+1)); 
                            Val = static_cast <LPBYTE> (malloc (dwMaxValueLen)); 

                            if (dwValues) {
                                for (int i=0; i<dwValues; i++){
                                    ValNameLen = dwMaxValueNameLen + 1;
                                    ValLen = dwMaxValueLen + 1;
                                    RegEnumValue (hInstanceKey, i, ValName, &ValNameLen,
                                            NULL, &ValType, Val, &ValLen);

                                    if (ValType == REG_SZ ||  ValType == REG_MULTI_SZ){
                                        if (_tcscmp(TEXT("ParentIdPrefix"), ValName) == 0) 
                                            _tcscpy(current->cParentIdPrefix, (LPTSTR) Val) ;
                                        if (_tcscmp(TEXT("FriendlyName"), ValName) == 0)
                                            _tcscpy(current->cFriendlyName, (LPTSTR) Val) ;
                                        if (_tcscmp(TEXT("HardwareID"), ValName) == 0)
                                            _tcscpy(current->cHardwareID, (LPTSTR) Val) ;
                                        if (_tcscmp(TEXT("Driver"), ValName) == 0)
                                            _tcscpy(current->cDriver, (LPTSTR) Val) ;
                                    }
                                }
                            }

                        }
                        RegCloseKey( hInstanceKey ) ;
                    }
                    if (usbList[i].instance == NULL)
                        usbList[i].instance = current ;
                    else
                        prev->next = current ;
                    current->next = NULL ;
                    prev = current ;

                }
            }

        }
        RegCloseKey( hKey ) ;
    }


    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT( DEVINTERFACE_DISK ), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey ( hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ;

        for (int i = 0; i < iSubKeyCount; i++) {
            current = usbList[i].instance ;

            if (dwSubKeys) {
                for (int i = 0; i < dwSubKeys; i++){
                    dwName = MAX_KEY_LENGTH ; 

                    if ( RegEnumKeyEx(hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) {

                        if ( _tcsstr( cSubKeyName, current->cInstanceID) != NULL ) {

                            TCHAR cControlKeyName[MAX_PATH +1] ;
                            _tcscpy(cControlKeyName, cSubKeyName) ;
                            _tcscat(cControlKeyName, TEXT("\\Control") ) ;

                            if ( ( RegOpenKeyEx( hKey, cControlKeyName, 0, KEY_READ, &hControlKey) == ERROR_SUCCESS) &&
                                    ( RegQueryInfoKey(hControlKey, NULL, NULL, NULL, NULL, NULL, NULL,
                                            NULL, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) ) {

                                FileTimeToSystemTime( &ft, &stGMT) ;
                                SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                                current->stDiskStamp.wMonth = stLocal.wMonth ;
                                current->stDiskStamp.wDay = stLocal.wDay ;
                                current->stDiskStamp.wYear = stLocal.wYear ;
                                current->stDiskStamp.wHour = stLocal.wHour ;
                                current->stDiskStamp.wMinute = stLocal.wMinute ;

                                RegCloseKey( hControlKey ) ;

                            } else {

                                FileTimeToSystemTime( &ft, &stGMT) ;
                                SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                                current->stDiskStamp.wMonth = stLocal.wMonth ;
                                current->stDiskStamp.wDay = stLocal.wDay ;
                                current->stDiskStamp.wYear = stLocal.wYear ;
                                current->stDiskStamp.wHour = stLocal.wHour ;
                                current->stDiskStamp.wMinute = stLocal.wMinute ;
                            }
                        }
                    }
                }
            }

            while (current->next != NULL) {
                current = current->next ;

                if (dwSubKeys) {
                    for (int i = 0; i < dwSubKeys; i++){
                        dwName = MAX_KEY_LENGTH ; //we must reset this EVERY TIME!

                        if ( RegEnumKeyEx(hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) {

                            if ( _tcsstr( cSubKeyName, current->cInstanceID) != NULL ) {
                                TCHAR cControlKeyName[MAX_PATH +1] ;
                                _tcscpy(cControlKeyName, cSubKeyName) ;
                                _tcscat(cControlKeyName, TEXT("\\Control") ) ;

                                if ( ( RegOpenKeyEx( hKey, cControlKeyName, 0, KEY_READ, &hControlKey) == ERROR_SUCCESS) &&
                                        ( RegQueryInfoKey(hControlKey, NULL, NULL, NULL, NULL, NULL, NULL,
                                                          NULL, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) ) {
                                    FileTimeToSystemTime( &ft, &stGMT) ;
                                    SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                                    current->stDiskStamp.wMonth = stLocal.wMonth ;
                                    current->stDiskStamp.wDay = stLocal.wDay ;
                                    current->stDiskStamp.wYear = stLocal.wYear ;
                                    current->stDiskStamp.wHour = stLocal.wHour ;
                                    current->stDiskStamp.wMinute = stLocal.wMinute ;

                                    RegCloseKey( hControlKey ) ;

                                } else {
                                    FileTimeToSystemTime( &ft, &stGMT) ;
                                    SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                            current->stDiskStamp.wMonth = stLocal.wMonth ;
                            current->stDiskStamp.wDay = stLocal.wDay ;
                            current->stDiskStamp.wYear = stLocal.wYear ;
                            current->stDiskStamp.wHour = stLocal.wHour ;
                            current->stDiskStamp.wMinute = stLocal.wMinute ;
                                }
                            }
                        }
                    }
                }
            }
        }
        RegCloseKey( hKey ) ;
    }

    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT( DEVINTERFACE_VOLUME ), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey ( hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ;

        for (int i = 0; i < iSubKeyCount; i++) {
            current = usbList[i].instance ;

            if (dwSubKeys) {
                for (int i = 0; i < dwSubKeys; i++){
                    dwName = MAX_KEY_LENGTH ; //we must reset this EVERY TIME!

                    if ( RegEnumKeyEx(hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) {

                        if ( _tcsstr( cSubKeyName, current->cParentIdPrefix) != NULL ) {
                        
                            TCHAR cControlKeyName[MAX_PATH +1] ;
                            _tcscpy(cControlKeyName, cSubKeyName) ;
                            _tcscat(cControlKeyName, TEXT("\\Control") ) ;

                            if ( ( RegOpenKeyEx( hKey, cControlKeyName, 0, KEY_READ, &hControlKey) == ERROR_SUCCESS) &&
                                    ( RegQueryInfoKey(hControlKey, NULL, NULL, NULL, NULL, NULL, NULL,
                                            NULL, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) ) {

                                FileTimeToSystemTime( &ft, &stGMT) ;
                                SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                                current->stVolumeStamp.wMonth = stLocal.wMonth ;
                                current->stVolumeStamp.wDay = stLocal.wDay ;
                                current->stVolumeStamp.wYear = stLocal.wYear ;
                                current->stVolumeStamp.wHour = stLocal.wHour ;
                                current->stVolumeStamp.wMinute = stLocal.wMinute ;

                                RegCloseKey( hControlKey ) ;

                            } else {

                            FileTimeToSystemTime( &ft, &stGMT) ;
                            SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                            current->stVolumeStamp.wMonth = stLocal.wMonth ;
                            current->stVolumeStamp.wDay = stLocal.wDay ;
                            current->stVolumeStamp.wYear = stLocal.wYear ;
                            current->stVolumeStamp.wHour = stLocal.wHour ;
                            current->stVolumeStamp.wMinute = stLocal.wMinute ;

                            }
                        }
                    }
                }
            }

            while (current->next != NULL) {

                current = current->next ;

                if (dwSubKeys) {
                    for (int i = 0; i < dwSubKeys; i++){

                        dwName = MAX_KEY_LENGTH ; //we must reset this EVERY TIME!

                        if ( RegEnumKeyEx(hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) {

                            if ( _tcsstr( cSubKeyName, current->cParentIdPrefix) != NULL ) {

                                TCHAR cControlKeyName[MAX_PATH +1] ;
                                _tcscpy(cControlKeyName, cSubKeyName) ;
                                _tcscat(cControlKeyName, TEXT("\\Control") ) ;

                                if ( ( RegOpenKeyEx( hKey, cControlKeyName, 0, KEY_READ, &hControlKey) == ERROR_SUCCESS) &&
                                        ( RegQueryInfoKey(hControlKey, NULL, NULL, NULL, NULL, NULL, NULL,
                                                          NULL, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) ) {
                                    FileTimeToSystemTime( &ft, &stGMT) ;
                                    SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                                    current->stVolumeStamp.wMonth = stLocal.wMonth ;
                                    current->stVolumeStamp.wDay = stLocal.wDay ;
                                    current->stVolumeStamp.wYear = stLocal.wYear ;
                                    current->stVolumeStamp.wHour = stLocal.wHour ;
                                    current->stVolumeStamp.wMinute = stLocal.wMinute ;

                                    RegCloseKey( hControlKey ) ;

                                } else {
                                    FileTimeToSystemTime( &ft, &stGMT) ;
                                    SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                                    current->stVolumeStamp.wMonth = stLocal.wMonth ;
                                    current->stVolumeStamp.wDay = stLocal.wDay ;
                                    current->stVolumeStamp.wYear = stLocal.wYear ;
                                    current->stVolumeStamp.wHour = stLocal.wHour ;
                                    current->stVolumeStamp.wMinute = stLocal.wMinute ;
                                }
                            }
                        }
                    }
                }
            }
        }
        RegCloseKey( hKey ) ;
    }

    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\MountedDevices"),
                0, KEY_READ, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
                &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, &ft ) ;
        ValName =reinterpet_cast<LPSTR>( malloc (dwMaxValueNameLen+1)); // Allow for null.
        Val =reinterpet_cast<LPBYTE>(malloc (dwMaxValueLen)); // Size in bytes.

        FileTimeToSystemTime( &ft, &stGMT) ;
        SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);

        if (dwValues) {
            for (int i=0; i<dwValues; i++){

                ValNameLen = dwMaxValueNameLen ;
                ValLen = dwMaxValueLen ;
                TCHAR valueString[ValLen+1] ;
                RegEnumValue (hKey, i, ValName, &ValNameLen, NULL, &ValType, Val, &ValLen);

                if (strncmp(  (LPSTR)ValName, "\\DosDev", 7) == 0) {

                    if (ValType == REG_BINARY)
                        for (int i = 0; i < ValLen; i++, Val++)
                            valueString[i] = Val[i] ;

                    valueString[ValLen+1] = '\0' ;    
                    if (strncmp( valueString, "\\??\\STORAGE#RemovableMedia#", 27) == 0) {

                        for (int i = 0; i < iSubKeyCount; i++) {

                            current = usbList[i].instance ;

                            if (  ( _tcsstr( valueString, current->cParentIdPrefix) != NULL)
                                    && (strlen(current->cParentIdPrefix) > 1 ) )
                                _tcscpy(current->cLastDriveLetter, (LPTSTR) ValName) ;
                            while (current->next != NULL) {
                                current = current->next ;
                                if ( ( _tcsstr( valueString, current->cParentIdPrefix) != NULL )
                                        && (strlen(current->cParentIdPrefix) > 1 ) )
                                    _tcscpy(current->cLastDriveLetter, (LPTSTR)ValName) ;
                            }
                        }
                        // Done Cycling Through the list.
                    }
                }
            }
        }


    }
    RegCloseKey( hKey ) ;
}

ava
feodorv | 21.03.2013, 14:17 #
Цитата (CynicRus @  21.3.2013,  14:00 findReferencedText)
Кажись по фиксил. Методом заменты static_cast на reinterpret_cast.

Вы пишете на C или C++?


Я вижу очевидные противоречия в Вашем коде. С одной стороны:
Цитата (CynicRus @  21.3.2013,  14:00 findReferencedText)
    RegQueryInfoKey ( hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ;
    if (dwSubKeys) {
    for (int i = 0; i < dwSubKeys; i++){
     ...
     usbList[i].... = ....;


(и это без проверки на выход за пределы массива!!! сколько памяти отведено под usbList?)

С другой стороны:
Цитата (CynicRus @  21.3.2013,  14:00 findReferencedText)
    int iSubKeyCount = countSubKeys( USBSTOR ) ;

Цитата (CynicRus @  21.3.2013,  14:00 findReferencedText)
    for (int i = 0; i < iSubKeyCount; i++) {

Цитата (CynicRus @  21.3.2013,  14:00 findReferencedText)
      _tcscpy(instanceIdKeyName, usbList[i].cKeyName) ;

Цитата (CynicRus @  21.3.2013,  14:00 findReferencedText)
     if (usbList[i].instance == NULL)
       usbList[i].instance = current ;
      else
       prev->next = current ;


Кому верить: dwSubKeys или iSubKeyCount?


По-моему, Вы банально перепутали индексы i и n (для предотвращения подобных ошибок всегда для одной и той же сущности пользуйтесь одним и тем же индексом, не меняйте смысл индекса по ходу кода).
ava
CynicRus | 21.03.2013, 16:32 #
Я пишу на Си, но некоторые вещи проверяю и на С++. И да, моя радость по поводу фикса не была долгой. В результате плюнул на С++ и вернул всё на Си.

subKeysCount вычисляется с помощью:


int countSubKeys( const TCHAR hMainKey[] ) 
{

    HKEY        hKey ;
    DWORD        dwSubKeys = 0 ;        

    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, hMainKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey ( hKey, NULL, NULL, NULL, &dwSubKeys, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL ) ;

        return (dwSubKeys) ;
    }

    RegCloseKey (hKey) ;

    return 0 ;
}


Под USBList отводится iSubKeyCount памяти. Я перестал падать при отладке очистки элемента, но теперь программа падает если я второй раз вызываю getDeviceList. И отладчик при падении указывает на

current = (struct instanceInfo *) malloc(sizeof(struct instanceInfo)) ;

Соответственно, перед вторым вызовом getDeviceList я провожу cleanDeviceList.
ava
feodorv | 21.03.2013, 17:38 #
Цитата (CynicRus @  21.3.2013,  17:32 findReferencedText)
Под USBList отводится iSubKeyCount памяти

В таком случае, в USBList нужно отправлять в качестве аргумента iSubKeyCount и работать исключительно с этой величиной. Теоретически (но маловероятно для HKEY_LOCAL_MACHINE) число subkeys между вызовами может измениться.

Далее. Проинициализируйте изначально весь массив usbInfo нулями:

if( iSubKeyCount > 0 )
{
  DWORD size = sizeof(struct usbInfo) * iSubKeyCount;
  usbInfo = (struct usbInfo *) malloc( size );
  memset( usbInfo, 0, size);
}
else
  usbInfo = NULL;

Дело в том, что у Вас инициализация отдельных элементов этого массива проходит только в том случае, если
Цитата (CynicRus @  21.3.2013,  14:00 findReferencedText)
    if ( RegEnumKeyEx(hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) {

А если нет, не ERROR_SUCCESS?
ava
CynicRus | 21.03.2013, 18:36 #
Хм...если я его изначально заполняю нулями я список не заполняю вообще ни разу. Вываливаятся с ошибкой сразу при попытке элементу usbList присвоить хоть чего нибудь. 
ava
feodorv | 21.03.2013, 18:57 #
Цитата (CynicRus @  21.3.2013,  19:36 findReferencedText)
Вываливаятся с ошибкой сразу при попытке элементу usbList присвоить хоть чего нибудь.  

Чему равно при этом usbList? Память точно выделяется?
ava
CynicRus | 21.03.2013, 19:22 #
Память выделяется, закрытие ключа поправил...но...Ноль эмоций. Код выполняется 1 раз, при повторном нажатии на кнопку, AV. В стеке - тоже что и в первом посте...Я чет уже мозг сломал на тему, где же оно может валиться.
ava
feodorv | 21.03.2013, 19:51 #
После cleanDeviceList Вы высвобождаете массив usbList? А потом - перезаказывете с переинициализацией? Или пользуетесь старым массивом?
Если старым, то
Цитата (feodorv @  21.3.2013,  13:10 findReferencedText)
Ну а потом 

1:  usbList[i].instance = NULL;

ava
CynicRus | 21.03.2013, 20:01 #
Сейчас покажу обработчик кнопки...исключительно тестовый:


case WM_COMMAND:
          switch(LOWORD(wParam))
           {
           case BTN_GETINFO:
             {
                int iSubKeyCount = countSubKeys( USBSTOR ) ;
                struct usbInfo deviceList[iSubKeyCount] ;
               struct instanceInfo * current ;
                TV_INSERTSTRUCT tvinsert;
                getDeviceList(deviceList) ;
                Sleep(100);
                for (int i = 0; i < iSubKeyCount; i++) {
                  current = deviceList[i].instance ;
                  if (i==0){
                            tvinsert.hParent=NULL; // top most level Item
    // root level item attribute.
                            tvinsert.hInsertAfter=TVI_ROOT;
    // attributs
                            tvinsert.item.mask=TVIF_TEXT||TVIF_PARAM;
                            tvinsert.item.lParam=i;
    // item text
                            tvinsert.item.pszText=current->cFriendlyName;;
                            tvinsert.item.iImage=0; // not pressed pic
                            tvinsert.item.iSelectedImage=1; // pressed pic
                            Parent=(HTREEITEM)SendDlgItemMessage(hwnd,NAMETREE,
                            TVM_INSERTITEM,0,(LPARAM)&tvinsert);
                            Root=Parent;
/* |  */                    Before=Parent;

                            } else {
                                tvinsert.hParent=Root;          // create a child to our parent ;-)
                                  tvinsert.hInsertAfter=TVI_LAST;   // put it under [ last item ]
                                  tvinsert.item.pszText=current->cFriendlyName;
                                  tvinsert.item.mask=TVIF_TEXT||TVIF_PARAM;
                                  tvinsert.item.lParam=i;
                                  Parent=(HTREEITEM)SendDlgItemMessage(hwnd,NAMETREE,
                                    TVM_INSERTITEM,0,(LPARAM)&tvinsert);
                            }
                      }
            cleanDeviceList(deviceList);
                }
               break;
            }
            break;


Переменная локальная, следовательно насколько я понимаю она должна при повторном нажатии на кнопку реинициализироваться с учётом того что память очищается после использования этой переменной.

usbList[i].instance = NULL; - так это же выполняется тут:


                if ( RegEnumKeyEx(hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS) {
                    TCHAR deviceKeyName[MAX_KEY_LENGTH] = USBSTOR ;
                    _tcscat(deviceKeyName, TEXT("\\") ) ;
                    _tcscat(deviceKeyName, cSubKeyName) ;
                    _tcscpy( usbList[i].cDeviceID, cSubKeyName) ;
                    _tcsncpy( usbList[i].cKeyName, deviceKeyName, MAX_KEY_LENGTH - 1 ) ;
                    // collect the creation time of this key - should be when they first plugged it in
                    FileTimeToSystemTime( &ft, &stGMT) ;
                    SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);
                    usbList[i].stStamp.wMonth = stLocal.wMonth ;
                    usbList[i].stStamp.wDay = stLocal.wDay ;
                    usbList[i].stStamp.wYear = stLocal.wYear ;
                    usbList[i].stStamp.wHour = stLocal.wHour ;
                    usbList[i].stStamp.wMinute = stLocal.wMinute ; 
                    usbList[i].instance = NULL ;
                }
ava
feodorv | 21.03.2013, 20:01 #
Я в код глубоко не лазил...

Что можно сделать:
  • избавиться от потенциально опасных _tcscpy и _tcscpy (Вы не контролируете выход за пределы массивов)
  • заменить malloc и free на HeapAlloc и HeapFree с контролем возвращаемого значения (ошибка/не ошибка), после каждой операции с памятью делать HeapCheck
  • распечатать список простым printf и убедится, что он в порядке
ava
CynicRus | 21.03.2013, 20:12 #
"Опять-таки, getDeviceList понятия не имеет об объёме deviceList, может быть всё что угодно."

Как же? Размер же указывается при инициализации переменной...Сейчас попробуй на HeapAlloc перейти..

"tvinsert.item.mask=TVIF_TEXT||TVIF_PARAM;"

скопипастил из примера-)))) Внимательно не посмотрев-))

"распечатать список простым printf и убедится, что он в порядке"

Это уже сделано, список выводится.
ava
feodorv | 21.03.2013, 20:14 #
Цитата (CynicRus @  21.3.2013,  21:12 findReferencedText)
Это уже сделано, список выводится. 

Вместе со всеми instanceInfo? Вы их печатали?
ava
CynicRus | 21.03.2013, 20:23 #
Может быть проблема в коде оттого, что вызывается несколько malloc и ниодного free? Но тогда я пока ума не приложу как правильно в этой функции память освободить.
ava
feodorv | 21.03.2013, 23:04 #
Ну не знаю. Я слегка переделал код, никакого падения:

#include <windows.h>
#include <stdio.h>
#include <string.h>

#define USBSTOR "SYSTEM\\CurrentControlSet\\Enum\\USBSTOR"

#define MAX_KEY_LENGTH 256
#define MAX_VALUE      256
#define MAX_VALUE_NAME 256

struct usbInfo
{
  TCHAR cKeyName[MAX_KEY_LENGTH];
  TCHAR cDeviceID[MAX_KEY_LENGTH];
  SYSTEMTIME stStamp;
  struct instanceInfo *instance;
};

struct instanceInfo
{
  TCHAR cInstanceID[MAX_KEY_LENGTH];
  TCHAR cFriendlyName[MAX_VALUE];
  TCHAR cDriver[MAX_VALUE];
  TCHAR cParentIdPrefix[MAX_VALUE];
  TCHAR cHardwareID[MAX_VALUE];
  TCHAR cLastDriveLetter[MAX_VALUE_NAME];
  SYSTEMTIME stDiskStamp;
  SYSTEMTIME stVolumeStamp;
  struct instanceInfo *next;
};

unsigned int getDeviceList( struct usbInfo *usbList, unsigned int iSubKeySize)
{
  HKEY hKey, hInstanceKey, hControlKey;
  DWORD dwName = MAX_KEY_LENGTH;
  TCHAR cSubKeyName[MAX_PATH+1];                 // buffer for subkey name
  DWORD dwSubKeys = 0;                           // number of subkeys
  DWORD dwValues = 0;                            // number of Values
  DWORD dwMaxValueNameLen = MAX_VALUE_NAME;      // Max Value Name Length
  DWORD dwMaxValueLen = MAX_VALUE;               // Max Value Length
  FILETIME ft;                                   // last write time (file time structure)
  SYSTEMTIME stGMT, stLocal;                     // system time for readability
  DWORD ValType, ValNameLen, ValLen;
  LPTSTR ValName;
  LPBYTE Val;
  struct instanceInfo *prev, *current;
  unsigned int iSubKeyCount = 0, i, n, j;

  if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, USBSTOR, 0, KEY_READ, &hKey) == ERROR_SUCCESS )
  {
    RegQueryInfoKey( hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
    if( dwSubKeys > 0 )
    {
      for( i = 0; i < dwSubKeys; i++)
      {
        dwName = MAX_KEY_LENGTH;
        if( RegEnumKeyEx( hKey, i, cSubKeyName, &dwName, NULL, NULL, NULL, &ft ) == ERROR_SUCCESS )
        {
          TCHAR deviceKeyName[MAX_KEY_LENGTH] = USBSTOR;
          strcat(deviceKeyName, "\\");
          strcat(deviceKeyName, cSubKeyName);
          strcpy( usbList[i].cDeviceID, cSubKeyName);
          strncpy( usbList[i].cKeyName, deviceKeyName, MAX_KEY_LENGTH-1);
          FileTimeToSystemTime( &ft, &stGMT);
          SystemTimeToTzSpecificLocalTime( NULL, &stGMT, &stLocal);
          usbList[iSubKeyCount].stStamp.wMonth = stLocal.wMonth;
          usbList[iSubKeyCount].stStamp.wDay = stLocal.wDay;
          usbList[iSubKeyCount].stStamp.wYear = stLocal.wYear;
          usbList[iSubKeyCount].stStamp.wHour = stLocal.wHour;
          usbList[iSubKeyCount].stStamp.wMinute = stLocal.wMinute;
          usbList[iSubKeyCount].instance = NULL;
          if( ++iSubKeyCount >= iSubKeySize ) break;
        }
      }
    }
    RegCloseKey( hKey );
  }

  // now we move on to getting the instance info from registry
  for( i = 0; i < iSubKeyCount; i++)
  {
    TCHAR instanceIdKeyName[MAX_KEY_LENGTH];
    if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, usbList[i].cKeyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS )
    {
      RegQueryInfoKey( hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
      if( dwSubKeys )
      {
        for( n = 0; n < dwSubKeys; n++)
        {
          dwName = MAX_KEY_LENGTH;
          if( RegEnumKeyEx( hKey, n, cSubKeyName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS )
          {
            current = (struct instanceInfo *) malloc(sizeof(struct instanceInfo));
            memset( current, 0, sizeof(struct instanceInfo));

            // fill out each instanceInfo
            strcpy( current->cInstanceID, cSubKeyName);
            strcpy( instanceIdKeyName, usbList[i].cKeyName);
            strcat( instanceIdKeyName, "\\");
            strcat( instanceIdKeyName, current->cInstanceID);

            // open each instanceID Registry Key to get the value data
            if( RegOpenKeyEx( hKey, cSubKeyName, 0, KEY_READ, &hInstanceKey) == ERROR_SUCCESS )
            {
              RegQueryInfoKey( hInstanceKey, NULL, NULL, NULL, NULL, NULL, NULL,
                                 &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL);
              if( dwValues )
              {
                ValName = (LPSTR) malloc( dwMaxValueNameLen+1 );
                Val = (LPBYTE) malloc( dwMaxValueLen );
                for( j = 0; j < dwValues; j++)
                {
                  ValNameLen = dwMaxValueNameLen + 1;
                  ValLen = dwMaxValueLen + 1;
                  RegEnumValue( hInstanceKey, j, ValName, &ValNameLen,
                                  NULL, &ValType, Val, &ValLen);
                  if( ValType == REG_SZ || ValType == REG_MULTI_SZ )
                  {
                    if( strcmp( "ParentIdPrefix", ValName) == 0 )
                      strcpy(current->cParentIdPrefix, (LPTSTR) Val);
                    if( strcmp( "FriendlyName", ValName) == 0 )
                      strcpy( current->cFriendlyName, (LPTSTR) Val);
                    if( strcmp( "HardwareID", ValName) == 0 )
                      strcpy( current->cHardwareID, (LPTSTR) Val);
                    if( strcmp( "Driver", ValName) == 0 )
                      strcpy( current->cDriver, (LPTSTR) Val);
                  }
                }
                free( ValName );
                free( Val );
              }
              RegCloseKey( hInstanceKey );
            }
            if( usbList[i].instance == NULL )
              usbList[i].instance = current;
            else
              prev->next = current;
            current->next = NULL ;
            prev = current;
          }
        }
      }
      RegCloseKey( hKey );
    }
  }

  /* погрызено */

  RegCloseKey( hKey ) ;
  return iSubKeyCount;
}

void printDeviceList( struct usbInfo *usbList, unsigned int iSubKeyCount)
{
  unsigned int i;

  for( i = 0; i < iSubKeyCount; i++)
  {
    struct instanceInfo *current;
    for( current = usbList[i].instance; current != NULL; current = current->next)
    {
      printf( "\n(%d) --- %s\n\n", i+1, current->cFriendlyName);
      printf( "\t\tinstanceID: %s\n", current->cInstanceID);
      printf( "\t\tParentIdPrefix: %s\n", current->cParentIdPrefix);
      if( strstr( current->cLastDriveLetter, "Dos") != NULL )
        printf( "\t\tLast Mounted As: %s\n", current->cLastDriveLetter);
      printf( "\t\tDriver:%s\n", current->cDriver);
      printf( "\t\tDisk Stamp: %02i/%02i/%04i %02i:%02i\n", current->stDiskStamp.wMonth, current->stDiskStamp.wDay,
        current->stDiskStamp.wYear, current->stDiskStamp.wHour, current->stDiskStamp.wMinute);
      printf( "\t\tVolume Stamp: %02i/%02i/%04i %02i:%02i\n", current->stVolumeStamp.wMonth, current->stVolumeStamp.wDay,
        current->stVolumeStamp.wYear, current->stVolumeStamp.wHour, current->stVolumeStamp.wMinute);
    }
  }
}

void cleanDeviceList( struct usbInfo *usbList, int Count)
{
  struct instanceInfo *next, *current;
  int i;

  for( i = 0; i < Count; i++)
  {
    current = usbList[i].instance;
    while( current != NULL )
    {
      next = current->next;
      free( current );
      current = next;
    }
  }
}

int main( void )
{
  struct usbInfo usbList[256];
  int i, count;

  for( i = 0; i < 100; i++)
  {
    count = getDeviceList( usbList, 256);
    printDeviceList( usbList, count);
    cleanDeviceList( usbList, count);
  }

  return 0;
}
ava
CynicRus | 22.03.2013, 08:41 #
Как показывает тест, ваша вариация кода работает. Я свой слегка допилил по вашему примеру, если я беру полностью функцию - то происходит падение. Если же я оставляю 2 блока - то всё работает. Сейчас начну потихоньку вводить по блоку кода и смотреть где падает..Спасибо Вам!
ava
CynicRus | 22.03.2013, 09:03 #
Как показывает тест - вот она, причина всех несчастий:


if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\MountedDevices"),
                0, KEY_READ, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
                &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, &ft ) ;
        ValName =reinterpret_cast<LPTSTR> (malloc (dwMaxValueNameLen+1)); // Allow for null.
        Val =reinterpret_cast<LPBYTE>(malloc (dwMaxValueLen)); // Size in bytes.

        FileTimeToSystemTime( &ft, &stGMT) ;
        SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);

        if (dwValues) {
            for (int i=0; i<dwValues; i++){

                ValNameLen = dwMaxValueNameLen ;
                ValLen = dwMaxValueLen ;
                TCHAR valueString[ValLen+1] ;
                RegEnumValue (hKey, i, ValName, &ValNameLen, NULL, &ValType, Val, &ValLen);

                // eleminate older volume's and only check for recent DosDevices
                if (strncmp(  (LPSTR)ValName, "\\DosDev", 7) == 0) {

                    // build a usable string out of the REG_BINARY data in the registry by
                    // skipping the white space in between each character.
                    if (ValType == REG_BINARY)
                        for (int i = 0; i < ValLen; i++, Val++)
                            valueString[i] = Val[i] ;

                    valueString[ValLen+1] = '\0' ;    //append a null by to the end of our string
                                                    //as a null character isn't guaranteed

                    // We only want to look at removable media and ignore fixed devices
                    if (strncmp( valueString, "\\??\\STORAGE#RemovableMedia#", 27) == 0) {

                        // Now cycle through each and see if hte ParentID is in valueString, if it is
                        // then copy ValName to lastDriveLetter
                        for (int i = 0; i < iSubKeyCount; i++) {

                            current = usbList[i].instance ;

                            if (  ( strstr( valueString, current->cParentIdPrefix) != NULL)
                                    && (strlen(current->cParentIdPrefix) > 1 ) )
                                strcpy(current->cLastDriveLetter, (LPTSTR) ValName) ;
                            while (current->next != NULL) {
                                current = current->next ;
                                if ( ( strstr( valueString, current->cParentIdPrefix) != NULL )
                                        && (strlen(current->cParentIdPrefix) > 1 ) )
                                    strcpy(current->cLastDriveLetter, (LPTSTR)ValName) ;
                            }
                        }
                        // Done Cycling Through the list.
                    }
                }
            }
        }

    free(Val) ; free(ValName) ;
    }
ava
xvr | 22.03.2013, 09:20 #
Цитата (CynicRus @  22.3.2013,  09:03 findReferencedText)
    TCHAR valueString[ValLen+1] ;


Цитата (CynicRus @  22.3.2013,  09:03 findReferencedText)
     valueString[ValLen+1] = '\0' ;    //append a null by to the end of our string

Налицо запись за пределы массива
ava
CynicRus | 22.03.2013, 09:31 #
Хм...Увеличиваю размер массива на [ValLen+2] или +10 всё равно тоже самое, при этом заменил использование strncmp на использование strstr.

сам код:


if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\MountedDevices"),
                0, KEY_READ, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
                &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, &ft ) ;
        ValName =reinterpret_cast<LPTSTR> (malloc (dwMaxValueNameLen+1)); // Allow for null.
        Val =reinterpret_cast<LPBYTE>(malloc (dwMaxValueLen)); // Size in bytes.

        FileTimeToSystemTime( &ft, &stGMT) ;
        SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);

        if (dwValues) {
            for (int v=0; v<dwValues; v++){

                ValNameLen = dwMaxValueNameLen ;
                ValLen = dwMaxValueLen ;
                TCHAR valueString[ValLen+2] ;
                RegEnumValue (hKey, v, ValName, &ValNameLen, NULL, &ValType, Val, &ValLen);

                // eleminate older volume's and only check for recent DosDevices
                if (strstr(  (LPSTR)ValName, "\\DosDev") != NULL) {

                    // build a usable string out of the REG_BINARY data in the registry by
                    // skipping the white space in between each character.
                    if (ValType == REG_BINARY)
                        for (int j = 0; j < ValLen; j++, Val++)
                            valueString[j] = Val[j] ;

                    valueString[ValLen+1] = '\0' ;    //append a null by to the end of our string
                                                    //as a null character isn't guaranteed

                    // We only want to look at removable media and ignore fixed devices
                    if (strstr( valueString, "\\??\\STORAGE#RemovableMedia#") != NULL) {

                        // Now cycle through each and see if hte ParentID is in valueString, if it is
                        // then copy ValName to lastDriveLetter
                        for (int i = 0; i < iSubKeyCount; i++) {

                            current = usbList[i].instance ;

                            if (  ( strstr( valueString, current->cParentIdPrefix) != NULL)
                                    && (strlen(current->cParentIdPrefix) > 1 ) )
                                strcpy(current->cLastDriveLetter, (LPTSTR) ValName) ;
                            while (current->next != NULL) {
                                current = current->next ;
                                if ( ( strstr( valueString, current->cParentIdPrefix) != NULL )
                                        && (strlen(current->cParentIdPrefix) > 1 ) )
                                    strcpy(current->cLastDriveLetter, (LPTSTR)ValName) ;
                            }
                        }
                        // Done Cycling Through the list.
                    }
                }
            }
        }

    free(Val) ; free(ValName) ;
    }

ava
CynicRus | 22.03.2013, 10:11 #
Вообщем кажись справился с проблемой:


    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\MountedDevices"),
                0, KEY_READ, &hKey) == ERROR_SUCCESS) {

        RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
                &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, &ft ) ;
        ValName =reinterpret_cast<LPTSTR> (malloc (dwMaxValueNameLen+1)); // Allow for null.
        Val =reinterpret_cast<LPBYTE>(malloc (dwMaxValueLen)); // Size in bytes.

        FileTimeToSystemTime( &ft, &stGMT) ;
        SystemTimeToTzSpecificLocalTime(NULL, &stGMT, &stLocal);

        if (dwValues) {
            for (int v=0; v<dwValues; v++){

                ValNameLen = dwMaxValueNameLen ;
                ValLen = dwMaxValueLen ;
                char * valueString ;
                RegEnumValue (hKey, v, ValName, &ValNameLen, NULL, &ValType, Val, &ValLen);

                // eleminate older volume's and only check for recent DosDevices
                if (strstr(  (LPSTR)ValName, "\\DosDev") != NULL) {

                    // build a usable string out of the REG_BINARY data in the registry by
                    // skipping the white space in between each character.
                    if (ValType == REG_BINARY)
                            valueString =(char *)Val;

                
                    // We only want to look at removable media and ignore fixed devices
                    if (strstr( valueString, "\\??\\STORAGE#RemovableMedia#") != NULL) {

                        // Now cycle through each and see if hte ParentID is in valueString, if it is
                        // then copy ValName to lastDriveLetter
                        for (int i = 0; i < iSubKeyCount; i++) {

                            current = usbList[i].instance ;

                            if (  ( strstr( valueString, current->cParentIdPrefix) != NULL)
                                    && (strlen(current->cParentIdPrefix) > 1 ) )
                                strcpy(current->cLastDriveLetter, (LPTSTR) ValName) ;
                            while (current->next != NULL) {
                                current = current->next ;
                                if ( ( strstr( valueString, current->cParentIdPrefix) != NULL )
                                        && (strlen(current->cParentIdPrefix) > 1 ) )
                                    strcpy(current->cLastDriveLetter, (LPTSTR)ValName) ;
                            }
                        }
                        // Done Cycling Through the list.
                    }
                }
            }
        }

    free(Val) ; free(ValName) ;
    }
ava
feodorv | 22.03.2013, 13:02 #
Цитата (CynicRus @  22.3.2013,  11:11 findReferencedText)
Вообщем кажись справился с проблемой:

Цитата (CynicRus @  22.3.2013,  11:11 findReferencedText)
    char * valueString ;


Цитата (CynicRus @  22.3.2013,  11:11 findReferencedText)
     if (ValType == REG_BINARY)
        valueString =(char *)Val;
     
      // We only want to look at removable media and ignore fixed devices
      if (strstr( valueString, "\\??\\STORAGE#RemovableMedia#") != NULL) {

Сделайте хотя бы 

                char * valueString = "";

Да и REG_BINARY никак не гарантирует, что возвращаемый из RegEnumValue массив символов будет завершен символом '\0'...
ava
CynicRus | 22.03.2013, 15:41 #
Цитата (feodorv @ 22.3.2013,  13:02)
Цитата (CynicRus @  22.3.2013,  11:11 \\"findReferencedText\\")
Вообщем кажись справился с проблемой:


Цитата (CynicRus @  22.3.2013,  11:11 \"findReferencedText\")
    char * valueString ;




Цитата (CynicRus @  22.3.2013,  11:11 \"findReferencedText\")
     if (ValType == REG_BINARY)
        valueString =(char *)Val;
     
      // We only want to look at removable media and ignore fixed devices
      if (strstr( valueString, "\\??\\STORAGE#RemovableMedia#") != NULL) {


Сделайте хотя бы 


                char * valueString = "";



Да и REG_BINARY никак не гарантирует, что возвращаемый из RegEnumValue массив символов будет завершен символом '\0'...

Это я уже допилил-) Я привёл тот код, с которым у меня наконец собралось и отработало без ошибок. Ещё раз Вам спасибо!
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
  xvr ava  feodorv   CynicRus   math64
advanced
Submit