Samstag, 9. Oktober 2010

Uptweak Windows XP Home Edition to XP Professional

There are a lot of annoying limitations in Windows XP Home Edition, that prevents me from switching the main account to a non-administrator, just user account. However, this page shows a way how to set an internal switch so that most included, but disabled functions are available.
  1. Boot with Bart PE Windows disc or any other Windows 2000 or later OS that is not the XP Home you want to modify.
  2. Start the registry editor and load the file %windir%\System 32\Config\SYSTEM.
  3. Switch to the key HKLM\RemoteSys\ControlSet001\Control\ProductOptions and delete "Personal" from the String Product-Suite. You have to keep the empty string!
  4. Reboot to your modified Windows XP Home Edition and open regedit.
  5. Open the key HKLM\System\CurrentControlSet\Control\Lsa and set the DWORD entry forceguest to 0.
  6. Reboot your Windows.
Now, what new features does your Windows XP "Prome" reveal?
  • Explorer shows the tab "Security"
  • EFS encryption is enabled
  • runas has a working "savecred" switch
  • many more...

Sonntag, 10. August 2008

HOWTO_ O2 DSL Surf & Phone-Router mit sipgate

Der O2 DSL Surf & Phone-Router ist für die alleinige Benutzung der O2-Rufnummern vorkonfiguriert. Dabei werden die 4 zugewiesenen Rufnummern auf die SIP-Konfigurationsplätz 1 bis vier gelegt, die Verbindung zum SIPserver wird über eine zweite PPPoE-Session hergestellt. Umkonfigurieren lässt sich jedoch nichts.

Allerdings gibt es eine Möglichkeit, doch noch alternative SIP-Provider wie etwa sipgate einzurichten und auch zu verwenden.

Zunächst muss man sich dazu wie gewohnt auf dem Router einloggen, per default ist das durch Aufrufen des Links http://192.168.0.1/ im Browser und Eingabe des Passworts erledigt. Anschließend kann der VoIP-Wizard unter dem URL http://192.168.0.1/wzVoIP_2.html aufgerufen werden. Die Plätze 5 bis 10 können frei vergeben werden. Sowohl für die Rufnummer als auch für den Benutzernamen ist die sipgate-User-ID einzutragen, als Server sipgate.de und bei Passwort das entsprechende Passwort einzutragen.

Nun versucht der Router jedoch, die Verbindung zu sipgate über die zweite PPPoE-Session aufzubauen. Um das umzustellen, muss man sich per Telnet auf den Router einloggen:

telnet 192.168.1.1
Benutzername: admin
Passwort: <Router-Passwort>

ras> voice config signal index 5
ras> voice config signal setport 5 0
ras> voice config signal portselectactive 5 1
port select active on
ras> voice config signal save 5

Das war's schon.

UPDATE
Mit dem Firmwareupdate V3.40(AOF.8)D0 | 21.11.2011 wurden die Einstellungsmöglichkeiten über das Webfrontend eingeschränkt. Daher müssen nun zusätzlich diverse Serveradressen sowie Benutzername und Passwort per Telnet eingegeben werden:

ras> voice config signal index 5
ras> voice config signal serveraddress 5 sipgate.de
ras> voice config signal registeraddress 5 sipgate.de
ras> voice config signal domain 5 sipgate.de
ras> voice config signal userid 5 <sipgate User-ID>
ras> voice config signal password 5 <SIP-Passwort>
ras> voice config signal save 5

Samstag, 29. März 2008

BATCHLIB_ Batchlib package v1.0

Download
Batchlib package v1.0 (5 KB zip file)

What is it?
Inspired by my library idea, I created a package containing several libraries with subroutines that I need more or less often.

What Libraries are contained?
Currently, the following libraries are contained in the package:
How to use the libraries?
Place the libraries in a subdirectory named "lib" of your batch script(s). To call the subroutine :TRIM of the string.cmd library, use the following code:
SET MY_STRING=    A string with spaces around the text   
CALL %~dps0lib\string.cmd :TRIM "%MY_STRING%"
ECHO Trimmed string is '%RESULT%'.

License
This work is licensed under the Creative Commons Attribution-Noncommercial 2.0 Germany (Namensnennung-Keine kommerzielle Nutzung 2.0 Deutschland).

History
  • v1.0 2008-03-29 First release

BATCHLIB_ Batchlib library string.cmd

The batchlib library string.cmd is part of the batchlib package. It provides the following subroutines:

:STRLEN: Returns the string length.
:SUBSTR: Extracts a substring. Works exactly the same the string substitution function %VAR:~x,y% does.
:TRIM: Trims whitespace at beginning and end of a string.
:GET_ASCII_CHARS: Returns a string containing all ASCII characters at their given offset.
:ASC2HEX: Converts the ASCII string to a space separated list of hex numbers.
:ASC2DEC: Converts an ASCII string to a space separated list of decimal numbers.
:HEX2ASC: Converts a list of hexadecimal numbers to an ASCII string.
:DEC2ASC: Converts a list of decimal numbers to an ASCII string.
:ASCII: Returns the numeric (decimal) ASCII code of the character.
:CHAR: Returns the ASCII character denoted by the decimal number.



Integer :STRLEN String
Returns the string length.
Parameters:
  1. string
Returns:
string length
Since: 1.0



String :SUBSTR String Integer Integer?
Extracts a substring. Works exactly the same the string substitution function %VAR:~x,y% does. Provides a way for dynamically extracting substrings.
Parameters:
  1. string to extract substring of
  2. x; 0 or greater: string offset, negative number: string offset from end
  3. (default -0) y; 0 or greater: number of characters to extract, negative number: string offset from end where to stop substring extraction
Returns:
substring
Since: 1.0



String :TRIM String
Trims whitespace at beginning and end of a string.
Parameters:
  1. string to trim
Returns:
trimmed string
Since: 1.0



String :GET_ASCII_CHARS
Returns a string containing all ASCII characters at their given offset. All (in batch) non-printable characters will be replaced by a space.
Returns:
all ASCII characters
Since: 1.0



String[] :ASC2HEX String Boolean? String?
Converts the ASCII string to a space separated list of hex numbers. For example "ABC" will be converted to "41 42 43".
Parameters:
  1. ASCII string
  2. (default false) use 0x prefix
  3. (default " ") separator string
Returns:
list of hex numbers
Since: 1.0



Integer[] :ASC2DEC String String?
Converts an ASCII string to a space separated list of decimal numbers. For each character in the the string it's decimal ASCII index will be used. For example the string "ABC" will be converted to "65 66 67".
Parameters:
  1. ASCII string
  2. (default " ") list item separator string
Returns:
list of decimals
Since: 1.0



String :HEX2ASC String[] String?
Converts a list of hexadecimal numbers to an ASCII string. Automatically detects if numbers are prefixed with "0x".
Parameters:
  1. hexadecimal list
  2. (default " ") list item separator
Returns:
ASCII string
Since: 1.0



String :DEC2ASC Integer[] String?
Converts a list of decimal numbers to an ASCII string.
Parameters:
  1. decimal list
  2. (default " ") list item separator string
Returns:
ASCII string
Since: 1.0



Integer :ASCII String
Returns the numeric (decimal) ASCII code of the character.
Parameters:
  1. single character
Returns:
ASCII code
Since: 1.0



String :CHAR Integer
Returns the ASCII character denoted by the decimal number. Non-printable characters will be returned as space.
Parameters:
  1. ASCII offset number of character
Returns:
ASCII character
Since: 1.0

Freitag, 28. März 2008

BATCHLIB_ Batchlib library io.cmd

The batchlib library io.cmd is part of the batchlib package. It provides the following subroutines:

:PRINT: Prints all arguments into one line without new line.
:PRINTLN: Prints all arguments into one line with delimiting new line.
:ISDIR: Tests for exisiting directory.
:CREATE_TEMPFILE: Creates an empty temporary file within the user's temp directory.


void :PRINT varargs
Prints all arguments into one line without new line.
Parameters:
  1. variable number of arguments
Since: 1.0


void :PRINTLN varargs
Prints all arguments into one line with delimiting new line.
Parameters:
  1. variable number of arguments
Since: 1.0


Boolean :ISDIR String
Tests for exisiting directory.
Parameters:
  1. path to directory or file
Returns:
"true" if input is an existing directory, otherwise "false"
Since: 1.0


String :CREATE_TEMPFILE
Creates an empty temporary file within the user's temp directory.
Returns:
full path to temp file
Since: 1.0

BATCHLIB_ Batchlib library number.cmd

The batchlib library number.cmd is part of the batchlib package. It provides the following subroutines:

:IS_NUMBER: Checks if the first parameter is a number.
:NEAREST: Returns the nearest matching number from a sorted list of numbers.
:NEAREST_LESS: Returns the nearest matching number from a sorted list of numbers that is equal or less.
:NEAREST_GREATER: Returns the nearest matching number from a sorted list of numbers that is equal or greater.
:DEC2HEX: Converts a decimal number to hex.


Boolean :IS_NUMBER String
Checks if the first parameter is a number. That is it only contains the characters 0 to 9 and additionally the minus as the first character.
Parameters:
  1. string to test for number
Returns:
"true" if string is a valid number, "false" otherwise
Since: 1.0


Integer :NEAREST Integer[] Integer
Returns the nearest matching number from a sorted list of numbers.
Parameters:
  1. list of integers sorted ascending
  2. number to match
Returns:
nearest matching number of list
Since: 1.0


Integer :NEAREST_LESS Integer[] Integer
Returns the nearest matching number from a sorted list of numbers that is equal or less. If no such number can be found, the smallest from the list will be returned.
Parameters:
  1. list of integers sorted ascending
  2. number to match
Returns:
nearest matching number of list
Since: 1.0


Integer :NEAREST_GREATER Integer[] Integer
Returns the nearest matching number from a sorted list of numbers that is equal or greater. If no such number can be found, the greatest from the list will be returned.
Parameters:
  1. list of integers sorted ascending
  2. number to match
Returns:
nearest matching number of list
Since: 1.0


String :DEC2HEX Integer
Converts a decimal number to hex. Currently only numbers 0 <= x <= 255 are supported (0x00 <= x <= 0xFF). The result will NOT be prefixed with 0x!
Parameters:
  1. decimal number 0 <= x <= 255
Returns:
hex representation of number
Since: 1.0

BATCH_ Convert decimal number to hex string

Though hex numbers can be converted to decimals using SET /A MY_DECIMAL=0xFF, the other way around is not natively supported in Windows batch. However, the following subroutine does this job for numbers 0 <= x <= 255 (8bit).
:: Converts a decimal number to hex. Currently only numbers 0 <= x <= 255 are 
:: supported (0x00 <= x <= 0xFF). The result will NOT be prefixed with 0x!
:: 
:: @PARAM Integer decimal number 0 <= x <= 255
:: @RETURN String hex representation of number
:: @SINCE 1.0
:DEC2HEX
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET HEX=0123456789ABCDEF
SET /A T1=%1 / 16
SET /A T2=%1 %% 16
SET RESULT=!HEX:~%T1%,1!!HEX:~%T2%,1!
ENDLOCAL & SET RESULT=%RESULT%
GOTO :EOF

Note: This subroutine is part of the number.cmd library contained in the batchlib package since version 1.0.

BATCH_ Find virtual cygwin SCSI device for a CD-ROM drive

I needed a command line tool for automatic extraction (ripping) of CDDA discs (CD Digital Audio). After long hours of searching the only tool that came up was AKRip. However, AKRip is a library (DLL) and only a demo application providing a command line interface exists. As the link on the AKRip homepage is dead, I downloaded it from Sonic Spot. It's not working though, and always fails with an exception when trying to list the drives available in my system.

So I finally fell back to the ported linux application cdda2wav, running under windows using cygwin. Unfortunately cdda2wav accesses CD-ROM drives using (emulated and virtual) SCSI devices in the form of Bus,ID,Lun, e.g. 0,3,0. Here is what cdda2wav.exe -scanbus tells me what I have:
scsibus0:
        0,0,0     0) *
        0,1,0     1) *
        0,2,0     2) 'HL-DT-ST' 'CD-RW GCE-8320B ' '1.04' Removable CD-ROM
        0,3,0     3) 'LG (KOR)' 'DVD-ROM DRD8120B' '1e05' Removable CD-ROM
        0,4,0     4) *
        0,5,0     5) *
        0,6,0     6) *
        0,7,0     7) HOST ADAPTOR
scsibus1:
        1,0,0   100) 'KB9081Z ' 'YHQ276H         ' '1.0 ' Removable CD-ROM
        1,1,0   101) *
        1,2,0   102) *
        1,3,0   103) *
        1,4,0   104) *
        1,5,0   105) *
        1,6,0   106) *
        1,7,0   107) HOST ADAPTOR
Note that running cdda2wav with and without Administrator priviledges might return different results! Now I need to find a way to map these virtual SCSI devices to the drive letters Windows uses. It should look like this:
X: -> 1,0,0
Y: -> 0,3,0
Z: -> 0,2,0
I figured out a solution in three varying ways that should work on Windows 2000 systems and newer (XP, 2003). I will start to explain these with the easyest, most simple yet most specific solution, and fall back step by step to the most complicated but compatible one.


WMIC

WMIC, the Windows Management Instrumentation Console, is a native tool since Windows XP Professional and 2003 Server. Although I only need it to query information, it needs Administrator priviledges. Okay, what information does WMIC provide for my CD-ROM drives? Using the command WMIC.EXE Path Win32_CDROMDrive GET * /VALUE /format:list tells me this (output shortened to one drive only):
Availability=3
Capabilities={3,7}
CapabilityDescriptions=
Caption=HL-DT-ST CD-RW GCE-8320B
CompressionMethod=
ConfigManagerErrorCode=0
ConfigManagerUserConfig=FALSE
CreationClassName=Win32_CDROMDrive
DefaultBlockSize=
Description=CD-ROM Drive
DeviceID=IDE\CDROMHL-DT-ST_CD-RW_GCE-8320B________________1.04____\4&amp;2EA472A
E&amp;0&amp;1.0.0
Drive=Z:
DriveIntegrity=
ErrorCleared=
ErrorDescription=
ErrorMethodology=
FileSystemFlags=
FileSystemFlagsEx=
Id=Z:
InstallDate=
LastErrorCode=
Manufacturer=(Standard CD-ROM drives)
MaxBlockSize=
MaximumComponentLength=
MaxMediaSize=
MediaLoaded=FALSE
MediaType=CD-ROM
MfrAssignedRevisionLevel=
MinBlockSize=
Name=HL-DT-ST CD-RW GCE-8320B
NeedsCleaning=
NumberOfMediaSupported=
PNPDeviceID=IDE\CDROMHL-DT-ST_CD-RW_GCE-8320B________________1.04____\4&amp;2EA4
72AE&amp;0&amp;1.0.0
PowerManagementCapabilities=
PowerManagementSupported=
RevisionLevel=
SCSIBus=0
SCSILogicalUnit=0
SCSIPort=0
SCSITargetId=2
Size=
Status=OK
StatusInfo=
SystemCreationClassName=Win32_ComputerSystem
SystemName=CYPRESSOR
TransferRate=
VolumeName=
VolumeSerialNumber=
I marked the important information. There seems to be some information in SCSI writing, namely SCSIBus, SCSITargetId and SCSILogicalUnit. Using these I get 0,2,0 for drive Z: which is exactly what I wanted (see beginning). But how bad - looking at Drive X:, WMIC says 0,0,0 which is obviously wrong. AFAIK only happy guessing could lead to the correct Bus number, but I don't like guessing in automated scripts. That's why I marked the drive name, too, because it seems to be similar to the name cdda2wav told me. Let's compare drive names. First, extract the information from cdda2wav's output to return the device for a specified name:
:: Returns the cygwin SCSI CD-ROM device Bus,ID,Lun (e.g. 1,3,0) for the
:: provided drive name (e.g. "HL-DT-ST CD-RW GCE-8320B").
::
:: @PARAM String drive name
:: @RETURN String cygwin SCSI device
:: @REQUIRES tools\cdda2wav.exe
:: @REQUIRES lib\string.cmd
:GET_SCSI_CDROM_DEVICE_FOR_NAME
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR /F "usebackq tokens=1,3,5,7 delims='	" %%A IN (`^
    %~dps0tools\cdda2wav.exe -scanbus 2^>^&1 ^| FIND "Removable CD-ROM"`) DO (
  :: A=device, B=vendor, C=model, D=version
  CALL %~dps0lib\string.cmd :TRIM "%%B"
  SET VENDOR=!RESULT!
  CALL %~dps0lib\string.cmd :TRIM "%%C"
  SET MODEL=!RESULT!
  SET NAME=!VENDOR! !MODEL!
  IF "!NAME!" == "%~1" (
    ENDLOCAL & SET RESULT=%%A
    GOTO :EOF
  )
)
ECHO ERROR: No CD-ROM device by the name '%~1' could be found. >&2
ENDLOCAL & SET RESULT=
GOTO :EOF
Now, I can query the drive name for a specific drive letter using the command WMIC.EXE Path Win32_CDROMDrive WHERE Drive='X:' GET Name /format:csv >NUL. SCSI drive name's will be postfixed with "SCSI CdRom Device", so that string has to be manually removed from the name. Here is all what it takes to get the device for a specific drive letter:
:: Returns the cygwin SCSI device Bus,ID,Lun (e.g. 1,3,0) for the provided
:: Windows drive letter (e.g. D:) using WMIC.EXE.
:: NOTE: WMIC is natively available since Windows XP/2003 and requires
:: Administrator priviledges.
::
:: @INTERNAL use :GET_SCSI_CDROM_DEVICE_FOR_DRIVE instead
:: @PARAM String Windows drive letter including colon
:: @RETURN String cygwin SCSI device
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_WMIC
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR /F "usebackq skip=2 tokens=2 delims=," %%N IN (`^
    WMIC.EXE Path Win32_CDROMDrive ^
        WHERE Drive^='%~1' GET Name /format:csv 2^>NUL`) DO (
  SET DRIVENAME=%%N
  SET DRIVENAME=!DRIVENAME: SCSI CdRom Device=!
)
IF DEFINED DRIVENAME (
  CALL :GET_SCSI_CDROM_DEVICE_FOR_NAME "!DRIVENAME!"
) ELSE (
  ECHO ERROR: No CD-ROM drive could be found for drive letter '%~1'. >&2
  SET RESULT=
)
ENDLOCAL & SET RESULT=%RESULT%
GOTO :EOF




REG

Unfortunately WMIC need Administrator priviledges as stated above. So I thought about another method for retrieving data about CD-ROM drives. All the information that WMIC returns is available in the registry.
First, the used drive letters can be found in HKLM\SYSTEM\MountedDevices, named like \DosDevices\X:. The value is a 16bit little-endian hex string, storing something like \??\SCSI#CdRom&Ven_KB9081Z&Prod_YHQ276H&Rev_1.0#5&3a3a60d9&0&000#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}. Replace the # through backslashes, remove the first 4 characters and the last element \{53f5630d-b6bf-11d0-94f2-00a0c91efb8b} and you get the registry path below HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\. And here I find the FriendlyName of our drive, in that case KB9081Z YHQ276H SCSI CdRom Device. From here on it's the very same as with WMIC.

Three simple steps to be taken:
  1. Query the drive letter from registry, convert the hex value to an ASCII string, and fix the registry path.
  2. Open the registry path and check if device's Class is CDROM.
  3. Query the FriendlyName.
:: Returns the cygwin SCSI CD-ROM device Bus,ID,Lun (e.g. 1,3,0) for the 
:: provided Windows drive letter (e.g. D:) using REG.EXE.
:: NOTE: REG.EXE is natively available since Windows XP/2003.
::
:: @INTERNAL use :GET_SCSI_CDROM_DEVICE_FOR_DRIVE instead
:: @PARAM String Windows drive letter including colon
:: @RETURN String cygwin SCSI device
:: @REQUIRES lib\string.cmd
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_REG
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR /F "usebackq tokens=3 delims=	" %%B IN (`^
    REG.EXE QUERY "HKLM\SYSTEM\MountedDevices" ^| ^
    FINDSTR /R "\\DosDevices\\%~1.*REG_BINARY.*5C00"`) DO (
  SET LINE=%%B
  :: remove high bytes (reduce 16bit hex to 8bit hex numbers)
  SET LINE=!LINE:000=0,!
  SET LINE=!LINE:00=,!
  :: extract registry path
  CALL %~dps0lib\string.cmd :HEX2ASC "!LINE:~0,-1!" ","
  SET REGPATH=!RESULT:~4,-39!
  SET REGPATH=HKLM\SYSTEM\CurrentControlSet\Enum\!REGPATH:#=\!
)
SET CDROM_DEVICE=
IF DEFINED REGPATH (
  FOR /F "tokens=1,2* delims=	 " %%C IN ('^
      REG.EXE QUERY "!REGPATH!" ^| ^
      FINDSTR /R "Class[^^A-Za-z0-9_-].*REG_SZ"') DO (
    IF "%%C" == "Class" IF "%%E" == "CDROM" (
      FOR /F "tokens=2* delims=	" %%M IN ('^
          REG.EXE QUERY "!REGPATH!" ^| FINDSTR /R "FriendlyName.*REG_SZ"') DO (
        SET DRIVENAME=%%N
        CALL :GET_SCSI_CDROM_DEVICE_FOR_NAME "!DRIVENAME: SCSI CdRom Device=!"
        SET CDROM_DEVICE=!RESULT!
      )
    )
  )
)
IF NOT DEFINED CDROM_DEVICE (
  ECHO ERROR: No CD-ROM drive could be found for drive letter '%~1'. >&2
)
ENDLOCAL & SET RESULT=%CDROM_DEVICE%
GOTO :EOF
Instead of converting little endian to big endian on the hex string, I simply remove all high bytes - which are always 00. Additionally I insert a comma as a delimiter as needed by the :HEX2ASC method. At first, I walked through the string, copying every first and second character, inserting a comma and simply omitting every third and fourth character. As this method was veeeery slow, I switched to the quick and dirty solution. Nevertheless, here is the good one:
:: remove high bytes and replace by comma
SET LINE_FIXED=
CALL %~dps0lib\string.cmd :STRLEN "!LINE!"
SET /A MAX=!RESULT! - 1
FOR /L %%I IN (0,2,!MAX!) DO (
  SET /A MOD=%%I%%4
  IF !MOD! == 0 (
    CALL %~dps0lib\string.cmd :SUBSTR "!LINE!" %%I 2
    SET LINE_FIXED=!LINE_FIXED!!RESULT!,
  )
)




REGEDIT

The last solution that should also work on Windows 2000 systems is much more complex. It works basically the same way as the REG.EXE one, however I have to export the registry keys to a file and work on that one. The problem is that long keys are spanned over multiple lines, indicated by a backslash at the end of the line. So I have to scan the file until finding my drive, and then starting concatenating the string until the last backslash. However I am using a little performance tweak here: Instead of checking each read line for my drive letter, I first retrieve the line where it is using FINDSTR, then start scanning until that line and begin concatenation. Testing each line was way to slow...
:: Returns the cygwin SCSI CD-ROM device Bus,ID,Lun (e.g. 1,3,0) for the 
:: provided Windows drive letter (e.g. D:) using REGEDIT.EXE.
::
:: @INTERNAL use :GET_SCSI_CDROM_DEVICE_FOR_DRIVE instead
:: @PARAM String Windows drive letter including colon
:: @RETURN String cygwin SCSI device
:: @REQUIRES lib\io.cmd
:: @REQUIRES lib\string.cmd
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_REGEDIT
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:: export registry key HKLM\SYSTEM\MountedDevices to a file
CALL %~dps0lib\io.cmd :CREATE_TEMPFILE
SET REG_FILENAME=!RESULT!
REGEDIT.EXE /E "!REG_FILENAME!" "HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices"
:: parse registry file excluding empty lines
SET HEX=
FOR /F "usebackq tokens=1 delims=:" %%I IN (`^
    TYPE "!REG_FILENAME!" ^| FINDSTR /R /V "^^$" ^| ^
    FINDSTR /R /N "^^.\\\\DosDevices\\\\%~1.=hex:5c,00"`) DO (
  :: %%I is the line number where the searched key starts
  SET CURRENTLINE=
  SET LINESTR=
  SET LINENR=0
  :: as a key might span over multiple lines, concat these lines
  FOR /F "usebackq tokens=1,2* delims=: " %%M IN (`TYPE data.reg ^| FINDSTR /R /V "^^$"`) DO (
    SET /A LINENR=!LINENR! + 1
    :: found the key, check for spanning (line ending with backslash "\")
    IF !LINENR! == %%I (
      SET CURRENTLINE=%%O
      IF "!CURRENTLINE:~-1!" == "\" (
        SET LINESTR="!CURRENTLINE:~0,-1!"
      ) ELSE (
        SET HEX=!CURRENTLINE!
	GOTO :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_REGEDIT_GET_NAME
      )
    ) ELSE IF DEFINED LINESTR (
      SET CURRENTLINE=%%M
      IF "!CURRENTLINE:~-1!" == "\" (
        SET LINESTR="!LINESTR:~1,-1!!CURRENTLINE:~0,-1!"
      ) ELSE (
        SET HEX=!LINESTR:~1,-1!!CURRENTLINE!
	SET LINESTR=
	GOTO :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_REGEDIT_GET_NAME
      )
    )
  )
)
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_REGEDIT_GET_NAME
SET CDROM_DEVICE=
IF DEFINED HEX (
  :: quick fix: convert 16bit hex to 8bit by removing high byte
  SET HEX=!HEX:,00=!
  CALL %~dps0lib\string.cmd :HEX2ASC "!HEX!" ","
  SET REGPATH=!RESULT:~4,-39!
  SET REGPATH=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\!REGPATH:#=\!
  REGEDIT.EXE /E "!REG_FILENAME!" "!REGPATH!"
  FOR /F %%X IN ('TYPE "!REG_FILENAME!" ^| FINDSTR /R "^^.Class.=.CDROM"') DO (
    FOR /F "tokens=2 delims==" %%N IN ('TYPE "!REG_FILENAME!" ^| FINDSTR /R "^^.FriendlyName.=."') DO (
      SET DRIVENAME=%%N
      CALL :GET_SCSI_CDROM_DEVICE_FOR_NAME !DRIVENAME: SCSI CdRom Device=!
      SET CDROM_DEVICE=!RESULT!
    )
  )
)
IF NOT DEFINED CDROM_DEVICE (
  ECHO ERROR: No CD-ROM drive could be found for drive letter '%~1'. >&2
)
DEL /F "!REG_FILENAME!"
ENDLOCAL & SET RESULT=%CDROM_DEVICE%
GOTO :EOF



Finally, here is my main method that checks what solution is available and selectes that one:
:: Returns the cygwin SCSI CD-ROM device Bus,ID,Lun (e.g. 1,3,0) for the 
:: provided Windows drive letter (e.g. D:).
::
:: @PARAM String Windows drive letter including colon
:: @RETURN String cygwin SCSI device
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE
:: Provides 3 internal methods to detect the device with auto-fallback.
:: 1) WMIC.EXE (since Windows XP/2003, requires Administrator priviledges)
:: 2) Registry through REG.EXE (since Windows XP/2003)
:: 3) Registry through REGEDIT.EXE (since Windows NT)
WMIC.EXE ALIAS /? >NUL 2>&1 || GOTO :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_REG_LABEL
FOR /F "skip=2 tokens=2 delims=:" %%T IN ('WMIC.EXE ALIAS /? 2^>^&1') DO (
  IF "%%T" == "Win32 Error" GOTO :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_REG_LABEL
  GOTO :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_WMIC_LABEL
)
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE_WMIC_LABEL
CALL :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_WMIC "%~1"
GOTO :EOF
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE_REG_LABEL
REG.EXE EXPORT /? >NUL 2>&1 || GOTO :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_REGEDIT_LABEL
CALL :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_REG "%~1"
GOTO :EOF
:GET_SCSI_CDROM_DEVICE_FOR_DRIVE_REGEDIT_LABEL
CALL :GET_SCSI_CDROM_DEVICE_FOR_DRIVE_BY_REGEDIT "%~1"
GOTO :EOF

Copy that stuff into one file, copy my libraries to lib\io.cmd, lib\string.cmd and lib\number.cmd and add tools\cdda2wav.exe including the tools\cygwin1.dll. Now by typing CALL :GET_SCSI_CDROM_DEVICE_FOR_DRIVE "X:" you will receive the SCSI device in the variable %RESULT%.

Sonntag, 3. Februar 2008

VIDEO_ Demux MPEG2 recording

Demuxing MPEG2 is quite simple. You can either use Project X or PVAStrumento which I prefer.

Download PVAStrumento and install it. Start the GUI, open your recording (TS, MPG, what so ever) and click demux. Give a base filename for output, and check all three options saying something with "Cuttermaran" so you can easily cut your recording afterwards. Now click start and you're done.

VIDEO_ Cut DVB-T recordings

Cutting DVB-T recordings is simple. If the recording is a MPEG2 transport stream (file ending .ts), you have to either convert or demux it.
If your just have MPEG2 Audio and Video, you can convert the transport stream to a MPEG2 program stream (PS, file ending .mpg) as described in this article and then cut it using TerraTec Cut!. That's it, you don't have to read any further.
If your recording contains AC3 audio streams you want to keep, you have to demux it to MPEG2 Video (.m2v), MPEG2 Audio (.mp2 or .mpa) and AC3 Audio (.ac3). See this article and then continue reading.

Open your video file(s) with Cuttermaran. Perhaps you have to open additional audio files if they are not automatically recognized. To use inter-frame cutting you have to configure a MPEG2-Encoder. I am using the free QuEnc, which you have to configure under Actions > Settings... > Encoding.
Navigate to the begin of the film and use the I-, P- and B-Controls to finetune. Click cut in. Navigate to the end, finetune and click cut out and then + to add the range to the cut list.
When done, click Cut audio and video to open the output dialogue. Specify the output path and change to the Mux tab. Choose any muxer you want and select the desired format. MPG or "Generic MPEG2" creates a standard MPEG2 file to play on your computer. Or create a DVD/VOB which you can directly burn, author or shrink. Start the process with Cut & Close.

VIDEO_ Archive DVB-T recordings

Here are some choices how I do this depending on what I am trying to achieve.

1. Simple cut and storing as MPEG2 file
2. Exact cut and storing as MPEG2 file
3. Exact cut and authoring a DVD


1. Simple cut and storing as MPEG2 file

I am assuming the record is a MPEG2 program stream (PS), the file has the ending .mpg. If you have recorded a MPEG2 transport stream (TS), where the file ending is .ts, read the article how to convert it to a program stream first.
Now, open it with the freeware TerraTec Cut!, which is included in the Home Cinema installation. Let it scan the file, mark all ranges to be included in the cut file and cut it. Finished!


2. Exact cut and storing as MPEG2 file

Download and install PVAStrumento. Start it, select the recording (either .mpg or .ts) and click demux. Enable all three checkboxes for Cuttermaran and start the demux.

Download and install Cuttermaran and the free MPEG2 encoder QuEnc. Start Cuttermaran, open the settings (Actions > Settings...) and change to the Encode tab. Enable encoding, select QuEnc and configure the path to the QuEnc.exe.

Open the files (yes, there might be multiple files!) you want to cut in Cuttermaran, each in it's own Video tab. Add additional audio files if cuttermaran did not autoload them.
Select the ranges (in order!) you want to have in the result cut file using the timeline below and the I-, P-, B-Buttons at the left side. Add the ranges.
When done, select Cut audio and video, configure the output path and start the cut.

Download and install the ImagoMPEG-Muxer. Select input video and audio files, the desired output format and path and start muxing. Additionally you can configure Cuttermaran to use ImagoMPEG-Muxer to auto-mux after cutting.



3. Exact cut and authoring a DVD

First cut your record using the steps above, but do not multiplex the resulting files at the end.

Download and install GUI for dvdauthor. Start it, browse in Source to the video file and drag it onto the empty menu. Add the audio tracks and set the according language. Create chapters using the Visual Chapter Editor. Additionally, you can create chapters in Cuttermaran before cut, advise Cuttermaran to create a text file for dvdauthor in the cut dialogue and open that file here.

Right click onto the newly create text button to edit it. Doubleclick it to go into the title menu where you can set the chapters. Mark a chapter in the chapter list, and click Insert > Chapter Button and then click into the preview window. Right click to edit. If you were using the Visual Chapter Editor to create chapters, you were able to create images or short clips for each chapter. These will be automatically inserted, too.

Now configure the output. Open the Settings (no matter which) and configure output directory and check Create ISO and tick ImgBurn. Switch to the Permanent tab and enter a volume name for the DVD to be created. Close the settings.

Create your DVD image by pressing Create DVD. Now you have an ISO image that you can burn to a CD or DVD.

VIDEO_ Convert TS to MPG

I have some DVB-T recordings made as a MPEG2 transport stream (file ending .ts). Unfortunately, the latest version of TerraTec Cut! cannot handle these. It just loads them, scans until the end of the first video (in most cases there are multiple videos contained in the stream) and then won't do anything more. So I was looking for a way to convert these to the "standard" MPEG2 program stream (PS) with file ending .mpg which Cut! handles without any problem.

Download and unpack PVAStrumento. Start the GUI, open the .ts-file and click make ps. Name an output file and and press start.

Now you will have a single mpg-file for each of the videos contained. Just delete the files you do not need, e.g. adverts, previews etc and you are finished.

Freitag, 25. Januar 2008

HOWTO_ Backup your IMAP mail accounts

I just thought about what might happen if accidentally a crash or whatever will cause all my hundreds of personal E-Mail including logins, subscriptions, personal notes, etc to disappear? After years of fine service I prefer to have a backup of all this stuff. This is how I achieved it.

Backup user

First step is to create a user for the sole purpose of backing up files. You do not need it, however it is advised to use such one which has generally limited and some special permissions regarding reading passwords etc.
Go to the Control Panel, click User Accounts, and create a new account (I named it backup) with Limited permissions (that is it belongs solely to the group Users). One could add it to the group Backup Operators, however as I am not running any system backup, the limited rights of the Users group should be fine.
Remember to set a secure password of at least 10 characters, including capital and small letters, numbers and special characters (,:_+-).


Note: Perform the following steps as an Administrator unless advised otherwise!

Install IMAPSize

Using the freeware IMAPSize (version as of now is 0.3.6), your backup is just some clicks away. Download and install/unzip to a directory of your choice, presumably something like C:\Program Files\IMAPSize.
Change to that directory and create a new text file. Rename it to imapsize.log. Mark that file and the configuration imapsize.xml, right click, open Properties and change to tab Security. Now remove all users and groups from the list. Some permissions might be inherited, so you have to uncheck the Inherit option in the Advanced dialogue. Now add the backup user created in the first step, and additionally allow him to Modify and Write these two files.

Create backup directory

Now create a backup directory. It should be always accessible when performing backups (more on that later), so when using automation, only internal hard drives, internal mounted flash memory or an always-on file server comes to my mind. For security reasons the file system should allow you to set explicit permissions. I am using the local hard drive which is formatted with NTFS.
Let's say you choose D:\backup\mail. Create that directory, right click backup, open the Properties dialogue, switch to the Security tab, remove all users and groups from the list and add the backup user. Allow him Full control.

Setup IMAPSize

Start IMAPSize as the backup user. You can either login as that user or start IMAPSize in his context via StartMenu > Run.. using the following command:
runas /USER:backup "C:\Program Files\IMAPSize\imapsize.exe"
Cancel the dialogue for creating a new account. Open View > Options..., change to tab Misc and set the Root Backup Directory to the backup directory you created in the preceding step (e.g. D:\backup\mail).

Switch to tab Accounts and create one for each E-Mail account you want to backup. You can choose whatever name you want to, however using the full E-Mail address is the best choice for easy overview. Choose no spam handler and save your E-Mail password (check Save it). The passwords will be stored in plain text in the configuration file imapsize.xml, and that's why it is only accessible by the backup user!

Initial backup

To allow automatic and incremental backups, each account has to be manually backed up a first time. Perform the following steps for each account.
  1. Select the account from the drop down list in the upper left.
  2. Click Account backup (CTRL+B).
  3. Check all folders you want to back up.
  4. Press Save Folders to use that setting for future backups.
  5. Press Backup to start the process. You will be notified by a dialogue when completed.

Regular incremental backup

IMAPSize allows a simple command line usage. I wrote the following batch script for automation and placed it as autobackup.cmd in the IMAPSize program folder. Remove all permissions and add the user backup as stated above.
@ECHO OFF
:: CONFIGURATION
:: IMAPSize account names to backup
SET IMAP_ACCOUNT_NAME_1=mail@domain.com
SET IMAP_ACCOUNT_NAME_2=user@gmx.net
SET IMAP_ACCOUNT_NAME_3=...
...

ECHO Starting IMAP account backup...
FOR /F "usebackq delims== tokens=2" %%A IN (`SET IMAP_ACCOUNT_NAME_`) DO (
ECHO * Backing up account %%A...
"%~dp0imapsize.exe" -backup -account=%%A
)
ECHO Backup finished.
ECHO Full backup log available in file %~dp0imapsize.log.
Open the task scheduler to setup a regular backup. Open it via Start > Programs > Accessories > System Tools > Scheduled Tasks. Double click Add Scheduled Task, click Next, Browse to the script file autobackup.cmd and select it. Now you can select a name like "Daily IMAP backup" and check Daily. Click Next and choose a time (should be a time when you your PC is online nearly every day). Click Next and set backup as the user. Type in twice the according password. Click Next and then Finish.

Increase security

To increase security, you also have to change to owner of the files you changed the permissions of. First, you have to add the backup user to the Administrators group. Open User Accounts in the Control Panel, click Change an account, select the user backup, click change the account type, and switch it to Computer Administrator.
Now log in with backup, browse to the program directory of IMAPSize, select the files imapsize.xml, imapsize.log and autobackup.cmd, right click and open Properties, change to Security tab, click the Advanced button, change to the Owner tab, select the backup user and apply changes.
Do the same with the backup folder, but additionally check Replace owner on subcontainers and objects.

Logout and login with administrator, and switch the backup user back to the Limited account. Now you're done!

Sonntag, 6. Januar 2008

HOWTO_ Ringtones for Grandstream BT-101

Grandstream's VoIP-Phone BT-101 allows up to 192 kBytes of custom ringtones, divided into a maximum of three 64 kByte blocks. As it is using the ULAW compression, one block can be up to 8 seconds long, which allows the following ringtone combination:
  • 3 ringtones, each up 8 seconds long
  • 1 ringtone with up to 8 sec, 1 ringtone with up to 16 sec
  • 1 ringtone with up to 24 seconds
Generation
Grandstream supports two ringtone generation tools, one sox based for Linux and Solaris, and another one for Windows. I first tried the Windows tool, but you have to provide 16 bit, 8kHz mono WAV files, otherwise it fails with error. Additionally, sound quality was more than poor.
So I fell back to the Linux tool, for which I first had to install the distribution specific sox (apt-get install sox under Debian). Then I created a 16-bit, 44kHz stereo ringtone with 3,5 seconds, copied the file to the tool directory and typed the following command:
./sox.linux ring.wav ring.ring


Upload to phone
At boottime the phone connects to the configured TFTP update server and looks for updates - including ringtones. The custom ringtones have to be named ring1.bin, ring2.bin and ring3.bin. It first tries to download ring1.bin and installs it if found. Depending on that ringtone's length, it will continue looking for tone 2 and 3.
I renamed ring.ring to ring1.bin and copied it into an empty directory (I could also use ring3.bin, but I wanted to overwrite the first ringtone, the other one's were alright). I configured my TFTP-Server Pumpkin to use that directory, started it, reconfigured the BT-101 to use my local PC as TFTP-Server and rebooted the phone. The ringtone was immediately installed and I could selected it using the phone's menu.

TECH_ Sambashares with UTF-8

Debian running with Samba 3 and Windows XP client.

Configure Debian to use UTF-8 locale by typing dpkg-reconfigure locale and select de_DE.UTF-8 and enable it as default. Set LC_CTYPE in the file /etc/environment to de_DE.UTF-8. Relogin to enable the new settings.

Configure Samba by setting unix encoding to UTF-8 in the file /etc/samba/smb.conf and restart the daemon by typing /etc/init.d/samba restart.

If puTTy won't display umlauts or other non-ASCII characters, enable UTF-8 in Window -> Translation.

You still have files named in another encoding? Use the tool convmv to convert for example ISO-8859-15:
convmv -f ISO-8859-15 -t UTF-8 -r --notest /dir/to/convert/recursively > renamed_files.txt

Freitag, 30. November 2007

BATCH_ Trim String

My first solution I came up with involved substring replacement including a helper string added before and after the real string. This works as long as that helper string does not appear anywhere in the original string.
:: Trims whitespace at beginning and end of a string.
:: PARAM
:: 1 string to trim
:: RETURN String trimmed string
:TRIM
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET HLPSTR=#####%RANDOM%#####
SET STR="!HLPSTR!%~1!HLPSTR!"& SET STR=!STR:~1,-1!
:TRIM_INNER_LOOP
IF "!STR:%HLPSTR% =%HLPSTR%!" NEQ "!STR!" (
    SET STR="!STR:%HLPSTR% =%HLPSTR%!"& SET STR=!STR:~1,-1!
    GOTO :TRIM_INNER_LOOP
) ELSE IF "!STR: %HLPSTR%=%HLPSTR%!" NEQ "!STR!" (
    SET STR="!STR: %HLPSTR%=%HLPSTR%!"& SET STR=!STR:~1,-1!
    GOTO :TRIM_INNER_LOOP
)
SET STR="!STR:%HLPSTR%=!"& SET STR=!STR:~1,-1!
ENDLOCAL & SET RESULT="%STR%"& SET RESULT=!RESULT:~1,-1!
GOTO :EOF
So after thinking about that for a while (~10 seconds), it came to my mind that I do have a way to retrieve the first or the last character of a string. So this solution followed:
:: Trims whitespace at beginning and end of a string.
:: PARAM
:: 1 string to trim
:: RETURN String trimmed string
:TRIM
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET STR="%~1"& SET STR=!STR:~1,-1!
:TRIM_INNER_LOOP
IF "!STR!" NEQ "" (
    IF "!STR:~0,1!" == " " (
        SET STR=!STR:~1!
    ) ELSE IF "!STR:0,1!" == "	" (
        SET STR=!STR:~1!
    ) ELSE IF "!STR:~-1!" == " " (
        SET STR=!STR:~0,-1!
    ) ELSE IF "!STR:~-1!" == "	" (
        SET STR=!STR:~0,-1!
    ) ELSE (
        GOTO :TRIM_INNER_LOOP_END
    )
    GOTO :TRIM_INNER_LOOP
)
:TRIM_INNER_LOOP_END
ENDLOCAL & SET RESULT="%STR%"& SET RESULT=!RESULT:~1,-1!
GOTO :EOF
What you cannot see: I compare against space and then against tab. But I disliked the horrible IF-ELSE comparison stuff and ended with replacement check against a whitespace-string:
:: Trims whitespace at beginning and end of a string.
:: PARAM
:: 1 string to trim
:: RETURN String trimmed string
:TRIM
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET STR="%~1"& SET STR=!STR:~1,-1!
:: whitespace is space and tab
SET WHITESPACE= 	
:TRIM_INNER_LOOP
IF "!STR!" NEQ "" (
    IF "!WHITESPACE:%STR:~0,1%=!" NEQ "!WHITESPACE!" (
        SET STR=!STR:~1!
        GOTO :TRIM_INNER_LOOP
    ) ELSE IF "!WHITESPACE:%STR:~-1%=!" NEQ "!WHITESPACE!" (
        SET STR=!STR:~0,-1!
        GOTO :TRIM_INNER_LOOP
    )
)
ENDLOCAL & SET RESULT="%STR%"& SET RESULT=!RESULT:~1,-1!
GOTO :EOF

Reflog

Informationstechnische Howtos, Hinweise und Merkwürdiges

Batchlib v1.0 2008-03-29

Aktuelle Beiträge

HOWTO_ O2 DSL Surf &...
Der O2 DSL Surf & Phone-Router ist für die alleinige...
cypressor - 12. Feb, 19:57
Uptweak Windows XP Home...
There are a lot of annoying limitations in Windows...
cypressor - 9. Okt, 19:30
BATCHLIB_ Batchlib package...
Download Batchlib package v1.0 (5 KB zip file) What...
cypressor - 29. Mär, 19:10
BATCHLIB_ Batchlib library...
The batchlib library string.cmd is part of the batchlib...
cypressor - 29. Mär, 18:10

Homepage Ticker

Links

Status

Online seit 6571 Tagen
Zuletzt aktualisiert: 28. Jun, 11:32
RSS XML 1.0 Button-Get-Firefox

batch
batchlib
howto
tech
video
Profil
Abmelden
Weblog abonnieren