Showing posts with label Visual Basic 6. Show all posts
Showing posts with label Visual Basic 6. Show all posts

Thursday, September 25, 2008

Why we need different version of MSXML dlls installed?

While still supporting VB6 legacy system that reference to MSXML 4.0, user (and even layman like me) curious why some PCs have installed MSXML 6.0, yet still need to install MSXML 4.0 (or SP2). We thought this should have backward compatibility or new version should act as a superset of old version, as most of the Microsoft's products do.


From VB6 MSXML sample (you can get it here), if MSXML 4.0 is installed and "DllTest.dll" is registered and this app is ran, you will get:


if "DllTest.dll" is not registered on PC without MSXML 4.0 installed, you might get :

After "DllTest.dll" registration on PC without MSXML 4.0 installed, you will still get:

(you might get: "Object variable or With block variable not set" as well for some other cases)

Version-Dependent ProgIDs
Prior to version 4.0 of MSXML, there was a notion of version independent ProgIDs. This meant that you could write a script that instantiated an instance of MSXML, and when a new version of MSXML was installed on your machine, you automatically would get the new version. However, this sometimes created problems. Replacing one version of MSXML with another version of MSXML created situations where the user's program would stop working due to changes in the programming interface.

Since version 4.0 of MSXML, each version has a unique ProgID for each interface in MSXML. This means that when you are using a scripting language, you will not suddenly be using a much newer version than you were previously. This is a much better approach - specifying exactly which version you want to run against, then coding specifically for that version, and being certain that the version would not change when the user updates their machine means that MSXML applications are much more reliable.

There is a situation where you will automatically be using MSXML version 3.0. If the computer that is fully patched uses MSXML as part of a web application in Internet Explorer using the MIME viewer, you automatically will be using MSXML 3.0. If you are using MSXML via a scripting language, and if you specify a version independent ProgID (such as Msxml2.DOMDocument), then you will be using MSXML 3.0. However, if you are using MSXML via a scripting language, and if you specify a version dependent ProgID (such as MSXML2.DOMDocument.6.0), then you will be using the version of MSXML corresponds to the specified ProgID.

Wednesday, September 17, 2008

Codepage and Compression/DEFLATE

While data compression is great to reduce the file size/content significantly, the code-page of the PC will affect the compression/decompression or INFLATE/DEFLATE too. If you compress the data in code-page A, you might not able to get it back through de-compression in code-page B. Some of the compression algorithms involves Huffman coding(here), thus making byte-encoding significant.

Here's the sample code executed using zLib:

0) Within the same PC, INFLATE/DEFLATE is ok.

1) DEFLATE under PC with code-page 1252 (XP: Control Panel->Regional and Language Options), compare with what you get from (2) later

(From wiki: Windows-1252 is a character encoding of the Latin alphabet, used by default in the legacy components of Microsoft Windows in English and some other Western languages. It is one version within the group of Windows code pages.)

2) DEFLATE under PC with code-page 936 (XP: Control Panel->Regional and Language Options), compare with what you get from (1) previously

(From wiki: A character is encoded as 1 or 2 bytes. A byte in the range 00–7F is a single byte that means the same thing as it does in ASCII. Strictly speaking, there are 96 characters and 32 control codes in this range.
A byte with the high bit set indicates that it is the first of 2 bytes. Loosely speaking, the first byte is in the range 81–FE (that is, never 80 or FF, and the second byte is 40–FE for some areas and 80–FE for others.)


You can check your PC's code-page using Win API: GetACP.
You also can get the VC++ zLib sample here, and VB6 GetACP sample here.

Sunday, August 17, 2008

Impersonation in VB6

Since VB6 is released around 1998 or earlier, and now we are on year 2008, this topic might be obsolete for some to discuss. Since supporting legacy system is inevitable, I have something simple but might useful to share, on impersonation.

(Sample source discussed can be downloaded here.)

When an application needs to perform any operation on a network folder, using UNC path, it's not like what we can simply do anything in our own drives. Let's say we try to do file copy with vb6 app using:

FileCopy App.Path & "\HelloWorld.txt", txtCurrNetworkPath.Text & "\HelloWorld.txt"

You will get this:

Some folders in the network only permit for certain personnel to access, to deal with it you must able to prove you are authorized to access it. By using LogonUser() API function, you can achieve it.

Visual Basic 6 provides an Win32 API viewer for you to invoke (copy-and-paste in source) it, it's normally located at: "Start">"All Programs">"Microsoft Visual Studio 6.0">"Microsoft Visual Studio 6.0 Tools">"API Text Viewer".

For the first-time user, you might need to load the look-up files or database before you can see the available API.

Type the API that you are looking for and the result will be filtered in real-time. Now you can get what you want, but beware the gotcha. It mentions you need to add reference with "Kernel32.lib":

From MSDN mentioned earlier, the actual library you need is "Advapi32.lib". OK, now you refer it using the correct library in the source with:

Private Declare Function LogonUser Lib "advapi32.dll" Alias _
"LogonUserA" _
(ByVal lpszUsername As String, _
ByVal lpszDomain As String, _
ByVal lpszPassword As String, _
ByVal dwLogonType As Long, _
ByVal dwLogonProvider As Long, _
phToken As Long) As Long

And we find a remote pc with a folder shared.

Let set "everybody" can access on it.


using this account in system account database, as shown in "Computer Management":

Next if you follow this tutorial (How to impersonate a user from Active Server Pages) or another tutorial (How to start a process as another user from Visual Basic), and apply it on a simple "Standard EXE".

You might use "LOGON32_LOGON_INTERACTIVE" as parameter "dwLogonType". Now you try to run it and you will get this error message:


What the heck?

Could it be this parameter "dwLogonType" that casue the error? So we browse to Win32 header file (usually at: C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include) first and check the possible value for parameter "dwLogonType" since we know the domain/user/password are all correct. From "winbase.h", "9" represent another constant for "LOGON32_LOGON_NEW_CREDENTIALS".

Declaring it at our VB6 application:

Private Const LOGON32_LOGON_NEW_CREDENTIALS = 9

replaces "LOGON32_LOGON_INTERACTIVE" with it as parameter "dwLogonType" for LogonUser() function and eventually it works.

Note that in some pc, the impersonation might take long time.

Also, the allowed user for accessing the shared folder must be taken note as well. Previously we use PC name or IP address as our domain for a shared folder that can be accessed by "everyone"; if only a particular user in Active Directory (AD) can access a network folder, then you must provide AD account to impersonate, instead of account in system account database.

If you have logon-ed the remote shared folder from "Run" before, the previous example might be useless to prove its worth. Try reboot your pc before you try example above.