$theTitle=wp_title(" - ", false); if($theTitle != "") { ?>
About Virtualization, VDI, SBC, Application Compatibility and anything else I feel like
14 Jan // php the_time('Y') ?>
I was writing a test program that will perform some actions when a USB Memory Stick is inserted.
When this happens Windows send a Broadcast a WM_DEVICECHANGE message.
The wParam member of this Message contains a (pointer to) a DEV_BROADCAST_HDR structure.
if the dbch_devicetype member of this structure is of type DBT_DEVTYP_VOLUME then we can cast the structure to DEV_BROADCAST_VOLUME.
And finally the dbcv_unitmask member of that structure returns a Bitmask containing the Drive Letter.
A fast and convenient method to convert this Bitmask to a Drive Letter (the first found) is the function below:
1 2 3 4 5 | function BitMaskToDriveLetter(const Bitmask: Cardinal): Char; asm bsr eax, eax; // Find first Bit Set add eax, 65; // 65 = ASCII value of A end; |
3 Jan // php the_time('Y') ?>
Have you developed an application that accesses files and may stop because a file cannot be accessed but you need to?
Since Windows Vista it is possible to find out the name of the application which holds open a file.
And we have created a solution for you that doesn’t require a driver, nor does it need Administrator rights! Just plain user source code for you to use instantly.
We have developed a solution in Delphi that can show your user which application stalls your application. Look at these screenshots:
In fact, these dialogs are only for demonstration purposes. But you can get them in addition as a Delphi project!
The code itself is fairly easy to use. We have developed an extension to the official IFileIsInUse Interface from Microsoft.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | type IFileIsInUse = interface(IUnknown) ['{64a1cbf0-3a1a-4461-9158-376969693950}'] function GetAppName(out ppszName: LPWSTR) : HRESULT; stdcall; function GetUsage(out pfut : FILE_USAGE_TYPE) : HRESULT; stdcall; function GetCapabilities(out pdwCapFlags : DWORD) : HRESULT; stdcall; function GetSwitchToHWND(out phwnd : HWND) : HRESULT; stdcall; function CloseFile() : HRESULT; stdcall; end; IFileIsInUse2 = interface(IFileIsInUse) ['{C69C0E72-DCE2-474D-AC16-E31B77B526B3}'] function GetProcessID(out pdwProcessID : DWORD) : HRESULT; stdcall; end; |
All you have to do it to call this function provides by us:
1 | function GetFileInUseInfo(const FileName : WideString) : IFileIsInUse2; |
The name of the app is returned by the method GetAppName. And if the other application supports IFileIsInUse (call method GetCapabilities) interface you even can close the file or switch to the window.
You’ll see how it works in the demonstration project (images above) accompanied by the function GetFileInUseInfo.
Currently, we only offer a Delphi solution. C++ may available in future or when there’s enough demand for it.
Please use the Contact Form to get more information about how to obtain the solution and conditions.
14 Dec // php the_time('Y') ?>
Today I needed to package an application that uses the Borland Database Engine (BDE).
The BDE is a database engine/connectivity component commonly used in Delphi and C++ Builder applications. It has been deprecated since 2000 when it was replaced by dbExpress.
But it’s still widely used so you may still find applications that require the BDE.
In my environment I already have a package for the BDE itsself. But the application I needed to package today, needs to have an Alias addded.
This is usually done manually by going into the BDEADMIN control panel applet or by copying the file where BDE saves the aliases (IDAPI32.CFG).
Here is a screenshot of the Alias my application needs (it uses an Interbase database):
I didn’t like the copy approach and didn’t even consider the manual option so I wrote 2 little tools.
12 Dec // php the_time('Y') ?>
If you read MSDN documentation for LSA_OBJECT_ATTRIBUTES you will think it’s defined in LsaLookup.h:
And that it’s supported since Windows 2000 but I couldn’t find it in this header file.
Instead I found it in NTSecAPI.h, so I decided to check the different SDK versions and starting from SDK v7 LsaLookup.h exists but in earlier SDK’s (v5.0, v6.0a and v6.1) there is no LsaLookup.h.
23 Nov // php the_time('Y') ?>
I have created a little tool for myself that I have call Altiris Job Builder, it retreives the Jobs from the Altiris database and shows them in a Treeview.
Then I can assemble a Master Build Job by dragging the needed Jobs to another Treeview on the right. Since it’s just for me it doesn’t have a fancy gui:
So why did I write it? Well I have divided my Jobs into Prerequisites and Packages, for instance IIS and Terminal Server and Java are prereqisuites for Citrix. But many prereqisuites are required for one or more other packages, eg Java is also used for certain applications. (more…)
11 Nov // php the_time('Y') ?>
Today I was tested my unattended Citrix installation (XenApp 5 on Windows 2003) and I noticed that the install was taking longer than expected.
This was because of a popup:
I am not sure if this popup is shown because I ran MsiExec with /Qb- (I usually do that when testing) but if the Popup is not shown it means that at least the installation of this driver (probably Citrix Universal Print driver) fails.
So this means I needed to script turning off Driver Signature Warnings. A quick search led me to kb article kb298503 which is titled “Driver signing registry values cannot be modified directly in Windows“. As you may guess that title drew my attention. (more…)
22 Oct // php the_time('Y') ?>
When you request Shadow (Remote Control) of a Remote Desktop (Terminal Server) or Citrix session the user gets a Dialog where he can Accept or Deny the Shadow Request.
It looks something like this:
It’s possible to change the default settings and remove the need for this permission but I think this is a bad idea since it violates the user’s privacy.
But sometimes it would be convenient to automatically accept, for instance for when a user is away or when you want to shadow a session that is “yours” but runs under another account.
I wrote a tool to do just that 😀
(more…)
20 Oct // php the_time('Y') ?>
Some time ago (2008 actually) I wrote a tool that can assign driveletters given a volumename. I use it myself after SysPrep operations to assign the desired drive letters. For instance after cloning a Virtual Machine from a template.
I noticed that I updated this tool sometime after the original post but never uploaded it here. The most important changes are:
15 Sep // php the_time('Y') ?>
Today I can proudly announce the official release of SasLibEx 2.0 which will bring support for new compilers, a native x64 version and some exciting new features!
New Compilers:
SasLibEx 2.0 introduces support for Visual Studio 2010 (C++), RAD Studio 2010 (Delphi and C++ personalities) and the new RAD Studio XE (Delphi and C++).
Native x64:
A separate native x64 version is available for Visual Studio 2005, 2008 or 2010 (C++).
New Features:
SasLibEx 2.0 introduces new unique features, the most important ones being:
Just like the old features, the new features do not require User Account Control to be enabled, nor does it require signing your executables.
If you would like to know more, upgrade or order please contact me using the Contact Form or directly by e-mail:
If you didn’t read before about SasLibEx and what it can do please read my earlier posts about it.
18 Jun // php the_time('Y') ?>
Today just some fun stuff with ASM, probably not the most recommended way to do things but for sure the most geeky way 😛
Get the Current Session Id:
1 2 3 4 5 6 | function GetCurrentSessionId: DWORD; asm mov eax,fs:[$00000018]; // Get TEB mov eax,[eax+$30]; // PPEB mov eax,[eax+$1d4]; // PEB.SessionId end; |
Get the Current Console Session Id:
1 2 3 4 | function GetConsoleSessionId: DWORD; asm mov eax, [$7ffe02d8]; end; |
And… if we can read it we can also write it?
1 2 3 4 5 6 | procedure SetCurrentSessionId(const SessionId: DWORD); asm mov edx,fs:[$00000018]; mov edx,[edx+$30]; mov [edx+$1d4], SessionId; end; |
and
1 2 3 4 5 6 7 8 9 10 | procedure SetConsoleSessionId(const SessionId: DWORD); var p: PDWORD; OldProtect: DWORD; begin p := PDWORD($7ffe02d8); Win32Check(VirtualProtect(p, SizeOf(p), PAGE_READWRITE, @OldProtect)); p^ := SessionId; Win32Check(VirtualProtect(p, SizeOf(p), OldProtect, @OldProtect)); end; |
You can safely try it since it of course affects the current process only, so don’t worry.
And perhaps more usefull
1 2 3 4 5 6 | procedure SetIsDebuggerPresent(const Value: Boolean); asm mov edx,fs:[$00000018]; // TEB mov edx, [edx+$30]; // PPEB mov byte ptr[edx+2], Value; // +0x002 BeingDebugged : UChar end; |