Saturday, December 30, 2006

How to create multibootable CD with ImgBurn?

ImgBurn is a great windows CD/DVD writing program. It's tiny compared to Nero (Imgburn v2.1.0.0 size is about 1Mb in install).
http://www.imgburn.com/

To create multibootable image you will need some tools from Bart Lagerweij http://www.nu2.nu/diskemu/ Namely diskem1x.zip archive. Then you need some bootable disk images - usually these are images of 1.44Mb floppy disks.

Now prepare your folder structure to be burnt on ISO and extract the following files from diskem1x.zip archive into the root of CD:

loader.bin - used to load bigger diskem1x.bin to memory
diskem1x.bin - used to execute diskemu.cmd batch file
diskemu.cmd - main configuration file with menus

Pay attention to diskemu.cmd - it is an exemplary configuration file. It will probably work for you, but will not load anything, because it is not configured for your images. This file contains description of actions that should be taken when you press keys. Actions are actually commands to run images. Just take a look at it and you'll get an idea.

Place you images in the folder structure of your ISO, so that diskem1x.bin (the loader) could find them and edit diskem1x.cmd accordingly.

Now launch ImgBurn, choose build mode, add your directory and set options as displayed on screenshots below. In particular, set options:
- Don't Add ";1" Version Number To Files
- Make Image Bootable
- Emulation Type: None (Custom)
- Boot image:
- Sectors To Load: 4

Burnnnn! =)

You will probably have to repeat this instructions several tim
es to debug your menus, but the final toast will worth it. Enjoy!

Friday, July 14, 2006

XSLT whitespaces beautifying

Sometimes it is necessary to regulate amount of whitespaces in XSLT output. Especially actual when you need to transform XML into human-readable text or to SQL dump, for example. With XSLT this often results in a compromise between ugly text and ugly templates. Most of the ugliness comes from linefeeds, which must be output at certain places, but any "beautifying" identation after such linefeed in template will also be automatically sent to output. Without the identation stylesheet becomes not that readable and to avoid this it is convenient to define an entity for a linefeed, such as:

<!ENTITY lf '<xsl:text>
</xsl:text>'>

XSLT strips whitespaces around tags (<xsl:text> tag in this case ), that's why there should not be any extra indentations in output. But this will not work, because of namespace error : Namespace prefix xsl on text is not defined. Let's define namespace:

<!ENTITY lf '<xsl:text xsl="http://www.w3.org/1999/XSL/Transform">
</xsl:text>'>

This should work as expected, but not with MSXML. We need to use xml:space="preserve" to satisfy it:

<!ENTITY lf '<xsl:text xsl="http://www.w3.org/1999/XSL/Transform" space="preserve">
</xsl:text>'>

That ok. The most important thing though is to embed this entity declaration directly into stylesheet. Like this:

<!DOCTYPE xsl:stylesheet [
<!ENTITY lf '<xsl:text xsl="http://www.w3.org/1999/XSL/Transform" space="preserve">
</xsl:text>'>
]>
<xsl:stylesheet>
...

Now you may use &lf; entity inside of stylesheet without these ugly <xsl:text>
</xsl:text> constructions.<xsl:text>

</xsl:text>Well, not really. If you use MSXML for XSLT transformation chances are that after insertion of <!DOCTYPE ...> you may encounter the error message like this one:

C:\farplugins\trunk\plugbase\mbxsl.wsf(50, 10) msxml4.dll: The stylesheet does not contain a document element. The stylesheet may be empty, or it may not be a well-formed XML document.

The magic is to turn off validation in your parser by setting validateOnParse attribute to false. In this case it was:

===================================================================
--- mbxsl.js (revision 298)
+++ mbxsl.js (working copy)
@@ -12,6 +12,7 @@
xslDoc=new ActiveXObject("MSXML2.FreeThreadedDOMDocument.4.0")
xmlDoc.async=false;
xslDoc.async=false;
+ xslDoc.validateOnParse=false;
xmlDoc.load(args("xml"));
xslDoc.load(args("xsl"));
if (xmlDoc.parseError.errorCode != 0)

Saturday, April 15, 2006

Eclipse can be a key of twilight

The Idea : http://www.eclipse.org/proposals/beacon/
The Project : http://www.eclipse.org/epf/

If Eclipse will find a way to make people not only organized, but also motivated then the art of creating value can be leveraged to make a new quality instead of new rules. It is hard to keep life out of work slavery, but it should be the aim.

Save001: Flow, Stuckness and Interruptions

Why daily programming output can be ineffective?

Article at Recycled Knowledge

Among things that break the Flow I can add room noise, talkative colleagues, daily and personal problems, ICQ links, emails, reminders. As it seems to me if you want to concentrate the best way is to delete any irrelevant applications from desktop, turn off email, ICQ, reminders and other stuff like this, then make a short schedule for a day and follow it - check email hourly - not every 15 minutes or use some AI to filter important mails that need your attention immediately.

Different interesting things can draw attention away while you're mining for information: idea for a great tool, obscure bugs in existing great tools or just this hackerish habit of making proof of concept to check if your fresh idea worths something. This draws the Flow into things far from your work and despite of positive effect of being in the Flow your main task to do is still in the same still condition. Sometimes a feeling from successfully finished proof-of-concept can keep you in the Flow for hours no matter what will you do next. A pity that in the morning after deep sleep ideas are not so bright and usually you have to find your Flow anew.

Monday, January 23, 2006

How to update old Windows 2000 from WSUS server on non-standard port?

Given: Windows 2000 machine in a local network that badly needs updates. No internet access due to high risk of attacks to the exposed system. Windows update server in the same local network.
Problem:
Windows 2000 won't update from server in local network, because service runs on non-standard port for this OS. Windows 2000 update client supplied with SP4 (aka SUS client) can only update from WSUS service on port 80.

Why the problem: Usually server machines in local networks run all kinds of services including intranet web sites and web-services among them. Needless to say that port 80 is very popular among these due to a browser preference to treat it like default. No surprise that update service is running on different port, but Windows 2000 deliberately looks for this service on port 80 (where it was in old good times) and to change this ill behavior it needs an update. A typical chicken and egg problem and here is how to resolve it.

So, what?: After update SUS client becomes WSUS client, which is able to operate with any port, but to bootstrap the process you need to make WSUS service available somewhere on port 80. If port 80 on server is busy with another service you need to use port 80 from another available machine - i.e. forward or map port. Which machine? The most simple - the same machine client is running - localhost. Just forward WSUS service port (e.g. 8530) from remote server to port 80 on local machine and tell old client to use the latter.


How: An example:
WSUS service is located at http://intranet:8530

Setup port forwarding/mapping by using trivialproxy [1] or other portmapping tool (like portmapper [2])
Local Port : 80
Remote Port : 8530 Remote Host : intranet

Launch reg file setup_windows_update_localhost.reg to tell native SUS client update itself from localhost next time.

---[setup_windows_update_localhost.reg ]
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate]
"WUServer"="http://localhost"
"WUStatusServer"="http://localhost"

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU]
"UseWUServer"=dword:00000001
"NoAutoUpdate"=dword:00000000
"AUOptions"=dword:00000003

---

Launch AUForceUpdate.cmd (slightly modified version of [3]) to force client start update ASAP.

---[AUForceUpdate.cmd]
@echo off
Echo This batch file will Force the Update Detection from the AU client by:
Echo 1. Stops the Automatic Updates Service (wuauserv)
Echo 2. Deletes the LastWaitTimeout registry key (if it exists)
Echo 3. Deletes the DetectionStartTime registry key (if it exists)
Echo 4. Deletes the NextDetectionTime registry key (if it exists)
Echo 5. Restart the Automatic Updates Service (wuauserv)

Pause
@echo on
net stop wuauserv
echo REGEDIT4 > temp.reg
echo. >> temp.reg
echo [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update] >> temp.reg
echo "LastWaitTimeout"=- >> temp.reg
echo "DetectionStartTime"=- >> temp.reg
echo "NextDetectionTime"=- >> temp.reg
regedit /s temp.reg
del temp.reg
net start wuauserv

@echo off
Echo This AU client will now check for the Updates on the Local SUS Server.
Echo After 10-20 min have a look at C:\Window\Windows update.log
Pause

---

After 10-20 minutes check if update completes successfully in C:\WINNT\WindowsUpdate.log and restart machine (there are also some registry status keys you can monitor [4]).

After restart restore port mapping to make it possible for update to finish the job and issue the following command to speed up update process:
wuauclt /detectnow

If update icon flickers in system tray and doesn't propose to install new updates - stop WU service, delete C:\WINNT\SoftwareDistribution and start update process again. In short:
net stop wuauserv
rmdir /s /q C:\WINNT\SoftwareDistribution
net start wuauserv
wuauclt /detectnow

Copy setup_windows_update_localhost.reg to setup_windows_update_intranet.reg and edit the latter to use http://intranet:8530 (example server) for subsequent updates. Port mapping is not needed from now on, so shutdown the software.

In case of one-time update you probably do not need to keep link with WSUS server on this machine. Then after repeated restarts and updates to make sure everything is installed successfully, launch setup_windows_update_default.reg file to remove WSUS server settings from the registry.

---[setup_windows_update_localhost.reg]
Windows Registry Editor Version 5.00

[-HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate]

---


References:

[1] Trivial Proxy http://www.xrayapp.com/trivialproxy/
[2] AnalogX PortMapper http://www.analogx.com/contents/download/network/pmapper.htm
[3] WSUS: Script to force update detection http://support.microsoft.com/?kbid=555453
[4] Interpreting AUState Values http://susserver.com/FAQs/FAQ-InterpretingAUStateValues.asp

Monday, January 16, 2006

MSXML XSLT processor in JScript

Here is XSLT transformation engine for Windows in just 4k of JScript code using MSXML SDK. Copy the snippet below and paste into mbxsl.wsf file then launch it to get usage help.

MSXML is probably the fastest and the worst engine at the time being. Do not ask why - it's empirical. You can try to catch that feeling by getting Windows Scripting Host 5.6 SDK, MS XML 4.0 SDK and making a simple XSLT transformation engine that should output text result in specific encoding like windows-1251. There are several ways to make the engine and only one to make it work as expected. Ok, let's finish this fast:

.transformNode() always returns UTF-16 string (no way to convert/iconv it while writing)
.transformNodeToObject() requires output to be well-formed XML if the output is DOMDocument. I didn't find anything else in these SDK's to substitute in this field, so no luck with plain text output. You can use IStream interface described below, but you will not find neither IStream interface nor it's ADODB.Stream implementation reference in these SDKs. So, I didn't know anything about ADODB.Stream and thought there must be another method described in SDKs to do the task. I've found IXSLProcessor interface, which, unfortunately, doesn't allow me to save "encoding" header in xml declaration along with (correctly, btw) encoded data via opened TextStream. Even though I didn't need that header to output plain text at the first time, later it turned into a problem. How much did you understood so far? Consider how many garbage had filtered through my head before I came up with the solution.. Ok, after some google cache data mining on IXSLProcessor+IStream I've found Rob Shields page, which fortunately contained an example of IStream implementation. I probably stop for now and post a solution "how to implement a binary XSLT transformation engine in JScript with MSXML".

If you need to make correct XSLT tranformation in MSXML with correct encoding specified in xsl:output try this:
cscript mbxsl.wsf /xml:in.xml /xsl:filter.xsl /out:result.out

---cut----[mbxsl.wsf]

<?xml version="1.0" encoding="windows-1251"?>
<package xmlns="uri:wsf">
<job id="mbxsl">
<?job error="true" debug="false"?>
<runtime>
<description>
XSLT engine implementation in MS XML using Windows Scripting Host
by Max Belugin and anatoly techtonik
http://farplugins.svn.sourceforge.net/viewvc/farplugins/trunk/plugbase/
</description>
<named
name ="xml"
helpstring ="source xml"
type ="string"
required ="true"
/>
<named
name ="xsl"
helpstring ="template xsl"
type ="string"
required ="true"
/>
<named
name ="out"
helpstring ="output file/folder"
type ="string"
required ="false"
/>

<named
name ="split"
helpstring ="if true (+) then split output to files and place in "
type ="boolean"
required ="false"
/>
<example>
cscript //nologo mbxsl.wsf /xml:navy.hrd /xsl:hrd2css.xsl
</example>
</runtime>

<script language="JScript">
<![CDATA[
var xmlDoc // as DOMDocument
var xslDoc // as FreeThreadedDOMDocument (required by XSLTemplate)
var xslObj // as XSLTemplate
var xslProc // as XSLProcessor
var targetDoc // as DOMDocument
var args // as WshNamed
=WScript.Arguments.Named;
if(args.Exists("xml")&&args.Exists("xsl")){
// WScript.Echo(args("xml"));
// WScript.Echo(args("xsl"));
xmlDoc=new ActiveXObject("MSXML2.DOMDocument.4.0")
xslDoc=new ActiveXObject("MSXML2.FreeThreadedDOMDocument.4.0")
xmlDoc.async=false;
xslDoc.async=false;
xmlDoc.validateOnParse=false;
xslDoc.validateOnParse=false;
xmlDoc.load(args("xml"));
xslDoc.load(args("xsl"));
if (xmlDoc.parseError.errorCode != 0)
WScript.echo("XML parse error: " + "line " + xmlDoc.parseError.line +
" pos " + xmlDoc.parseError.linepos + " code " +
xmlDoc.parseError.errorCode + "\n" + xmlDoc.parseError.reason);
if (xslDoc.parseError.errorCode != 0)
WScript.echo("XSL parse error: " + "line " + xmlDoc.parseError.line +
" pos " + xmlDoc.parseError.linepos + " code "+
xmlDoc.parseError.errorCode + "\n" + xmlDoc.parseError.reason);

if(args("split")){
targetDoc=new ActiveXObject("MSXML2.DOMDocument.4.0")
targetDoc.async=false;
//targetDoc.preserveWhiteSpace=true;
xmlDoc.transformNodeToObject(xslDoc, targetDoc);
if(args.Exists("out")){
var fs // as FileSystemObject
=new ActiveXObject("Scripting.FileSystemObject");
var out // as Folder
=fs.GetFolder(args("out"));
var files // as IXMLDOMNodeList
=targetDoc.selectNodes("/files/file");
var i=new Enumerator(files);
for (;!i.atEnd();i.moveNext()){
var file// as IXMLDOMNode
=i.item();
var fileName=file.getAttribute("name");
//var outPath=fs.BuildPath(out.Path, fileName);
var outFile=out.CreateTextFile(fileName);
outFile.write(file.firstChild.xml);
outFile.close();
};

}else
WScript.echo(targetDoc.xml);
}else{
xslObj=new ActiveXObject("MSXML2.XSLTemplate.4.0")
xslObj.stylesheet=xslDoc;
xslProc=xslObj.createProcessor();
xslProc.input = xmlDoc;
// IStream is necessary to avoid conversion from to UTF-16 and
// losing encoding="windows-1251" attribute from xml declaration
if(!args.Exists("out")){
if (!xslProc.transform())
WScript.echo("transformation error");
WScript.echo(xslProc.output);
}else{
var oStream = new ActiveXObject ("ADODB.Stream");
oStream.Mode = 3; // adModeReadWrite
oStream.Type = 1; // adTypebinary
oStream.Open();
xslProc.output = oStream;
if (!xslProc.transform())
WScript.echo("transformatin error");
oStream.saveToFile(args("out"), 2); // adSaveCreateOverWrite
oStream.close();
}
};
} else {
WScript.Arguments.ShowUsage();
};
]]>
</script>
</job>
</package>

---cut----[mbxsl.wsf]

Problem description.
[1] Encoding issues using the MS XSLT engine
[2] transformNodeToObject method error

Tnx Rob Shields for ADODB.Stream usage example