Unicode bug (exe/module name and paths)

Just starting out? Need help? Post your questions and find answers here.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Unicode bug (exe/module name and paths)

Post by Rescator »

Compile this as a unicode option on, and as a console app:

And execute it from DOS as: program.exe >result.txt

Code: Select all

Procedure printError(msg.s)
Protected eNum.l,sysMsg.s{256},p.s

 eNum=GetLastError_()
 FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM|#FORMAT_MESSAGE_IGNORE_INSERTS,#Null,eNum,0,@sysMsg,256,#Null)
 Print(#CRLF$+"  WARNING: "+msg+" failed with error "+StrU(eNum,#Long)+" ("+sysMsg+")")
EndProcedure

Procedure.l ListProcessModules(dwPID.l)
 Protected hModuleSnap.l,me32.MODULEENTRY32

  hModuleSnap=#INVALID_HANDLE_VALUE;

  ;Take a snapshot of all modules in the specified process.
  hModuleSnap=CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE,dwPID)

  If hModuleSnap=#INVALID_HANDLE_VALUE
   printError("CreateToolhelp32Snapshot (of modules)")
   ProcedureReturn #False
  EndIf

  ;Set the size of the structure before using it.
  me32\dwSize=SizeOf(MODULEENTRY32)

  ;Retrieve information about the first module,
  ;and exit if unsuccessful
  If Module32First_(hModuleSnap,me32)=#False
   printError("Module32First") ;Show cause of failure
   CloseHandle_(hModuleSnap)   ;Must clean up the snapshot object!
   ProcedureReturn #False
  EndIf

  ;Now walk the module list of the process,
  ;and display information about each module
  Repeat
    Print(#CRLF$+#CRLF$+"     MODULE NAME:     "+PeekS(@me32\szModule,#MAX_MODULE_NAME32))
    Print(#CRLF$+"     executable     = "+PeekS(@me32\szExePath,#MAX_PATH))
    Print(#CRLF$+"     process ID     = $"+LSet(Hex(me32\th32ProcessID),8,"0"))
    Print(#CRLF$+"     ref count (g)  = $"+LSet(Hex(me32\GlblcntUsage),4,"0"))
    Print(#CRLF$+"     ref count (p)  = $"+LSet(Hex(me32\ProccntUsage),4,"0"))
    Print(#CRLF$+"     base address   = $"+LSet(Hex(me32\modBaseAddr),8,"0"))
    Print(#CRLF$+"     base size      = "+StrU(me32\modBaseSize,#Long))
  Until Module32Next_(hModuleSnap,me32)=#False

  CloseHandle_(hModuleSnap)
   ProcedureReturn #True
EndProcedure

Procedure.l ListProcessThreads(dwOwnerPID.l) 
Protected hThreadSnap.l,te32.THREADENTRY32
 hThreadSnap=#INVALID_HANDLE_VALUE

 ;Take a snapshot of all running threads  
 hThreadSnap=CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD,0)
 If hThreadSnap=#INVALID_HANDLE_VALUE
  ProcedureReturn #False
 EndIf

 ;Fill in the size of the structure before using it. 
 te32\dwSize=SizeOf(THREADENTRY32)

 ;Retrieve information about the first thread,
 ;and exit if unsuccessful
 If Thread32First_(hThreadSnap,te32)=#False 
  printError("Thread32First" ) ;Show cause of failure
  CloseHandle_(hThreadSnap)     ;Must clean up the snapshot object!
  ProcedureReturn #False
 EndIf

 ;Now walk the thread list of the system,
 ;and display information about each thread
 ;associated with the specified process

 Repeat
  If te32\th32OwnerProcessID=dwOwnerPID
   Print(#CRLF$+#CRLF$+"     THREAD ID      = $"+LSet(Hex(te32\th32ThreadID),8,"0"))
   Print(#CRLF$+"     base priority  = "+StrU(te32\tpBasePri,#Long))
   Print(#CRLF$+"     delta priority = "+StrU(te32\tpDeltaPri,#Long))
  EndIf
 Until Thread32Next_(hThreadSnap,te32)=#False

 CloseHandle_(hThreadSnap)
 ProcedureReturn #True
EndProcedure

Procedure.l GetProcessList()
Protected hProcessSnap.l,hProcess.l,wPriorityClass.l,pe32.PROCESSENTRY32

 ;Take a snapshot of all processes in the system.
 hProcessSnap=CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS,0)
 If(hProcessSnap=#INVALID_HANDLE_VALUE)
  printError("CreateToolhelp32Snapshot (of processes)")
  ProcedureReturn #False
 EndIf

 ;Set the size of the Structure before using it.
 pe32\dwSize=SizeOf(PROCESSENTRY32)

 ;Retrieve information about the first process,
 ;And exit if unsuccessful
 If Process32First_(hProcessSnap,pe32)=#False
  printError("Process32First") ;Show cause of failure
  CloseHandle_(hProcessSnap)    ;Must clean up the snapshot object!
  ProcedureReturn #False
 EndIf

 ;Now walk the snapshot of processes, and
 ;display information about each process in turn

 Repeat
  Print(#CRLF$+#CRLF$+"=====================================================")
  Print(#CRLF$+"PROCESS NAME:  "+PeekS(@pe32\szExeFile,260,#PB_Ascii))
  Print(#CRLF$+"-----------------------------------------------------" )

  ;Retrieve the priority class.
  dwPriorityClass=0
  hProcess=OpenProcess_(#PROCESS_ALL_ACCESS,#False,pe32\th32ProcessID)
  If hProcess=#Null
   printError("OpenProcess")
  Else
   dwPriorityClass=GetPriorityClass_(hProcess)
   If dwPriorityClass=#False
    printError("GetPriorityClass")
   EndIf
   CloseHandle_(hProcess)
  EndIf

  Print(#CRLF$+"  process ID        = $"+LSet(Hex(pe32\th32ProcessID),8,"0"))
  Print(#CRLF$+"  thread count      = "+StrU(pe32\cntThreads,#Long))
  Print(#CRLF$+"  parent process ID = $"+LSet(Hex(pe32\th32ParentProcessID),8,"0"))
  Print(#CRLF$+"  Priority Base     = "+StrU(pe32\pcPriClassBase,#Long))
  If dwPriorityClass
   Print(#CRLF$+"  Priority Class    = "+StrU(dwPriorityClass,#Long))
  EndIf

  ;List the modules and threads associated with this process
  ListProcessModules(pe32\th32ProcessID)
  ListProcessThreads(pe32\th32ProcessID)
 Until Process32Next_(hProcessSnap,pe32)=#False

 CloseHandle_(hProcessSnap)
 ProcedureReturn #True
EndProcedure

OpenConsole()
GetProcessList()
CloseConsole()
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Here is a "hack/workaround" the code works but obviously this is "wrong".
Please look at the two places PeekS is used.

Code: Select all

;BOOL GetProcessList( );
;BOOL ListProcessModules( DWORD dwPID );
;BOOL ListProcessThreads( DWORD dwOwnerPID );
;void printError( TCHAR* msg );

Procedure printError(msg.s)
Protected eNum.l,sysMsg.s{256},p.s

 eNum=GetLastError_()
 FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM|#FORMAT_MESSAGE_IGNORE_INSERTS,#Null,eNum,0,@sysMsg,256,#Null)
 Print(#CRLF$+"  WARNING: "+msg+" failed with error "+StrU(eNum,#Long)+" ("+sysMsg+")")
EndProcedure

Procedure.l ListProcessModules(dwPID.l)
 Protected hModuleSnap.l,me32.MODULEENTRY32

  hModuleSnap=#INVALID_HANDLE_VALUE;

  ;Take a snapshot of all modules in the specified process.
  hModuleSnap=CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE,dwPID)

  If hModuleSnap=#INVALID_HANDLE_VALUE
   printError("CreateToolhelp32Snapshot (of modules)")
   ProcedureReturn #False
  EndIf

  ;Set the size of the structure before using it.
  me32\dwSize=SizeOf(MODULEENTRY32)

  ;Retrieve information about the first module,
  ;and exit if unsuccessful
  If Module32First_(hModuleSnap,me32)=#False
   printError("Module32First") ;Show cause of failure
   CloseHandle_(hModuleSnap)   ;Must clean up the snapshot object!
   ProcedureReturn #False
  EndIf

  ;Now walk the module list of the process,
  ;and display information about each module
  Repeat
    Print(#CRLF$+#CRLF$+"     MODULE NAME:     "+PeekS(@me32\szModule,#MAX_MODULE_NAME32,#PB_Ascii))
    Print(#CRLF$+"     executable     = "+PeekS((@me32\szModule+#MAX_MODULE_NAME32)+1,#MAX_PATH,#PB_Ascii))
;The two above is a "hack", proper way is below, wait for PB4 fix so they work.
;    Print(#CRLF$+#CRLF$+"     MODULE NAME:     "+PeekS(@me32\szModule,#MAX_MODULE_NAME32))
;    Print(#CRLF$+"     executable     = "+PeekS(@me32\szExePath,#MAX_PATH))

    Print(#CRLF$+"     process ID     = $"+LSet(Hex(me32\th32ProcessID),8,"0"))
    Print(#CRLF$+"     ref count (g)  = $"+LSet(Hex(me32\GlblcntUsage),4,"0"))
    Print(#CRLF$+"     ref count (p)  = $"+LSet(Hex(me32\ProccntUsage),4,"0"))
    Print(#CRLF$+"     base address   = $"+LSet(Hex(me32\modBaseAddr),8,"0"))
    Print(#CRLF$+"     base size      = "+StrU(me32\modBaseSize,#Long))
  Until Module32Next_(hModuleSnap,me32)=#False

  CloseHandle_(hModuleSnap)
   ProcedureReturn #True
EndProcedure

Procedure.l ListProcessThreads(dwOwnerPID.l) 
Protected hThreadSnap.l,te32.THREADENTRY32
 hThreadSnap=#INVALID_HANDLE_VALUE

 ;Take a snapshot of all running threads  
 hThreadSnap=CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD,0)
 If hThreadSnap=#INVALID_HANDLE_VALUE
  ProcedureReturn #False
 EndIf

 ;Fill in the size of the structure before using it. 
 te32\dwSize=SizeOf(THREADENTRY32)

 ;Retrieve information about the first thread,
 ;and exit if unsuccessful
 If Thread32First_(hThreadSnap,te32)=#False 
  printError("Thread32First" ) ;Show cause of failure
  CloseHandle_(hThreadSnap)     ;Must clean up the snapshot object!
  ProcedureReturn #False
 EndIf

 ;Now walk the thread list of the system,
 ;and display information about each thread
 ;associated with the specified process

 Repeat
  If te32\th32OwnerProcessID=dwOwnerPID
   Print(#CRLF$+#CRLF$+"     THREAD ID      = $"+LSet(Hex(te32\th32ThreadID),8,"0"))
   Print(#CRLF$+"     base priority  = "+StrU(te32\tpBasePri,#Long))
   Print(#CRLF$+"     delta priority = "+StrU(te32\tpDeltaPri,#Long))
  EndIf
 Until Thread32Next_(hThreadSnap,te32)=#False

 CloseHandle_(hThreadSnap)
 ProcedureReturn #True
EndProcedure

Procedure.l GetProcessList()
Protected hProcessSnap.l,hProcess.l,wPriorityClass.l,pe32.PROCESSENTRY32

 ;Take a snapshot of all processes in the system.
 hProcessSnap=CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS,0)
 If(hProcessSnap=#INVALID_HANDLE_VALUE)
  printError("CreateToolhelp32Snapshot (of processes)")
  ProcedureReturn #False
 EndIf

 ;Set the size of the Structure before using it.
 pe32\dwSize=SizeOf(PROCESSENTRY32)

 ;Retrieve information about the first process,
 ;And exit if unsuccessful
 If Process32First_(hProcessSnap,pe32)=#False
  printError("Process32First") ;Show cause of failure
  CloseHandle_(hProcessSnap)    ;Must clean up the snapshot object!
  ProcedureReturn #False
 EndIf

 ;Now walk the snapshot of processes, and
 ;display information about each process in turn

 Repeat
  Print(#CRLF$+#CRLF$+"=====================================================")
  Print(#CRLF$+"PROCESS NAME:  "+PeekS(@pe32\szExeFile,260,#PB_Ascii)) ;#PB_Ascii should not be necessary, but there is a PB bug.
  Print(#CRLF$+"-----------------------------------------------------" )

  ;Retrieve the priority class.
  dwPriorityClass=0
  hProcess=OpenProcess_(#PROCESS_ALL_ACCESS,#False,pe32\th32ProcessID)
  If hProcess=#Null
   printError("OpenProcess")
  Else
   dwPriorityClass=GetPriorityClass_(hProcess)
   If dwPriorityClass=#False
    printError("GetPriorityClass")
   EndIf
   CloseHandle_(hProcess)
  EndIf

  Print(#CRLF$+"  process ID        = $"+LSet(Hex(pe32\th32ProcessID),8,"0"))
  Print(#CRLF$+"  thread count      = "+StrU(pe32\cntThreads,#Long))
  Print(#CRLF$+"  parent process ID = $"+LSet(Hex(pe32\th32ParentProcessID),8,"0"))
  Print(#CRLF$+"  Priority Base     = "+StrU(pe32\pcPriClassBase,#Long))
  If dwPriorityClass
   Print(#CRLF$+"  Priority Class    = "+StrU(dwPriorityClass,#Long))
  EndIf

  ;List the modules and threads associated with this process
  ListProcessModules(pe32\th32ProcessID)
  ListProcessThreads(pe32\th32ProcessID)
 Until Process32Next_(hProcessSnap,pe32)=#False

 CloseHandle_(hProcessSnap)
 ProcedureReturn #True
EndProcedure

OpenConsole()
GetProcessList()
CloseConsole()
Fred
Administrator
Administrator
Posts: 18252
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

OpenProcess() doesn't have an unicode counterpart, so it is logical and not a PB bug...
Post Reply