⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 profile.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:

                continue;
            }
        }

        /* get rid of white space after the name and before the start
         * of the value */
        len = szLineEnd - szLineStart;
        if ((szValueStart = memchrW( szLineStart, '=', szLineEnd - szLineStart )) != NULL)
        {
            const WCHAR *szNameEnd = szValueStart;
            while ((szNameEnd > szLineStart) && PROFILE_isspaceW(szNameEnd[-1])) szNameEnd--;
            len = szNameEnd - szLineStart;
            szValueStart++;
            while (szValueStart < szLineEnd && PROFILE_isspaceW(*szValueStart)) szValueStart++;
        }

        if (len || !prev_key || *prev_key->name)
        {
            /* no need to allocate +1 for NULL terminating character as
             * already included in structure */
            if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) + len * sizeof(WCHAR) ))) break;
            memcpy(key->name, szLineStart, len * sizeof(WCHAR));
            key->name[len] = '\0';
            if (szValueStart)
            {
                len = (int)(szLineEnd - szValueStart);
                key->value = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
                memcpy(key->value, szValueStart, len * sizeof(WCHAR));
                key->value[len] = '\0';
            }
            else key->value = NULL;

           key->next  = NULL;
           *next_key  = key;
           next_key   = &key->next;
           prev_key   = key;

           DPRINT("New key: name=%S, value=%S\n",
                  key->name, key->value ?key->value : L"(none)");
        }
    }
    if (szFile != pBuffer)
        HeapFree(GetProcessHeap(), 0, szFile);
    HeapFree(GetProcessHeap(), 0, pBuffer);
    return first_section;
}


/***********************************************************************
 *           PROFILE_DeleteSection
 *
 * Delete a section from a profile tree.
 */
static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCWSTR name )
{
    while (*section)
    {
        if ((*section)->name[0] && !_wcsicmp( (*section)->name, name ))
        {
            PROFILESECTION *to_del = *section;
            *section = to_del->next;
            to_del->next = NULL;
            PROFILE_Free( to_del );
            return TRUE;
        }
        section = &(*section)->next;
    }
    return FALSE;
}


/***********************************************************************
 *           PROFILE_DeleteKey
 *
 * Delete a key from a profile tree.
 */
static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
                LPCWSTR section_name, LPCWSTR key_name )
{
    while (*section)
    {
        if ((*section)->name[0] && !_wcsicmp( (*section)->name, section_name ))
        {
            PROFILEKEY **key = &(*section)->key;
            while (*key)
            {
                if (!_wcsicmp( (*key)->name, key_name ))
                {
                    PROFILEKEY *to_del = *key;
                    *key = to_del->next;
                    HeapFree( GetProcessHeap(), 0, to_del->value);
                    HeapFree( GetProcessHeap(), 0, to_del );
                    return TRUE;
                }
                key = &(*key)->next;
            }
        }
        section = &(*section)->next;
    }
    return FALSE;
}


/***********************************************************************
 *           PROFILE_DeleteAllKeys
 *
 * Delete all keys from a profile tree.
 */
static void PROFILE_DeleteAllKeys( LPCWSTR section_name)
{
    PROFILESECTION **section= &CurProfile->section;
    while (*section)
    {
        if ((*section)->name[0] && !_wcsicmp( (*section)->name, section_name ))
        {
            PROFILEKEY **key = &(*section)->key;
            while (*key)
            {
                PROFILEKEY *to_del = *key;
                *key = to_del->next;
                HeapFree( GetProcessHeap(), 0, to_del->value);
                HeapFree( GetProcessHeap(), 0, to_del );
                CurProfile->changed =TRUE;
            }
        }
        section = &(*section)->next;
    }
}


/***********************************************************************
 *           PROFILE_Find
 *
 * Find a key in a profile tree, optionally creating it.
 */
static PROFILEKEY *PROFILE_Find( PROFILESECTION **section, LPCWSTR section_name,
                                 LPCWSTR key_name, BOOL create, BOOL create_always )
{
    LPCWSTR p;
    int seclen, keylen;

    while (PROFILE_isspaceW(*section_name)) section_name++;
    p = section_name + wcslen(section_name) - 1;
    while ((p > section_name) && PROFILE_isspaceW(*p)) p--;
    seclen = p - section_name + 1;

    while (PROFILE_isspaceW(*key_name)) key_name++;
    p = key_name + wcslen(key_name) - 1;
    while ((p > key_name) && PROFILE_isspaceW(*p)) p--;
    keylen = p - key_name + 1;

    while (*section)
    {
        if ( ((*section)->name[0])
             && (!(_wcsnicmp( (*section)->name, section_name, seclen )))
             && (((*section)->name)[seclen] == '\0') )
        {
            PROFILEKEY **key = &(*section)->key;

            while (*key)
            {
                /* If create_always is FALSE then we check if the keyname
                 * already exists. Otherwise we add it regardless of its
                 * existence, to allow keys to be added more than once in
                 * some cases.
                 */
                if(!create_always)
                {
                    if ( (!(_wcsnicmp( (*key)->name, key_name, keylen )))
                         && (((*key)->name)[keylen] == '\0') )
                        return *key;
                }
                key = &(*key)->next;
            }
            if (!create)
                return NULL;
            if (!(*key = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILEKEY) + wcslen(key_name) * sizeof(WCHAR) )))
                return NULL;
            wcscpy( (*key)->name, key_name );
            (*key)->value = NULL;
            (*key)->next  = NULL;
            return *key;
        }
        section = &(*section)->next;
    }
    if (!create) return NULL;
    *section = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILESECTION) + wcslen(section_name) * sizeof(WCHAR) );
    if(*section == NULL) return NULL;
    wcscpy( (*section)->name, section_name );
    (*section)->next = NULL;
    if (!((*section)->key  = HeapAlloc( GetProcessHeap(), 0,
                                        sizeof(PROFILEKEY) + wcslen(key_name) * sizeof(WCHAR) )))
    {
        HeapFree(GetProcessHeap(), 0, *section);
        return NULL;
    }
    wcscpy( (*section)->key->name, key_name );
    (*section)->key->value = NULL;
    (*section)->key->next  = NULL;
    return (*section)->key;
}


/***********************************************************************
 *           PROFILE_FlushFile
 *
 * Flush the current profile to disk if changed.
 */
static BOOL PROFILE_FlushFile(void)
{
    HANDLE hFile = NULL;
    FILETIME LastWriteTime;

    if(!CurProfile)
    {
        DPRINT("No current profile!\n");
        return FALSE;
    }

    if (!CurProfile->changed) return TRUE;

    hFile = CreateFileW(CurProfile->filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        DPRINT("could not save profile file %S (error was %ld)\n", CurProfile->filename, GetLastError());
        return FALSE;
    }

    DPRINT("Saving %S\n", CurProfile->filename);
    PROFILE_Save( hFile, CurProfile->section, CurProfile->encoding );
    if(GetFileTime(hFile, NULL, NULL, &LastWriteTime))
       CurProfile->LastWriteTime=LastWriteTime;
    CloseHandle( hFile );
    CurProfile->changed = FALSE;
    return TRUE;
}


/***********************************************************************
 *           PROFILE_ReleaseFile
 *
 * Flush the current profile to disk and remove it from the cache.
 */
static void PROFILE_ReleaseFile(void)
{
    PROFILE_FlushFile();
    PROFILE_Free( CurProfile->section );
    HeapFree( GetProcessHeap(), 0, CurProfile->filename );
    CurProfile->changed = FALSE;
    CurProfile->section = NULL;
    CurProfile->filename  = NULL;
    CurProfile->encoding = ENCODING_ANSI;
    ZeroMemory(&CurProfile->LastWriteTime, sizeof(CurProfile->LastWriteTime));
}


/***********************************************************************
 *           PROFILE_Open
 *
 * Open a profile file, checking the cached file first.
 */
static BOOL PROFILE_Open( LPCWSTR filename )
{
    WCHAR windirW[MAX_PATH];
    WCHAR buffer[MAX_PATH];
    HANDLE hFile = INVALID_HANDLE_VALUE;
    FILETIME LastWriteTime;
    int i,j;
    PROFILE *tempProfile;

    ZeroMemory(&LastWriteTime, sizeof(LastWriteTime));

    /* First time around */

    if(!CurProfile)
       for(i=0;i<N_CACHED_PROFILES;i++)
       {
          MRUProfile[i]=HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILE) );
          if(MRUProfile[i] == NULL) break;
          MRUProfile[i]->changed=FALSE;
          MRUProfile[i]->section=NULL;
          MRUProfile[i]->filename=NULL;
          MRUProfile[i]->encoding=ENCODING_ANSI;
          ZeroMemory(&MRUProfile[i]->LastWriteTime, sizeof(FILETIME));
       }

    GetWindowsDirectoryW( windirW, MAX_PATH );

    if ((RtlDetermineDosPathNameType_U(filename) == RtlPathTypeRelative) &&
        !wcschr(filename, '\\') && !wcschr(filename, '/'))
    {
        static const WCHAR wszSeparator[] = {'\\', 0};
        wcscpy(buffer, windirW);
        wcscat(buffer, wszSeparator);
        wcscat(buffer, filename);
    }
    else
    {
        LPWSTR dummy;
        GetFullPathNameW(filename, sizeof(buffer)/sizeof(buffer[0]), buffer, &dummy);
    }

    DPRINT("path: %S\n", buffer);

    hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if ((hFile == INVALID_HANDLE_VALUE) && (GetLastError() != ERROR_FILE_NOT_FOUND))
    {
        DPRINT("Error %ld opening file %S\n", GetLastError(), buffer);
        return FALSE;
    }

    for(i = 0; i < N_CACHED_PROFILES; i++)
    {
       if ((MRUProfile[i]->filename && !wcscmp( buffer, MRUProfile[i]->filename )))
       {
          DPRINT("MRU Filename: %S, new filename: %S\n", MRUProfile[i]->filename, buffer);
          if(i)
          {
             PROFILE_FlushFile();
             tempProfile=MRUProfile[i];
             for (j = i; j > 0; j--)
                MRUProfile[j] = MRUProfile[j-1];
             CurProfile=tempProfile;
          }
          if (hFile != INVALID_HANDLE_VALUE)
             GetFileTime(hFile, NULL, NULL, &LastWriteTime);
          else
             LastWriteTime.dwHighDateTime = LastWriteTime.dwLowDateTime = 0;
          if (memcmp(&CurProfile->LastWriteTime, &LastWriteTime, sizeof(FILETIME)))
          {
             DPRINT("(%S): already opened (mru = %d)\n",
                    buffer, i );
          }
          else
          {
              DPRINT("(%S): already opened, needs refreshing (mru = %d)\n",
                     buffer, i );
          }
          if (hFile != INVALID_HANDLE_VALUE)
             CloseHandle(hFile);
          return TRUE;
       }
    }

    /* Flush the old current profile */
    PROFILE_FlushFile();

    /* Make the oldest profile the current one only in order to get rid of it */
    if(i == N_CACHED_PROFILES)
      {
       tempProfile = MRUProfile[N_CACHED_PROFILES-1];
       for (i = N_CACHED_PROFILES - 1; i > 0; i--)
          MRUProfile[i] = MRUProfile[i-1];
       CurProfile=tempProfile;
      }

    if (CurProfile->filename)
        PROFILE_ReleaseFile();

    /* OK, now that CurProfile is definitely free we assign it our new file */
    CurProfile->filename  = HeapAlloc( GetProcessHeap(), 0, (wcslen(buffer)+1) * sizeof(WCHAR) );
    if(CurProfile->filename == NULL)
    {
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return FALSE;
    }
    wcscpy( CurProfile->filename, buffer );

    if (hFile != INVALID_HANDLE_VALUE)
    {
        CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding);
        GetFileTime(hFile, NULL, NULL, &CurProfile->LastWriteTime);
        CloseHandle(hFile);
    }
    else
    {
        /* Does not exist yet, we will create it in PROFILE_FlushFile */
        DPRINT("profile file %S not found\n", buffer);
    }
    return TRUE;
}


/***********************************************************************
 *           PROFILE_GetSection
 *
 * Returns all keys of a section.
 * If return_values is TRUE, also include the corresponding values.
 */
static INT PROFILE_GetSection( PROFILESECTION *section, LPCWSTR section_name,
                LPWSTR buffer, UINT len, BOOL return_values, BOOL return_noequalkeys )
{
    PROFILEKEY *key;

    if (!buffer)
        return 0;

    DPRINT("%S,%p,%u\n", section_name, buffer, len);

    while (section)
    {
        if (section->name[0] && !_wcsicmp( section->name, section_name ))
        {
            UINT oldlen = len;
            for (key = section->key; key; key = key->next)
            {
                if (len <= 2) break;
                if (!*key->name) continue;  /* Skip empty lines */
                if (IS_ENTRY_COMMENT(key->name)) continue;  /* Skip comments */
                if (!return_noequalkeys && !return_values && !key->value) continue;  /* Skip lines w.o. '=' */
                PROFILE_CopyEntry( buffer, key->name, len - 1, 0 );
                len -= wcslen(buffer) + 1;
                buffer += wcslen(buffer) + 1;
                if (len < 2)
                    break;
                if (return_values && key->value)
                {
                    buffer[-1] = '=';
                    PROFILE_CopyEntry ( buffer, key->value, len - 1, 0 );
                    len -= wcslen(buffer) + 1;
                    buffer += wcslen(buffer) + 1;
                }
            }
            *buffer = '\0';
            if (len <= 1)
            {
                /*If either lpszSection or lpszKey is NULL and the supplied
                  destination buffer is too small to hold all the strings,
                  the last string is truncated and followed by two null characters.
                  In this case, the return value is equal to cchReturnBuffer
                  minus two. */
                buffer[-1] = '\0';
                return oldlen - 2;
            }
            return oldlen - len;
        }
        section = section->next;
    }
    buffer[0] = buffer[1] = '\0';
    return 0;
}

/* See GetPrivateProfileSectionNamesA for documentation */
static INT PROFILE_GetSectionNames( LPWSTR buffer, UINT len )
{
    LPWSTR buf;
    UINT buflen,tmplen;
    PROFILESECTION *section;

    DPRINT("(%p, %d)\n", buffer, len);

    if (!buffer || !len)
        return 0;
    if (len == 1) {
        *buffer = '\0';
        return 0;
    }

    buflen=len-1;
    buf = buffer;
    section = CurProfile->section;
    while ((section!=NULL)) {
        if (section->name[0]) {
            tmplen = wcslen(section->name)+1;
            if (tmplen > buflen) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -