March 2, 2021
Hot Topics:

Using RAPI to Find Remote Files

  • By Nancy Nicolaisen
  • Send Email »
  • More Articles »

Our tool for retrieving information about files on the CE device is the powerhouse function, CeFindAllFiles(). CeFindAllFiles() has no analog on the CE side. It is specifically designed for RAPI applications, and retrieves all the files and folders under a particular node, in a single call. This is advantageous because it is much more efficient for the CE side than enumerating files and folders individually, and for this reason saves both processing time and battery power.

The arguments to the function are: a pointer to a Unicode string specifying a DOS style search path, a DWORD containg flags that determine what file attributes to return, a count of the returned items, and the address of a pointer of type LPCE_FIND_DATA. On successful return, the last parameter contains the address of an array of CE_FIND_DATA structures. Here is the typedef for CE_FIND_DATA:

typedef struct _CE_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;        //0, unless the overall file size is >
DWORD nFileSizeLow;         //file size in bytes
DWORD dwOID;                //CE Object Identifier for this file
WCHAR cFileName[MAX_PATH];  //Unicode file name

Based on the state of the checkbox controls, we add flags to dwFileAttributeFlags. At a minimum, we'll retrieve the filename, and optionally the creation time, last write time, and CE Object ID for the file. If the GetFoldersOnly box is checked, we retrieve information for all the folders in the search path and skip over the files. Here's a complete list of the CE_FIND_DATA () file attribute flags, along with their meanings.

Table 1: CE_FIND_DATA File Attribute Flags And Their Meanings

File Attribute Flag Name Meaning
FAF_ATTRIB_CHILDREN Only retrieve information for directories with child items
FAF_ATTRIB_NO_HIDDEN Omit files or directories that have the hidden attribute set
FAF_FOLDERS_ONLY Retrieve information for directories only
FAF_NO_HIDDEN_SYS_ROMMODULES Omit ROM files or directories
FAF_ATTRIBUTES Return file attributes in dwFileAttributes
FAF_CREATION_TIME Return file creation time in ftCreationTime
FAF_LASTACCESS_TIME Return last access time in ftLastAccessTime
FAF_LASTWRITE_TIME Return last write time in ftLastWriteTime
FAF_SIZE_HIGH Return the high-order DWORD value of the file size in nFileSizeHigh
FAF_SIZE_LOW Return the low-order DWORD value of the file size in nFileSizeLow
FAF_OID Return the CE object identifier of the file in dwOID
FAF_NAME Return the Unicode file name in cFileName
DWORD dwFileAttributeFlags = FAF_NAME;

if( m_GetCreationTime.GetCheck() )
{ dwFileAttributeFlags |= FAF_CREATION_TIME ; }

if( m_GetLastWriteTime.GetCheck() )
{ dwFileAttributeFlags |= FAF_LASTWRITE_TIME ; }

if( m_GetFoldersOnly.GetCheck() )
{ dwFileAttributeFlags |= FAF_FOLDERS_ONLY; }

if( m_GetCEOID.GetCheck() )
{ dwFileAttributeFlags |= FAF_OID; }

BOOL bOk = CeFindAllFiles( (LPCWSTR)&wszFileName[0],
                          dwFileAttributeFlags, &dwFoundCount,
                          &pFindDataArray );

    if(!bOk )
        { return; }

On successful return for CeFindAllFiles, we loop through the array of returned structures, transferring the retrieved information to the list control, m_FilesList. Notice that we use the count of found items, dwFoundCount, returned by CeFindAllFiles to set the loop limit. Because the returned file name is a Unicode string, we must translate it to multi byte character format by using wcstombs() before attempting to insert it into the list control.

char szLineBuff[MAX_PATH]; 

for( int i = 0; i < dwFoundCount; i++ )

   wcstombs( szLineBuff, pFindDataArray[i].cFileName,
   m_FilesList.InsertString( -1, szLineBuff );

   if( m_GetCreationTime.GetCheck() )
      CTime FileCreationTime(pFindDataArray[i].ftCreationTime, -1 );
      CString csBuff = FileCreationTime.Format("%A, %B %d, %Y" );
      sprintf( szLineBuff, "  %s: %s", "Creation Time",
              csBuff.GetBuffer(csBuff.GetLength())  );
      m_FilesList.InsertString( -1, szLineBuff );


   if( m_GetLastWriteTime.GetCheck() )
      CTime LastWriteTime(pFindDataArray[i].ftCreationTime, -1 );
      CString csBuff = LastWriteTime.Format("%A, %B %d, %Y" ); 
      sprintf( szLineBuff, "  %s: %s", "Last Write", 
               csBuff.GetBuffer(csBuff.GetLength())  );
      m_FilesList.InsertString( -1, szLineBuff );


   if( m_GetCEOID.GetCheck() )
      sprintf( szLineBuff, "  %s: %s%x", "CEOID", "0x",
               pFindDataArray[i].dwOID );
      m_FilesList.InsertString( -1, szLineBuff );

//    m_FilesList.InsertString( -1, " " );
}//end for()

Notice that our call to CeFindAllFiles() returned a pointer to a dynamically allocated array of CE_FIND_DATA structures. We must free this buffer that was allocated in our behalf before we uninitialize the RAPI subsystem, or memory will be "leaked."

//free the CE_FIND_DATA structure array buffer
hr =  CeRapiFreeBuffer((LPVOID) pFindDataArray);

//now uninitialize RAPI.


Looking Ahead

In our next lesson, we'll learn how to remotely walk the CE side Registry tree, a very useful technique for remotely managing CE side configurations.

About the Author

Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, and entry time data validation.

In addition to writing for Developer.com, she has written several books, including Making Win 32 Applications Mobile.

# # #

Page 2 of 2

This article was originally published on July 26, 2004

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date