dFPUG.fll Version 3 – Zip, Scan, and more - dFPUG-Portal
dFPUG.fll Version 3 – Zip, Scan, and more - dFPUG-Portal
dFPUG.fll Version 3 – Zip, Scan, and more - dFPUG-Portal
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>dFPUG</strong>.<strong>fll</strong> <strong>Version</strong> 3 <strong>–</strong> <strong>Zip</strong>,<br />
<strong>Scan</strong>, <strong>and</strong> <strong>more</strong><br />
Venelina Jordanova, Uwe Habermann, Erich Todt<br />
The <strong>dFPUG</strong>.<strong>fll</strong> has grown up. The little FLL with<br />
functions for compressing <strong>and</strong> decompressing files<br />
has become an ample collection of functions indispensable<br />
for many purposes. FoxPro developers<br />
are offered capabilites hitherto unknown.<br />
The History<br />
The first version of the <strong>dFPUG</strong>.<strong>fll</strong> was published<br />
in January 2004. It provided a simple ZIP functionality.<br />
Owing to the huge feedback from developers,<br />
the second version was released in March 2005.<br />
That one made many further features of the ZIP<br />
algorithm available.<br />
Now the third version of the <strong>dFPUG</strong>.<strong>fll</strong> provides<br />
substantially <strong>more</strong> functions from various<br />
functional areas.<br />
In its first two versions, the <strong>dFPUG</strong>.<strong>fll</strong> contained<br />
merely functions for creating <strong>and</strong> extracting ZIP<br />
archives. Of course those functions stay available.<br />
The ZIP functions have been described extensively<br />
in the two previous articles. Therefore they won’t<br />
be treated here in depth.<br />
New Functions<br />
The new functions may be divided into four functional<br />
areas.<br />
At first, there are scanning functions. They<br />
permit to control TWAIN scanners from VFP<br />
applications <strong>and</strong> to scan images.<br />
The second functional area comprises Internet<br />
<strong>and</strong> Windows API programming. Sometimes you<br />
need functions which convert a string in such a<br />
manner that it can be used as a parameter in a URL.<br />
Now there is a function for that purpose, <strong>and</strong> of<br />
course another one to execute the conversion the<br />
other way round.<br />
In a further area, entries can be added to the<br />
Windows Event Viewer. A real alternative to own<br />
log files. These functions become particularly<br />
interesting if you develop COM servers or Windows<br />
services which shall log information about their<br />
current state or errors.<br />
And finally we have a set of functions that<br />
provide Windows system information.<br />
Dependencies<br />
The new <strong>dFPUG</strong>.<strong>fll</strong> has been written in C like its<br />
previous versions.<br />
MSVC71.dll can be registered at the target<br />
machine; if it is not registered, it must reside in<br />
the same folder as the <strong>dFPUG</strong>.<strong>fll</strong>. In both cases the<br />
<strong>dFPUG</strong>.<strong>fll</strong> can be used from any VFP 9 application<br />
from any folder on the target machine.<br />
If a MSVC71.dll is stored in a different folder<br />
<strong>and</strong> is registered there, it will be recognized by the<br />
<strong>dFPUG</strong>.<strong>fll</strong>, <strong>and</strong> it can be used from that folder.<br />
In case you want to use the <strong>dFPUG</strong>.<strong>fll</strong> together<br />
with older versions of VFP, you’ll normally have to<br />
copy the file MSVC71.dll to the target PC.<br />
For the scanning functions the file GDIPLUS.<br />
DLL is needed. Since Windows 98, that file has<br />
been present in every Windows installation, so we<br />
need not worry about it.<br />
For the individual functions, further DLLs or<br />
other files of Windows are required if need be.<br />
Those files are being loaded dynamically during<br />
runtime. Thus, to our advantage, the <strong>dFPUG</strong>.<strong>fll</strong><br />
may in any case be loaded without problems via<br />
the comm<strong>and</strong><br />
SET LIBRARY TO <strong>dFPUG</strong>.<strong>fll</strong><br />
If in using a function a dependent DLL cannot<br />
be loaded, a corresponding return value is yielded.<br />
So the developer need not worry about error<br />
messages due to missing dependencies.<br />
The ZIP functions continue to be contained<br />
unchanged in the FLL, making the new version 3<br />
fully upward compatible to the previous one.<br />
A sample application<br />
Naturally we have a sample application for this<br />
version of the <strong>dFPUG</strong>.<strong>fll</strong>, too. It demonstrates how<br />
to use the functions. Screenshots of the sample app<br />
are shown in the course of this article.<br />
And there are further examples about some of<br />
the functions.<br />
May 2011 FoxRockX Page 1
Figure 1. <strong>–</strong> determining the version number<br />
Functions by categories<br />
The <strong>dFPUG</strong>.FLL provides the following functions.<br />
General<br />
<strong>dFPUG</strong>Initialize<br />
Call at initializing.<br />
<strong>dFPUG</strong>UnInitialize<br />
Call at release.<br />
<strong>dFPUG</strong>Fll<strong>Version</strong><br />
Returns the version number of the <strong>dFPUG</strong>.FLL or<br />
of some dynamically loaded system files.<br />
Compressing or extracting files<br />
Create<strong>Zip</strong>Archive<br />
Serves to create ZIP archive files.<br />
Extract<strong>Zip</strong>Archive<br />
Serves to extract ZIP archive files.<br />
<strong>Scan</strong>ner Support<br />
GetTWAINSources<br />
Display the available scanners.<br />
GetTWAINImage<br />
Trigger the scanning.<br />
Internet<br />
UrlEscape<br />
Converts characters which are not allowed in URLs<br />
into the respective escape sequences (“%xy”).<br />
UrlUnescape<br />
Converts Escape sequences (“%xy”) in a URL into<br />
readable text.<br />
Windows API Programming<br />
GetNullSA<br />
This function returns a pointer to a SECURITY_<br />
ATTRIBUTES structure with a nullsecurity descriptor.<br />
With this function you can, by means of Windows API<br />
functions, create files, create folders, or create kernel<br />
objects etc. with the permission All <strong>–</strong> Full access.<br />
GetWinErrorString<br />
Converts a Win32 oder COM/<br />
OLE error number into the<br />
equivalent error message of<br />
the operating system.<br />
Windows Event Viewer<br />
RegisterEventSource<br />
Adds the necessary entries to<br />
the Windows registry so that<br />
event numbers can be converted<br />
into a message text by the<br />
Event Viewer.<br />
UnregisterEventSource<br />
Deletes entries from the Windows<br />
registry which enter<br />
event numbers into the Event<br />
Viewer.<br />
ReportEvent<br />
Adds an entry to the Windows event list.<br />
Windows System Information<br />
CheckAdminRights<br />
Tells whether the user running the current thread<br />
has adminstrator rights.<br />
ComputerName<br />
Returns the NetBIOS or DNS name of the local<br />
computer.<br />
GetShortPath<br />
Converts a long path name or file name into its<br />
short equivalent (MS DOS 8.3 convention).<br />
IsWinNT<br />
Tells whether the operating system is based on<br />
Windows NT (WinNT, 2000, XP, 2003, Vista).<br />
ShellFolder<br />
This function yields the paths to various Windows<br />
system folders.<br />
UserName<br />
Returns the name of the user or of the security policy<br />
under which the current thread is being executed.<br />
Reference<br />
This chapter introduces all functions in detail with<br />
their parameters <strong>and</strong> return values.<br />
<strong>dFPUG</strong>Fll<strong>Version</strong><br />
Returns the version number of the <strong>dFPUG</strong>.FLL or<br />
of some dynamically loaded system files.<br />
<strong>dFPUG</strong>Fll<strong>Version</strong>([nFormat])<br />
Return value<br />
See table 1.<br />
Parameter<br />
If you don’t provide the optional parameter nFormat,<br />
the return value is identical to the value given in<br />
table 1 under nFormat = 0.<br />
Page 2 FoxRockX May 2011
Table 1. <strong>–</strong> Parameters <strong>and</strong> return values of <strong>dFPUG</strong>Fll<strong>Version</strong><br />
Parameter<br />
nFormat<br />
Data type Return Value Description<br />
0 Character <strong>dFPUG</strong> Funktions- Description <strong>and</strong> complete version number. The output<br />
Bibliothek<br />
does not have a st<strong>and</strong>ardized format. If you want be able<br />
03.00.7071.0 to evaluate a query about the version in a programme,<br />
better call the function with the parameter 4 or 5.<br />
4 Character 03.03.6029.0002 <strong>Version</strong> number in a st<strong>and</strong>ardized format:<br />
MM.mm.YDDD.nnnn<br />
MM<br />
Main version<br />
mm<br />
Minor version<br />
YDDD<br />
Build number<br />
NNNN<br />
Serial number<br />
5 Numeric 300 Numerical version number, calculated by the formula<br />
(100* Main version) + Minor version.<br />
105 Numeric 600 Numerical version number of shlwapi.dll, calculated by<br />
the formula (100* Main version) + Minor version.<br />
The functions UrlEscape() <strong>and</strong> UrlUnescape() require<br />
the file shlwapi.dll version 5.0 or higher. This file is part<br />
of the operating system or is installed with the Internet<br />
Explorer respectively.<br />
205 Numeric 700 Numerical version number of wininet.dll, calculated by<br />
the formula (100* Main version) + Minor version.<br />
The function CrackUrl() requires the file wininet.dll<br />
version 3.0 or higher. This file is part of the operating<br />
system or is installed with the Internet Explorer<br />
respectively.<br />
CheckAdminRights<br />
Tells whether the user excecuting the current thread<br />
has administrator rights.<br />
CheckAdminRights()<br />
Return value<br />
Logical.<br />
Comments<br />
This function only makes sense<br />
with Windows NTbased operating<br />
systems (WinNT, 2000,<br />
XP, 2003, Vista).<br />
In Windows 9x systems<br />
(Win95, 98, ME) the function<br />
always returns .T. because<br />
the operating system does not<br />
support anything we may call<br />
a real administration of user<br />
rights.<br />
To ask for the OS platform,<br />
you can use either IsWinNT()<br />
or the FoxPro function OS(6).<br />
A return value of “2” (Look<br />
out: string!) indicates that it is<br />
a Windows NTbased operating<br />
system.<br />
ComputerName<br />
Returns the NetBIOS name or DNS name of the<br />
local computer.<br />
ComputerName([nFormat])<br />
Return value<br />
Character.<br />
Figure 2. <strong>–</strong> display of the computer name<br />
May 2011 FoxRockX Page 3
Parameter<br />
Return value<br />
nFormat<br />
node<br />
N/A NetBIOS name of the local computer. NetBIOS name of the virtual cluster server.<br />
0 NetBIOS name of the local computer. NetBIOS name of the virtual cluster server.<br />
1 DNS host name of the local computer. DNS host name of the virtual cluster server.<br />
2 DNS domain name of the local computer. DNS domain name of the virtual cluster server.<br />
3 Fully qualified DNS name which uniquely Fully qualified DNS name of the virtual cluster<br />
identifies the local computer.<br />
server.<br />
4 NetBIOS name of the local computer. NetBIOS name of the local computer.<br />
5 DNS host name of the local computer. DNS host name of the local computer.<br />
6 DNS domain name of the local computer. DNS domain name of the local computer.<br />
7 Fully qualified DNS name which uniquely<br />
identifies the local computer.<br />
Fully qualified DNS name of the local computer.<br />
Table 2. - Parameters <strong>and</strong> return values of ComputerName<br />
Parameter<br />
When you call the function without parameters,<br />
it yields the NetBIOS name of the local computer.<br />
If the local Computer is a node in a cluster, the<br />
function will return the NetBIOS name of the virtual<br />
cluster server.<br />
By providing the optional parameter nFormat<br />
you can determine not only the NetBIOS name, but<br />
also the DNS name of the computer, of the host or<br />
of the domain. This applies to Windows 2000 or<br />
higher versions. In the table below you find the<br />
valid values for nFormat <strong>and</strong> the respective return<br />
values. If the local computer is a node in a cluster,<br />
the function yields the value shown in the column<br />
“node”.<br />
In case the name of the computer cannot be<br />
determined in the given format, or if the value for<br />
nFormat is not valid, the function will return an<br />
empty string.<br />
Comments<br />
System requirements: The optional parameter<br />
nFormat is only supported on Windows NTbased<br />
operating systems from Windows 2000 upwards.<br />
With all other operating sysystems (Win95, 98,<br />
ME, NT4) the function produces the FoxPro error<br />
1098 with a matching error message text, e.g.<br />
”This function is not supported by the operating<br />
system”.<br />
Calling this function without the optional<br />
parameter nFormat is supported in all Windows<br />
operating systems on which Visual FoxPro can<br />
run.<br />
You may either use IsWinNT() or the FoxPro<br />
function OS(6) to inquire about the OS platform. A<br />
return value of “2” (Attention: string!) means that it<br />
is a Windows NTbased opearting system.<br />
You can employ the FoxPro function OS(3) to<br />
determine the main version number of the operating<br />
system. E.g. in Windows 2000, OS(3) returns the<br />
string “5”.<br />
DNS names constist of one or several<br />
components, each one up to 63 characters long <strong>and</strong><br />
delimited from each other by periods, for example<br />
“www.dfpug.de”.<br />
A cluster is a group of two or <strong>more</strong> servers (aka<br />
nodes) which cooperate <strong>and</strong> appear in the network<br />
as one single virtual server.<br />
With DNS names, uppercase <strong>and</strong> lowercase<br />
spelling are not discerned.<br />
The fully qualified DNS name is a combination<br />
of the DNS host name <strong>and</strong> the DNS domain name,<br />
written in the form HostName.DomainName. For<br />
instance, if the DNS host name is “corporatemailserver”<br />
<strong>and</strong> the DNS domain name is “dfpug.<br />
de”, then the fully qualified DNS name will be<br />
“corporatemailserver.dfpug.de”.<br />
NetBIOS names consist of up to 15 bytes of<br />
OEM characters, <strong>and</strong> as a rule one character equals<br />
one byte. However, some countryspecific OEM<br />
characters can be two bytes long.<br />
With NetBIOS names, uppercase <strong>and</strong> lowercase<br />
spelling are in principle not discerned, but<br />
uppercase spelling is preferred, especially so if the<br />
conversion from lowercase to uppercase letters is<br />
dependent on the OEM character set.<br />
The NetBIOS name <strong>and</strong> the DNS host name<br />
depend on each other. Whenever you change the<br />
DNS host name, the NetBIOSname is changed as<br />
well <strong>and</strong> truncated to 15 bytes. E.g. if the DNS name<br />
is “corporatemailserver”, the NetBIOS name<br />
“corporatemail” will result from this.<br />
If you change the name of a computer, you will<br />
have to restart it to let the changes take effect. The<br />
NetBIOS name is read from the Windows Registry<br />
during startup.<br />
Create<strong>Zip</strong>Archive<br />
Serves to create ZIP archives.<br />
Create<strong>Zip</strong>Archive( cPath, cFileSkeleton,<br />
cArchiveFullPathName, cFeedbackFunction,<br />
nCompressionLevel, lResurseSubfolders,<br />
cPassword )<br />
Page 4 FoxRockX May 2011
Figure 3 .<strong>–</strong> Example of creating ZIP archives<br />
Return value<br />
Not defined. Status messages are given via the<br />
FeedBack function.<br />
Parameters<br />
cPath<br />
Character. Path of the folder which is to be archived.<br />
cFileSkeleton<br />
Character. Names of the files to be archived. The<br />
wildcards “?” <strong>and</strong> “*” can be used. Several file<br />
names may be given, separated by semicolon.<br />
Example: “*.dbf;*.fpt;*.cdx”<br />
cArchiveFullPathName<br />
Character. Complete path name <strong>and</strong> file name of<br />
the ZIP archive to be created.<br />
cFeedBackFunction<br />
Character. Name of a function or method which is<br />
called by Create<strong>Zip</strong>Archive() to reveal information<br />
about the progress. This function or method must<br />
be declared thus:<br />
[Object.](<br />
tcCurrentOperatedFile, tnState,<br />
tnAllFilesSize, tnZIPedFilesSize,<br />
tnArchiveCurrentSize ): nResult<br />
tcCurrentOperatedFile<br />
name of the file which is currently being processed.<br />
tnState<br />
Current state:<br />
1. The archive file cArchiveFullPath-<br />
Name already exists.<br />
2. Beginning to add the file tcCurrent-<br />
OperatedFile to the archive.<br />
3. Finish of adding the file tcCurrent-<br />
OperatedFile to the archive.<br />
4. The file tcCurrentOperatedFile could<br />
not be added to the archive.<br />
5. The creation of the archive was complete<br />
<strong>and</strong> has been concluded.<br />
6. The creation of the archive could not<br />
be concluded.<br />
7. No valid path name or file name was<br />
given, or there are no files to be put<br />
into the archive.<br />
tnAllFilesSize<br />
Total size of all files which shall be added to<br />
the archive.<br />
tnZIPedFilesSize<br />
Size of the files that have already been added<br />
to the archive.<br />
tnArchiveCurrentSize<br />
Current size of the created archive file.<br />
nResult<br />
The return value controls the further behaviour of<br />
the function Create<strong>Zip</strong>Archive():<br />
0 The process shall be aborted.<br />
1 The files have been added to the archive.<br />
2 The process is being continued.<br />
nCompressionLevel<br />
The ZIP algorithm permits different levels of compression.<br />
The values 1 to 9 are allowed. The values<br />
mean:<br />
-1 St<strong>and</strong>ard compression<br />
(identical to the value 6)<br />
0 No compression<br />
1 Maximum speed<br />
6 St<strong>and</strong>ard compression<br />
9 Best compression<br />
lResurseSubfolders<br />
If the value of this parameter is .T., subfolders<br />
are recursively included. The files selected as<br />
cFileSkeleton are being taken care of in the subfolders,<br />
too.<br />
If the value of this parameter is .F., subfolders are<br />
not included.<br />
cPassword<br />
Here a password must be put in if the archive shall<br />
be protected. In case you do not need a password<br />
protection, an empty string must be put in here. For<br />
the password, all characters except for CHR(0) are<br />
permissible.<br />
May 2011 FoxRockX Page 5
Comments<br />
As the return value is not defined, you should never<br />
try to evaluate or save the result of this function.<br />
Extract<strong>Zip</strong>Archive<br />
Service to unpack ZIP archive files.<br />
Extract<strong>Zip</strong>Archive( cExtractFilesFolder,<br />
cFileSkeleton, cArchiveFullPathName,<br />
cFeedBackFunction, cPassword )<br />
Return value<br />
Not defined. Status messages happen via the FeedBack<br />
function.<br />
The process could not be finished.<br />
Page 6 FoxRockX May 2011<br />
6.<br />
7.<br />
8.<br />
Reserved.<br />
Invalid password.<br />
tnArchiveFilesSize<br />
Size of the archived files.<br />
tnUnZIPedFilesSize<br />
Size of the files already unpacked.<br />
nResult<br />
The return value controls the further behaviour of<br />
the function Extract<strong>Zip</strong>Archive():<br />
Parameters<br />
0 The unpacking shall be aborted.<br />
cExtractFilesFolder<br />
1 The process shall be continued.<br />
Character. Folder where the unpacked files are<br />
being stored.<br />
2<br />
Overwriting the existing file with the archived<br />
file.<br />
cFileSkeleton<br />
cPassword<br />
Character. Names of the files to unpack. The wildcards Here a password must be put in if the archive is<br />
“?” <strong>and</strong> “*” may be used. Several file names can be protected by a password. In case you do not need<br />
given, separated from each other by semicolons.<br />
a password protection, an empty string must be<br />
Example: “*.dbf;*.fpt;*.cdx”<br />
passed here. For the password, all characters except<br />
for CHR(0) are permissible.<br />
cArchiveFullPathName<br />
Character. Complete path <strong>and</strong> file name of the<br />
archive file to be unpacked.<br />
cFeedBackFunction<br />
Character. Name of a function<br />
or method which is called<br />
by Extract<strong>Zip</strong>Archive() to<br />
yield information about the<br />
progress. This function or<br />
method must be declared as<br />
follows:<br />
[Object.]<br />
(<br />
tcCurrentOperatedFiles,<br />
tnState, tnArchiveFiles-<br />
Size, tnUnZIPed-FilesSize<br />
): nResult<br />
tcCurrentOperatedFiles<br />
Name of the file which is currently<br />
being unpacked.<br />
tnState<br />
Current state:<br />
Comments<br />
As the return value is not defined, you should never<br />
try to evaluate or save the result of this function.<br />
1. The file to be<br />
unpacked does<br />
alerady exist.<br />
2. Begin of the<br />
unpacking of the file<br />
Figure 4. <strong>–</strong> The <strong>Scan</strong> dialogue of the sample application<br />
3.<br />
4.<br />
5.<br />
tcCurrentOperatedFile.<br />
End of the unpacking of the file<br />
tcCurrentOperatedFile.<br />
The file tcCurrentOperatedFile could not be<br />
unpacked.<br />
The process has been finished<br />
successfully<br />
GetTWAINSources<br />
GetTWAINSources(@tcTwainSources) <strong>–</strong> Returns a list<br />
of the available TWAIN devices connected to the<br />
computer.<br />
Return value<br />
0 <strong>–</strong> If the operation has been completed successfully.
nErrorNumber <strong>–</strong> If an error has occurred. Cf the<br />
TWAIN error messages.<br />
Parameter<br />
tcTwainSources <strong>–</strong> A string, passed via a reference. In<br />
this string, a semicolondelimited list of available<br />
TWAIN devices is returned.<br />
GetTWAINImage<br />
GetTWAINImage(tcFileName, tcFileFormat,<br />
tlUseDefaultTWAINSource, tcTWAINSource,<br />
tlDisplayAdvancedSettingsDialog,<br />
tlDisplayprogressDialog) <strong>–</strong> <strong>Scan</strong>s an image <strong>and</strong><br />
stores it in the file tcFileName.<br />
Return value<br />
0 <strong>–</strong> If the process has been executed successfully.<br />
nErrorNumber <strong>–</strong> if an error has occurred, TWAIN<br />
error message.<br />
Parameters<br />
tcFileName <strong>–</strong> Complete path <strong>and</strong> file name of the file<br />
in which the scanned image shall be stored.<br />
tcFileFormat <strong>–</strong> Name extension of the file format.<br />
The value can be BMP, JPG, GIF, PNG, or TIFF.<br />
When this parameter is empty, the st<strong>and</strong>ard value<br />
is TIFF.<br />
tlUseDefaultTWAINSource <strong>–</strong> If the value is .T., the<br />
default TWAIN device will be used. When this<br />
parameter is empty, the default value .T. is applied.<br />
tcTWAINSource <strong>–</strong> string with the TWAIN source to<br />
be used. If the value of tlUseDefaultTWAINSource is<br />
.F. <strong>and</strong> if the value of the property tcTWAINSource<br />
is empty <strong>and</strong> <strong>more</strong> than one TWAIN device is<br />
connected, a dialogue to choose the TWAIN device<br />
is shown.<br />
tlDisplayAdvancedSettingsDialog <strong>–</strong> When this value<br />
is .T., a dialogue with advanced settings shows. Depending<br />
on the TWAIN source used, this dialogue<br />
may possibly not be available. If this parameter is<br />
empty, the default value .F. is used.<br />
tlDisplayprogressDialog <strong>–</strong> When this value is .T., a<br />
progress bar is displayed. If this parameter is empty,<br />
the default value .T. is used.<br />
GetNullSA<br />
Returns a pointer to a SECURITY_ATTRIBUTES<br />
structure with a nullsecurity descriptor.<br />
You can pass this pointer as a LPSECTURITY_<br />
ATTRIBUTES parameter to Windows API functions<br />
in order to create files, folders, or kernel objects etc.<br />
to which all users have access without limitation<br />
(Permissions: Everyone <strong>–</strong> Full Control).<br />
GetNullSA([lInheritH<strong>and</strong>le])<br />
Return value<br />
Numeric.<br />
Parameter<br />
In case you call the function without a parameter,<br />
the element bInheritH<strong>and</strong>le of the SECURITY_<br />
ATTRIBUTES structure created is initialized as<br />
FALSE.<br />
lInheritH<strong>and</strong>le<br />
lInheritH<strong>and</strong>le Description<br />
.F. The element bInheritH<strong>and</strong>le of<br />
the SECURITY_ATTRIBUTES<br />
structure created is initialized as<br />
FALSE.<br />
.T. The element bInheritH<strong>and</strong>le of<br />
the SECURITY_ATTRIBUTES<br />
structure created is initialized as<br />
TRUE.<br />
The exact meaning of the element bInheritH<strong>and</strong>le<br />
is mostly different among the individual Windows<br />
API functions. You will find further information in<br />
the documentation of the respective Windows API<br />
functions.<br />
Example of usage<br />
A typical example would consist in using FoxPro as<br />
a debugger to which other applications are sending<br />
information. As a communication interface you<br />
could use e.g. a Named Pipe or a FileMapping<br />
object. The latter is being created by the debugger<br />
with a nullsecurity descriptor; thus it can be opened<br />
to write by the single applications, independent of<br />
their user context.<br />
Comments<br />
The memory reserved by this function is released<br />
automatically upon the release of the <strong>dFPUG</strong>.FLL.<br />
It can constitute a considerable security risk to<br />
permit every user full control of a file, a folder, or<br />
a kernel object. Therefore you should only consider<br />
doing this in particular cases <strong>and</strong> deliberate it<br />
thoroughly.<br />
You should never store the return value of this<br />
function in a variable, but always call this function<br />
<strong>and</strong> pass the result directly to your Windows API<br />
function.<br />
If you declare a Windows API function in<br />
FoxPro with DECLAREDLL, you have to declare<br />
the data type Integer for lpSecurityAttributes.<br />
If you pass 0 (zero) for lpSecurityAttributes to a<br />
Windows API function, this usually means that the<br />
file to be created (or the folder or the kernel object)<br />
takes the security attributes of the current thread or<br />
the superior object. But in any case it does not mean<br />
that the permissions are set to Everyone. Further<br />
information you will find in the documentation for<br />
the respective Windows API functions.<br />
In practice you can mostly leave out lInheritH<strong>and</strong>le<br />
<strong>and</strong> thus initialize the element bInheritH<strong>and</strong>le of the<br />
SECURITY_ATTRIBUTES structure with FALSE.<br />
May 2011 FoxRockX Page 7
Example<br />
In the following example we create two new folders,<br />
one of them with the st<strong>and</strong>ard permissions <strong>and</strong> the<br />
other with Everyone <strong>–</strong> Full Control.<br />
SET LIBRARY TO dfpug.<strong>fll</strong><br />
DECLARE Integer CreateDirectory ;<br />
IN WIN32API ;<br />
String lpPathName, ;<br />
Integer lpSecurityAttributes<br />
*-- Create a folder with st<strong>and</strong>ard access<br />
*-- rights:<br />
CreateDirectory(SYS(2015)+”_St<strong>and</strong>ard”,0)<br />
*-- And now a folder with full access for all<br />
*-- users:<br />
CreateDirectory(SYS(2015)+”_<br />
Everyone”,GetNullSA())<br />
You can check the difference between the two<br />
folders by marking one in the Windows Explorer<br />
<strong>and</strong> a right mouse click to open the Properties in the<br />
context menu.<br />
Note<br />
In some newer operating systems (like Windows<br />
XP Professional without domain membership), in<br />
order to see the above mentioned tabs Sharing <strong>and</strong><br />
Security in the Properties window, you will have<br />
to deactivate “use simple file sharing” in the folder<br />
options in the Windows Explorer.<br />
GetWinErrorString<br />
When an error occurs, many Windows API functions<br />
<strong>and</strong> COM/OLE objects return a numerical value<br />
which represents an error code or a status code,<br />
though in some cases it can mean a warning or<br />
a message about a successful operation (e.g. 0 =<br />
ERROR_SUCCESS).<br />
This function converts such a Win32 or COM/<br />
OLE error number to the corresponding error<br />
message of the operating system. Apart from this,<br />
up to three parameters can be passed which are<br />
inserted in place of the wildcard characters [1], [2],<br />
<strong>and</strong> [3], provided that the message text contains<br />
these wildcards.<br />
Note: The Win32 error numbers are completely<br />
different from FoxPro or TWAIN error numbers as<br />
regards their scope <strong>and</strong> their meaning. They must<br />
not be mixed up.<br />
GetWinErrorString( nErrorCode [ , [ cParam1]<br />
[, [cParam2] [, cParam3 ]]] )<br />
Return value<br />
Character.<br />
If the operating system provides no error message<br />
for nErrorCode , the function returns the empty<br />
string.<br />
Some Win32 error messages contain wildcards<br />
to be replaced by applicationspecific strings, e.g.<br />
nErrorCode = 34 (ERROR_WRONG_DISK). If the<br />
optional parameters cParam1 to cParam3 are not<br />
given, the returned message text contains the<br />
wildcards, e.g. [1], [2] or [3].<br />
Parameters<br />
nErrorCode<br />
Numeric Win32 error number between 2147483648<br />
<strong>and</strong> 2147483647 (0x000000000xFFFFFFFF). COM/<br />
OLE error numbers are by definition negative<br />
number values which can also be stated as<br />
hexadecimal. For example, E_OUTOFMEMORY<br />
is defined as 0x80000002, <strong>and</strong> it can be passed to<br />
the function either as 0x80000002 or as 2147483646.<br />
Values between 2147483648 (0x80000000) <strong>and</strong><br />
4294967295 (0xFFFFFFFF) automatically get<br />
converted into negative number values.<br />
cParam1<br />
Optional. When the message text contains a<br />
wildcard “[1]” <strong>and</strong> a string is given for cParam1, the<br />
function replaces the wildcard with the string.<br />
cParam2<br />
Optional. When the message text contains a<br />
wildcard “[2]” <strong>and</strong> a string is given for cParam2, the<br />
function replaces the wildcard with the string.<br />
cParam3<br />
Optional. When the message text contains a<br />
wildcard “[3]” <strong>and</strong> a string is given for cParam3, the<br />
function replaces the wildcard with the string.<br />
Comments<br />
In case the operating system supports several<br />
language versions, the function will search for the<br />
message text in the following sequence:<br />
1. Current Visual FoxPro localization<br />
2. Languageneutral<br />
3. Language setting of the threads<br />
4. Default language setting of the user<br />
5. Default language setting of the system<br />
6. English (USA)<br />
In addition to this, if the system itself supplies<br />
no message text, the function tries to load the<br />
following file <strong>and</strong> to retrieve the message text in it:<br />
Module<br />
Error<br />
numbers<br />
Declaration Comments<br />
wininet.dll From 12000 wininet.h Microsoft<br />
to 12999<br />
Win32<br />
Internet API<br />
If the message text concludes with one or<br />
several of the characters CR, LF, TAB, or SPACE,<br />
the function automatically chops them off.<br />
With an OLE error you can determine the<br />
COM/OLE error number via AERROR() <strong>and</strong> pass<br />
it to this function as nErrorCode, e.g. 0x080020005<br />
for a type conflict.<br />
Page 8 FoxRockX May 2011
Most Windows API<br />
functions do not return error<br />
numbers directly. Instead they<br />
retrun a value defined as invalid,<br />
like NULL, FALSE, or 1. Only<br />
calling the Windows API<br />
function GetLastError() yields<br />
the actual error number. You<br />
will find further information<br />
in the documentation of the<br />
respective Windows API<br />
functions.<br />
The FoxPro comm<strong>and</strong><br />
ERROR as a clause does not<br />
only permit numerical FoxPro<br />
error numbers, but also<br />
strings. Here you can directly<br />
use the return value from<br />
GetWinErrorString(). For instance, the comm<strong>and</strong><br />
ERROR GetWinErrorString(1223)<br />
will raise the FoxPro error 1098 with the<br />
message text (that is localized according to the<br />
operating system) “Process aborted by the user“.<br />
Examples<br />
Here we attempt to create a folder with an invalid<br />
path name. When an error occurs, CreateDirectory()<br />
returns 0, <strong>and</strong> the subsequent call of GetLastError()<br />
yields the Win32 error number. By means of<br />
GetWinErrorString() we convert that error number<br />
into a string which we then report to FoxPro via<br />
ERROR:<br />
SET LIBRARY TO dfpug.<strong>fll</strong><br />
DECLARE Integer CreateDirectory ;<br />
IN WIN32API ;<br />
String lpPathName, ;<br />
Integer lpSecurityAttributes<br />
DECLARE Integer GetLastError ;<br />
IN WIN32API<br />
IF 0 = CreateDirectory(“Test:\/”,0)<br />
ERROR GetWinErrorString(GetLastError())<br />
ENDIF<br />
The following example demonstrates<br />
the behaviour of the<br />
function when the message text<br />
contains wildcards:<br />
SET LIBRARY TO dfpug.<strong>fll</strong><br />
#define ERROR_WRONG_DISK 34<br />
? GetWinErrorString(;<br />
ERROR_WRONG_DISK)<br />
? GetWinErrorString(;<br />
ERROR_WRONG_DISK,”A:”,,;<br />
”0000-0000”)<br />
? GetWinErrorString(;<br />
ERROR_WRONG_DISK,”A:”,;<br />
Disk 1”,”0000-0000”)<br />
Figure 5. <strong>–</strong> Example about the Windows System Info<br />
GetShortPath<br />
Converts a long path name or file name into its<br />
short equivalent (MSDOS 8.3 convention).<br />
GetShortPath( cFileName | cPath )<br />
Return value<br />
Character.<br />
Parameter<br />
cFileName, cPath<br />
Character. Absolute oder relative path name or file<br />
name. The folder or file must exist.<br />
Comments<br />
If the given path name or file name already fulfills<br />
the MSDOS 8.3 convention, the function returns<br />
the path name or file name unchanged.<br />
In case the drive supports no 8.3 file names <strong>and</strong><br />
the path length exceeds 67 characters, the function<br />
will produce the FoxPro error 1098 with an appropriate<br />
message text such as “Wrong Parameter.”<br />
Example<br />
SET LIBRARY TO dfpug.<strong>fll</strong><br />
?getshortpath(“C:\Programme”) && C:\PROGRA~1<br />
Figure 6. <strong>–</strong> Example of an entry in the Windows Event Log<br />
May 2011 FoxRockX Page 9
RegisterEventSource<br />
Adds those items to the Windows Registry which<br />
are necessary so that the Event Viewer can convert<br />
event numbers into a suitable message text.<br />
Note: Generally you need administrator rights to<br />
be able to execute the function successfully.<br />
RegisterEventSource( [ cSourceName ] [,nTypes-<br />
Supported] )<br />
Return value<br />
Numeric.<br />
If it has been executed successfully, the function<br />
returns 0 (ERROR_SUCCESS).<br />
If an error has occurred, the function returns a<br />
Win32 error code which you can convert into a<br />
message text through GetWinErrorString().<br />
ReportEvent<br />
Adds an entry to the Windows application log.<br />
Note: The concept “ReportEvent” means “report<br />
an event” <strong>and</strong> has nothing to do with the concepts<br />
“Report” or “Event” as they are used in FoxPro!<br />
The name of this function was deliberately chosen<br />
because (a) the underlying Windows API function<br />
also bears the name ReportEvent(), <strong>and</strong> (b) because<br />
presumably in many projects there are already<br />
functions or methods with the name “Log”, <strong>and</strong><br />
therefore conflicts or mixups would be quite likely<br />
if similar names were used.<br />
ReportEvent( [cUNCServerName] , [cSourceName]<br />
, [nType] , nErrorCode [ , [cParamCode] [<br />
,cRawData]] )<br />
Return value<br />
Numeric.<br />
If it has been executed successfully, the function returns<br />
0 (ERROR_SUCCESS).<br />
If an error has occurred, the function returns a<br />
Win32 error code which you can convert into a<br />
message text through GetWinErrorString().<br />
Figure 7. <strong>–</strong> Converting URLs into Escape sequences<br />
UrlEscape<br />
Converts characters which are not allowed in URLs<br />
into the respective Escape sequences (“%xy”).<br />
UrlEscape( cURL [,nFlags] )<br />
UrlUnescape<br />
UrlUnescape<br />
Converts Escape sequences (“%xy”) in a URL into<br />
readable text.<br />
UrlUnescape( cURL [,nFlags] )<br />
IsWinNT<br />
Tells whether the operating system is based on<br />
Windows NT (WinNT, 2000, XP, 2003, Vista).<br />
IsWinNT()<br />
Return value<br />
Logical.<br />
Comments<br />
On Windows 9x systems (Win95, 98, ME) , the function<br />
always returns .F.<br />
Alternatively to this function you may also use<br />
the FoxPro function OS(6) to query the OS platform.<br />
The return value “2” (Caution: String!) indicates<br />
that it is a Windows NTbased operating system.<br />
UserName<br />
Returns the name of the user or of the security policy<br />
by which the current thread is being executed.<br />
This need not necessarily be the name of<br />
the currently loggedin user. On Windows NTbased<br />
operating systems (WinNT, 2000, XP, 2003,<br />
Vista) you can run programs under different login<br />
credentials (“Execute as...”).<br />
UserName( [nFormat] )<br />
Return value<br />
Character.<br />
Parameters<br />
When you call the function<br />
without any parameter, it<br />
returns the user name under<br />
which the current thread is<br />
being executed.<br />
nFormat<br />
In Windows 2000, by providing<br />
the optional parameter<br />
nFormat you can determine the<br />
user name of the name or the<br />
security principal in various<br />
formats.<br />
The function returns an<br />
empty string if the user name<br />
cannot be determined in the<br />
given format, or if the domain controller is not<br />
available for a request, or the value for nFormat is<br />
invalid.<br />
Page 10 FoxRockX May 2011
Figure 8. <strong>–</strong> display of the user name<br />
Comments<br />
System requirements: The optional parameter<br />
nFormat is only supported on Windows NTbased<br />
operating systems from Windows 2000 onwards.<br />
On all other operating systems (Win95, 98, ME,<br />
NT4) the function triggers the FoxPro error 1098<br />
with a matching message text, e.g. “This function is<br />
not supported by the system.”<br />
The calling of this function without the optional<br />
parameter nFormat is supported by all operating<br />
systems Visual FoxPro can run on.<br />
You can apply either IsWinNT() or the FoxPro<br />
function OS(6) to query the OS platform. A return<br />
value of “2” (Caution: String!) means that it is a<br />
Windows NTbased operating system.<br />
You may use the FoxPro function OS(3) to retrieve<br />
the main version number of the operating<br />
system. E.g. in Windows 2000, OS(3) yields the<br />
String “5”.<br />
At a single workplace PC<br />
without a domain membership<br />
<strong>and</strong> without an Active<br />
Directory, generally only<br />
function calls with nFormat = 2<br />
or without nFormat will return<br />
a sensible value.<br />
A security principal is an<br />
account owner to whom a security<br />
ID for the access to resources is<br />
being assigned automatically. A<br />
security principal can be a user, a<br />
group, a service or a computer.<br />
Defined names are strings<br />
according to the RFC 1779.<br />
nFormat Description Example<br />
N/A User name. JohnDoe<br />
1 Fully qualified defined name.<br />
CN=John Doe, OU=Software,<br />
OU=Engineering, O=Widget, C=US<br />
2 Windows NT 4.0 compatible SAM account<br />
name.<br />
Engineering\JohnDoe<br />
3 Complete name. As a rule, this name consists<br />
of the first name <strong>and</strong> the surname. It does not<br />
necessarily have to match the value CN of the<br />
fully qualified defined name.<br />
JohnDoe<br />
6 GUID {4fa050f0-f561-11cf-bdd9-00aa003a77b6}<br />
7 Canonical name engineering.widget.com/software/John Doe<br />
8 User Principal Name (aka UPN). johndoe@engineering.com<br />
9 Same as canoni-cal name (nFor-mat=7) except<br />
that the first slash from the right is replaced by<br />
a line feed character.<br />
engineering.widget.com/software<br />
John Doe<br />
10 Generalized ser-vice principal name. www/srv.engineering.com/engineering.com<br />
12 DNS domain name followed by a backslash ("\") engineering.widget.com\JohnDoe<br />
<strong>and</strong> the SAM user name.<br />
Memberware<br />
FoxRockX subscribers can download the <strong>dFPUG</strong>.<strong>fll</strong><br />
<strong>and</strong> the sample application described from http://<br />
portaladmin.dfpug.de/ dokumente/foxtalk/memberware/.<br />
FoxRockX subscribers may use the <strong>dFPUG</strong>.<br />
<strong>fll</strong> in their own applications <strong>and</strong> also h<strong>and</strong> it over<br />
to their customers. The code from the samples, <strong>and</strong><br />
the wrapper class for the encapsulation of the ZIP<br />
functionality <strong>and</strong> provision of the progress bar may<br />
also be integrated into own applications <strong>and</strong> may<br />
thus be h<strong>and</strong>ed over to customers.<br />
The license of the memberware is valid as long<br />
as the FoxRockX subscription exists. The license expires<br />
at the end of the subscription.<br />
Have fun using the <strong>dFPUG</strong>.<strong>fll</strong>!<br />
May 2011 FoxRockX Page 11