Can the name of internal flashdrive programmatically found? - Windows Mobile Development and Hacking General

Hi,
I want to get out via a MortScript-routine the folder name of the internal flashdrive, e.x. \My Flash Drive. I wrote a routine that looks for all installed drives that are FAT/EXFAT formatted, but that down't help:
Code:
#TestDrivesFATFS.mscr
###########################################################################
#Searches all installed FATFS/exFAT drives except the one this script resides,
#because only those drives MioPocket can be installed on
###########################################################################
#
#Each filesystem is described in registry as
# [HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\<MyProfileName>]
# "DefaultFileSystem"="<MyFileSystem>"
# "Folder"="<MyFolderName>"
Local()
#Obligatory coding as to be found in some MioPocket's scripts
Drive = "\" & Part(SystemPath("ScriptPath"), "\", 2)
#Test starts here
ExcludeDrive = Substr(Drive, 2)
DrivesFATFS = Array()
RegKey = "System\StorageManager\Profiles"
Idx = 0
#Walk the chain of profiles
ForEach variable In RegSubkeys("HKLM", RegKey)
ForEach value, contents In Regvalues("HKLM", RegKey & "\" & variable)
#Some newer CE devices know of exFAT format
If((value eq "DefaultFileSystem") AND (contents ne "FATFS") AND (contents ne "EXFAT"))
Break
EndIf
If((value eq "Folder") AND (contents ne ExcludeDrive))
Idx += 1
DrivesFATFS[Idx] = "\" & contents
EndIf
EndForEach
EndForEach
If(Debug)
ForEach drv in Array(DrivesFATFS)
Message(drv)
EndForeach
EndIf
Any help appriciated. TIA

It can be found in the Registry (at least in my WinMo 6.1... don't know if it's the same way in CE releases or other brands). Look in "HKLM\System\StorageManager\INAND" (or MMC instead of INAND...). The drive name is the "folder" string value).

Thanks for your reply. What I'm searching for is a hint how I can determine per software (MortScript), already having got ( with a piece of code as postet above ) a list of drive-names, which of those is the Storage Card and which is the Flash Drive, not by default knowing of the drive-names, because those differ from device to device.
Running the code above on my device (Medion PNA with CE 5) returns among others the names \Storage Card and/or \My Flash Disk, but this doesn't really help me a lot.

Thanks to all for your interest.
=> SOLVED IT BY MYSELF!
If you are interested in how I did it, here the code to detect the name of SD(HC), MMC, etc card:
Code:
ErrorLevel("warn")
sd = @FindSDDrives()
ForEach drv in Array(sd)
Message(drv)
EndForEach
Sub FindSDDrives()
Local()
SDProfiles = Array()
SDDrives = Array()
SDDrives2 = Array()
#All CE filesystem profiles related to Storage Cards are listet under
#[HKEY_LOCAL_MACHINE\Drivers\SDCARD\ClientDrivers\Class\******]
#E.x. MMC_Class, SDMemory_Class
idx = 0
RegKey = "Drivers\SDCARD\ClientDrivers\Class"
ForEach sdcard In RegSubkeys("HKLM", RegKey)
ForEach value, contents In RegValues("HKLM", RegKey & "\" & sdcard)
If(value eq "Profile")
idx += 1
SDProfiles[idx] = contents
EndIf
EndForEach
EndForEach
#Each CE filesystem is described in registry as
# [HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\<MyProfileName>]
# "DefaultFileSystem"="<MyFileSystem>"
# "Folder"="<MyFolderName>"
# "Name"="<MyName>
idx = 0
RegKey = "System\StorageManager\Profiles"
ForEach profile in Array(SDProfiles)
ForEach value, contents In RegValues("HKLM", RegKey & "\" & profile)
If(value eq "Folder")
idx += 1
SDDrives[idx] = "\" & contents
EndIf
EndForeach
EndForEach
Clear(SDProfiles)
#Remove duplicates
idx = 0
idx2 = 0
prevdrv = ""
ForEach drv in Array(SDDrives)
idx += 1
If(SDDrives[idx] ne prevdrv)
idx2 += 1
prevdrv = SDDrives[idx]
SDDrives2[idx2] = prevdrv
EndIf
EndForEach
Clear(SDDrives)
Return(SDDrives2)
EndSub

Thanks
jwoegerbauer said:
Thanks to all for your interest.
=> SOLVED IT BY MYSELF!
If you are interested in how I did it, here the code to detect the name of SD(HC), MMC, etc card:
Click to expand...
Click to collapse
Usefull for XDA_UC build in like EnergyROMs. Don't try the German ROMs because of copying files from "Storage Crad" vs. "Speicherkarte" . Now thats solved.
Thanks.

Related

.CAB can not write registry at WM2005

yesterday,my C500 upgrade to WM2005,i make a Chinese Fonts pakage,only packs .ttf file can be writer in ram,but add registry value Latter,install cab file show:Installation was unsuccessful.Theprogram or setting cannot be installed because it does not have sufficient system permissions.
cab inf file:
Code:
[Version]
Signature = "$Windows NT$"
Provider = "Microsoft"
CESignature = "$Windows CE$"
[CEStrings]
CompanyName="Cloud-Castle Studio."
AppName="WM2005 Chs Fonts Installer"
InstallDir=%CE2%\Fonts
[DefaultInstall]
AddReg = RegSettings.All
CopyFiles = CopyToInstallDir.All
[SourceDisksNames]
1 = ,"ttf",,D:\smartphone\fonts
[SourceDisksFiles]
nina.ttf = 1
ninab.ttf = 1
MSSONG.TTF = 1
[DestinationDirs]
CopyToInstallDir.All=0,%InstallDir%
[CopyToInstallDir.All]
nina.ttf,,,0
ninab.ttf,,,0
MSSONG.TTF,,,0
[RegSettings.All]
HKLM,Software\Microsoft\FontLink\SystemLink,nina,0x00000000,"\Windows\Fonts\mssong.ttf,SC_Song"
HKLM,Software\Microsoft\FontPath,FontPath,0x00000000,"\Windows\Fonts"
help me,thanks![/b]
in HKLM\Security\Policies\Policies add DWORD key,"0000101b"=1
all ok!

RAPI problem writing registry key value

I am presently writing a RegEdit program to run on my PC and allow editing of the registry on the connected PPC. I have got to the point where I can read the entire registry and I am now implementing function to update the registry i.e. insert new key, delete key, add new Key Values etc...
The problem I have at the moment is trying to add a new value to an existing key. The function I have written so far to do this is as follows, but the call to CeRegSetValueEx(...) returns an error code 5!
Code:
//-----------------------------------------------------------------------------------
// Adds a new key value into the registry.
// // TO DO - add the data
int CRegEditDoc::AddNewKeyValue(HTREEITEM hParent, HKEY hRoot, LPTSTR lpszKey, LPTSTR lpszValueName, DWORD dwType)
{
USES_CONVERSION;
int nItem, rc;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPWSTR lpwszValueName = T2W(lpszValueName);
try
{
if (lstrlen (lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
CString strValue = "my data";
LPWSTR lpwszData = T2W(strValue);
DWORD length = dim(lpwszData);
nItem = m_pRightView->GetListCtrl().GetItemCount();
if (m_rapi.CeRegSetValueEx(hKey, lpwszValueName, 0, dwType, (LPBYTE)lpwszData, length*2) != ERROR_SUCCESS) // last 2 lpData, szie in bytes of data.
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
return 0;
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::AddNewKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
I would appreciate a little advise on the matter, as this is the first time I have used the RAPI.
Thanks.
Hi VZ800!
The error you're getting is 'access denied'. In WM5 many RAPI functions (including writing to registry) are blocked for security reasons. Your only choice is to use a dll with CeRapiInvoke functions, but it needs to be deployed through a special cab.
You can read about this on msdn.
By the way, the app you're writing already exists, and it has the same problem.
Good luck!
Thanks for the advice. Since my post I have found that my code works for the HKEY_LOCAL_MACHINE, "/Software".
I will investigate the issue you have pointed me to.
Actually, your code should work for the entire HKEY_CLASSES_ROOT as well. MS decided to block only certain 'sensitive' parts of the registry so they can not be corrupted from the outside by malicious software.
If you noticed, MS's own remote registry editor works through DLLs (a ton of them).
Any way, I skimped on words in my first post, since I was writing it on a bus, and while I love my Jamin, writing long text on it is not very enjoyable.
Let me elaborate on CeRapiInvoke:
It's a function you call on the PC side that receives a DLL name and a function name (in that DLL) as parameters and calls that function on the device. It also lets you transfer buffers of data to and from the called function.
It's a great way to communicate with a PPC device without using sockets. You can write the device side DLL to do what ever you wont (like access protected registry) and report back to the PC.
The only drawback is in WM5 this DLL has to be registered and have a 'system' file attribute set. That's why you have to deploy it by cab.
Like I said before it's all in the MSDN.
Hope this helps.
Thanks. I have read the articles (and printed them) about RAPI Restricted Mode Security etc... http://msdn.microsoft.com/library/d...5/html/wce51conRAPIRestrictedModeSecurity.asp and will write a DLL to go on the PPC which will be installed via CAB etc...
I updated the function to add a new value anyway. Rather than calling the RAPI functions for the registry CeRapi... I will call my own functions in my authorised DLL.
Code:
//-----------------------------------------------------------------------------------
// Adds a new key value into the registry.
//
int CRegEditDoc::AddNewKeyValue(HTREEITEM hParent, HKEY hRoot, LPTSTR lpszKey,
LPTSTR lpszValName, DWORD dwDType, LPBYTE lpData)
{
USES_CONVERSION;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPWSTR lpwszValName = T2W(lpszValName);
DWORD dwDSize = sizeof(lpData);
try
{
if (lstrlen(lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
// Check if valuename already exists. Should never happen, but just in case.
if (m_rapi.CeRegQueryValueEx(hKey, lpwszValName, 0, &dwDType, NULL, &dwDSize) == ERROR_SUCCESS)
{
AfxMessageBox(_T("Value of this name already exists!"));
return 0;
}
if (m_rapi.CeRegSetValueEx(hKey, lpwszValName, 0, dwDType, lpData, dwDSize) != ERROR_SUCCESS)
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
AfxMessageBox(_T("Unable to create new value for this key!\nPlease check access rights."));
return 0;
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::AddNewKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
A question on using the CeRapiInvoke function. Obviously my function that I will be invoking in my DLL will need to conform to the following footprint:
Code:
LPCWSTR, LPCWSTR, DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream**, DWORD
What I would like to know is this: If I want my function to be a wrapper to say the
Code:
CeRegQueryValueEx(HKEY, LPWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)
function, how do I parse the function args? Please suggest how I would pack them into a BYTE* for the pInput parameter.
Actually, you got it a bit wrong:
Code:
FuncName(DWORD cbInput, BYTE *pInput, DWORD *pcbOutput, BYTE **ppOutput, IRAPIStream *ppIRAPIStream);
The prototype you specified is for the PC side (the first two strings are DLL name and function name);
I use the following parsing method:
Code:
BYTE* curInputPos = pInput;
memcpy((BYTE*)&hKey, curInputPos, sizeof(HKEY));
curInputPos += sizeof(HKEY);
memcpy((BYTE*)&dwIndex, curInputPos, sizeof(DWORD));
curInputPos += sizeof(DWORD);
memcpy((BYTE*)&Reserved, curInputPos, sizeof(DWORD));
curInputPos += sizeof(DWORD);
It works fine both ways.
Just don't forget to use LocalAlloc for inBuffer and LocalFree for outBuffer.
Thanks. I'll let you know how I get on.
So if I were to parse an HKEY and an LPTSTR accross I would do the following to put the data into a BYTE array:
Code:
DWORD dwIn, dwOut;
LPBYTE pInput;
PDWORD pOut;
dwIn = sizeof(HKEY) + (strlen(lpszKey)*sizeof(TCHAR));
pInput = (BYTE*)(LocalAlloc(LPTR, dwIn));
memcpy(pInput, (BYTE*)&hKey, sizeof(HKEY));
pInput += sizeof(HKEY);
memcpy(pInput, (BYTE*)&lpszKey, strlen(lpszKey)*sizeof(TCHAR));
// move pointer back to begining.
pInput -= sizeof(HKEY);
Basically, yes but with two reservations:
1) I recommend using a different pointer for the current position in buffer, to avoid errors.
2) you need to put the string length in the byte array before the string, otherwise you won't know it's length on the device side. Alternatively, you have to add 1 to the length so the 0 byte at the end gets packed and you can use strlen on the device.
Also keep in mined that unless you define the PC side project to work with UNICODE libraries, THCHAR will be defined as char, while on the device it's always WCHAR.
I really apreciate your help. I still can't get my DLL function to work I keep getting error 1064!
This is my code for the DLL named REditSvr.dll:
Code:
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec (dllexport) INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved);
#ifdef __cplusplus
}
#endif
BOOL WINAPI DllMain (HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
return TRUE;
}
INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved)
{
INT rc = 0;
BYTE* curInputPos = pInput;
HKEY hKey;
DWORD dwLength;
// Copy args out of input buffer.
memcpy((BYTE*)&hKey, curInputPos, sizeof(HKEY));
curInputPos += sizeof(HKEY);
memcpy((BYTE*)&dwLength, curInputPos, sizeof(DWORD));
curInputPos += sizeof(DWORD);
// Allocate enough memory for local wchar.
LPWSTR lpszValueName = (WCHAR*)malloc(dwLength);
memcpy((BYTE*)&lpszValueName, curInputPos, sizeof(dwLength));
curInputPos += sizeof(dwLength);
// Do the registry delete.
rc = RegDeleteValue(hKey, lpszValueName);
// Allocate memory for the return buffer.
BYTE* pOutput = (BYTE*)LocalAlloc(LPTR, sizeof(long));
memcpy(pOutput, (BYTE*)rc, sizeof(long));
*ppOutput = pOutput;
*pcbOutput = sizeof(long);
// Free input buffer.
LocalFree(pInput);
// Free WCHAR
free(lpszValueName);
return GetLastError();
}
and this is the code in my PC application which invokes the above function (or I would hope it did):
Code:
//-----------------------------------------------------------------------------------
// Deletes the key value from the registry.
//
int CRegEditDoc::DeleteKeyValue(HKEY hRoot, LPCTSTR lpszKey, LPCTSTR lpszValName)
{
USES_CONVERSION;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPWSTR lpwszValName = T2W(lpszValName);
try
{
if (lstrlen(lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
/* if (m_rapi.CeRegDeleteValue(hKey, lpwszValName) != ERROR_SUCCESS)
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
AfxMessageBox(_T("Unable to delete value for this key!\nPlease check access rights."));
return 0;
}
*/
// Testing remote registry value deletion.
DWORD dwIn, dwOut;
LPBYTE pInput, pCurInputPos;
PDWORD pOut;
DWORD dwLength = wcslen(lpwszValName)*sizeof(WCHAR);
dwIn = sizeof(HKEY) + dwLength;
pInput = (BYTE*)(LocalAlloc(LPTR, dwIn));
pCurInputPos = pInput;
memcpy(pCurInputPos, (BYTE*)&hKey, sizeof(HKEY));
pCurInputPos += sizeof(HKEY);
// Store the length of the string
memcpy(pCurInputPos, (BYTE*)&dwLength, sizeof(DWORD));
pCurInputPos += sizeof(DWORD);
memcpy(pCurInputPos, (BYTE*)&lpwszValName, dwLength);
HRESULT hr = m_rapi.CeRapiInvoke(L"REditSvr", L"RegEditDeleteValue", dwIn,
pInput, &dwOut, (PBYTE*)&pOut, NULL, 0);
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
LocalFree(pOut);
if (hKey != hRoot)
{
m_rapi.CeRegCloseKey(hKey);
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::DeleteKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
The DLL has been deployed to the PPC \Windows folder by eVC4. My PPC runs WM5 (is this the problem, although I have written programs with eVC4 ok for it).
I would again appreciate your help/advice on why this isn't working. At present I have unlocked my PPC and I am able to edit any part of the registry etc...
Hi VZ800!
I noticed a couple of errors in your code (which you may have corrected yourself by now) but the biggest problem, I think is that you don't register the dll.
Here is the part you missed from MSDN:
(full link: http://msdn.microsoft.com/library/d...en-us/mobilesdk5/html/mob5lrfcerapiinvoke.asp)
To satisfy the requirements of the Remote Access Security Policy
1. Create a provisioning XML document that adds the new node "RAPI" to the metabase. This node must include the absolute path to the *.DLL file. For more information, see Metabase Settings. The following code example shows the contents of a typical provisioning XML file.
<wap-provisioningdoc>
<characteristic type="Metabase">
<characteristic type="RAPI\Program Files\Green Sky\recaller.dll\*">
<parm name="rw-access" value="3"/>
<parm name="access-role" value="152"/>
</characteristic>
</characteristic>
</wap-provisioningdoc>
2. Pass the file name of the provisioning XML document to the CAB wizard using the /postxml command line option. The CAB wizard will append the XML to the _setup.xml file it places in the CAB. For more information on creating CAB files, see CAB Wizard.
3. Set the System attribute on the *.DLL file.
Only the Manager security role provides the required permissions for modifying the metabase. The ideal way to get this security role is to have your application signed with a privileged certificate.
Note Since Pocket PC implements a one-tier security model, the CAB install process will automatically have the Manager security role.
Click to expand...
Click to collapse
Here's my advice:
Create a simple function that doesn't receive parameters, but pops up a message on the device. When you see that calling it works, try adding the rest of the code.
Hi
As I understand the DLL does not require code to self- register. Anyway, I can call the DLL function and did as you suggested and put a MessageBox in the function. This displayed fine. My code for the DLL is as follows now:
Code:
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec (dllexport) INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved);
#ifdef __cplusplus
}
#endif
BOOL WINAPI DllMain (HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
return TRUE;
}
INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved)
{
DWORD rc = 0;
BYTE* curInputPos = pInput;
LPCWSTR lpszValueName;
HKEY hKey;
int len;
// Copy args out of input buffer.
memcpy((BYTE*)&hKey, curInputPos, sizeof(HKEY));
curInputPos += sizeof(HKEY);
// Size of value name string.
memcpy((BYTE*)&len, curInputPos, sizeof(int));
curInputPos += sizeof(int);
// Value name string.
memcpy((BYTE*)&lpszValueName, curInputPos, sizeof(len));
curInputPos += sizeof(len);
// Do the registry delete.
rc = RegDeleteValue(hKey, lpszValueName);
// Allocate memory for the return buffer.
*ppOutput = (BYTE*)LocalAlloc(LPTR, rc);
memcpy(*ppOutput, (BYTE*)&rc, sizeof(DWORD));
*pcbOutput = sizeof(DWORD);
// Free input buffer.
if (pInput)
LocalFree(pInput);
return GetLastError();
}
and this is the code from which I am calling it:
Code:
//-----------------------------------------------------------------------------------
// Deletes the key value from the registry.
//
int CRegEditDoc::DeleteKeyValue(HKEY hRoot, LPCTSTR lpszKey, LPCTSTR lpszValName)
{
USES_CONVERSION;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPCWSTR lpwszValName = T2W(lpszValName);
try
{
if (lstrlen(lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
/* if (m_rapi.CeRegDeleteValue(hKey, lpwszValName) != ERROR_SUCCESS)
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
AfxMessageBox(_T("Unable to delete value for this key!\nPlease check access rights."));
return 0;
}
*/
// Testing remote registry value deletion.
DWORD dwIn, dwOut;
LPBYTE pInput, pCurInputPos;
PDWORD pOut, rc;
int len = wcslen(lpwszValName)*sizeof(WCHAR);
dwIn = sizeof(HKEY) + len;
pInput = (BYTE*)(LocalAlloc(LPTR, dwIn));
pCurInputPos = pInput;
// Store the hKey value in the output buffer.
memcpy(pCurInputPos, (BYTE*)&hKey, sizeof(HKEY));
pCurInputPos += sizeof(HKEY);
// Store the length of the string in the output buffer.
memcpy(pCurInputPos, (BYTE*)&len, sizeof(int));
pCurInputPos += sizeof(int);
// Store the value name string in the output buffer.
memcpy(pCurInputPos, (BYTE*)&lpwszValName, len);
HRESULT hr = m_rapi.CeRapiInvoke(L"REditSvr", L"RegEditDeleteValue", dwIn,
pInput, &dwOut, (PBYTE*)&pOut, NULL, 0);
// HRESULT hr = RapiFuncTest(dwIn, pInput, &dwOut, (PBYTE*)&pOut, NULL);
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
if (dwOut)
{
memcpy((BYTE*)&rc, pOut, sizeof(DWORD));
}
if (pOut)
{
LocalFree(pOut);
}
if (hKey != hRoot)
{
m_rapi.CeRegCloseKey(hKey);
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::DeleteKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
As you can see in the DeleteKeyValue(...) function I called a test-function just to check that I was retrieving the data out of the pInput buffer ok, which I am.
I signed the DLL with the SDKSamplePrivDeveloper.pfx, added the /postxml via the /postxml switch in the cabwiz and successfully created a CAB file which installs the DLL into the \Windows folder on the PPC. The .inf file is as follows:
Code:
[CEStrings]
InstallDir=%CE2%
AppName="REditSvr"
[Strings]
CompanyName="AHartley"
[Version]
Signature="$Chicago$"
CESignature="$Windows CE$"
Provider=%CompanyName%
[SourceDisksNames.Arm]
1=,"arm files",,C:\eMDevelopment\PPCRegEdit\REditSvr\REL
[SourceDisksFiles.Arm]
REditSvr.dll=1
[Files.ARM]
REditSvr.dll
[DestinationDirs]
Files.Arm=,%InstallDir%
[DefaultInstall.Arm]
CopyFiles=Files.Arm
My PC side code invokes the DLL function return 0 as error code. But the error code returned in the ppOutput buffer is 0x00000057 Dec 87. Which equates to the error message "The parameter is incorrect."! Which must be a param of the RegDeleteValue(...) function, as if I comment this out I don't get any error return values!!
Any odeas?
This is all academic now as I won't be finishing the PPCRegEdit program coz of the Remote Registry Editor tool available in the eVC4 IDE, which I hadn't noticed before, duh. But I would like to know why the function isn't working as required.
You were writing this as a tool? :shock:
If you just asked, people would have told you about the existing reg edit and CeRegEdit witch works through RAPI directly.
Still, it is a nice exercise in coding which I done my self once (for other purposes)
Any way, your error is simple:
Code:
// Value name string.
memcpy((BYTE*)&lpszValueName, curInputPos, sizeof(len));
curInputPos += sizeof(len);
You are parsing it incorrectly.
This is how it should look:
Code:
// Value name string.
memcpy((BYTE*)lpszValueName, curInputPos, len);
curInputPos += len;
and on the PC side:
Code:
memcpy(pCurInputPos, (BYTE*)&lpwszValName, len);
should be:
Code:
memcpy(pCurInputPos, (BYTE*)lpwszValName, len);
once again, no offence but if you just read your code more carefully and use debug prints to check parameters, you won't need anyone's help.
Good luck in future projects.
(whoops, made an error my self while correcting another)
Yes, it is just an exercise.
Thanks for all your help. Sorry for the silly errors, I will try and take more care in future.

[WinXP Script] Extend Search Companion

Annoyed by the fact that Search Companion doesn't return the text string you specified even though you indicated All Files & Folders?
This handy script allows you to extend the PersistenHandlers to include other extension. In my case, I added: provxml and rgu. Copy and paste the following code into notepad and save as a .VB script (ex: xp_persisthandler.vbs). Execute the script and specifiy the file extension you wish to include in Search Companion.
Code:
'Add files to Search for files containing text
'© Doug Knox - 11/04/2001
'This code may be freely distributed/modified
Option Explicit
On Error Resume Next
Dim WshShell, N, P, P1, P2, ItemType, MyBox, FileType, Title, Prompt, RegKey, X
Set WSHShell = WScript.CreateObject("WScript.Shell")
P = "HKEY_CLASSES_ROOT\."
P1 = "\PersistentHandler\"
N = "{5e941d80-bf96-11cd-b579-08002b30bfeb}"
Prompt = "Enter the file extension for the file you wish to add." & vbCR
Prompt = Prompt & "Examples: txt, adm, inf"
Title = "Enter File Type"
FileType = InputBox(Prompt, Title, "")
If FileType = "" Then
MyBox = MsgBox("You left the box blank.",4096,"Error.")
Set WshShell = Nothing
WScript.Quit
Else
'Check to see if there is already a PersistentHandler default value
RegKey = P & FileType & P1
X = WshShell.RegRead(RegKey)
End If
'MyBox = MsgBox("The PersistentHandler value for ." & FileType & " is: " & X,4096,"Results")
'Set WshShell = Nothing
If X = N Then
MyBox = MsgBox("This value already exists, and is correct." & vbCR & "No Changes were made.", 4096, "No Changes")
Set WshShell = Nothing
WScript.Quit
End If
If X <> N AND X <> "" Then
MyBox = MsgBox("The Persistent Handler value already exists and is different." & vbCR & "No changes were made.", 4096, "No Changes")
Set WshShell = Nothing
WScript.Quit
End If
If Err.Number <> 0 Then
WshShell.RegWrite RegKey, N
MyBox = MsgBox("The Registry has been updated." & vbCR & "Restart your computer.", 4096, "Done")
Set WshShell = Nothing
End If

[Ruby] SMS Converter (from Pim Backup -> HTML)

I wanted to share a small script I wrote for those who know how to use it. It converts non-binary pim-backup message files to html files.
Usage: ruby <file> <message_file>
Code:
#-sms2html----------------------------------------------------------------#
# ChaosR (<[email protected]>) wrote this file. As long as #
# you do not touch this note and keep this note here you can do whatever #
# you want with this stuff. Also, the author(s) are not responsible for #
# whatever happens using this. #
#-------------------------------------------------------------------------#
require 'jcode' if RUBY_VERSION[0..2] == "1.8"
class SMSConverter
attr_accessor :messages, :raw, :by_folder, :by_name, :by_number
SPEC = [
:msg_id,
:sender_name,
:sender_address,
:sender_address_type,
:prefix,
:subject,
:body,
:body_type,
:folder,
:account,
:msg_class,
:content_length,
:msg_size,
:msg_flags,
:msg_status,
:modify_time,
:delivery_time,
:recipient_nbr,
:recipients,
:attachment_nbr,
:attachments
]
RECIP_SPEC = [
:id,
:name,
:phone,
:var1,
:var2,
:type
]
FOLDERS = {
"\\%MDF1" => "INBOX",
"\\%MDF2" => "OUTBOX",
"\\%MDF3" => "SENT",
"\\%MDF4" => "TRASH",
"\\%MDF5" => "DRAFTS"
}
def initialize(file)
f = File.open(file)
@raw = f.read
f.close
raw2array
clean_messages
sort_messages
end
def raw2array
messages = []
state = { :arg => 0, :escaped => false, :in_string => false }
sms = {}
@raw.each_char do |byte|
arg = SPEC[state[:arg]]
sms[arg] = "" unless sms[arg]
if byte == "\0" or byte == "\r"
next
elsif state[:escaped]
sms[arg] << byte
state[:escaped] = false
elsif state[:in_string]
if byte == "\""
state[:in_string] = false
elsif byte == "\\"
state[:escaped] = true
else
sms[arg] << byte
end
elsif byte == "\\"
state[:escaped] = true
elsif byte == "\""
state[:in_string] = true
elsif byte == ";"
state[:arg] += 1
elsif byte == "\n"
raise "Faulty conversion or corrupt file" if state[:escaped] or state[:in_string] or state[:arg] != 20
messages << sms
sms = {}
state[:arg] = 0
else
sms[arg] << byte
end
end
@messages = messages
end
def clean_messages
@messages.map! do |sms|
sms[:modify_time] = Time.local( *sms[:modify_time].split(",") )
unless sms[:delivery_time] == ""
sms[:delivery_time] = Time.local( *sms[:delivery_time].split(",") )
else
sms[:delivery_time] = sms[:modify_time]
end
sms[:recipient_nbr] = sms[:recipient_nbr].to_i
sms[:body_type] = sms[:body_type].to_i
sms[:msg_flags] = sms[:msg_flags].to_i
sms[:msg_status] = sms[:msg_status].to_i
sms[:attachment_nbr] = sms[:attachment_nbr].to_i
sms[:content_length] = sms[:content_length].to_i
sms[:msg_size] = sms[:msg_size].to_i
sms[:folder] = FOLDERS[sms[:folder]]
if sms[:recipient_nbr] > 0
recipients = {}
sms[:recipients].split(";").each_with_index { |var, index| recipients[RECIP_SPEC[index]] = var }
recipients[:id] = recipients[:id].to_i
recipients[:var1] = recipients[:var1].to_i
recipients[:var2] = recipients[:var2].to_i
sms[:recipients] = recipients
end
sms
end
end
def sort_messages
@messages = @messages.sort { |a, b| a[:delivery_time] <=> b[:delivery_time] }
@by_folder = {}
@messages.each do |sms|
@by_folder[sms[:folder]] = [] unless @by_folder[sms[:folder]]
@by_folder[sms[:folder]] << sms
end
@by_name = {}
@messages.each do |sms|
if sms[:recipient_nbr] > 0
if sms[:recipients][:name] != ""
name = sms[:recipients][:name]
else
name = sms[:recipients][:phone]
end
else
if sms[:sender_name] != ""
name = sms[:sender_name]
else
name = get_number_from_address(sms[:sender_address])
end
end
@by_name[name] = [] unless @by_name[name]
@by_name[name] << sms
end
@by_number = {}
@messages.each do |sms|
if sms[:recipient_nbr] > 0
name = sms[:recipients][:phone]
else
name = get_number_from_address(sms[:sender_address])
end
@by_number[name] = [] unless @by_number[name]
@by_number[name] << sms
end
end
def get_number_from_address(address)
if address =~ /^(\+?\d+)$/
return address
elsif address =~ /\<(\+?\d+)\>/
return $1
else
return false
end
end
end
if $0 == __FILE__
require 'fileutils'
dir = "./messages"
my_name = "yourname"
sms = SMSConverter.new(ARGV[0])
FileUtils.mkdir_p(dir)
sms.by_name.each { |name, messages|
filename = File.join(dir, "#{name}.html")
f = File.open(filename, "w")
f << "<html><body>"
messages.each { |sms|
sent = sms[:recipient_nbr] > 0
message = sms[:subject]
f << "<b>--- #{sent ? my_name : name} (#{sms[:delivery_time].strftime("%H:%M:%S, %a %d-%b-%Y")}) ---</b><br/>"
f << "<pre>#{message.strip}</pre><br/><br/>"
}
f << "</body></html>"
f.close
}
end
I'm a little new to this, but am really interested.
I installed Ruby and then created your ruby script. I then run from command prompt:
convertsms.rb pim.vol convertedsms.htm
but I get the following error. What have I done wrong?
C:\Users\mjt\Desktop>convertsms.rb pim.vol convertedsms.htm
C:/Users/mjt/Desktop/convertsms.rb:67:in `raw2array': undefined method `each_cha
r' for #<String:0x24ee9d4> (NoMethodError)
from C:/Users/mjt/Desktop/convertsms.rb:57:in `initialize'
from C:/Users/mjt/Desktop/convertsms.rb:199:in `new'
from C:/Users/mjt/Desktop/convertsms.rb:199
I'm just supposed to run it on a copy of my pim.vol correct?
Thanks!
You have to install pimbackup on your phone, make a non-binary backup. Download the backup to your computer, unzip it, and run this script on the msgs_<date>.csm file. This script will then create a folder called messages and store all the messages per user in it.
ChaosR said:
You have to install pimbackup on your phone, make a non-binary backup. Download the backup to your computer, unzip it, and run this script on the msgs_<date>.csm file. This script will then create a folder called messages and store all the messages per user in it.
Click to expand...
Click to collapse
Ok, I installed pim backup backed up the messages, copied the file to my computer, extracted the csm file and the following happened when I tried to run it.
C:\Users\mjt\Desktop>ruby convertsms.rb msgs.csm
convertsms.rb:67:in `raw2array': undefined method `each_char' for #<String:0x33e
94c> (NoMethodError)
from convertsms.rb:57:in `initialize'
from convertsms.rb:199:in `new'
from convertsms.rb:199
Thanks!
Heh, it seems on Windows you need to include jcode for each_char to work. Put the new code in. Cheers.
how to convert the binary backup to a non binary backup? other than restoring and backing up.
Relaying SMS
Would it be possible to relay the SMS to another phone when backing up, perhaps as a transfer operation, or by sending SMS via a webservice?

[Q] [HELP] Rename a folder by current date via mortscript

How can I rename a folder or create a new one, with naming the current date via mortscript?
Try this
Code:
createDir=1 #0 = FALSE, 1 = TRUE
dirRoot="\blahblah"
unixTime=TimeStamp()
readableTime=FormatTime("Y-m-d H:i:s",unixTime)
If(createDir)
#create directory, if not still there
If(NOT DirExists(dirRoot\readableTime))
MkDir(dirRoot\readableTime)
EndIf
Else
#rename directory, if not still done, i.e. move all files to new directory
If(NOT DirExists(dirRoot\readableTime))
MkDir(dirRoot\readableTime)
EndIf
Move(dirRoot\"*.*",dirRoot\readableTime,1,1)
#delete (now emptied) old directory
DelTree(dirRoot)
EndIf

Categories

Resources