* 29/feb/2004 pdv > >* PGD_EE means Pretty Good Discriminator of Executable's Environment. > >* This routine must provide a 'pretty good discriminator' with regard to the executable's environment, that is, >* a string that identifies the environment of the executable in such a way that there's a pretty good chance >* that it will be another string if the executable is run from another environment. > >* Here's the logic: >* - If it is run from a network drive, then it will be based on the server name, e.g. '\\PC1\'. >* - If it is run from a local drive, then it will be the drive's volume name, e.g. 'HD_WinXP'. >* - If it is a local drive, but no volume name has been specified so far, then it will be the >* the local drive's serial number. >* - If no name could be determined (empty result), then it will be 'HUH'. > >* Why this logic? The idea is that a license file initially comes without this info. On the first usage >* this info is added to the license file. If a user wants to steal a copy of the (modified) license file >* for usage on another machine, then there will be a 'pretty good' chance that the result of this function >* will be different. That fact can be used to deny (full) usage. The only situation that will lead to the same >* result is where the new environment is exactly the same with regard to server name or volume name. So be it. >* The drawback is that the user will also be denied (full) usage if the application is moved to another location. >* The application should then display a messagebox asking the user to write a copy of the original license >* key to the application's folder. Big chance that the thief has no original license key! > >FUNCTION PGD_EE() > > local lnDrvType, lcResult, lnBufsize, lcBuff, lcExePath, lcDrvLetter, llUNC, llDrive > local lcRoot, lcVolName, lnVolSize, lnSerialNO, lnCompLen, lnSysFlags, lcSysName, lnNameSize > > lcResult = '' > lcExePath = addbs( justpath( fullpath( sys( 16, 0 ) ) ) ) > llUNC = .f. > llDrive = .f. > > do case > case left( lcExePath, 2 ) == '\\' > * > llUNC = .t. > > case substr( lcExePath, 2, 1 ) = ':' > * > * These defines are from F:\Microsoft Visual Studio\VC98\Include\WINBASE.H > *#define DRIVE_UNKNOWN 0 > *#define DRIVE_NO_ROOT_DIR 1 > *#define DRIVE_REMOVABLE 2 > *#define DRIVE_FIXED 3 > *#define DRIVE_REMOTE 4 > *#define DRIVE_CDROM 5 > *#define DRIVE_RAMDISK 6 > > * Based on (but not equal to!) <B>Re: How to identify the server name.</B> Thread #817893 Message #817926 > * > DECLARE INTEGER GetDriveType IN kernel32 STRING RootPath > DECLARE INTEGER WNetGetConnection IN mpr STRING lpLocalName, STRING @lpRemoteName, INTEGER @lpnLen > > lcDrvLetter = left( lcExePath, 1 ) > lnDrvType = GetDriveType( lcDrvLetter + ':\' ) > > if lnDrvType = 4 &&DRIVE_REMOTE > * > lnBufsize = 250 > lcBuff = Replicate( chr(0), lnBufsize ) > * > if WNetGetConnection( lcDrvLetter + ':', @lcBuff, @lnBufsize ) = 0 > * > lcExePath = strtran( lcBuff, chr(0), '' ) > llUNC = .t. > endif > else > llDrive = .t. > endif > > clear dlls "GetDriveType", "WNetGetConnection" > > endcase > > do case > case llUNC > * > lcResult = left( lcExePath, at( '\', lcExePath, 3 ) ) && e.g. '\\PC1\' > > case llDrive > > * http://fox.wikis.com/wc.dll?Wiki~GetVolumeInformation~WIN_COM_DNA > * > DECLARE SHORT GetVolumeInformation IN Win32API ; > STRING @lpRootPathName, ; > STRING @lpVolumeNameBuffer, ; > INTEGER nVolumeNameSize, ; > INTEGER @lpVolumeSerialNumber, ; > INTEGER @lpMaximumComponentLength, ; > INTEGER @lpFileSystemFlags, ; > STRING @lpFileSystemNameBuffer, ; > INTEGER nFileSystemNameSize > > STORE 0 TO lnSerialNO, lnCompLen, lnSysFlags > STORE SPACE(260) TO lcVolName, lcSysName > STORE LEN(lcVolName) TO lnVolSize, lnNameSize > lcRoot = lcDrvLetter + ':\' > > if GetVolumeInformation( ; > @lcRoot, @lcVolName, lnVolSize, @lnSerialNO, @lnCompLen, ; > @lnSysFlags, @lcSysName, lnNameSize) # 0 > * > lcResult = strtran( rtrim( lcVolName ), chr(0), '' ) > * > if empty( lcResult ) > lcResult = ltrim( str( lnSerialNO, 20 ) ) > endif > endif > > clear dlls "GetVolumeInformation" > > endcase > > if empty( lcResult ) > lcResult = 'huh' > endif > >RETURN upper( lcResult )Nice code, Peter.