Archive: newbie trying to use System plugin to call RAPI to detect Compact Framework


newbie trying to use System plugin to call RAPI to detect Compact Framework
I've been reading about this for awhile and finally decided to try it. My script actually compiled and ran, but now I have a couple questions:

Does anyone know if the string I passed is correct, to search for that 'GAC_mscorlib_*' with the '*' wildcard? I don't even know how to try to use the RAPI functions outside of NSIS to test this, I'm really operating outside my expertise here.

How would I look at the last output parameter, the r3/$3 which is supposed to be a pointer to the array of _CE_FIND_DATA structures?

Thanks

Here's my script:


Section "DetectCF"

System::Call "rapi::CeRapiInit() i .r0"

/***************
Dll Call Structure

STDAPI_(BOOL) CeFindAllFiles(
LPCWSTR szPath,
DWORD dwFlags,
LPDWORD lpdwFoundCount,
LPLPCE_FIND_DATA ppFindDataArray
);


These are flags for CeFindAllFiles

#define FAD_NAME ((WORD) 0x04)

//
// The Windows CE WIN32_FIND_DATA structure differs from the
// Windows WIN32_FIND_DATA stucture so we copy the Windows CE
// definition to here so that both sides match.
//
typedef struct _CE_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwOID;
WCHAR cFileName[MAX_PATH];
} CE_FIND_DATA, *LPCE_FIND_DATA;

typedef CE_FIND_DATA** LPLPCE_FIND_DATA;

*/

# Use CeFindAllFiles to search the device's Windows directory for GAC_mscorlib_*.dll

System::Call "rapi::CeFindAllFiles(t '\Windows\GAC_mscorlib_*.dll', \
i 0x04, \
*l . r2, \
*i . r3) b r4"

${If} $4 == 'some value'
MessageBox MB_OK 'Found a version of Compact Framework'
${Else}
MessageBox MB_OK 'Did not find a version of Compact Framework'
${EndIf}

System::Call "rapi::CeRapiUninit() i .r0"

SectionEnd

You're actually supposed to pass a pointer to an allocated structure in the fourth parameter. The structure must be the size of CE_FIND_DATA, which is 552, according to my count. To allocate such a structure, you can use System::Alloc. Pass the result of Alloc as an integer, not a pointer, as it's already the address to the structure.

After the call, you can read the result with System::Call as in the example in the documents. FILETIME is `l`, DWORD is `i` and WCHAR[MAX_PATH] is &w256.

Also, there's no such type as `b`, like you've used in the return value of CeFindAllFiles.

See the System readme for more information.


Thanks for the reply. My next attempt is below.

It appears to be not finding the file. CeRapiGetError returns 0, but CeGetLastError returns 87. The docs for that say to use FormatMessage to get a meaningful error out of that, but I haven't figured that out yet.

I also tried searching for a simpler-named file that I verified was actually on the device, in the Windows directory, and it didn't find that one either. I tried finding '\\Windows\\memo.*'. This makes me think I'm doing something else wrong, maybe something wrong with the file string I'm looking for, or the 2nd argument, the Flags parameter to CeFindAllFiles.

Any ideas?

Thanks


Section "DetectCF"

System::Call "rapi::CeRapiInit() i .r0"
DetailPrint "CeRapiInit return : $0"

/***************
Dll Call Structure

STDAPI_(BOOL) CeFindAllFiles(
LPCWSTR szPath,
DWORD dwFlags,
LPDWORD lpdwFoundCount,
LPLPCE_FIND_DATA ppFindDataArray
);


These are flags for CeFindAllFiles

#define FAD_NAME ((WORD) 0x04)

//
// The Windows CE WIN32_FIND_DATA structure differs from the
// Windows WIN32_FIND_DATA stucture so we copy the Windows CE
// definition to here so that both sides match.
//
typedef struct _CE_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwOID;
WCHAR cFileName[MAX_PATH];
} CE_FIND_DATA, *LPCE_FIND_DATA;

typedef CE_FIND_DATA** LPLPCE_FIND_DATA;

*/

# Use CeFindAllFiles to search the device's Windows directory for GAC_mscorlib_*.dll

System::Alloc 552
Pop $3

System::Call "rapi::CeFindAllFiles(t '\\Windows\\GAC_mscorlib_*.dll', \
i 0x04, \
*l . r2, \
i . r3) i r4"

${If} $4 == 1
MessageBox MB_OK 'Found a version of Compact Framework'
System::Call "*$3(i .r5, l .r6, l .r7, l .r8, i .r9, i .r10, i .r11, &w256 .r12)"
DetailPrint "File Found : $R02"
${Else}
MessageBox MB_OK 'Did not find a version of Compact Framework'
System::Call "rapi::CeRapiGetError() i .r0"
DetailPrint "RapiGetError return : $0"
${If} $0 == 0
System::Call "rapi::CeGetLastError() i .r0"
DetailPrint "CeGetLastError return : $0"
${EndIf}
${EndIf}

System::Free $3
System::Call "rapi::CeRapiUninit() i .r0"

SectionEnd

The fourth parameter is passed wrongly. Use `ir3` instead of `i.r3`. The dot means no input and only output, so it's not passing anything to the function.


Thanks for the reply, that got rid of the error that was reported from CeGetLastError.

However, since I tried this, I've learned that the problem is likely ActiveSync. There's some issue with version 3.7 of ActiveSync that causes CeFindAllFiles to not work.

So now I'm trying CeFindFirstFile. The only problem is I can't find a definition of it's return value, a HANDLE. I tried just returning it to an int/pointer, but I probably need to allocate the space for this structure just like CE_FIND_DATA, right?

This is what I tried :


System::Alloc 552
Pop $3

System::Call "rapi::CeFindFirstFile(t '\Windows\GAC_mscorlib_*.dll', ir3) i r4"

Integer is fine. There's no need to allocate space for a handle.


Wow, another fast response, thanks. CeGetLastError is returning 18. How do I get more information than that? I'm confused by the FormatMessage documentation.


You can use an error lookup tool that calls FormatMessage for you. There's a version that comes with Platform SDK and VC. I couldn't find one for download with a quick search, but I'm sure you'll find one somewhere, if you search a bit more.