PHP program execution error

I want to execute a C ++ program using my PHP Back-end. The C ++ program is responsible for removing USB devices, such as USB drives, from my PC. When I open a program (which is located on a separate local disk) with the CLI without administrative rights, the program starts and ends correctly.

When I run the program using PHP using exec("/path/to/my/program.exe and-parameters") , which literally matches the CLI, the program just starts and returns a "failure", so when using the CLI, something happens something else.

C ++ Code:

 // // RemoveDriveByLetter.cpp by Uwe Sieber - www.uwe-sieber.de // // Simple demonstration how to prepare a disk drive for save removal // // Works with removable and fixed drives under W2K, XP, W2K3, Vista // // Console application - expects the drive letter of the drive to remove as parameter // // you are free to use this code in your projects // #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <Setupapi.h> #include <winioctl.h> #include <winioctl.h> #include <cfgmgr32.h> #include <string> //------------------------------------------------- DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber, UINT DriveType, char* szDosDeviceName); //------------------------------------------------- //------------------------------------------------- int main(int argc, char* argv[]) { /*if ( argc != 2 ) { return 1; }*/ char DriveLetter = argv[1][0]; DriveLetter &= ~0x20; // uppercase if ( DriveLetter < 'A' || DriveLetter > 'Z' ) { return 1; } std::string path = ""; path += DriveLetter; path.append(":\\"); printf(path.c_str()); char szRootPath[sizeof(path)] =""; strncpy(szRootPath, path.c_str(), sizeof(path)); std::string device = ""; device += DriveLetter; device.append(":"); printf(device.c_str()); char szDevicePath[sizeof(device)] = ""; strncpy(szDevicePath, device.c_str(), sizeof(device)); std::string accesspath = ""; accesspath += "\\\\.\\"; accesspath += device; printf(accesspath.c_str()); char szVolumeAccessPath[sizeof(accesspath)] = ""; // "\\.\X:" -> to open the volume strncpy(szVolumeAccessPath, accesspath.c_str(), sizeof(accesspath)); long DeviceNumber = -1; // open the storage volume HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); if (hVolume == INVALID_HANDLE_VALUE) { return 1; } // get the volume device number STORAGE_DEVICE_NUMBER sdn; DWORD dwBytesReturned = 0; long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL); if ( res ) { DeviceNumber = sdn.DeviceNumber; } CloseHandle(hVolume); if ( DeviceNumber == -1 ) { return 1; } // get the drive type which is required to match the device numbers correctely UINT DriveType = GetDriveType(szRootPath); // get the dos device name (like \device\floppy0) to decide if it a floppy or not - who knows a better way? char szDosDeviceName[MAX_PATH]; res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH); if ( !res ) { return 1; } // get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName); if ( DevInst == 0 ) { return 1; } PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown; WCHAR VetoNameW[MAX_PATH]; VetoNameW[0] = 0; bool bSuccess = false; // get drives parent, eg the USB bridge, the SATA port, an IDE channel with two drives! DEVINST DevInstParent = 0; res = CM_Get_Parent(&DevInstParent, DevInst, 0); for ( long tries=1; tries<=3; tries++ ) { // sometimes we need some tries... VetoNameW[0] = 0; // CM_Query_And_Remove_SubTree doesn't work for restricted users //res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K! //res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART); // with messagebox (W2K, Vista) or balloon (XP) res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0); //res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP) bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown); if ( bSuccess ) { break; } Sleep(500); // required to give the next tries a chance! } if ( bSuccess ) { printf("Success\n\n"); return 0; } printf("failed\n"); printf("Result=0x%2X\n", res); if ( VetoNameW[0] ) { printf("VetoName=%ws)\n\n", VetoNameW); } return 1; } //----------------------------------------------------------- char* appendCharToCharArray(char* array, char a) { size_t len = strlen(array); char* ret = new char[len+2]; strcpy(ret, array); ret[len] = a; ret[len+1] = '\0'; return ret; } //---------------------------------------------------------------------- // returns the device instance handle of a storage volume or 0 on error //---------------------------------------------------------------------- DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber, UINT DriveType, char* szDosDeviceName) { bool IsFloppy = (strstr(szDosDeviceName, "\\Floppy") != NULL); // who knows a better way? GUID* guid; switch (DriveType) { case DRIVE_REMOVABLE: if ( IsFloppy ) { guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY; } else { guid = (GUID*)&GUID_DEVINTERFACE_DISK; } break; case DRIVE_FIXED: guid = (GUID*)&GUID_DEVINTERFACE_DISK; break; case DRIVE_CDROM: guid = (GUID*)&GUID_DEVINTERFACE_CDROM; break; default: return 0; } // Get device interface info set handle for all devices attached to system HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (hDevInfo == INVALID_HANDLE_VALUE) { return 0; } // Retrieve a context structure for a device interface of a device information set DWORD dwIndex = 0; long res; BYTE Buf[1024]; PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf; SP_DEVICE_INTERFACE_DATA spdid; SP_DEVINFO_DATA spdd; DWORD dwSize; spdid.cbSize = sizeof(spdid); while ( true ) { res = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &spdid); if ( !res ) { break; } dwSize = 0; SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL); // check the buffer size if ( dwSize!=0 && dwSize<=sizeof(Buf) ) { pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes! ZeroMemory(&spdd, sizeof(spdd)); spdd.cbSize = sizeof(spdd); long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd, dwSize, &dwSize, &spdd); if ( res ) { // in case you are interested in the USB serial number: // the device id string contains the serial number if the device has one, // otherwise a generated id that contains the '&' char... /* DEVINST DevInstParent = 0; CM_Get_Parent(&DevInstParent, spdd.DevInst, 0); char szDeviceIdString[MAX_PATH]; CM_Get_Device_ID(DevInstParent, szDeviceIdString, MAX_PATH, 0); printf("DeviceId=%s\n", szDeviceIdString); */ // open the disk or cdrom or floppy HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if ( hDrive != INVALID_HANDLE_VALUE ) { // get its device number STORAGE_DEVICE_NUMBER sdn; DWORD dwBytesReturned = 0; res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL); if ( res ) { if ( DeviceNumber == (long)sdn.DeviceNumber ) { // match the given device number with the one of the current device CloseHandle(hDrive); SetupDiDestroyDeviceInfoList(hDevInfo); return spdd.DevInst; } } CloseHandle(hDrive); } } } dwIndex++; } SetupDiDestroyDeviceInfoList(hDevInfo); return 0; } //----------------------------------------------------------- 

The program returns:

array (2) ([0] => (string) D: \ D: \. \ D: failed [1] => (string) Result = 0x33)

Anyone suggest?

+7
c ++ windows php iis
source share
3 answers

If you use PHP in safe mode, then only files in safe_mode_exec_dir will be allowed.

You seem to be working in a Windows environment. You might want to consider doing this using the Windows shell, which gives you more control over your external executing programs and can return additional information if it doesn't work, and help diagnose that the main problem is related to the exec () function.

Comments on the PHP online manual:

Run Notepad.exe in the background with a minimum value:

 <?php $WshShell = new COM("WScript.Shell"); $oExec = $WshShell->Run("notepad.exe", 7, false); ?> 

run a shell command invisible in the background:

 <?php $WshShell = new COM("WScript.Shell"); $oExec = $WshShell->Run("cmd /C dir /S %windir%", 0, false); ?> 

start up MSPaint and wait until you close it before continuing with the script:

 <?php $WshShell = new COM("WScript.Shell"); $oExec = $WshShell->Run("mspaint.exe", 3, true); ?> 

For more information about the Run () method, go to: https://msdn.microsoft.com/en-us/subscriptions/d5fk67ky(v=vs.84).aspx

+5
source share

First run the command through php client (from the shell).

 <?php exec("/path/to/my/program.exe and-parameters"); 

.

 $ php.exe -f file.php //Check link above. I am used to Linux and you might need diffrent params 

If this works, then this is most likely an iis resolution issue.

+9
source share

This article describes how to configure the application pool and associate them with your PHP service. After that, right-click the created application pool and select "Advanced Settings". In the heading "Process Model" you will see the setting "Identity"; change the value to an account that has the required permissions (for example, "Local System" or "Local Service").

The default application pool identifier (where your PHP service is currently running) is not enough for your purposes!

+1
source share

All Articles