Category Archives: PortICA

Single User ICA Server – Citrix Product Idea 431

This idea was documented in an email on May 30, 2003. It had been an idea that I had advocated from years before but it seemed like a good time to document it with the hopes that it would get better chances. The basic idea was to sell a single user version of our main product for use on consumer computers. During the early 2000s, there was a strong push to have more products with the hopes of raising more market share and more business in general.

Here is the idea:

This idea for a single user ICA server has been around for quite some time but I wanted to formalize why it is important.

1. Gets us into the consumer market so that people can use it at home and on their workstations
2. Potentially gives us a product that is extremely popular with consumers that give us better name recognition

3. Allows for sharing applications between users using the machines they are working on
4. Avoid issues that multi-user situations brings to applications (all apps should work given enough bandwidth)
5. We can charge money for this and improve our income
6. Could be sold in retail markets
7. Would encourage people to further invest in Citrix technology in the MetaFrame suite
8. Allows for the allocation of one machine per user which would guarantee performance and usuability.
9. Lower cost entry point to using Citrix technology
10. Single user server could integrate into Citrix farms for the intent of publishing one app to one user
11. It solves the problem of getting the user to their desktop to run their desktop apps if they are remote

The first problem with getting to be a $1 billion dollar company is to get people to know who you are. The easiest way to do this is sell them products that they can use. We currently do not sell to users. We sell to companies and IT managers. Some users do not even know they are using Citrix technology. Having a consumer product is a big step forward to having people know what you do.

That is why people will pick big software companies first since those companies usually have a strong consumer presence (like Microsoft).

Technically, I do not think it is difficult to do this product. The base is already with Windows XP and a prototype has already been done with Jardine.

If we do decide to go ahead with this project, we have the potential to greatly expand our business.

This idea was not rejected but marked for revisit in 2004. As far as I know, it was not revisited.

XenDesktop with PortICA was first to address the single user solution. Jardine got bogged down with Microsoft since it used Terminal Services API.

It is unknown if this would have really made a difference to Citrix. At this point most people that use remote connections in the consumer market would use Microsoft RDP. It helps to be built in. In most cases the consumers aren’t even aware of what is going on. Microsoft has done a great job of blending it in.

Even now there is an opportunity to make PortICA a standalone solution. If it was enabled this way, it would essentially allow for this idea to exist fully. Many customers have asked for a standalone version in the last few months. There is a sense that some don’t want a full VDI implementation and just want an integrated Citrix experience.

Brian Madden Writes about PortICA (XenDesktop ICA)

Brian Madden was in Sydney recently and got the chance to gather more detail about PortICA from the actual developers.  As expected, he has taken the time to summarize his findings in a recent post about PortICA.  It is a fair and comprehensive assessment of Citrix’s new ICA technology for XP and Vista.

What is really cool is that the industry is starting to catch on to the fact this is actually new technology.  The catch phrase “same but different” rings true and I am pleased to see that Brian gets it and has captured it so well in this post.

If you are following XenDesktop, this is a perfect opportunity to understand the technology a bit more and contrast it with other vendors in the VDI space.

Besides that, I have worked on PortICA over the last two years and it feels good to get some outside feedback.  The rest of the PortICA team feels the same way.

Techniques for Generating Fake COM Ports

I wrote this last July on an internal blog.  Now it seems that it should be made available outside as well.  It is only meant for testing COM port mappings with Citrix but the ideas could be applied elsewhere with regards to building fake device names.

Original Post:

Since I am doing testing with PortICA and COM ports, I needed a way of constructing COM ports to test the full range of Client ComPort Mapping (CCM) support.  CCM can support up to 32 COM ports from the client and normally this would be difficult to create.

With some games within symbolic links, it actually is not that bad.

I only started working on this on Tuesday so please excuse the roughness of how it is laid out.

//
// FAKECOM.cpp : Incredibly simple program to generate fake COM ports for the sake of testing.
//               This program will create all the COM ports from COM1 to COM32 in the current session.
//               All of these COM ports will point to the standard serial driver with the first port (\Device\Serial0)
//
#include “stdafx.h”

#define MAX_COM_PORT_NUMBER         32
#define MAX_COM_PORT_NAME_LENGTH    10
#define MAX_DEVICE_NAME_LENGTH      500
#define SERIAL_DRIVER_PATH          L”\\Device\\Serial0″

WCHAR g_ComPortName[MAX_COM_PORT_NAME_LENGTH];
WCHAR g_DeviceName[MAX_DEVICE_NAME_LENGTH];

void RemoveDeviceDefine(LPCWSTR ComPortName);

int wmain(int argc, WCHAR * argv[])
{
int i;
BOOL bRet;
DWORD Size;

for(i=1; i <= MAX_COM_PORT_NUMBER; i++)
{
swprintf(g_ComPortName, MAX_COM_PORT_NAME_LENGTH, L”COM%u”, i);

// make sure to remove all other entries first
RemoveDeviceDefine(g_ComPortName);

bRet = DefineDosDeviceW(DDD_RAW_TARGET_PATH, g_ComPortName, SERIAL_DRIVER_PATH);

if(bRet == FALSE)
{
wprintf(L”DefineDosDeviceW failed index(%u) rc(%x)\n”, i, GetLastError());
}
else
{
wprintf(L”Device %s defined\n”, g_ComPortName);
}
}

// now go prove that it is set correctly
for(i=1; i <= MAX_COM_PORT_NUMBER; i++)
{
swprintf(g_ComPortName, MAX_COM_PORT_NAME_LENGTH, L”COM%u”, i);

Size = QueryDosDeviceW(g_ComPortName, g_DeviceName, MAX_DEVICE_NAME_LENGTH);

if(Size == 0)
{
wprintf(L”QueryDosDeviceW failed index(%u) rc(%x)\n”, i, GetLastError());
}
else
{
wprintf(L”Device %s defined as %s\n”, g_ComPortName, g_DeviceName);
}
}

return 0;
}

void RemoveDeviceDefine(LPCWSTR ComPortName)
{
DWORD Size = 0;
BOOL bRet;

do
{
bRet = DefineDosDeviceW(DDD_REMOVE_DEFINITION, ComPortName, NULL);

// check to see if there is anything left to remove
if(bRet)
{
Size = QueryDosDeviceW(ComPortName, g_DeviceName, MAX_DEVICE_NAME_LENGTH);
}

} while((bRet != FALSE) && (Size != 0));

return;
}

Enjoy!

Cursor Blinking

There is a feature in operating systems that most of us take for granted.  This is the simple text cursor.   There is a bit of confusion within Windows whether it is called a caret or a cursor (based on the API) but for most people it would just be called a cursor.  The definition of what a cursor is and does is summarized at Wikipedia(cursor).

Blinking Cursor example

Even though computer systems are very different, the cursor remains essentially the same.  Wikipedia makes a good point that there are two cursors typically involved.  One belongs to the mouse pointer and the other shows where the text input will go.  It’s a simplistic explanation but I wanted to make sure that you know I’m talking about the text cursor this time.

The mouse was invented in 1963 by Doug Englebert so it is easy to guess that the mouse cursor was invented then as well.  The text cursor was invented in 1954 as part of the IBM 610 project.  At the same time the first video console was created, so was the first text cursor.

I don’t know when the blinking cursor first came into being.  There is a chance that it existed at the beginning.  It would have been pretty obvious that a cursor isn’t much good unless you can find it.  Blinking things tend to get your attention.  It is clever that it blinks at a frequency that gets your attention but does not annoy you.  It has been known to cause problems for people who have epilepsy.  Microsoft recommends turning off the cursor blinking to avoid seizure.

Cursor Blink-Rate Options

Users who have seizures might be sensitive to the blink rate of screen images, such as the cursor. You can use the Keyboard option in Control Panel to adjust the rate at which the cursor blinks, or you can prevent it from blinking at all. On the Speed tab, move the Cursor blink rate slider all the way to the left to prevent the cursor from blinking.

However, there is another reason why cursor blinking should be off.  In a Terminal Services environment (including Citrix), the cursor blinking can actually be a drain on the system and network.  Each cursor flash (on or off) is sent as a video update to the client.  This can create a sizable amount of traffic if hundreds of users are involved.  In fact, both the network bandwidth and CPU cycles would be wasted.  This is especially true for when there is no user there.  Idle sessions with blinking cursors can create activity that is essentially wasteful.  Usually the cursor is turned off in Terminal Services environments but sometimes it can still be active.  For example, in Windows XP, the cursor flashes as if it would do on the console but going through RDP.  The easiest way to disable the flashing is to use the keyboard control panel applet and shift the blinking rate to none.

CursorBlinkRate

The cursor to the left of the slider will show you how fast the cursor will blink.  The default is to cycle the cursor every 1060ms (1.06s).  This is for both the on and off stages.  The default I quoted is from Windows 2003 and Windows XP.  Windows 2000 had it at 1000ms for some reason.  The real question is why 530ms was chosen over 500ms for each stage.  If you know the answer, I’m curious to know.

There is one downside to turning off the blinking however.  It makes the cursor blend in with the rest of the screen.  It also looks a bit strange if you are used to flashing cursors.  We had a bit of a debate about this with PortICA and the ultimate decision has yet to be reached.  The current bias is towards not adjusting what the administrator or user has chosen.  In other words, respect the settings and make it look just like how it would normally.  Microsoft and Citrix have a history of wanting to turn off the blinking.  There were lots of good arguments against it in the past.  Many of those reasons aren’t as valid as they used to be based on the exploding capacity of network bandwidth and CPU cycles.

In PortICA we want to make it as normal an experience as possible.  We also have the luxury of claiming a workstation for ourselves (unless we are being virtualized).  This means that we prefer the user experience over worrying about resource usage.  Rest assured, we do not want to waste resources but we do want to present the best face.  This means that the user should see what they normally see.  Based on my own experiences, the cursor does add a lot of value to doing text input and it feels like something is just not right when it doesn’t act like it normally does.

All of this was recently triggered by the problem that was found with HyperTerminal.  Some applications just don’t like having the cursor being non-blinking.

As this post comes to an end, I realize that what would normally be considered a boring topic is actually interesting.  Well, maybe not that interesting but at least relevant.  I could have dived into the realm of the Windows API related to the cursor (caret) blinking or even the place in the registry where the user profile stores the blink value for Windows.  Not that, for most, would truly be boring so I’ll just skip it.

If you have opinions about what PortICA should do for this, please leave a comment.  Assume for now that we will fully respect the user’s setting for blink rate.

HyperTerminal Goes Hyper

I recently had the pleasure of debugging HyperTerminal on PortICA.  It is going to take some time to put together the story of how things turned out but I wanted to start by saying something obvious.

If you are going to use HyperTerminal on Windows XP (since Vista does not have it), be sure to never turn the cursor blink off.  HyperTerminal has a built in bug where the -1 setting (which means don’t turn off the cursor ever) makes it think that it needs to constantly redraw the cursor (caret) in its message processing loop.

The cost was high to determine this.  It turns out that it was first reported in 2001 and apparently discovered in Windows 2000.  It was later reported in 2005 as well.  Not that it is a common problem since it is hard to find on the Internet.  It must be one of those kind of things that people just avoid.

I was naive enough not to know that this was the real problem and was instead focusing on the COM port angle.

The symptoms were pretty drastic.  Once started with a session, HyperTerminal would freeze.  It didn’t seem to matter how many different combinations were tried.

It is more common for the cursor blink to be turned off for remote sessions since there is a desire to reduce bandwidth for what would normally be considered pointless.  The cursor blink traffic can be chatty and turning it off makes things look better for the network.

Historically this was very important for WinFrame since having a server with lots of users and flashing cursors leads to an annoying amount of traffic that would be difficult to support over a modem.

Moving forward to today and it is much less of a concern but would still be a problem if a massive amount of users are using the same cluster of servers.  I don’t know of any recent studies on this.

The debug sessions started with using WinDbg into Windows XP with a debug PICASER.SYS . This helped to find a problem but not the problem that I cared about.  Fixing this and moving on, I needed to switch to different strategies since HyperTerminal was making no active requests to the Citrix serial driver.  All it had was an outstanding read request.  This looked like it was working fine.

At some point I decided to debug HyperTerminal directly.  This showed that it was looping in the first thread in the message loop.  Further work showed that once it received a certain message, it would get stuck.  Later on it became more obvious that callbacks were being used related to tick count differences.  At this point I asked for help internally and Michael Wookey showed me how to use IDA to look at these kind of problems.  IDA is much more talented at figuring things out than WinDbg can.  It sped up understanding much quicker.

By now, it was proven that it was stuck processing timer callbacks.  I started mapping out the data structures being referred and a pattern emerged.  I could describe each structure used and how they were connected.  The loop in question was checking values that made sure it was always looping more.

One of the key finds was that it had a relative delay of 0xffffffff (-1).  This was bad since adding -1 to the current tick count would always come up with a value one less than the current value.  This meant the loop would continue to dispatch forever since the event would never be waited for and always executed.  Zero was okay since it would purposely delay for 1 millisecond.  The core bug is that it is not doing overflow checking.  The rollover is ignored and there seems to be some confusion on the special meaning for -1.

The final step was to find where this came from.  I set debug registers on the setting of the memory location that held 0xffffffff.  I tracked this back a few times until the holy grail was found.  HyperTerminal does a call to GetCaretBlinkTime which sets this value.  GetCaretBlinkTime is fed by SetCaretBlinkTime.  SetCaretBlinkTime was being set with -1 by PortICA for the sake of turning off cursor blinking during the session.

It took roughly a week to clear this one up.

Frustration point #1: Microsoft did not provide any symbols for HyperTerminal even though other things in XP are covered.

Frustration point #2: Microsoft never fixed this obvious bug

Frustration point #3: I wish I had known the answer before I spent that week :)

Oh well.  Chalk it up to increased debugging experience.  I used to love this kind of stuff.  Now that I’m older I don’t like diving in quite as fast.  It’s draining to understand what only the coders knew for sure.  It does feel good that I can pull something like this off still.

The fix will be coming soon to PortICA.

Any opinions on cursor flashing on a remote session?  Like it?  Hate it?  Faster? Slower? Not at all?

Your opinion could actually have an influence with how this falls.

XenDesktop and PortICA

The evolution of names is always interesting to watch.  Citrix likes changing names to better suit the market it wants to address.  Based on the recent acquisition of XenSource, there has been a shift in focus to better embrace the virtualization market.  As part of this, the Citrix Desktop Server has been renamed to XenDesktop.  It isn’t just a rename since now it will be possible to actually include XenSource products as part of XenDesktop.

I am not a company spokesperson and certainly have nothing to do with product positioning or naming.  What I can tell you is that PortICA (which happens to be JUST a codename for a project) is a part of XenDesktop.  Recently XenDesktop was demonstrated at iForum in Las Vegas.  Two of the managers from Sydney were actually there.  One was lucky enough to show XenDesktop to customers for the first time.  The reaction was very positive.  As some of you probably already know there is a Beta that should be available soon.

For those of you unfamiliar with PortICA, you can read the original post here.

The only real purpose of this post is to make sure that it was understood that the PortICA project is alive and included as part of the XenDesktop product.

Another point of clarification is that it will still be possible to use XenDesktop on other VMs and actual hardware as well as XenServer.  Please excuse me if I have the terminology wrong with XenServer since this is a fairly recent change.

In general it seems the desktop virtualization market has really heated up over the last year or so and that there is a surprising amount of demand for doing these kind of things.  There are certainly some trends developing with providing these kind of services.

PortICA Time Zone Support

This post is really about trying to catch up with what has been going on with PortICA Time Zone Support. For those of you that haven’t read about Citrix Time Zone Support, please look at my previous post. The idea is to preserve the user’s local time zone while working on a potentially very distant machine. Time is very important to the user and even though a server might be in London, the user in Sydney can’t accept the time difference from their sense of time.

Personally, even though I live in Australia, I still have trouble adjusting to remembering time differences between locations especially with daylight savings in effect in opposite directions. The point is that I don’t want to see a different time zone in effect on systems I would use remotely.

With PortICA, we use the same framework as Presentation Server for changing the time. However, there is a key difference. PortICA changes the time zone for real versus Presentation Server which virtualizes it per user. This means that when a user connects, PortICA will automatically re-adjust the time zone based on the client’s time zone. When the user logs off or disconnects, PortICA will automatically restore the time zone.

This implementation is much simpler than a virtual method. It also gives you full compatibility with all applications. There is a catch however. Now that PortICA really changes the time zone, the user must have the privilege to change the time (in XP). By default, only administrators and power users have the rights to change the time. It is possible to give other users the rights to change the time, but it requires two different categories of changes.

First, you must have the privilege to change the time on that system. This can be changed with GPOs (policies) or the local policies (if not in the domain). This privilege isn’t necessarily a light weight thing to be giving out but it is necessary to allow the time zone support to work with users in PortICA.

Secondly, you must change the registry rights for the time zone information on the machine to allow the user to change the time zone. This isn’t known as well. There is a Microsoft support knowledge base article about this.

Earlier in PortICA development we had a service that would do the work of changing the time zone for the users that didn’t have the rights to do so. This avoided the need to set policies or change registry security rights but was not considered a secure enough solution. The idea is that the administrators need to be responsible for privilege allocation. It’s the classic balance between usability versus security.

In a way this post is a heads up to the potential complexity of supporting time zone support on PortICA for XP. The good news from this story is that Vista doesn’t have this problem due to users given the rights to change the time zone isolated from changing the actual time. From this move, it appears Microsoft has considered the decision to connect changing the time and changing the time zone incorrect. I would agree. Changing the time zone does not change the core time and therefore is much less sensitive to security threats.

My bit of advice for this is to setup a group that has rights to the privilege and registry areas. Then it is just a matter of adding users into that group (which might be a different group like remote users) to get them access to changing the time zone for PortICA.

Overall PortICA is progressing very well and should be talked about a fair amount at the upcoming iForum in Las Vegas. It has been great to see this project reach critical mass and reach wider audiences.

Not Cut and Dry, Cut and Paste

Assumptions are easy to make.  We do them all the time.  Usually they help to speed up understand and create a kind of common language.  Other times, they lead only to confusion.

The clipboard design is based on one primary assumption.  The core idea is that data is exchanged between programs using a common clipboard.  One program puts it on and another takes it off.  There are all kinds of cool features like being able to host multiple formats at the same time so that programs can take what they understand.  This seems very clever to me.

However, there is one major failing point when it comes to taking this data to another machine.  With Citrix, it is possible to transfer the clipboard items between client and server and back again the other way.  Citrix’s view to this problem is to transport the clipboard data “as is” to the other side.

This is an assumption as well.  The thought is that the data contains everything you need to know.

The truth is that this is not always the case.  Take the “HTML Format” which Microsoft created for its programs.  It’s clever in how encodes the data into essentially a HTML document and puts the images as references.  It’s small and efficient at its task compared to the much bigger and awkward “Rich Text Format”.  The “HTML Format” works really well for transferring data from web pages.  The problem, for Citrix, is that the “HTML Format” cannot be used 100% on the client or server machine from the other machine.  It works great for web content but fails badly on clip art or pictures from local resources.  The reason is simple enough.  The client or server is not guaranteed to get access to the resources it needs to do the whole task.  Pictures can be saved in temporary directories for Office but cannot be reached from the other machine.

From the user point of view, all they would see is little red x’s in the places where there pictures should be.  Very frustrating, to be sure.

I only learned of this aspect a couple of weeks ago and it lead to a major shift in thinking for PortICA clipboard support.  Instead of throwing open the gates to let everything through, we need to be more conservative so that only the formats that are “self-contained” are let through.  This means that the data has to provide everything on the clipboard and make no assumptions about local resources being present.

To support clipboard support with all the formats would be a formidable task.  It would assume full knowledge of the formats and the ability to translate them across.  For example, the “HTML Format” problem could be solved by re-writing the tags to point to resources that are correct and can be viewed from the remote system.  The simplest variant of this idea would be as easy as changing the drive letter (assuming that the drives have not been remapped).  Basically, there is a need to make sure that the data is managed so that the remote system will get everything it needs.

There is a very wide range of things that the clipboard supports.  Such things are OLE object embedding and file lists are used to reduce the amount of clipboard data while still providing value between applications.

If we had a decent solution for remapping file lists, we could potentially support copy and paste of files between systems in a much more fluid way.

There is an idea that using more native clipboard support for files that it would be possible to transfer files much more efficiently than the current client drive mapping model.  The reason for this is that we do not need to base the protocol on the existing CIFS style transfer model and would be able to stream the files using the best algorithms possible.

It’s very early to talk about such an idea but it is fun to see what kind of interest there would be in such a thing.

There has been some testing on the PortICA clipboard and it has created much investigation into how things work right now.  As an interesting experiment, I suggest you try this (if you have a spare minute).

  1. Open Word or similar on local machine
  2. Insert a bunch of pictures (clip art or photos) with some text.  Ten big photos will probably do.
  3. Select all and copy to clipboard
  4. Switch to your server session and start Word or similar
  5. Paste

Assuming that you have a slow enough connection (slower than LAN) and big enough pictures, the transfer will take longer than one minute.  If this true, I would bet that your copy will fail.

The reason for this will be explained in a future post :)

MAPPORT – Simple alternative to NET USE for Citrix COM and LPT Ports

I posted this internally first but have realized that it has value outside Citrix as well.

Surprise. Citrix could support more than COM9 for its COM port redirection.

Currently Citrix recommends using NET USE to map COM ports. The problem is that NET USE has a feature (bug?) that only allows up to COM9. This is because as soon as you try COM10, it mistakenly thinks that COM10 is the remote name. There must be parsing in NET USE that only allows for a one digit suffix. Besides this, NET USE is really only meant for LPT ports anyways.

So, why not build our own version of NET USE? Good question. Here’s the answer:

// MAPPORT.cpp : Simple Program to map COM and LPT ports
//

#include "stdafx.h"


int wmain(int argc, WCHAR* argv[])
{
    if(argc == 3)
    {
        DWORD rc;
        NETRESOURCE NetResource;

        memset(&NetResource, 0, sizeof(NetResource));

        NetResource.dwType          = RESOURCETYPE_PRINT;
        NetResource.lpLocalName     = argv[1];
        NetResource.lpRemoteName    = argv[2];

        wprintf(L"Mapping Local(%s) to Remote(%s)\n", argv[1], argv[2]);

        // we want a added connection with nothing special
        rc = WNetAddConnection2(&NetResource, NULL, NULL, 0);

        if(rc != NO_ERROR)
        {
            wprintf(L"Error with WNetAddConnection2 rc(0x%x, %u)\n", rc, rc);
        }
        else
        {
            wprintf(L"Mapped successfully\n");
        }

    }
    else
    {
        wprintf(L"MAPPORT local_device remote_device");
    }

	return 0;
}

This is a simple tool I wrote just for the sake of testing. It turns out to be very handy for this issue (>COM9). There is a tool that Citrix has provided internally called MAPCOMPORT (Internal Article CTX109186) but I believe you can only get it if your are a reseller. This tool was created in 2006 based on the problem with greater than 9 COM ports.
If there is interest, I am willing to look into providing this code in executable form. I realize that not everyone has Visual Studio installed. I do not think that it is common within Citrix blogs to provide executables. It will be interesting to see how this would work.

Citrix Time Zone Support

One of the most confusing things ever invented is time zones.  Well, they aren’t inherently confusing by themselves but when you start talking about different time zones and daylight savings, then things get messy.  Add in a factor of government zeal and you have daylight savings that can change dates depending on the laws and years that pass.

Microsoft has struggled with this for years with fairly regular updates based on regional changes.  As you probably already know, the US has changed the default dates this year in an attempt to save energy.

Obviously computers don’t care much about time zones themselves but obviously the applications and users do.  If the time zone is wrong then the time is wrong and all kinds of other bad things can happen from there.  Sometimes it is not obvious that it is the time zone settings that are incorrect.

Regardless of all this fanfare, time zones are usually right and do provide a useful service to the user.  When Windows correctly adjusts the time for daylight or standard times, it is actually a bit handy.

From a Citrix point of view, we had a new problem.  What if the client and server time zones do not match?  If a user logs into a Presentation Server, which time zone is he or she going to see?  In the old days, the user would get the server time zone and would just have to put up with it.  Around the year 2000, Citrix added support for using the time zone of the client on the server.  The enabled the user to see their time zone being used for all the applications on the server.  This includes applications that are time aware like Outlook to be able to display the meeting times in the correct local (user) time.

How was this accomplished?  Basically the client started to send its time zone information to the server during initialization.  Once the server starts the session, WFSHELL loads TZUSER which then starts the process of getting the client time zone and then configuring TZHOOK to actually change the time zone for that session.  TZHOOK, as it sounds, hooks the time zone API and reports the client time zone information instead of the server’s time zone.  This way, the applications things it is asking Windows for the native time zone information when really it is coming from the client.

The Presentation Server time zone support also supports clients that might not have the built in support for time zones.  It does estimation based on the client time.  It also has a policy defined that turns off time zone support if desired.

In PortICA we have a very different model.  Because we are a single user system, we can get away with changing the real time zone during the session.  This gets rid of the need to fool applications with the hook since it is already embedded with Windows with the server and client time zone matching.  We do not match the time itself.  This approach greatly simplifies the code which now really just to worry about saving and restoring the “real” time zone for the machine.

By the way, the time zone support does not use a virtual channel.  The information about the client time zone is embedded in the standard information used during the initial exchange between client and server.  Also, on PortICA, the PICASHELL component is responsible for loading TZUSER and there is no TZHOOK to process.